diff --git a/.gitmodules b/.gitmodules index acf322b..bc32b9a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,9 +31,6 @@ [submodule "Tweaks/iSponsorBlock"] path = Tweaks/iSponsorBlock url = https://github.com/Galactic-Dev/iSponsorBlock.git -[submodule "Extensions"] - path = Extensions - url = https://github.com/CokePokes/YoutubeExtensions.git [submodule "Tweaks/YTHoldForSpeed"] path = Tweaks/YTHoldForSpeed url = https://github.com/arichorn/YTHoldForSpeed.git @@ -43,3 +40,6 @@ [submodule "Tweaks/YTLite"] path = Tweaks/YTLite url = https://github.com/dayanch96/YTLite.git +[submodule "Extensions"] + path = Extensions + url = https://github.com/CokePokes/YoutubeExtensions.git diff --git a/Extensions b/Extensions new file mode 160000 index 0000000..a68d708 --- /dev/null +++ b/Extensions @@ -0,0 +1 @@ +Subproject commit a68d70883d297fcc6669429dfd1439848e96e411 diff --git a/Extensions/.gitattributes b/Extensions/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Extensions/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Extensions/.gitignore b/Extensions/.gitignore deleted file mode 100644 index 496ee2c..0000000 --- a/Extensions/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store \ No newline at end of file diff --git a/Extensions/OpenYoutubeSafariExtension.appex/Info.plist b/Extensions/OpenYoutubeSafariExtension.appex/Info.plist deleted file mode 100644 index 5d7d778..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/Info.plist and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/OpenYoutube b/Extensions/OpenYoutubeSafariExtension.appex/OpenYoutube deleted file mode 100755 index 2555c7a..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/OpenYoutube and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/_CodeSignature/CodeResources b/Extensions/OpenYoutubeSafariExtension.appex/_CodeSignature/CodeResources deleted file mode 100644 index b9dc07e..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/_CodeSignature/CodeResources +++ /dev/null @@ -1,333 +0,0 @@ - - - - - files - - Info.plist - - 5KaPBsMVTGZfcc05Od8nGW6/EyQ= - - _locales/en/messages.json - - 8cPkszxzYFSjhRWsf34A0AiHaPM= - - background.js - - tClFxbnUm0L65Qj+Qu8Fk9asL2o= - - content.js - - a6o4B4PMlrIOBXlniU2NS4D9SJE= - - embedded.mobileprovision - - dVGLS8Qpu/eCI1J5VCu9IfYq3Z4= - - images/cat_1.0.gif - - DtSTnvB7wRt647kM1b38KLfDfXA= - - images/icon-128.png - - rYa1lv1LgkO3fkP9h6gRSjlQgqk= - - images/icon-256.png - - 05xbekvTg28KsH9RRIKQRL8tqQs= - - images/icon-48.png - - BWUZe8raKzOzA2cDWIYFoBPxxw8= - - images/icon-512.png - - shzpVHJMsAu4q820Fb+YzByiFhc= - - images/icon-64.png - - HZC4YIb4ZLg4lpjNAKFqSaka6r0= - - images/icon-96.png - - IPAOd1HfCtCI7ybhVhwA5TU/BZ8= - - images/toolbar-icon-16.png - - Bkb2Cy8VYIcWl7wFZ2HcWZcCoyA= - - images/toolbar-icon-19.png - - XLkdODJ73CVbwn/1LCAsfB6scPg= - - images/toolbar-icon-32.png - - 0cQgf/z3urGdzsmtmc2Wnim1+lg= - - images/toolbar-icon-38.png - - eas7Tl3/r2JMZf6nK84ZjoBJrZo= - - images/toolbar-icon-48.png - - fxyz1xgkIR877Cf/7uYNUqXrxoM= - - images/toolbar-icon-72.png - - pHL3CJwjPY30T9sFvvcA2qlraBw= - - manifest.json - - b37QyqMYHlvlfOjbvJLOKeAM5Y4= - - popup.css - - mXR2qQxu+ceMOItNpc4aImux5wY= - - popup.html - - zTk6QImmvcZjMYLQY8ek+cqSEWg= - - popup.js - - grmSQBg1aRbGzHHjd3TWHS/HbOY= - - - files2 - - _locales/en/messages.json - - hash2 - - 4pOaVgBrOGGIoI81XdEOZidIyW9peYtz85HIYX7d1QE= - - - background.js - - hash2 - - 2S7ONYvdkGsryEavyrR7nMCTwsjNGqMV2BSWIxWLSYg= - - - content.js - - hash2 - - 9CYz6yZ8bRI2JRzRwnn4DOGuPuy2GSsOudXSZU6s1po= - - - embedded.mobileprovision - - hash2 - - 4TQyzTTz0VYUTM0IXf2PMSufVEkzd4WlPWbwKMyfKfQ= - - - images/cat_1.0.gif - - hash2 - - 65Ql3FhfivRMoMifbuY5KK8I/1rZx/Zmmwsx1La4OyI= - - - images/icon-128.png - - hash2 - - TV8I8bcVP9rAnVA4AJRAWtkJveIenMpYsd/7+rsMLzo= - - - images/icon-256.png - - hash2 - - kksdsW0Y1svz0bT0i3UzQGBmBDxJGr2eTCZmaqTS+XM= - - - images/icon-48.png - - hash2 - - mBNPpZ78p0eH4WsNdF/EXw/sFHq5f8PqERARlLulYbY= - - - images/icon-512.png - - hash2 - - waQn18oFc3GbhXXm2HEn6xFQk3HKehp9crGljWAMsGQ= - - - images/icon-64.png - - hash2 - - CJwxajQk49Cd0RfR22yEPO6pjDbg+Aa4Ocxi+812CiM= - - - images/icon-96.png - - hash2 - - zuzRjCepizxOWXh9ftCPth38GUxy1Ea/4zS3dw19OXo= - - - images/toolbar-icon-16.png - - hash2 - - xmXH4YHb+Pq/YuC1e8JLIun93LuM3+/8MvB3r8oTKls= - - - images/toolbar-icon-19.png - - hash2 - - qSX/1Ux4BOUIhixJK5NkvyTomLwp0yISfsQ97uF8/5g= - - - images/toolbar-icon-32.png - - hash2 - - pGDg4NcSdD5EQaZgaiwxNosbSEXmZnpRc79RfitKc1c= - - - images/toolbar-icon-38.png - - hash2 - - BUU3dwrCSvNOiFkBQWdPkrwASjUvxSxbizW+Izt3LBA= - - - images/toolbar-icon-48.png - - hash2 - - JLZV5da+fZkfw0m2KfMqHSixWBCJvZoUNlt3la7gm54= - - - images/toolbar-icon-72.png - - hash2 - - TwM7A1Bkuv4C3SWorFNwG+w38mWo3TaMtglLdDXxcFw= - - - manifest.json - - hash2 - - +nWdvS9ap7YzpjqKSWsGUHP5K2irkTGozQX/tI4WrYc= - - - popup.css - - hash2 - - LIfF3an8mzKIMD8PDhKILnrZBhxxSTzoZQKyRiyWuB0= - - - popup.html - - hash2 - - 9Ro1fCC5Meq0eSNrYab7V3uc4tNvmwRqMsCb1757M6Q= - - - popup.js - - hash2 - - ruLXAORE+vDoLKPGBSkl7hnXv8V+ZexCoX3KvJyHxBk= - - - - rules - - ^.* - - ^.*\.lproj/ - - optional - - weight - 1000 - - ^.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Base\.lproj/ - - weight - 1010 - - ^version.plist$ - - - rules2 - - .*\.dSYM($|/) - - weight - 11 - - ^(.*/)?\.DS_Store$ - - omit - - weight - 2000 - - ^.* - - ^.*\.lproj/ - - optional - - weight - 1000 - - ^.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Base\.lproj/ - - weight - 1010 - - ^Info\.plist$ - - omit - - weight - 20 - - ^PkgInfo$ - - omit - - weight - 20 - - ^embedded\.provisionprofile$ - - weight - 20 - - ^version\.plist$ - - weight - 20 - - - - diff --git a/Extensions/OpenYoutubeSafariExtension.appex/_locales/en/messages.json b/Extensions/OpenYoutubeSafariExtension.appex/_locales/en/messages.json deleted file mode 100644 index 12ab694..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/_locales/en/messages.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extension_name": { - "message": "OpenYoutube", - "description": "The display name for the extension." - }, - "extension_description": { - "message": "Displays an Open in Youtube alert for sideloaded YT", - "description": "Description of what the extension does." - } -} diff --git a/Extensions/OpenYoutubeSafariExtension.appex/background.js b/Extensions/OpenYoutubeSafariExtension.appex/background.js deleted file mode 100644 index ff39b3b..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/background.js +++ /dev/null @@ -1,6 +0,0 @@ -browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - console.log("Received request: ", request); - - if (request.greeting === "hello") - sendResponse({ farewell: "goodbye" }); -}); diff --git a/Extensions/OpenYoutubeSafariExtension.appex/content.js b/Extensions/OpenYoutubeSafariExtension.appex/content.js deleted file mode 100644 index 8c80064..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/content.js +++ /dev/null @@ -1,25 +0,0 @@ -browser.runtime.sendMessage({ greeting: "hello" }).then((response) => { - console.log("Received response: ", response); -}); - -browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - console.log("Received request: ", request); -}); - -function afterNavigate() { - if ('/watch' === location.pathname) { - window.location.href = `youtube://${window.location.pathname.slice(1)}${ - window.location.search - }${window.location.hash}`; - } -} -(document.body || document.documentElement).addEventListener('transitionend', - function(/*TransitionEvent*/ event) { - if (event.propertyName === 'width' && event.target.id === 'progress') { - afterNavigate(); - } -}, true); -// After page load -afterNavigate(); - - diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/cat_1.0.gif b/Extensions/OpenYoutubeSafariExtension.appex/images/cat_1.0.gif deleted file mode 100644 index ce1e88b..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/cat_1.0.gif and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-128.png b/Extensions/OpenYoutubeSafariExtension.appex/images/icon-128.png deleted file mode 100644 index c919eb0..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-128.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-256.png b/Extensions/OpenYoutubeSafariExtension.appex/images/icon-256.png deleted file mode 100644 index 6bd3d20..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-256.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-48.png b/Extensions/OpenYoutubeSafariExtension.appex/images/icon-48.png deleted file mode 100644 index 353e8fb..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-48.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-512.png b/Extensions/OpenYoutubeSafariExtension.appex/images/icon-512.png deleted file mode 100644 index 2200828..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-512.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-64.png b/Extensions/OpenYoutubeSafariExtension.appex/images/icon-64.png deleted file mode 100644 index 995689f..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-64.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-96.png b/Extensions/OpenYoutubeSafariExtension.appex/images/icon-96.png deleted file mode 100644 index cb079d2..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/icon-96.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-16.png b/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-16.png deleted file mode 100644 index ad014f6..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-16.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-19.png b/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-19.png deleted file mode 100644 index 33eb01e..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-19.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-32.png b/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-32.png deleted file mode 100644 index a71914b..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-32.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-38.png b/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-38.png deleted file mode 100644 index 990e7f4..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-38.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-48.png b/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-48.png deleted file mode 100644 index f4c70ad..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-48.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-72.png b/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-72.png deleted file mode 100644 index 9bf6d4e..0000000 Binary files a/Extensions/OpenYoutubeSafariExtension.appex/images/toolbar-icon-72.png and /dev/null differ diff --git a/Extensions/OpenYoutubeSafariExtension.appex/manifest.json b/Extensions/OpenYoutubeSafariExtension.appex/manifest.json deleted file mode 100644 index a7c520e..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/manifest.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "manifest_version": 2, - "default_locale": "en", - - "name": "__MSG_extension_name__", - "description": "__MSG_extension_description__", - "version": "1.0", - - "icons": { - "48": "images/icon-48.png", - "96": "images/icon-96.png", - "128": "images/icon-128.png", - "256": "images/icon-256.png", - "512": "images/icon-512.png" - }, - - "background": { - "scripts": [ "background.js" ], - "persistent": false - }, - - "content_scripts": [{ - "js": [ "content.js" ], - "matches": [ "*://*.youtube.com/*" ] - }], - - "browser_action": { - "default_popup": "popup.html", - "default_icon": { - "16": "images/toolbar-icon-16.png", - "19": "images/toolbar-icon-19.png", - "32": "images/toolbar-icon-32.png", - "38": "images/toolbar-icon-38.png", - "48": "images/toolbar-icon-48.png", - "72": "images/toolbar-icon-72.png" - } - }, - - "permissions": [ ] -} diff --git a/Extensions/OpenYoutubeSafariExtension.appex/popup.css b/Extensions/OpenYoutubeSafariExtension.appex/popup.css deleted file mode 100644 index 5b149b9..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/popup.css +++ /dev/null @@ -1,15 +0,0 @@ -:root { - color-scheme: light dark; -} - -body { - width: 100px; - padding: 10px; - - font-family: system-ui; - text-align: center; -} - -@media (prefers-color-scheme: dark) { - /* Dark Mode styles go here. */ -} diff --git a/Extensions/OpenYoutubeSafariExtension.appex/popup.html b/Extensions/OpenYoutubeSafariExtension.appex/popup.html deleted file mode 100644 index 0287388..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/popup.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - Extension made by @CokePokes - - diff --git a/Extensions/OpenYoutubeSafariExtension.appex/popup.js b/Extensions/OpenYoutubeSafariExtension.appex/popup.js deleted file mode 100644 index 5c1aa86..0000000 --- a/Extensions/OpenYoutubeSafariExtension.appex/popup.js +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello World!", browser); diff --git a/Extensions/README.md b/Extensions/README.md deleted file mode 100644 index 5b68abf..0000000 --- a/Extensions/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# YoutubeExtensions - appex extensions for sideloaded YT - - - What is this? - - These plugins enable "Open In" for sideloaded Youtube without any need to download other Opener apps /Shortcuts. - - - How to install: - - 1. Download the .appex files here - 2. Unzip Youtube.ipa & copy them to /Payload/Youtube.app/Plugins - 3. Compress Payload folder & rename .zip to .ipa - 4. Sign & Install onto device - 5. Open YouTube once & then open Safari to enable the iOS 15 safari plugin [prompted always allow - do it] - 6. Press the Share icon in Safari scroll app list > More > Enable Youtube - - Done! - diff --git a/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/Info.plist b/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/Info.plist deleted file mode 100644 index c231977..0000000 Binary files a/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/Info.plist and /dev/null differ diff --git a/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib b/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib deleted file mode 100644 index 8dac7fd..0000000 Binary files a/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib and /dev/null differ diff --git a/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib b/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib deleted file mode 100644 index a0da51e..0000000 Binary files a/Extensions/ShareServiceExtension.appex/Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib and /dev/null differ diff --git a/Extensions/ShareServiceExtension.appex/Info.plist b/Extensions/ShareServiceExtension.appex/Info.plist deleted file mode 100644 index 427b324..0000000 Binary files a/Extensions/ShareServiceExtension.appex/Info.plist and /dev/null differ diff --git a/Extensions/ShareServiceExtension.appex/Youtube b/Extensions/ShareServiceExtension.appex/Youtube deleted file mode 100755 index f903ca4..0000000 Binary files a/Extensions/ShareServiceExtension.appex/Youtube and /dev/null differ diff --git a/Extensions/ShareServiceExtension.appex/Youtube@2x.png b/Extensions/ShareServiceExtension.appex/Youtube@2x.png deleted file mode 100644 index 36773c5..0000000 Binary files a/Extensions/ShareServiceExtension.appex/Youtube@2x.png and /dev/null differ diff --git a/Extensions/ShareServiceExtension.appex/_CodeSignature/CodeResources b/Extensions/ShareServiceExtension.appex/_CodeSignature/CodeResources deleted file mode 100644 index d2950b5..0000000 --- a/Extensions/ShareServiceExtension.appex/_CodeSignature/CodeResources +++ /dev/null @@ -1,157 +0,0 @@ - - - - - files - - Base.lproj/MainInterface.storyboardc/Info.plist - - Bgt43YuQd48Y7NBkKAH/I1Nd+7Q= - - Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib - - t/rVTMy59WLCl0e0ydlT2JlJKIs= - - Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib - - 56s4vIzFNrq5HEvB3Mr6qnqVRFg= - - Info.plist - - 7+n2S5sS/Ngeoe21gJMc6iC6+ac= - - embedded.mobileprovision - - dVGLS8Qpu/eCI1J5VCu9IfYq3Z4= - - icon.png - - /pip+c1EETgjhxNcOhgiyQxxzyU= - - - files2 - - Base.lproj/MainInterface.storyboardc/Info.plist - - hash2 - - Qnp5pVqL/lRCSEISDYZs1VBLxfcEnfpOzHg6WgcgLgk= - - - Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib - - hash2 - - VpQww1vK2BoM0RIaiw/B/8JZ3kp5Pks5bM8Sjtjju9w= - - - Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib - - hash2 - - C87FO0vFlvhG8vp7+3v+EcR9kbOeu9v+mDLy/iU+6e8= - - - embedded.mobileprovision - - hash2 - - 4TQyzTTz0VYUTM0IXf2PMSufVEkzd4WlPWbwKMyfKfQ= - - - icon.png - - hash2 - - mfufJ0CJyFLUpRnLC8q8awHkGqmWeQtRDgF5EBXKUQs= - - - - rules - - ^.* - - ^.*\.lproj/ - - optional - - weight - 1000 - - ^.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Base\.lproj/ - - weight - 1010 - - ^version.plist$ - - - rules2 - - .*\.dSYM($|/) - - weight - 11 - - ^(.*/)?\.DS_Store$ - - omit - - weight - 2000 - - ^.* - - ^.*\.lproj/ - - optional - - weight - 1000 - - ^.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Base\.lproj/ - - weight - 1010 - - ^Info\.plist$ - - omit - - weight - 20 - - ^PkgInfo$ - - omit - - weight - 20 - - ^embedded\.provisionprofile$ - - weight - 20 - - ^version\.plist$ - - weight - 20 - - - - diff --git a/Extensions/ShareServiceExtension.appex/test.json b/Extensions/ShareServiceExtension.appex/test.json deleted file mode 100644 index 06c02da..0000000 --- a/Extensions/ShareServiceExtension.appex/test.json +++ /dev/null @@ -1,7 +0,0 @@ -var GetURL = function() {}; -GetURL.prototype = { -run: function(arguments) { - arguments.completionFunction({"URL": document.URL}); -} -}; -var ExtensionPreprocessingJS = new GetURL; diff --git a/Tweaks/Alderis b/Tweaks/Alderis new file mode 160000 index 0000000..7992b3b --- /dev/null +++ b/Tweaks/Alderis @@ -0,0 +1 @@ +Subproject commit 7992b3b57e86beca069905df121dc57542ae5b6f diff --git a/Tweaks/Alderis/.gitignore b/Tweaks/Alderis/.gitignore deleted file mode 100644 index 5b863e9..0000000 --- a/Tweaks/Alderis/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# Crap -.DS_Store - -# Xcode -*.pbxuser -!default.pbxuser -xcuserdata -*.xccheckout -*.xcuserstate - -# Carthage -Carthage/ - -# Theos -.theos -packages/ diff --git a/Tweaks/Alderis/.jazzy.yaml b/Tweaks/Alderis/.jazzy.yaml deleted file mode 100644 index fedf7e6..0000000 --- a/Tweaks/Alderis/.jazzy.yaml +++ /dev/null @@ -1,36 +0,0 @@ -clean: true -author: HASHBANG Productions -author_url: https://hbang.github.io/ -github_url: https://github.com/hbang/Alderis -root_url: https://hbang.github.io/Alderis/ -dash_url: https://hbang.github.io/Alderis/docsets/Alderis.xml -documentation: info/*.md -hide_documentation_coverage: true - -custom_categories: - - name: "Guides" - children: - - "Preference Bundles" - - "Migrating to 1.1" - - - name: "Color Picker" - children: - - ColorPickerViewController - - ColorPickerConfiguration - - ColorPickerDelegate - - ColorPickerTab - - - name: "UI Components" - children: - - ColorWell - - - name: "Extensions" - children: - - UIColor - - ColorPropertyListValue - - String - - Array - - - name: "Deprecated" - children: - - ColorPickerCircleView diff --git a/Tweaks/Alderis/.swiftlint.yml b/Tweaks/Alderis/.swiftlint.yml deleted file mode 100644 index 8e390d9..0000000 --- a/Tweaks/Alderis/.swiftlint.yml +++ /dev/null @@ -1,61 +0,0 @@ -disabled_rules: - - trailing_comma - - nesting - - fallthrough - - shorthand_operator - - todo - - large_tuple - - identifier_name - - type_name - - type_body_length - # TODO: Why is vertical_parameter_alignment giving false positives? - - vertical_parameter_alignment - - vertical_parameter_alignment_on_call - # TODO: Enable when removing support for older Swift versions (<5.6) - - unavailable_condition -opt_in_rules: - - closure_end_indentation - - closure_spacing - - contains_over_first_not_nil - - empty_count - - explicit_init - - fatal_error_message - - first_where - - joined_default_parameter - - literal_expression_end_indentation - - overridden_super_call - - prohibited_super_call - - sorted_first_last - - unneeded_parentheses_in_closure_argument - - vertical_parameter_alignment_on_call - - yoda_condition - - nslocalizedstring_key - - unused_setter_value -custom_rules: - comment_whitespace: - name: "Comment Whitespace" - regex: //\S - match_kinds: comment - message: "Comments must begin with a whitespace character" - spaces_not_tabs: - name: "Tabs not Spaces" - regex: ^( ) - message: "Use tabs instead of spaces" - point_zero: - name: "Point Zero" - regex: '(? "https://github.com/hbang/Alderis.git", :tag => "#{spec.version}" } - spec.requires_arc = true - spec.source_files = [ "Alderis/*.swift", "Alderis/*.h" ] - spec.resource_bundles = { "Alderis" => "Alderis/Assets-ios12.xcassets" } -end diff --git a/Tweaks/Alderis/Alderis.xcodeproj/project.pbxproj b/Tweaks/Alderis/Alderis.xcodeproj/project.pbxproj deleted file mode 100644 index a2db244..0000000 --- a/Tweaks/Alderis/Alderis.xcodeproj/project.pbxproj +++ /dev/null @@ -1,482 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 52; - objects = { - -/* Begin PBXBuildFile section */ - 4E1C741328266C5900227EC3 /* UIFontDescriptorAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C741228266C5900227EC3 /* UIFontDescriptorAdditions.swift */; }; - 4E1C74172826C1F100227EC3 /* ColorPickerAccessibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C74162826C1F100227EC3 /* ColorPickerAccessibilityViewController.swift */; }; - 4E1C741928276D5600227EC3 /* TextViewLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C741828276D5600227EC3 /* TextViewLabel.swift */; }; - 4E1C741B2827829E00227EC3 /* AccessibilityComplianceLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C741A2827829E00227EC3 /* AccessibilityComplianceLabel.swift */; }; - 4E1C741D2827882600227EC3 /* AccessibilityContrastSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C741C2827882600227EC3 /* AccessibilityContrastSelector.swift */; }; - 4E1C741F2827B3C800227EC3 /* UIFloat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C741E2827B3C800227EC3 /* UIFloat.swift */; }; - 4E1C74212827B8F800227EC3 /* NSBeep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1C74202827B8F800227EC3 /* NSBeep.swift */; }; - 4E2E6C06282BD5990089E4FB /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2E6C05282BD5990089E4FB /* GradientView.swift */; }; - 569C25522427F57000022C60 /* ColorPickerTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 569C25512427F57000022C60 /* ColorPickerTabViewController.swift */; }; - 569C25582428346900022C60 /* ColorPickerMapSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 569C25572428346900022C60 /* ColorPickerMapSlider.swift */; }; - 56C74667242F722A003ED00A /* ColorPickerSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56C74666242F722A003ED00A /* ColorPickerSlider.swift */; }; - 56C74669242F75E3003ED00A /* ColorPickerNumericSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56C74668242F75E3003ED00A /* ColorPickerNumericSlider.swift */; }; - 94A2368C252B5951002B5D0B /* UIColorAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A2368B252B5951002B5D0B /* UIColorAdditions.swift */; }; - CF73D33A241F9C23000B1B10 /* Alderis.h in Headers */ = {isa = PBXBuildFile; fileRef = CF73D338241F9C23000B1B10 /* Alderis.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CF73D344241F9C31000B1B10 /* ColorWell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF73D32D241E49EE000B1B10 /* ColorWell.swift */; }; - CF73D345241F9C31000B1B10 /* ColorPickerMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE70280241CBDE700083903 /* ColorPickerMapViewController.swift */; }; - CF73D346241F9C31000B1B10 /* ColorPickerSlidersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE70282241CC88D00083903 /* ColorPickerSlidersViewController.swift */; }; - CF73D347241F9C31000B1B10 /* ColorPickerWheelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE70288241D0E7300083903 /* ColorPickerWheelView.swift */; }; - CF73D348241F9C31000B1B10 /* ColorPickerInnerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE7027B241A62ED00083903 /* ColorPickerInnerViewController.swift */; }; - CF73D34A241F9C31000B1B10 /* ColorPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE70273241A4C5500083903 /* ColorPickerViewController.swift */; }; - CF73D34B241F9C31000B1B10 /* ColorPickerSwatchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE7027E241B984600083903 /* ColorPickerSwatchViewController.swift */; }; - CF73D34C241F9C4D000B1B10 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF73D32B241E4720000B1B10 /* Color.swift */; }; - CF73D351241F9FB3000B1B10 /* ColorPickerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF73D350241F9FB3000B1B10 /* ColorPickerDelegate.swift */; }; - CF7750B72520D3B50069CC57 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF7750B62520D3B50069CC57 /* Assets.swift */; }; - CF7750BE252203630069CC57 /* DialogButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF7750BD252203630069CC57 /* DialogButton.swift */; }; - CF7750CF252433680069CC57 /* ColorPickerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF7750CE252433680069CC57 /* ColorPickerConfiguration.swift */; }; - CF7750D62524615D0069CC57 /* SeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF7750D52524615D0069CC57 /* SeparatorView.swift */; }; - CF775122252852460069CC57 /* AlderisSDKCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = CF775121252852110069CC57 /* AlderisSDKCompatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CF79DA31251723C500F17BCB /* BottomSheetTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF79DA30251723C500F17BCB /* BottomSheetTransition.swift */; }; - CFAFFC9124277CEE005AD4C1 /* Assets-ios12.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CFAFFC9024277CEE005AD4C1 /* Assets-ios12.xcassets */; platformFilter = ios; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 4E1C741228266C5900227EC3 /* UIFontDescriptorAdditions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFontDescriptorAdditions.swift; sourceTree = ""; }; - 4E1C74162826C1F100227EC3 /* ColorPickerAccessibilityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerAccessibilityViewController.swift; sourceTree = ""; }; - 4E1C741828276D5600227EC3 /* TextViewLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewLabel.swift; sourceTree = ""; }; - 4E1C741A2827829E00227EC3 /* AccessibilityComplianceLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityComplianceLabel.swift; sourceTree = ""; }; - 4E1C741C2827882600227EC3 /* AccessibilityContrastSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityContrastSelector.swift; sourceTree = ""; }; - 4E1C741E2827B3C800227EC3 /* UIFloat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFloat.swift; sourceTree = ""; }; - 4E1C74202827B8F800227EC3 /* NSBeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSBeep.swift; sourceTree = ""; }; - 4E2E6C05282BD5990089E4FB /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; - 569C25512427F57000022C60 /* ColorPickerTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerTabViewController.swift; sourceTree = ""; }; - 569C25572428346900022C60 /* ColorPickerMapSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerMapSlider.swift; sourceTree = ""; }; - 56C74666242F722A003ED00A /* ColorPickerSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerSlider.swift; sourceTree = ""; }; - 56C74668242F75E3003ED00A /* ColorPickerNumericSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerNumericSlider.swift; sourceTree = ""; }; - 94A2368B252B5951002B5D0B /* UIColorAdditions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColorAdditions.swift; sourceTree = ""; }; - CF73D32B241E4720000B1B10 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; - CF73D32D241E49EE000B1B10 /* ColorWell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorWell.swift; sourceTree = ""; }; - CF73D336241F9C23000B1B10 /* Alderis.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Alderis.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CF73D338241F9C23000B1B10 /* Alderis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Alderis.h; sourceTree = ""; }; - CF73D339241F9C23000B1B10 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CF73D350241F9FB3000B1B10 /* ColorPickerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerDelegate.swift; sourceTree = ""; }; - CF7750B62520D3B50069CC57 /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = ""; }; - CF7750BD252203630069CC57 /* DialogButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogButton.swift; sourceTree = ""; }; - CF7750CE252433680069CC57 /* ColorPickerConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPickerConfiguration.swift; sourceTree = ""; }; - CF7750D52524615D0069CC57 /* SeparatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeparatorView.swift; sourceTree = ""; }; - CF775121252852110069CC57 /* AlderisSDKCompatibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AlderisSDKCompatibility.h; sourceTree = ""; }; - CF79DA30251723C500F17BCB /* BottomSheetTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetTransition.swift; sourceTree = ""; }; - CFAFFC9024277CEE005AD4C1 /* Assets-ios12.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Assets-ios12.xcassets"; sourceTree = ""; }; - CFE70273241A4C5500083903 /* ColorPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerViewController.swift; sourceTree = ""; }; - CFE7027B241A62ED00083903 /* ColorPickerInnerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerInnerViewController.swift; sourceTree = ""; }; - CFE7027E241B984600083903 /* ColorPickerSwatchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerSwatchViewController.swift; sourceTree = ""; }; - CFE70280241CBDE700083903 /* ColorPickerMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerMapViewController.swift; sourceTree = ""; }; - CFE70282241CC88D00083903 /* ColorPickerSlidersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerSlidersViewController.swift; sourceTree = ""; }; - CFE70288241D0E7300083903 /* ColorPickerWheelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerWheelView.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - CF73D333241F9C23000B1B10 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - CF39D435222BC07C001EF57F = { - isa = PBXGroup; - children = ( - CF73D337241F9C23000B1B10 /* Alderis */, - CF39D43F222BC07C001EF57F /* Products */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - usesTabs = 1; - }; - CF39D43F222BC07C001EF57F /* Products */ = { - isa = PBXGroup; - children = ( - CF73D336241F9C23000B1B10 /* Alderis.framework */, - ); - name = Products; - sourceTree = ""; - }; - CF73D337241F9C23000B1B10 /* Alderis */ = { - isa = PBXGroup; - children = ( - CF73D338241F9C23000B1B10 /* Alderis.h */, - CF775121252852110069CC57 /* AlderisSDKCompatibility.h */, - CF7750B62520D3B50069CC57 /* Assets.swift */, - CF79DA30251723C500F17BCB /* BottomSheetTransition.swift */, - CF73D32B241E4720000B1B10 /* Color.swift */, - CFE70273241A4C5500083903 /* ColorPickerViewController.swift */, - CF7750CE252433680069CC57 /* ColorPickerConfiguration.swift */, - CF73D350241F9FB3000B1B10 /* ColorPickerDelegate.swift */, - CFE7027B241A62ED00083903 /* ColorPickerInnerViewController.swift */, - 569C25512427F57000022C60 /* ColorPickerTabViewController.swift */, - 56C74666242F722A003ED00A /* ColorPickerSlider.swift */, - CFE7027E241B984600083903 /* ColorPickerSwatchViewController.swift */, - 569C25572428346900022C60 /* ColorPickerMapSlider.swift */, - CFE70280241CBDE700083903 /* ColorPickerMapViewController.swift */, - CFE70288241D0E7300083903 /* ColorPickerWheelView.swift */, - CFE70282241CC88D00083903 /* ColorPickerSlidersViewController.swift */, - 56C74668242F75E3003ED00A /* ColorPickerNumericSlider.swift */, - 4E1C74162826C1F100227EC3 /* ColorPickerAccessibilityViewController.swift */, - 4E1C741A2827829E00227EC3 /* AccessibilityComplianceLabel.swift */, - 4E1C741C2827882600227EC3 /* AccessibilityContrastSelector.swift */, - CF73D32D241E49EE000B1B10 /* ColorWell.swift */, - CF7750BD252203630069CC57 /* DialogButton.swift */, - CF7750D52524615D0069CC57 /* SeparatorView.swift */, - 4E2E6C05282BD5990089E4FB /* GradientView.swift */, - 94A2368B252B5951002B5D0B /* UIColorAdditions.swift */, - 4E1C741228266C5900227EC3 /* UIFontDescriptorAdditions.swift */, - 4E1C741E2827B3C800227EC3 /* UIFloat.swift */, - 4E1C741828276D5600227EC3 /* TextViewLabel.swift */, - 4E1C74202827B8F800227EC3 /* NSBeep.swift */, - CF73D339241F9C23000B1B10 /* Info.plist */, - CFAFFC9024277CEE005AD4C1 /* Assets-ios12.xcassets */, - ); - path = Alderis; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - CF73D331241F9C23000B1B10 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CF73D33A241F9C23000B1B10 /* Alderis.h in Headers */, - CF775122252852460069CC57 /* AlderisSDKCompatibility.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - CF73D335241F9C23000B1B10 /* Alderis */ = { - isa = PBXNativeTarget; - buildConfigurationList = CF73D340241F9C23000B1B10 /* Build configuration list for PBXNativeTarget "Alderis" */; - buildPhases = ( - CF73D331241F9C23000B1B10 /* Headers */, - CF73D332241F9C23000B1B10 /* Sources */, - CF73D333241F9C23000B1B10 /* Frameworks */, - CF73D334241F9C23000B1B10 /* Resources */, - CF77511225281F7E0069CC57 /* SwiftLint */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Alderis; - productName = Alderis; - productReference = CF73D336241F9C23000B1B10 /* Alderis.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - CF39D436222BC07C001EF57F /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1330; - ORGANIZATIONNAME = "HASHBANG Productions"; - TargetAttributes = { - CF73D335241F9C23000B1B10 = { - CreatedOnToolsVersion = 11.3.1; - }; - }; - }; - buildConfigurationList = CF39D439222BC07C001EF57F /* Build configuration list for PBXProject "Alderis" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = CF39D435222BC07C001EF57F; - productRefGroup = CF39D43F222BC07C001EF57F /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - CF73D335241F9C23000B1B10 /* Alderis */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - CF73D334241F9C23000B1B10 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CFAFFC9124277CEE005AD4C1 /* Assets-ios12.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - CF77511225281F7E0069CC57 /* SwiftLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = SwiftLint; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "export PATH=$PATH:/opt/homebrew/bin\nif which swiftlint >/dev/null; then\n\tswiftlint\nelse\n\techo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - CF73D332241F9C23000B1B10 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CF73D34B241F9C31000B1B10 /* ColorPickerSwatchViewController.swift in Sources */, - CF7750BE252203630069CC57 /* DialogButton.swift in Sources */, - 4E1C741928276D5600227EC3 /* TextViewLabel.swift in Sources */, - CF73D347241F9C31000B1B10 /* ColorPickerWheelView.swift in Sources */, - CF7750D62524615D0069CC57 /* SeparatorView.swift in Sources */, - CF73D34C241F9C4D000B1B10 /* Color.swift in Sources */, - 94A2368C252B5951002B5D0B /* UIColorAdditions.swift in Sources */, - 569C25582428346900022C60 /* ColorPickerMapSlider.swift in Sources */, - 4E2E6C06282BD5990089E4FB /* GradientView.swift in Sources */, - CF73D344241F9C31000B1B10 /* ColorWell.swift in Sources */, - CF7750B72520D3B50069CC57 /* Assets.swift in Sources */, - CF73D348241F9C31000B1B10 /* ColorPickerInnerViewController.swift in Sources */, - 56C74667242F722A003ED00A /* ColorPickerSlider.swift in Sources */, - 4E1C74212827B8F800227EC3 /* NSBeep.swift in Sources */, - 4E1C74172826C1F100227EC3 /* ColorPickerAccessibilityViewController.swift in Sources */, - 4E1C741D2827882600227EC3 /* AccessibilityContrastSelector.swift in Sources */, - CF73D345241F9C31000B1B10 /* ColorPickerMapViewController.swift in Sources */, - CF79DA31251723C500F17BCB /* BottomSheetTransition.swift in Sources */, - 4E1C741328266C5900227EC3 /* UIFontDescriptorAdditions.swift in Sources */, - CF73D34A241F9C31000B1B10 /* ColorPickerViewController.swift in Sources */, - CF7750CF252433680069CC57 /* ColorPickerConfiguration.swift in Sources */, - 56C74669242F75E3003ED00A /* ColorPickerNumericSlider.swift in Sources */, - 569C25522427F57000022C60 /* ColorPickerTabViewController.swift in Sources */, - 4E1C741F2827B3C800227EC3 /* UIFloat.swift in Sources */, - CF73D351241F9FB3000B1B10 /* ColorPickerDelegate.swift in Sources */, - CF73D346241F9C31000B1B10 /* ColorPickerSlidersViewController.swift in Sources */, - 4E1C741B2827829E00227EC3 /* AccessibilityComplianceLabel.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - CF39D452222BC07E001EF57F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - CF39D453222BC07E001EF57F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - CF73D341241F9C23000B1B10 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CURRENT_PROJECT_VERSION = 3; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = Alderis/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MARKETING_VERSION = 1.2; - PRODUCT_BUNDLE_IDENTIFIER = ws.hbang.Alderis; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - CF73D342241F9C23000B1B10 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CURRENT_PROJECT_VERSION = 3; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = Alderis/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MARKETING_VERSION = 1.2; - PRODUCT_BUNDLE_IDENTIFIER = ws.hbang.Alderis; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - CF39D439222BC07C001EF57F /* Build configuration list for PBXProject "Alderis" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF39D452222BC07E001EF57F /* Debug */, - CF39D453222BC07E001EF57F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CF73D340241F9C23000B1B10 /* Build configuration list for PBXNativeTarget "Alderis" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF73D341241F9C23000B1B10 /* Debug */, - CF73D342241F9C23000B1B10 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = CF39D436222BC07C001EF57F /* Project object */; -} diff --git a/Tweaks/Alderis/Alderis.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tweaks/Alderis/Alderis.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index e210b76..0000000 --- a/Tweaks/Alderis/Alderis.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Tweaks/Alderis/Alderis.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tweaks/Alderis/Alderis.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Tweaks/Alderis/Alderis.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Tweaks/Alderis/Alderis.xcodeproj/xcshareddata/xcschemes/Alderis.xcscheme b/Tweaks/Alderis/Alderis.xcodeproj/xcshareddata/xcschemes/Alderis.xcscheme deleted file mode 100644 index 76b6914..0000000 --- a/Tweaks/Alderis/Alderis.xcodeproj/xcshareddata/xcschemes/Alderis.xcscheme +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tweaks/Alderis/Alderis/AccessibilityComplianceLabel.swift b/Tweaks/Alderis/Alderis/AccessibilityComplianceLabel.swift deleted file mode 100644 index e54d569..0000000 --- a/Tweaks/Alderis/Alderis/AccessibilityComplianceLabel.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// AccessibilityComplianceLabel.swift -// Alderis -// -// Created by Adam Demasi on 8/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class AccessibilityComplianceLabel: UIView { - - var text: String { - get { label.text! } - set { label.text = newValue } - } - - var isCompliant = false { - didSet { updateState() } - } - - private let tickImage = Assets.systemImage(named: "checkmark.circle.fill") - private let crossImage = Assets.systemImage(named: "xmark.circle.fill") - - private var imageView: UIImageView! - private var label: UILabel! - - override init(frame: CGRect) { - super.init(frame: frame) - - let font = UIFont.systemFont(ofSize: UIFloat(16), weight: .medium) - - imageView = UIImageView() - if #available(iOS 13, *) { - imageView.preferredSymbolConfiguration = UIImage.SymbolConfiguration(font: font, scale: .small) - } - - label = UILabel() - label.font = font - - let stackView = UIStackView(arrangedSubviews: [imageView, label]) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.alignment = .center - stackView.spacing = UIFloat(6) - addSubview(stackView) - - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: self.topAnchor), - stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor), - stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor) - ]) - } - - convenience init(text: String) { - self.init(frame: .zero) - self.text = text - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func updateState() { - let color = isCompliant ? Assets.green : Assets.red - - tintColor = color - accessibilityLabel = "\(text): \(isCompliant ? "Compliant" : "Not compliant")" - imageView.image = isCompliant ? tickImage : crossImage - } - - override func tintColorDidChange() { - super.tintColorDidChange() - label.textColor = tintColor - } - -} diff --git a/Tweaks/Alderis/Alderis/AccessibilityContrastSelector.swift b/Tweaks/Alderis/Alderis/AccessibilityContrastSelector.swift deleted file mode 100644 index 3ef0773..0000000 --- a/Tweaks/Alderis/Alderis/AccessibilityContrastSelector.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// AccessibilityContrastSelector.swift -// Alderis -// -// Created by Adam Demasi on 8/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class AccessibilityContrastSelector: UIView { - - enum Mode: Int, CaseIterable { - case color, black, white - - var label: String { - switch self { - case .color: return "Color" - case .black: return "Black" - case .white: return "White" - } - } - - func color(withColor color: Color) -> Color { - switch self { - case .color: return color - case .black: return .black - case .white: return .white - } - } - } - - var text: String { - get { label.text! } - set { label.text = newValue } - } - - var value: Mode = .white { - didSet { - if segmentedControl.selectedSegmentIndex != value.rawValue { - segmentedControl.selectedSegmentIndex = value.rawValue - handleChange?(value) - } - } - } - - var handleChange: ((Mode) -> Void)? - - private var label: UILabel! - private var segmentedControl: UISegmentedControl! - - override init(frame: CGRect) { - super.init(frame: frame) - - label = UILabel() - label.font = UIFont.systemFont(ofSize: UIFloat(16), weight: .medium) - - segmentedControl = UISegmentedControl(items: Mode.allCases.map(\.label)) - segmentedControl.addTarget(self, action: #selector(handleValueChanged), for: .valueChanged) - - let stackView = UIStackView(arrangedSubviews: [label, UIView(), segmentedControl]) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.alignment = .center - stackView.distribution = .fill - stackView.spacing = UIFloat(5) - addSubview(stackView) - - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: self.topAnchor), - stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor), - stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - convenience init(text: String, value: Mode) { - self.init(frame: .zero) - self.text = text - self.value = value - } - - @objc private func handleValueChanged() { - value = Mode(rawValue: segmentedControl.selectedSegmentIndex)! - handleChange?(value) - } - -} diff --git a/Tweaks/Alderis/Alderis/Alderis.h b/Tweaks/Alderis/Alderis/Alderis.h deleted file mode 100644 index b801478..0000000 --- a/Tweaks/Alderis/Alderis/Alderis.h +++ /dev/null @@ -1,11 +0,0 @@ -// -// Alderis.h -// Alderis -// -// Created by Adam Demasi on 16/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -@import UIKit; - -#import "AlderisSDKCompatibility.h" diff --git a/Tweaks/Alderis/Alderis/AlderisSDKCompatibility.h b/Tweaks/Alderis/Alderis/AlderisSDKCompatibility.h deleted file mode 100644 index 4fbe860..0000000 --- a/Tweaks/Alderis/Alderis/AlderisSDKCompatibility.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// AlderisSDKCompatibility.h -// Alderis -// -// Created by Adam Demasi on 3/10/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -@import UIKit; - -#ifndef __IPHONE_14_0 -// Allows building with the iOS 13 SDK while retaining iOS 14 compatibility. - -@interface UIControl () - -- (void)addAction:(UIAction *)action forControlEvents:(UIControlEvents)controlEvents NS_SWIFT_NAME(addAction(_:for:)) API_AVAILABLE(ios(14.0)); -- (void)removeAction:(UIAction *)action forControlEvents:(UIControlEvents)controlEvents NS_SWIFT_NAME(removeAction(_:for:)) API_AVAILABLE(ios(14.0)); -- (void)removeActionForIdentifier:(UIActionIdentifier)actionIdentifier forControlEvents:(UIControlEvents)controlEvents NS_SWIFT_NAME(removeAction(identifiedBy:for:)) API_AVAILABLE(ios(14.0)); - -@end -#endif diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/Contents.json deleted file mode 100644 index 5a6c8c8..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "sun.max.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "sun.max@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "sun.max@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max.png deleted file mode 100644 index c5e742d..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max@2x.png deleted file mode 100644 index 63e276f..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max@3x.png deleted file mode 100644 index 9ac5d14..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.max.imageset/sun.max@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/Contents.json deleted file mode 100644 index 9abdbb5..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "sun.min.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "sun.min@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "sun.min@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "template-rendering-intent" : "template" - } -} \ No newline at end of file diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min.png deleted file mode 100644 index 8e3b0dc..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min@2x.png deleted file mode 100644 index 52d0b0b..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min@3x.png deleted file mode 100644 index 5ebf1c5..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Brightness Slider/sun.min.imageset/sun.min@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/Contents.json deleted file mode 100644 index 57a752a..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "checkmark.circle.fill.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "checkmark.circle.fill@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "checkmark.circle.fill@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill.png deleted file mode 100644 index 866f762..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill@2x.png deleted file mode 100644 index bd37650..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill@3x.png deleted file mode 100644 index b765c07..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/checkmark.circle.fill.imageset/checkmark.circle.fill@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/Contents.json deleted file mode 100644 index c23f0a8..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "sparkles.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "sparkles@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "sparkles@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles.png deleted file mode 100644 index ca6719b..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles@2x.png deleted file mode 100644 index 7e52803..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles@3x.png deleted file mode 100644 index 1b85e58..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/sparkles.imageset/sparkles@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/Contents.json deleted file mode 100644 index c569aa6..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "xmark.circle.fill.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "xmark.circle.fill@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "xmark.circle.fill@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill.png deleted file mode 100644 index 5e3ce94..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill@2x.png deleted file mode 100644 index 3f5c29c..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill@3x.png deleted file mode 100644 index 2d96119..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Contrast Checker/xmark.circle.fill.imageset/xmark.circle.fill@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/Contents.json deleted file mode 100644 index 818d8fc..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "circle.righthalf.fill.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "circle.righthalf.fill@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "circle.righthalf.fill@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill.png deleted file mode 100644 index 32d27c9..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill@2x.png deleted file mode 100644 index b7926fc..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill@3x.png deleted file mode 100644 index 23d85a8..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/circle.righthalf.fill.imageset/circle.righthalf.fill@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/Contents.json deleted file mode 100644 index a5c3941..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "slider.horizontal.3.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "slider.horizontal.3@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "slider.horizontal.3@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3.png deleted file mode 100644 index f0f741f..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3@2x.png deleted file mode 100644 index c48ecea..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3@3x.png deleted file mode 100644 index 324a185..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.3.imageset/slider.horizontal.3@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/Contents.json deleted file mode 100644 index 2f4068e..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "slider.horizontal.below.rectangle.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "slider.horizontal.below.rectangle@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "slider.horizontal.below.rectangle@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle.png deleted file mode 100644 index aa95cf6..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle@2x.png deleted file mode 100644 index f35abf8..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle@3x.png deleted file mode 100644 index aba0cd5..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/slider.horizontal.below.rectangle.imageset/slider.horizontal.below.rectangle@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/Contents.json b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/Contents.json deleted file mode 100644 index 86e632b..0000000 --- a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/Contents.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "images" : [ - { - "filename" : "square.grid.4x3.fill.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "square.grid.4x3.fill@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "square.grid.4x3.fill@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill.png deleted file mode 100644 index 11f84fa..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill@2x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill@2x.png deleted file mode 100644 index 635183e..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill@2x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill@3x.png b/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill@3x.png deleted file mode 100644 index 714ab9a..0000000 Binary files a/Tweaks/Alderis/Alderis/Assets-ios12.xcassets/Tabs/square.grid.4x3.fill.imageset/square.grid.4x3.fill@3x.png and /dev/null differ diff --git a/Tweaks/Alderis/Alderis/Assets.swift b/Tweaks/Alderis/Alderis/Assets.swift deleted file mode 100644 index 7289a9c..0000000 --- a/Tweaks/Alderis/Alderis/Assets.swift +++ /dev/null @@ -1,135 +0,0 @@ -// -// Assets.swift -// Alderis -// -// Created by Adam Demasi on 27/9/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal struct Assets { - - internal enum SymbolScale: Int { - case `default` = -1 - case unspecified, small, medium, large - - @available(iOS 13, *) - var uiImageSymbolScale: UIImage.SymbolScale { UIImage.SymbolScale(rawValue: rawValue)! } - } - - private static let bundle: Bundle = { - let myBundle = Bundle(for: ColorPickerViewController.self) - if let resourcesURL = myBundle.url(forResource: "Alderis", withExtension: "bundle"), - let resourcesBundle = Bundle(url: resourcesURL) { - return resourcesBundle - } - return myBundle - }() - private static let uikitBundle = Bundle(for: UIView.self) - - // MARK: - Localization - - static func uikitLocalize(_ key: String) -> String { - uikitBundle.localizedString(forKey: key, value: nil, table: nil) - } - - // MARK: - Images - - static func systemImage(named name: String, font: UIFont? = nil, scale: SymbolScale = .default) -> UIImage? { - if #available(iOS 13, *) { - var configuration: UIImage.SymbolConfiguration? - if let font = font { - configuration = UIImage.SymbolConfiguration(font: font, scale: scale.uiImageSymbolScale) - } - return UIImage(systemName: name, withConfiguration: configuration) - } - return UIImage(named: name, in: bundle, compatibleWith: nil) - } - - // MARK: - Fonts - - static func niceMonospaceDigitFont(ofSize size: CGFloat) -> UIFont { - // Take the monospace digit font and enable stylistic alternative 6, which provides a - // high-legibility, monospace-looking style of the system font. - let font = UIFont.monospacedDigitSystemFont(ofSize: size, weight: .regular) - let fontDescriptor = font.fontDescriptor.addingAttributes([ - .featureSettings: [ - [ - .alderisFeature: kStylisticAlternativesType, - .alderisSelector: kStylisticAltSixOnSelector - ] - ] as [[UIFontDescriptor.FeatureKey: Int]] - ]) - return UIFont(descriptor: fontDescriptor, size: 0) - } - - // MARK: - Colors - - private static func color(userInterfaceStyles colors: [UIUserInterfaceStyle: UIColor], fallback: UIUserInterfaceStyle = .light) -> UIColor { - if #available(iOS 13, *) { - return UIColor { colors[$0.userInterfaceStyle] ?? colors[fallback] ?? colors.values.first! } - } - return colors[fallback] ?? colors.values.first! - } - - static let backdropColor = UIColor(white: 0, alpha: 0.2) - static let separatorColor = UIColor(white: 1, alpha: 0.15) - - static let labelColor: UIColor = { - if #available(iOS 13, *) { - return .label - } - return .black - }() - - static let secondaryLabelColor: UIColor = { - if #available(iOS 13, *) { - return .secondaryLabel - } - return UIColor(white: 60 / 255, alpha: 0.6) - }() - - static let borderColor: UIColor = { - if #available(iOS 13, *) { - return .separator - } - return UIColor(white: 1, alpha: 0.35) - }() - - @available(iOS 13, *) - static let macTabBarSelectionColor = color(userInterfaceStyles: [ - .light: .black, - .dark: .label - ]) - - static let red = UIColor.systemRed - - // .systemGreen adjusted to be more consistent / easier to read - static let green = color(userInterfaceStyles: [ - .light: UIColor(red: 15 / 255, green: 189 / 255, blue: 59 / 255, alpha: 1), - // swiftlint:disable:next colon - .dark: UIColor(red: 41 / 255, green: 179 / 255, blue: 76 / 255, alpha: 1) - ]) - - static let checkerboardPatternColor = color(userInterfaceStyles: [ - .light: renderCheckerboardPattern(colors: (UIColor(white: 200 / 255, alpha: 1), - UIColor(white: 255 / 255, alpha: 1))), - // swiftlint:disable:next colon - .dark: renderCheckerboardPattern(colors: (UIColor(white: 140 / 255, alpha: 1), - UIColor(white: 186 / 255, alpha: 1))) - ]) - - private static func renderCheckerboardPattern(colors: (dark: UIColor, light: UIColor)) -> UIColor { - let size = 11 - let image = UIGraphicsImageRenderer(size: CGSize(width: size * 2, height: size * 2)).image { context in - colors.dark.setFill() - context.fill(CGRect(x: 0, y: 0, width: size * 2, height: size * 2)) - colors.light.setFill() - context.fill(CGRect(x: size, y: 0, width: size, height: size)) - context.fill(CGRect(x: 0, y: size, width: size, height: size)) - } - return UIColor(patternImage: image) - } - -} diff --git a/Tweaks/Alderis/Alderis/BottomSheetTransition.swift b/Tweaks/Alderis/Alderis/BottomSheetTransition.swift deleted file mode 100644 index f131fbf..0000000 --- a/Tweaks/Alderis/Alderis/BottomSheetTransition.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// BottomSheetTransition.swift -// Alderis -// -// Created by Adam Demasi on 20/9/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class BottomSheetTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate { - - func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { - return BottomSheetTransition(direction: true) - } - - func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { - return BottomSheetTransition(direction: false) - } - -} - -internal class BottomSheetTransition: NSObject, UIViewControllerAnimatedTransitioning { - - // Opening: true - // Closing: false - let direction: Bool - - init(direction: Bool) { - self.direction = direction - } - - func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { - 0.4 - } - - func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { - if direction { - let to = transitionContext.viewController(forKey: .to)! - transitionContext.containerView.addSubview(to.view) - } - - Timer.scheduledTimer(withTimeInterval: transitionDuration(using: transitionContext), repeats: false) { _ in - transitionContext.completeTransition(true) - } - } - -} diff --git a/Tweaks/Alderis/Alderis/Color.swift b/Tweaks/Alderis/Alderis/Color.swift deleted file mode 100644 index a7ebc0f..0000000 --- a/Tweaks/Alderis/Alderis/Color.swift +++ /dev/null @@ -1,342 +0,0 @@ -// -// Color.swift -// Alderis -// -// Created by Adam Demasi on 15/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal struct Color: Equatable, Hashable { - static let black = Color(white: 0, alpha: 1) - static let white = Color(white: 1, alpha: 1) - - var red: CGFloat = 0 { - didSet { - self = Color(red: red, green: green, blue: blue, alpha: alpha) - } - } - var green: CGFloat = 0 { - didSet { - self = Color(red: red, green: green, blue: blue, alpha: alpha) - } - } - var blue: CGFloat = 0 { - didSet { - self = Color(red: red, green: green, blue: blue, alpha: alpha) - } - } - - var hue: CGFloat = 0 { - didSet { - self = Color(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha) - } - } - var saturation: CGFloat = 0 { - didSet { - self = Color(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha) - } - } - var brightness: CGFloat = 0 { - didSet { - self = Color(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha) - } - } - var hslSaturation: CGFloat = 0 { - didSet { - self = Color(hue: hue, saturation: hslSaturation, lightness: lightness, alpha: alpha) - } - } - var lightness: CGFloat = 0 { - didSet { - self = Color(hue: hue, saturation: hslSaturation, lightness: lightness, alpha: alpha) - } - } - - var white: CGFloat = 0 { - didSet { - self = Color(white: white, alpha: alpha) - } - } - - var alpha: CGFloat = 0 - - static func == (lhs: Color, rhs: Color) -> Bool { - lhs.red == rhs.red && - lhs.green == rhs.green && - lhs.blue == rhs.blue && - lhs.alpha == rhs.alpha - } - - func hash(into hasher: inout Hasher) { - hasher.combine(red) - hasher.combine(green) - hasher.combine(blue) - hasher.combine(alpha) - } - - var uiColor: UIColor { .init(red: red, green: green, blue: blue, alpha: alpha) } - - init(uiColor: UIColor) { - uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha) - uiColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil) - self.white = brightness - (self.hslSaturation, self.lightness) = hslValue - } - - init(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { - self.red = red - self.green = green - self.blue = blue - self.alpha = alpha - let uiColor = UIColor(red: red, green: green, blue: blue, alpha: alpha) - uiColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil) - self.white = brightness - (self.hslSaturation, self.lightness) = hslValue - } - - init(white: CGFloat, alpha: CGFloat) { - self.init(red: white, green: white, blue: white, alpha: alpha) - } - - init(hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat) { - self.hue = hue - self.saturation = saturation - self.brightness = brightness - self.white = brightness - self.alpha = alpha - let uiColor = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha) - uiColor.getRed(&red, green: &green, blue: &blue, alpha: nil) - (self.hslSaturation, self.lightness) = hslValue - } - - init(hue: CGFloat, saturation: CGFloat, lightness: CGFloat, alpha: CGFloat) { - self.hue = hue - self.hslSaturation = saturation - self.lightness = lightness - self.alpha = alpha - (self.saturation, self.brightness) = hsbValue - let uiColor = UIColor(hue: hue, saturation: self.saturation, brightness: self.brightness, alpha: alpha) - uiColor.getRed(&red, green: &green, blue: &blue, alpha: nil) - self.white = brightness - } -} - -extension Color { - static var brightnessThreshold: CGFloat { - // Accessibility enabled: conforms to WCAG 2.1 AAA - // Accessibility disabled: conforms to WCAG 2.1 AA - UIAccessibility.isDarkerSystemColorsEnabled ? 7 : 4.5 - } - - var relativeLuminanceValues: (red: CGFloat, green: CGFloat, blue: CGFloat) { - // https://www.w3.org/TR/WCAG21/#dfn-relative-luminance - let values = [red, green, blue] - .map { $0 <= 0.03928 ? $0 / 12.92 : pow((($0 + 0.055) / 1.055), 2.4) } - return (values[0], values[1], values[2]) - } - - var relativeLuminance: CGFloat { - // https://www.w3.org/TR/WCAG21/#dfn-relative-luminance - let (r, g, b) = relativeLuminanceValues - return (r * 0.2126) + (g * 0.7152) + (b * 0.0722) - } - - func perceivedBrightness(onBackgroundColor background: Color) -> CGFloat { - // https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio - between 0-21 - let a = relativeLuminance + 0.05 - let b = background.relativeLuminance + 0.05 - return a > b ? a / b : b / a - } - - var isDark: Bool { perceivedBrightness(onBackgroundColor: .white) > Self.brightnessThreshold && alpha > 0.5 } -} - -extension Color { - struct HexOptions: OptionSet { - let rawValue: Int - static let allowShorthand = Self(rawValue: 1 << 0) - static let forceAlpha = Self(rawValue: 1 << 1) - } - - // if the character in `value` is repeated, `repeatedValue` is a single copy of that character. If - // `value` consists of two unique characters, `repeatedValue` is nil - // e.g. valid return values are `("AA", "A")` and `("AB", nil)` - private func hex(_ val: CGFloat) -> (value: String, repeatedValue: Character?) { - let byte = Int(val * 255) & 0xFF - let isRepeated = (byte & 0xF) == (byte >> 4) - let value = String(format: "%02X", byte) - return (value, isRepeated ? value.first : nil) - } - - func hexString(with options: HexOptions = []) -> String { - let (r, rRep) = hex(red) - let (g, gRep) = hex(green) - let (b, bRep) = hex(blue) - let (a, aRep) = hex(alpha) - let showAlpha = options.contains(.forceAlpha) || alpha != 1 - if options.contains(.allowShorthand), - let rRep = rRep, let gRep = gRep, let bRep = bRep, let aRep = aRep { - return "#\(rRep)\(gRep)\(bRep)\(showAlpha ? "\(aRep)" : "")" - } else { - return "#\(r)\(g)\(b)\(showAlpha ? a : "")" - } - } - - var hexString: String { hexString() } - - var hslValue: (saturation: CGFloat, lightness: CGFloat) { - let lightness = brightness - (brightness * (saturation / 2)) - var saturation = min(lightness, 1 - lightness) - saturation = saturation == 0 ? 0 : (brightness - lightness) / saturation - return (saturation, lightness) - } - - var hsbValue: (saturation: CGFloat, brightness: CGFloat) { - let brightness = hslSaturation * min(lightness, 1 - lightness) + lightness - let saturation = brightness == 0 ? 0 : 2 - 2 * lightness / brightness - return (saturation, brightness) - } - - private func cssString(function: String, params: [String?]) -> String { - let filteredParams = params.compactMap { $0 } - return "\(function)\(filteredParams.count == 4 ? "a" : "")(\(filteredParams.joined(separator: ", ")))" - } - - var rgbString: String { - cssString(function: "rgb", params: [ - "\(Int(red * 255))", - "\(Int(green * 255))", - "\(Int(blue * 255))", - alpha == 1 ? nil : String(format: "%.2f", alpha) - ]) - } - - var hslString: String { - cssString(function: "hsl", params: [ - "\(Int(hue * 360))", - "\(Int(hslSaturation * 100))%", - "\(Int(lightness * 100))%", - alpha == 1 ? nil : String(format: "%.2f", alpha) - ]) - } - - var objcString: String { - red == green && green == blue - ? String(format: "[UIColor colorWithWhite:%.3f alpha:%.2f]", white, alpha) - : String(format: "[UIColor colorWithRed:%.3f green:%.3f blue:%.3f alpha:%.2f]", red, green, blue, alpha) - } - - var swiftString: String { - red == green && green == blue - ? String(format: "UIColor(white: %.3f, alpha: %.3f", white, alpha) - // swiftlint:disable:next color_init - : String(format: "UIColor(red: %.3f, green: %.3f, blue: %.3f, alpha: %.2f)", red, green, blue, alpha) - } -} - -extension Color { - struct Component { - let keyPath: WritableKeyPath - let limit: CGFloat - let title: String - private let sliderTintColorForColor: (Color) -> [Color] - - init( - keyPath: WritableKeyPath, - limit: CGFloat, - title: String, - sliderTintColorForColor: @escaping (Color) -> [Color] - ) { - self.keyPath = keyPath - self.limit = limit - self.title = title - self.sliderTintColorForColor = sliderTintColorForColor - } - - init( - keyPath: WritableKeyPath, - limit: CGFloat, - title: String, - sliderTint: [Color] - ) { - self.keyPath = keyPath - self.limit = limit - self.title = title - self.sliderTintColorForColor = { _ in sliderTint } - } - - func sliderTintColor(for color: Color) -> [Color] { - sliderTintColorForColor(color) - } - - static let red: Component = .init(keyPath: \.red, limit: 255, title: "Red") { color in - [ - Color(red: 0, green: color.green, blue: color.blue, alpha: 1), - Color(red: 1, green: color.green, blue: color.blue, alpha: 1) - ] - } - - static let green: Component = .init(keyPath: \.green, limit: 255, title: "Green") { color in - [ - Color(red: color.red, green: 0, blue: color.blue, alpha: 1), - Color(red: color.red, green: 1, blue: color.blue, alpha: 1) - ] - } - - static let blue: Component = .init(keyPath: \.blue, limit: 255, title: "Blue") { color in - [ - Color(red: color.red, green: color.green, blue: 0, alpha: 1), - Color(red: color.red, green: color.green, blue: 1, alpha: 1) - ] - } - - static let hue: Component = .init(keyPath: \.hue, limit: 360, title: "Hue") { color in - Array(0...8).map { Color(hue: CGFloat($0) * 45 / 360, saturation: color.saturation, brightness: color.brightness, alpha: 1) } - } - - static let saturation: Component = .init(keyPath: \.saturation, limit: 100, title: "Satur.") { color in - [ - .white, - Color(hue: color.hue, saturation: 1, brightness: color.brightness, alpha: 1) - ] - } - - static let brightness: Component = .init(keyPath: \.brightness, limit: 100, title: "Bright") { color in - [ - .black, - Color(hue: color.hue, saturation: color.saturation, brightness: 1, alpha: 1) - ] - } - - static let hslSaturation: Component = .init(keyPath: \.hslSaturation, limit: 100, title: "Satur.") { color in - [ - Color(hue: color.hue, saturation: 0, lightness: color.lightness, alpha: 1), - Color(hue: color.hue, saturation: 1, lightness: color.lightness, alpha: 1) - ] - } - - static let lightness: Component = .init(keyPath: \.lightness, limit: 100, title: "Light") { color in - [ - .black, - Color(hue: color.hue, saturation: color.hslSaturation, lightness: 0.5, alpha: 1), - .white - ] - } - - static let white: Component = .init(keyPath: \.white, limit: 255, title: "White") { _ in - [ - .black, - .white - ] - } - - static let alpha: Component = .init(keyPath: \.alpha, limit: 100, title: "Alpha") { color in - [ - Color(red: color.red, green: color.green, blue: color.blue, alpha: 0), - Color(red: color.red, green: color.green, blue: color.blue, alpha: 1) - ] - } - } -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerAccessibilityViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerAccessibilityViewController.swift deleted file mode 100644 index faf1065..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerAccessibilityViewController.swift +++ /dev/null @@ -1,218 +0,0 @@ -// -// ColorPickerAccessibilityViewController.swift -// Alderis -// -// Created by Adam Demasi on 8/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class ColorPickerAccessibilityViewController: ColorPickerTabViewController { - - static let title = "Contrast Checker" - static let imageName = "circle.righthalf.fill" - - private static let percentFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.numberStyle = .percent - return formatter - }() - - private var backgroundMode: AccessibilityContrastSelector.Mode = .white { - didSet { colorDidChange() } - } - private var foregroundMode: AccessibilityContrastSelector.Mode = .color { - didSet { colorDidChange() } - } - - private var scrollView: UIScrollView! - - private var demoContainerView: UIView! - private var demoLabels: [UIView]! - - private var contrastStackView: UIStackView! - private var contrastRatioLabel: UILabel! - private var aaComplianceLabel: AccessibilityComplianceLabel! - private var aaaComplianceLabel: AccessibilityComplianceLabel! - - private var backgroundSelector: AccessibilityContrastSelector! - private var foregroundSelector: AccessibilityContrastSelector! - - override func viewDidLoad() { - super.viewDidLoad() - - // Catalyst in iPad UI mode scales all UI down to 77%, so we cancel out the scaling (as well as - // we possibly can, given scaling down is throwing away quality) for the demo labels. - let scaleFactor: CGFloat = isCatalystPad ? 1 / 0.77 : 1 - - let demoTitleLabel = UILabel() - demoTitleLabel.translatesAutoresizingMaskIntoConstraints = false - demoTitleLabel.font = .systemFont(ofSize: 18 * scaleFactor, weight: .semibold) - demoTitleLabel.text = "Size 18 • Contrast Checker" - - let demoImageView = UIImageView(image: Assets.systemImage(named: "sparkles", font: demoTitleLabel.font, scale: .small)) - demoImageView.translatesAutoresizingMaskIntoConstraints = false - - let titleStackView = UIStackView(arrangedSubviews: [demoImageView, demoTitleLabel]) - titleStackView.translatesAutoresizingMaskIntoConstraints = false - titleStackView.spacing = UIFloat(6) - titleStackView.alignment = .center - - let demoSubtitleLabel = UILabel() - demoSubtitleLabel.translatesAutoresizingMaskIntoConstraints = false - demoSubtitleLabel.font = .systemFont(ofSize: 14 * scaleFactor, weight: .medium) - demoSubtitleLabel.text = "Size 14 • Contrast ratios are a measure of how easily text and images can be read, especially by people with lower vision." - demoSubtitleLabel.numberOfLines = 0 - - let demoTextLabel = TextViewLabel() - demoTextLabel.translatesAutoresizingMaskIntoConstraints = false - demoTextLabel.linkTextAttributes = [ - .underlineStyle: NSUnderlineStyle.single.rawValue - ] - let explainerText = "Size 12 • Learn more about minimum (AA) and enhanced (AAA) contrast." - let attributedString = NSMutableAttributedString(string: explainerText, - attributes: [ - .font: UIFont.systemFont(ofSize: 12 * scaleFactor, weight: .regular) - ]) - attributedString.addAttribute(.link, - value: URL(string: "https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum")!, - range: (attributedString.string as NSString).range(of: "minimum (AA)")) - attributedString.addAttribute(.link, - value: URL(string: "https://www.w3.org/WAI/WCAG21/Understanding/contrast-enhanced")!, - range: (attributedString.string as NSString).range(of: "enhanced (AAA)")) - demoTextLabel.attributedText = attributedString - - demoLabels = [demoTitleLabel, demoSubtitleLabel, demoTextLabel] - - let demoStackView = UIStackView(arrangedSubviews: [titleStackView, demoSubtitleLabel, demoTextLabel]) - demoStackView.translatesAutoresizingMaskIntoConstraints = false - demoStackView.axis = .vertical - demoStackView.alignment = .leading - demoStackView.spacing = UIFloat(8) - - demoContainerView = UIView() - demoContainerView.translatesAutoresizingMaskIntoConstraints = false - demoContainerView.layer.cornerRadius = 12 - if #available(iOS 13, *) { - demoContainerView.layer.cornerCurve = .continuous - } - demoContainerView.addSubview(demoStackView) - - contrastRatioLabel = UILabel() - contrastRatioLabel.translatesAutoresizingMaskIntoConstraints = false - contrastRatioLabel.font = .systemFont(ofSize: UIFloat(16), weight: .medium) - - aaComplianceLabel = AccessibilityComplianceLabel(text: "AA") - aaaComplianceLabel = AccessibilityComplianceLabel(text: "AAA") - - let complianceStackView = UIStackView(arrangedSubviews: [UIView(), aaComplianceLabel, aaaComplianceLabel]) - complianceStackView.translatesAutoresizingMaskIntoConstraints = false - complianceStackView.spacing = UIFloat(12) - - contrastStackView = UIStackView(arrangedSubviews: [contrastRatioLabel, complianceStackView]) - contrastStackView.translatesAutoresizingMaskIntoConstraints = false - contrastStackView.spacing = UIFloat(8) - - backgroundSelector = AccessibilityContrastSelector(text: "Background", value: backgroundMode) - backgroundSelector.handleChange = { self.backgroundMode = $0 } - - foregroundSelector = AccessibilityContrastSelector(text: "Foreground", value: foregroundMode) - foregroundSelector.handleChange = { self.foregroundMode = $0 } - - scrollView = UIScrollView() - scrollView.translatesAutoresizingMaskIntoConstraints = false - scrollView.alwaysBounceVertical = false - view.addSubview(scrollView) - - let rootStackView = UIStackView(arrangedSubviews: [demoContainerView, UIView(), contrastStackView, backgroundSelector, foregroundSelector, UIView()]) - rootStackView.translatesAutoresizingMaskIntoConstraints = false - rootStackView.axis = .vertical - rootStackView.alignment = .fill - rootStackView.distribution = .fill - rootStackView.spacing = UIFloat(10) - scrollView.addSubview(rootStackView) - - NSLayoutConstraint.activate([ - scrollView.topAnchor.constraint(equalTo: view.topAnchor), - scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - - rootStackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: UIFloat(15)), - rootStackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: UIFloat(-15)), - rootStackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor, constant: UIFloat(15)), - rootStackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: UIFloat(-15)), - rootStackView.heightAnchor.constraint(equalTo: scrollView.contentLayoutGuide.heightAnchor, constant: UIFloat(-30)), - scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: scrollView.widthAnchor), - scrollView.contentLayoutGuide.heightAnchor.constraint(greaterThanOrEqualTo: scrollView.heightAnchor), - - demoStackView.topAnchor.constraint(equalTo: demoContainerView.topAnchor, constant: UIFloat(16)), - demoStackView.bottomAnchor.constraint(equalTo: demoContainerView.bottomAnchor, constant: UIFloat(-17)), - demoStackView.leadingAnchor.constraint(equalTo: demoContainerView.leadingAnchor, constant: UIFloat(20)), - demoStackView.trailingAnchor.constraint(equalTo: demoContainerView.trailingAnchor, constant: UIFloat(-20)), - - contrastStackView.heightAnchor.constraint(greaterThanOrEqualTo: backgroundSelector.heightAnchor), - contrastStackView.heightAnchor.constraint(greaterThanOrEqualTo: foregroundSelector.heightAnchor) - ]) - - colorDidChange() - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - scrollView.flashScrollIndicators() - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - contrastStackView.axis = view.frame.size.width > UIFloat(300) ? .horizontal : .vertical - } - - override func colorDidChange() { - let backgroundColor = backgroundMode.color(withColor: color) - let foregroundColor = foregroundMode.color(withColor: color) - - if backgroundColor == foregroundColor { - // Change one or the other to not be identical - if backgroundMode == foregroundMode { - switch backgroundMode { - case .black, .white: foregroundMode = .color - default: foregroundMode = .white - } - } else { - if foregroundMode == .color { - backgroundMode = backgroundColor == .white ? .black : .white - } else if backgroundMode == .color { - foregroundMode = foregroundColor == .white ? .black : .white - } - } - return - } - - backgroundSelector.value = backgroundMode - foregroundSelector.value = foregroundMode - - demoContainerView.backgroundColor = backgroundColor.uiColor - demoContainerView.tintColor = foregroundColor.uiColor - for label in demoLabels { - if let label = label as? UILabel { - label.textColor = foregroundColor.uiColor - } else if let label = label as? UITextView, - let attributedString = label.attributedText.mutableCopy() as? NSMutableAttributedString { - attributedString.addAttribute(.foregroundColor, - value: foregroundColor.uiColor, - range: NSRange(location: 0, length: attributedString.string.count)) - label.attributedText = attributedString - } - } - - let contrastRatio = foregroundColor.perceivedBrightness(onBackgroundColor: backgroundColor) - contrastRatioLabel.text = "Contrast: \(String(format: "%.2f", contrastRatio)) (\(Self.percentFormatter.string(for: contrastRatio / 21)!))" - aaComplianceLabel.isCompliant = contrastRatio > 4.5 - aaaComplianceLabel.isCompliant = contrastRatio > 7 - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerConfiguration.swift b/Tweaks/Alderis/Alderis/ColorPickerConfiguration.swift deleted file mode 100644 index ce23ef6..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerConfiguration.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// ColorPickerConfiguration.swift -// Alderis -// -// Created by Adam Demasi on 10/5/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -/// An enumeration of the tabs `ColorPickerViewController` features. Use these enumeration values to -/// set tab-related settings on `ColorPickerConfiguration`. -@objc(HBColorPickerTab) -public enum ColorPickerTab: Int, CaseIterable { - /// Tab 1: A grid of 9 variations of 11 colours, and a grayscale ramp. The first and default tab. - case swatch = 0 - - /// Tab 2: A color wheel displaying every possible hue and saturation combination. The user can - /// additionally adjust the brightness of the colour using a slider. - case map = 1 - - /// Tab 3: A set of sliders for red, green, and blue color values, which can be switched to hue, - /// saturation, and brightness. The user can additionally copy or enter a color value expressed - /// using a CSS-style hexadecimal string, and adjust alpha transparency. - case sliders = 2 - - /// Tab 4: A tab that allows the user to test various configurations of the color, and its - /// conformance to WCAG color contrast. - case accessibility = 3 -} - -/// ColorPickerConfiguration is used to configure an instance of `ColorPickerViewController`. -@objc(HBColorPickerConfiguration) -open class ColorPickerConfiguration: NSObject { - - /// Initialise a configuration object with the required color property configured. - @objc public init(color: UIColor) { - self.color = color - super.init() - } - - /// The initial color to use when launching the color picker. Required. If you don’t have a value - /// set yet, provide a sensible default. - @objc open var color: UIColor - - /// Whether to allow the user to set an alpha transparency value on the color. This controls the - /// visibility of an Alpha slider on the Sliders tab. When set to `false`, alpha values provided - /// via the `color` property, or by the user when entering a hexadecimal value on the Sliders tab, - /// will be discarded. - @objc open var supportsAlpha = true - - /// The title to display at the top of the popup. If set to `nil`, no title will be displayed. The - /// default is `nil`. - @objc open var title: String? - - /// The initial tab to select when the color picker is presented. The default is - /// `ColorPickerTab.swatch`. - /// - /// This value must be found in `visibleTabs`. - /// - /// - see: `visibleTabs` - @objc open var initialTab = ColorPickerTab.swatch - - /// The tabs the user can select and switch between at the top of the window, if tabs are enabled - /// by `showTabs`. - /// - /// - see: `initialTab` - @nonobjc open var visibleTabs: [ColorPickerTab] = [.swatch, .map, .sliders, .accessibility] - - /// Maps `visibleTabs` to Objective-C due to Swift limitations. This is an implementation detail. - /// Ignore this and use `visibleTabs` per usual. - @objc(visibleTabs) - open var _visibleTabsObjC: [ColorPickerTab.RawValue] { - get { visibleTabs.map(\.rawValue) } - set { visibleTabs = newValue.map { ColorPickerTab(rawValue: $0)! } } - } - - /// Whether to display the tab selection at the top of the popup. The default is `true`. When set - /// to `false`, the user will only be able to access the tab specified in initialTab. - @objc open var showTabs = true - - /// When the Smart Invert accessibility feature is enabled, Alderis instructs the system to not - /// invert most of its user interface. This ensures the user can make a more accurate color - /// selection. If this behavior is not desired, you can disable it here. - @objc open var overrideSmartInvert = true - - /// Whether the user can end a drag interaction by dropping on the color picker window, allowing - /// them to drag a color from a supporting app. The default is `true`. - @objc open var isDropInteractionEnabled = true - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerDelegate.swift b/Tweaks/Alderis/Alderis/ColorPickerDelegate.swift deleted file mode 100644 index e989b7e..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerDelegate.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// ColorPickerDelegate.swift -// Alderis -// -// Created by Adam Demasi on 16/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -/// Use `ColorPickerDelegate` to handle the user’s response to `ColorPickerViewController`. -@objc(HBColorPickerDelegate) -public protocol ColorPickerDelegate: NSObjectProtocol { - - /// Informs the delegate that the user has selected a color in the color picker. Optional. - /// - /// Use this to update your user interface with the new color value, if suitable to your use case. - /// - /// You should, at minimum, implement either this method or `colorPicker(_:didAccept:)`. If you - /// don’t intend to implement this method, it is expected that you implement - /// `colorPicker(_:didAccept:)`. If you implement this method and the user selects Cancel, this - /// method will be called with the initial color passed in via `ColorPickerConfiguration.color` to - /// undo the selection. - /// - /// - parameter colorPicker: The `ColorPickerViewController` instance that triggered the action. - /// - parameter color: The `UIColor` selection the user made. - /// - see: `colorPicker(_:didAccept:)` - @objc(colorPicker:didSelectColor:) - optional func colorPicker(_ colorPicker: ColorPickerViewController, didSelect color: UIColor) - - /// Informs the delegate that the user has dismissed the color picker with a positive response, - /// having selected the selected color. Optional. - /// - /// You should, at minimum, implement either this method or `colorPicker(_:didSelect:)`. - /// - /// - parameter colorPicker: The `ColorPickerViewController` instance that triggered the action. - /// - parameter color: The `UIColor` selection the user made. - /// - see: `colorPicker(_:didSelect:)` - @objc(colorPicker:didAcceptColor:) - optional func colorPicker(_ colorPicker: ColorPickerViewController, didAccept color: UIColor) - - /// Informs the delegate that the user has dismissed the color picker with a negative response. - /// Optional. - /// - /// You usually do not need to handle this condition. - /// - /// - parameter colorPicker: The `ColorPickerViewController` instance that triggered the action. - @objc(colorPickerDidCancel:) - optional func colorPickerDidCancel(_ colorPicker: ColorPickerViewController) - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerInnerViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerInnerViewController.swift deleted file mode 100644 index f555b50..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerInnerViewController.swift +++ /dev/null @@ -1,445 +0,0 @@ -// -// ColorPickerInnerViewController.swift -// Alderis -// -// Created by Adam Demasi on 12/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal extension ColorPickerTab { - var tabClass: ColorPickerTabViewController.Type { - switch self { - case .swatch: return ColorPickerSwatchViewController.self - case .map: return ColorPickerMapViewController.self - case .sliders: return ColorPickerSlidersViewController.self - case .accessibility: return ColorPickerAccessibilityViewController.self - } - } - - var index: Int { Self.allCases.firstIndex(of: self)! } -} - -internal class ColorPickerInnerViewController: UIViewController { - - weak var delegate: ColorPickerDelegate? - let configuration: ColorPickerConfiguration - var color: Color - - var tab: ColorPickerTab { - get { configuration.visibleTabs[currentTab] } - set { currentTab = configuration.visibleTabs.firstIndex(of: newValue) ?? 0 } - } - - var compatibilityMode = false - - private var colorPicker: ColorPickerViewController { - // swiftlint:disable:next force_cast - parent as! ColorPickerViewController - } - - init(delegate: ColorPickerDelegate?, configuration: ColorPickerConfiguration) { - self.delegate = delegate - self.configuration = configuration - color = Color(uiColor: configuration.color) - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private var currentTab = 0 { - didSet { tabDidChange(oldValue: oldValue) } - } - - func setColor(_ color: Color, withSource source: ColorPickerTabViewControllerBase? = nil) { - self.color = color - colorDidChange(withSource: source) - } - - private var pageViewController: UIPageViewController! - private var tabs = [ColorPickerTabViewController]() - private var tabsView: UISegmentedControl! - private var titleLabel: UILabel! - private var cancelButton: DialogButton? - private var saveButton: DialogButton? - private var tabsBackgroundView: UIView! - private var buttonsBackgroundView: UIView? - private var heightConstraint: NSLayoutConstraint! - private var backgroundView: UIView! - - override func viewDidLoad() { - super.viewDidLoad() - - for tabType in configuration.visibleTabs { - let tab = tabType.tabClass.init(tabDelegate: self, configuration: configuration, color: color) - // Force the view to be initialised - tab.loadViewIfNeeded() - tabs.append(tab) - } - - if configuration.isDropInteractionEnabled { - view.addInteraction(UIDropInteraction(delegate: self)) - } - - backgroundView = UIView() - backgroundView.translatesAutoresizingMaskIntoConstraints = false - backgroundView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - view.addSubview(backgroundView) - - let tabsCheckerboardView = UIView() - tabsCheckerboardView.translatesAutoresizingMaskIntoConstraints = false - tabsCheckerboardView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - tabsCheckerboardView.backgroundColor = Assets.checkerboardPatternColor - view.addSubview(tabsCheckerboardView) - - tabsBackgroundView = UIView() - tabsBackgroundView.translatesAutoresizingMaskIntoConstraints = false - tabsBackgroundView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - view.addSubview(tabsBackgroundView) - - let topSeparatorView = SeparatorView(direction: .horizontal) - topSeparatorView.translatesAutoresizingMaskIntoConstraints = false - tabsBackgroundView.addSubview(topSeparatorView) - - let titleView = UIView() - titleView.translatesAutoresizingMaskIntoConstraints = false - titleView.isHidden = configuration.title == nil || configuration.title!.isEmpty - - titleLabel = UILabel() - titleLabel.translatesAutoresizingMaskIntoConstraints = false - titleLabel.textAlignment = .center - titleLabel.font = .systemFont(ofSize: UIFloat(17), weight: .semibold) - titleLabel.text = configuration.title - titleView.addSubview(titleLabel) - - let tabsContainerView = UIView() - tabsContainerView.translatesAutoresizingMaskIntoConstraints = false - tabsContainerView.isHidden = !configuration.showTabs - - tabsView = UISegmentedControl() - tabsView.translatesAutoresizingMaskIntoConstraints = false - tabsView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - tabsView.addTarget(self, action: #selector(segmentControlChanged(_:)), for: .valueChanged) - tabsContainerView.addSubview(tabsView) - - if #available(iOS 13, *) { - tabsView.selectedSegmentTintColor = UIColor.white.withAlphaComponent(0.35) - if isCatalystMac { - tabsView.setTitleTextAttributes([ .foregroundColor: Assets.macTabBarSelectionColor ], for: .highlighted) - tabsView.setTitleTextAttributes([ .foregroundColor: Assets.macTabBarSelectionColor ], for: .selected) - } - } - - for (i, tab) in tabs.enumerated() { - let tabClass = type(of: tab) - #if swift(>=5.3) - if #available(iOS 14, *) { - tabsView.insertSegment(action: UIAction(title: tabClass.title, - image: tabClass.image, - handler: { _ in }), - at: i, - animated: false) - } else { - tabsView.insertSegment(with: tabClass.image, at: i, animated: false) - } - #else - tabsView.insertSegment(with: tabClass.image, at: i, animated: false) - #endif - } - - NSLayoutConstraint.activate([ - tabsView.centerXAnchor.constraint(equalTo: tabsContainerView.centerXAnchor), - tabsView.centerYAnchor.constraint(equalTo: tabsContainerView.centerYAnchor), - tabsView.leadingAnchor.constraint(greaterThanOrEqualTo: tabsContainerView.leadingAnchor, constant: 4), - tabsView.trailingAnchor.constraint(lessThanOrEqualTo: tabsContainerView.trailingAnchor, constant: -4) - ]) - - if #available(iOS 13, *) { - } else { - NSLayoutConstraint.activate([ - tabsView.heightAnchor.constraint(equalToConstant: 32) - ]) - for i in 0.. Bool { - return session.items.count == 1 && session.canLoadObjects(ofClass: UIColor.self) - } - - /// :nodoc: - public func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal { - return UIDropProposal(operation: .copy) - } - - /// :nodoc: - public func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { - session.loadObjects(ofClass: UIColor.self) { items in - if let color = items.first as? UIColor { - self.setColor(Color(uiColor: color), withSource: nil) - } - } - } - -} - -extension ColorPickerInnerViewController: UIPopoverPresentationControllerDelegate { - - /// :nodoc: - public func presentationControllerWillDismiss(_ presentationController: UIPresentationController) { - saveTapped() - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerMapSlider.swift b/Tweaks/Alderis/Alderis/ColorPickerMapSlider.swift deleted file mode 100644 index 3da68ff..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerMapSlider.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// ColorPickerMapSlider.swift -// Alderis -// -// Created by Kabir Oberai on 23/03/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class ColorPickerMapSlider: ColorPickerComponentSlider { - - init(minImageName: String, maxImageName: String, component: Color.Component, overrideSmartInvert: Bool) { - super.init(component: component, overrideSmartInvert: overrideSmartInvert) - - stackView.alignment = .center - stackView.spacing = UIFloat(13) - - let leftImageView = UIImageView(image: Assets.systemImage(named: minImageName)) - leftImageView.translatesAutoresizingMaskIntoConstraints = false - leftImageView.contentMode = .center - leftImageView.tintColor = Assets.secondaryLabelColor - stackView.insertArrangedSubview(leftImageView, at: 0) - - let rightImageView = UIImageView(image: Assets.systemImage(named: maxImageName)) - rightImageView.translatesAutoresizingMaskIntoConstraints = false - rightImageView.contentMode = .center - rightImageView.tintColor = Assets.secondaryLabelColor - stackView.addArrangedSubview(rightImageView) - - if #available(iOS 13, *) { - let symbolConfig = UIImage.SymbolConfiguration(font: .systemFont(ofSize: UIFloat(18), weight: .medium), scale: .medium) - leftImageView.preferredSymbolConfiguration = symbolConfig - rightImageView.preferredSymbolConfiguration = symbolConfig - } - - NSLayoutConstraint.activate([ - leftImageView.widthAnchor.constraint(equalToConstant: UIFloat(22)), - leftImageView.widthAnchor.constraint(equalTo: rightImageView.widthAnchor), - leftImageView.heightAnchor.constraint(equalTo: leftImageView.widthAnchor), - rightImageView.heightAnchor.constraint(equalTo: rightImageView.widthAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerMapViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerMapViewController.swift deleted file mode 100644 index 725e692..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerMapViewController.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// ColorPickerMapViewController.swift -// Alderis -// -// Created by Adam Demasi on 14/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class ColorPickerMapViewController: ColorPickerTabViewController { - - static let title = "Color Wheel" - static let imageName = "slider.horizontal.below.rectangle" - - private var wheelView: ColorPickerWheelView! - private var sliders = [ColorPickerMapSlider]() - - override func viewDidLoad() { - super.viewDidLoad() - - wheelView = ColorPickerWheelView(color: color) - wheelView.translatesAutoresizingMaskIntoConstraints = false - wheelView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - wheelView.delegate = self - view.addSubview(wheelView) - - sliders = [ - ColorPickerMapSlider( - minImageName: "sun.min", maxImageName: "sun.max", component: .brightness, - overrideSmartInvert: configuration.overrideSmartInvert - ) - ] - - sliders.forEach { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged) - } - - let mainStackView = UIStackView(arrangedSubviews: [wheelView] + sliders) - mainStackView.translatesAutoresizingMaskIntoConstraints = false - mainStackView.axis = .vertical - mainStackView.alignment = .fill - mainStackView.distribution = .fill - view.addSubview(mainStackView) - - NSLayoutConstraint.activate([ - mainStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: UIFloat(15)), - mainStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: UIFloat(-15)), - mainStackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0), - mainStackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: UIFloat(-10)) - ]) - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - colorDidChange() - } - - @objc private func sliderChanged(_ slider: ColorPickerMapSlider) { - var color = self.color - slider.apply(to: &color) - self.setColor(color) - } - - override func colorDidChange() { - wheelView.color = color - sliders.forEach { $0.setColor(color) } - } - -} - -extension ColorPickerMapViewController: ColorPickerWheelViewDelegate { - - func colorPickerWheelView(didSelectColor color: Color) { - self.setColor(color) - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerNumericSlider.swift b/Tweaks/Alderis/Alderis/ColorPickerNumericSlider.swift deleted file mode 100644 index 784f0c8..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerNumericSlider.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// ColorPickerNumericSlider.swift -// Alderis -// -// Created by Kabir Oberai on 28/03/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class ColorPickerNumericSlider: ColorPickerComponentSlider { - - private var textField: UITextField! - - override init(component: Color.Component, overrideSmartInvert: Bool) { - super.init(component: component, overrideSmartInvert: overrideSmartInvert) - - stackView.alignment = .fill - stackView.spacing = UIFloat(8) - - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: UIFloat(16), weight: .medium) - label.text = component.title - stackView.insertArrangedSubview(label, at: 0) - - textField = UITextField() - textField.translatesAutoresizingMaskIntoConstraints = false - textField.delegate = self - textField.returnKeyType = .next - textField.keyboardType = .numberPad - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.spellCheckingType = .no - textField.textAlignment = .right - textField.font = Assets.niceMonospaceDigitFont(ofSize: UIFloat(16)) - stackView.addArrangedSubview(textField) - - NSLayoutConstraint.activate([ - label.widthAnchor.constraint(equalToConstant: UIFloat(50)), - textField.widthAnchor.constraint(equalToConstant: UIFloat(35)) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func setColor(_ color: Color) { - super.setColor(color) - textField.text = "\(Int((color[keyPath: component.keyPath] * component.limit).rounded()))" - } - -} - -extension ColorPickerNumericSlider: UITextFieldDelegate { - - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - let newString = textField.text!.replacingCharacters(in: Range(range, in: textField.text!)!, with: string) - guard !newString.isEmpty else { return true } - - // Numeric only, 0-limit - let badCharacterSet = CharacterSet(charactersIn: "0123456789").inverted - guard newString.rangeOfCharacter(from: badCharacterSet) == nil else { - beep() - return false - } - let limit = component.limit - guard let value = Int(newString), 0...limit ~= CGFloat(value) else { - beep() - return false - } - - // Run this after the input is fully processed by enqueuing it onto the run loop - OperationQueue.main.addOperation { - self.value = CGFloat(value) / limit - self.sliderChanged() - } - - return true - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerSlider.swift b/Tweaks/Alderis/Alderis/ColorPickerSlider.swift deleted file mode 100644 index 45872b6..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerSlider.swift +++ /dev/null @@ -1,206 +0,0 @@ -// -// ColorPickerSlider.swift -// Alderis -// -// Created by Kabir Oberai on 28/03/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class ColorPickerSliderBase: UIControl { - - var overrideSmartInvert: Bool { - didSet { - slider.accessibilityIgnoresInvertColors = overrideSmartInvert - } - } - - let stackView: UIStackView - let slider: ColorSlider - - var value: CGFloat { - get { CGFloat(slider.value) } - set { slider.value = Float(newValue) } - } - - init(overrideSmartInvert: Bool) { - self.overrideSmartInvert = overrideSmartInvert - - slider = ColorSlider() - slider.translatesAutoresizingMaskIntoConstraints = false - slider.accessibilityIgnoresInvertColors = overrideSmartInvert - - stackView = UIStackView(arrangedSubviews: [slider]) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.axis = .horizontal - stackView.distribution = .fill - - super.init(frame: .zero) - - slider.addTarget(self, action: #selector(sliderChanged), for: .valueChanged) - addSubview(stackView) - - NSLayoutConstraint.activate([ - stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor), - stackView.topAnchor.constraint(equalTo: self.topAnchor), - stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc internal func sliderChanged() { - sendActions(for: .valueChanged) - } - -} - -internal protocol ColorPickerSliderProtocol: ColorPickerSliderBase { - func setColor(_ color: Color) - func apply(to color: inout Color) -} - -internal typealias ColorPickerSlider = ColorPickerSliderBase & ColorPickerSliderProtocol - -internal class ColorPickerComponentSlider: ColorPickerSlider { - - let component: Color.Component - - init(component: Color.Component, overrideSmartInvert: Bool) { - self.component = component - super.init(overrideSmartInvert: overrideSmartInvert) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setColor(_ color: Color) { - value = color[keyPath: component.keyPath] - slider.color = color.uiColor - slider.gradientColors = component.sliderTintColor(for: color).map(\.uiColor) - } - - func apply(to color: inout Color) { - color[keyPath: component.keyPath] = value - } - -} - -internal class ColorSlider: UISlider { - private let thumbImage = UIGraphicsImageRenderer(size: CGSize(width: 26, height: 26)).image { _ in } - - var gradientColors = [UIColor]() { - didSet { gradientView.gradientLayer.colors = gradientColors.map(\.cgColor) } - } - - var color: UIColor? { - get { selectionView?.color } - set { selectionView?.color = newValue } - } - - private var checkerboardView: UIView! - private var gradientView: GradientView! - - private var selectionView: ColorWell? - private var selectionViewXConstraint: NSLayoutConstraint? - private var valueObserver: NSKeyValueObservation? - - override init(frame: CGRect) { - super.init(frame: frame) - - #if swift(>=5.5) - var useSliderTrack = !isCatalystMac - if #available(iOS 15, *) { - preferredBehavioralStyle = .pad - useSliderTrack = true - } - #else - let useSliderTrack = true - #endif - if useSliderTrack { - setMinimumTrackImage(UIImage(), for: .normal) - setMaximumTrackImage(UIImage(), for: .normal) - setThumbImage(thumbImage, for: .normal) - } - - checkerboardView = UIView() - checkerboardView.translatesAutoresizingMaskIntoConstraints = false - checkerboardView.backgroundColor = Assets.checkerboardPatternColor - checkerboardView.clipsToBounds = true - if #available(iOS 13, *) { - checkerboardView.layer.cornerCurve = .continuous - } - insertSubview(checkerboardView, at: 0) - - gradientView = GradientView() - gradientView.translatesAutoresizingMaskIntoConstraints = false - gradientView.gradientLayer.startPoint = CGPoint(x: 0, y: 0) - gradientView.gradientLayer.endPoint = CGPoint(x: 1, y: 0) - gradientView.gradientLayer.allowsGroupOpacity = false - checkerboardView.addSubview(gradientView) - - NSLayoutConstraint.activate([ - checkerboardView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: UIFloat(-3)), - checkerboardView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: UIFloat(3)), - checkerboardView.topAnchor.constraint(equalTo: self.topAnchor, constant: -1), - checkerboardView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 1), - - gradientView.leadingAnchor.constraint(equalTo: checkerboardView.leadingAnchor), - gradientView.trailingAnchor.constraint(equalTo: checkerboardView.trailingAnchor), - gradientView.topAnchor.constraint(equalTo: checkerboardView.topAnchor), - gradientView.bottomAnchor.constraint(equalTo: checkerboardView.bottomAnchor), - ]) - - if useSliderTrack { - let selectionView = ColorWell() - selectionView.translatesAutoresizingMaskIntoConstraints = false - selectionView.isDragInteractionEnabled = false - selectionView.isDropInteractionEnabled = false - #if swift(>=5.3) - if #available(iOS 14, *) { - selectionView.isContextMenuInteractionEnabled = false - } - #endif - insertSubview(selectionView, aboveSubview: checkerboardView) - self.selectionView = selectionView - - selectionViewXConstraint = selectionView.leadingAnchor.constraint(equalTo: checkerboardView.leadingAnchor) - - // Remove minimum width constraint configured by ColorWell internally - let selectionWidthConstraint = selectionView.constraints.first { $0.firstAnchor == selectionView.widthAnchor } - selectionWidthConstraint?.isActive = false - - NSLayoutConstraint.activate([ - selectionViewXConstraint!, - selectionView.centerYAnchor.constraint(equalTo: self.centerYAnchor), - selectionView.widthAnchor.constraint(equalToConstant: UIFloat(24)) - ]) - - valueObserver = observe(\.value) { _, _ in self.valueChanged() } - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func layoutSubviews() { - super.layoutSubviews() - checkerboardView.layer.cornerRadius = checkerboardView.frame.size.height / 2 - valueChanged() - } - - private func valueChanged() { - guard let selectionView = selectionView, - let selectionViewXConstraint = selectionViewXConstraint else { - return - } - let spacing = frame.size.height - selectionView.frame.size.height - selectionViewXConstraint.constant = (spacing / 2) + ((frame.size.width - selectionView.frame.size.width - spacing) * CGFloat(value)) - } -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerSlidersViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerSlidersViewController.swift deleted file mode 100644 index 67d7625..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerSlidersViewController.swift +++ /dev/null @@ -1,266 +0,0 @@ -// -// ColorPickerSlidersViewController.swift -// Alderis -// -// Created by Adam Demasi on 14/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit -import AudioToolbox - -internal class ColorPickerSlidersViewController: ColorPickerTabViewController { - - static let title = "Sliders" - static let imageName = "slider.horizontal.3" - - private enum Mode: CaseIterable { - case rgb, hsl, hsb, white - - var title: String { - switch self { - case .rgb: return "RGB" - case .hsl: return "HSL" - case .hsb: return "HSB" - case .white: return "White" - } - } - - private var components: [Color.Component] { - switch self { - case .rgb: return [.red, .green, .blue, .alpha] - case .hsl: return [.hue, .hslSaturation, .lightness, .alpha] - case .hsb: return [.hue, .saturation, .brightness, .alpha] - case .white: return [.white, .alpha] - } - } - - func makeSliders(overrideSmartInvert: Bool, supportsAlpha: Bool) -> [ColorPickerNumericSlider] { - components.compactMap { component in - if component.keyPath == \.alpha && !supportsAlpha { - return nil - } - return ColorPickerNumericSlider(component: component, overrideSmartInvert: overrideSmartInvert) - } - } - } - - private var mode: Mode = .rgb { - didSet { updateMode() } - } - - private var segmentedControl: UISegmentedControl! - - private var allSliders = [Mode: [ColorPickerNumericSlider]]() - private var sliderStacks = [Mode: UIStackView]() - - private let colorWell = ColorWell() - - private var hexTextField: UITextField! - private var hexOptions = Color.HexOptions() - - private var eggLabel: UILabel! - private var eggString = "" - - override func viewDidLoad() { - super.viewDidLoad() - - let segmentedControlContainer = UIView() - segmentedControlContainer.translatesAutoresizingMaskIntoConstraints = false - - segmentedControl = UISegmentedControl(items: Mode.allCases.map(\.title)) - segmentedControl.translatesAutoresizingMaskIntoConstraints = false - segmentedControl.selectedSegmentIndex = 0 - segmentedControl.addTarget(self, action: #selector(segmentControlChanged(_:)), for: .valueChanged) - segmentedControlContainer.addSubview(segmentedControl) - - let topSpacerView = UIView() - topSpacerView.translatesAutoresizingMaskIntoConstraints = false - - let mainStackView = UIStackView(arrangedSubviews: [segmentedControlContainer, topSpacerView]) - mainStackView.translatesAutoresizingMaskIntoConstraints = false - mainStackView.axis = .vertical - mainStackView.alignment = .fill - mainStackView.distribution = .fill - mainStackView.spacing = UIFloat(6) - view.addSubview(mainStackView) - - for mode in Mode.allCases { - let modeSliders = mode.makeSliders(overrideSmartInvert: configuration.overrideSmartInvert, - supportsAlpha: configuration.supportsAlpha) - for slider in modeSliders { - slider.addTarget(self, action: #selector(sliderChanged(_:)), for: .valueChanged) - } - allSliders[mode] = modeSliders - - let sliderStackView = UIStackView(arrangedSubviews: modeSliders) - sliderStackView.axis = .vertical - sliderStackView.alignment = .fill - sliderStackView.distribution = .fill - sliderStackView.spacing = UIFloat(10) - sliderStacks[mode] = sliderStackView - mainStackView.addArrangedSubview(sliderStackView) - } - - colorWell.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - colorWell.isDragInteractionEnabled = true - colorWell.isDropInteractionEnabled = false - - hexTextField = UITextField() - hexTextField.translatesAutoresizingMaskIntoConstraints = false - hexTextField.delegate = self - hexTextField.textAlignment = .right - hexTextField.returnKeyType = .done - hexTextField.autocapitalizationType = .none - hexTextField.autocorrectionType = .no - hexTextField.spellCheckingType = .no - hexTextField.font = Assets.niceMonospaceDigitFont(ofSize: UIFloat(16)) - hexTextField.setContentHuggingPriority(.required, for: .vertical) - hexTextField.setContentHuggingPriority(.defaultHigh, for: .horizontal) - - eggLabel = UILabel() - eggLabel.translatesAutoresizingMaskIntoConstraints = false - eggLabel.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - eggLabel.font = UIFont.systemFont(ofSize: UIFloat(24), weight: .heavy) - eggLabel.isHidden = true - - let bottomSpacerView = UIView() - bottomSpacerView.translatesAutoresizingMaskIntoConstraints = false - mainStackView.addArrangedSubview(bottomSpacerView) - - let hexStackView = UIStackView(arrangedSubviews: [colorWell, eggLabel, hexTextField]) - hexStackView.translatesAutoresizingMaskIntoConstraints = false - hexStackView.axis = .horizontal - hexStackView.alignment = .fill - hexStackView.distribution = .fill - hexStackView.spacing = UIFloat(10) - mainStackView.addArrangedSubview(hexStackView) - - NSLayoutConstraint.activate([ - mainStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: UIFloat(15)), - mainStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: UIFloat(-15)), - mainStackView.topAnchor.constraint(equalTo: view.topAnchor, constant: UIFloat(15)), - mainStackView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor, constant: UIFloat(-15)), - - segmentedControl.topAnchor.constraint(equalTo: segmentedControlContainer.topAnchor), - segmentedControl.bottomAnchor.constraint(equalTo: segmentedControlContainer.bottomAnchor), - segmentedControl.centerXAnchor.constraint(equalTo: segmentedControlContainer.centerXAnchor), - - topSpacerView.heightAnchor.constraint(equalToConstant: UIFloat(3)), - bottomSpacerView.heightAnchor.constraint(equalToConstant: UIFloat(3)), - - colorWell.widthAnchor.constraint(equalToConstant: UIFloat(32)), - colorWell.heightAnchor.constraint(equalTo: colorWell.widthAnchor) - ]) - - updateMode() - } - - @objc func segmentControlChanged(_ sender: UISegmentedControl) { - view.endEditing(true) - mode = Mode.allCases[sender.selectedSegmentIndex] - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - super.touchesBegan(touches, with: event) - view.endEditing(true) - } - - func updateMode() { - for (stackMode, stack) in sliderStacks { - stack.isHidden = stackMode != mode - } - colorDidChange() - } - - func setColor(_ color: Color, hexOptions: Color.HexOptions, shouldBroadcast: Bool = true) { - self.hexOptions = hexOptions - super.setColor(color, shouldBroadcast: shouldBroadcast) - } - - override func setColor(_ color: Color, shouldBroadcast: Bool = true) { - self.setColor(color, hexOptions: [], shouldBroadcast: shouldBroadcast) - } - - @objc func sliderChanged(_ slider: ColorPickerNumericSlider) { - var color = self.color - slider.apply(to: &color) - setColor(color) - } - - override func colorDidChange() { - allSliders[mode]?.forEach { - $0.setColor(color) - } - - colorWell.color = color.uiColor - hexTextField.text = color.hexString(with: hexOptions) - - if #available(iOS 13, *) { - } else { - let foregroundColor: UIColor = color.isDark ? .white : .black - segmentedControl.setTitleTextAttributes([ - .foregroundColor: foregroundColor - ], for: .selected) - } - } - -} - -extension ColorPickerSlidersViewController: UITextFieldDelegate { - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - view.endEditing(true) - return true - } - - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - let newString = textField.text!.replacingCharacters(in: Range(range, in: textField.text!)!, with: string) - guard !newString.isEmpty else { return true } - - // #AAAAAA - eggString = "\(eggString.suffix(3))\(string)" - if eggString.lowercased() == "holo" { - self.setColor(Color(red: 51 / 255, green: 181 / 255, blue: 229 / 255, alpha: 1)) - eggLabel.text = "Praise DuARTe" - eggLabel.textColor = color.uiColor - eggLabel.isHidden = false - eggString = "" - return false - } - - let canonicalizedString = newString.hasPrefix("#") ? newString.dropFirst() : Substring(newString) - guard canonicalizedString.count <= 8 else { - beep() - return false - } - - let badCharacterSet = CharacterSet(charactersIn: "0123456789ABCDEFabcdef").inverted - guard canonicalizedString.rangeOfCharacter(from: badCharacterSet) == nil else { - beep() - return false - } - - if canonicalizedString.count != 6 && canonicalizedString.count != 8 { - // User is probably still typing it out. Don’t do anything yet. - return true - } - - guard var uiColor = UIColor(propertyListValue: "#\(canonicalizedString)") else { - return true - } - - if !configuration.supportsAlpha { - // Discard the alpha component. - uiColor = uiColor.withAlphaComponent(1) - } - - let color = Color(uiColor: uiColor) - OperationQueue.main.addOperation { - self.setColor(color, hexOptions: canonicalizedString.count == 3 ? .allowShorthand : []) - } - - return true - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerSwatchViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerSwatchViewController.swift deleted file mode 100644 index b249f74..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerSwatchViewController.swift +++ /dev/null @@ -1,303 +0,0 @@ -// -// ColorPickerSwatchViewController.swift -// Alderis -// -// Created by Adam Demasi on 13/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class ColorPickerSwatchViewController: ColorPickerTabViewController { - - private class ColorLayer: CALayer { - let color: Color - init(color: Color) { - self.color = color - super.init() - backgroundColor = color.uiColor.cgColor - } - override init(layer: Any) { - color = Color(white: 1, alpha: 1) - super.init(layer: layer) - } - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - } - - static let title = "Swatch" - static let imageName = "square.grid.4x3.fill" - - static let colorSwatch = [ - [ - Color(hue: 0.000000, saturation: 0.000000, brightness: 1.000000, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.921569, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.839216, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.760784, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.678431, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.600000, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.521569, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.439216, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.360784, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.278431, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.200000, alpha: 1), - Color(hue: 0.000000, saturation: 0.000000, brightness: 0.000000, alpha: 1), - ], - [ - Color(hue: 0.542793, saturation: 1.000000, brightness: 0.290196, alpha: 1), - Color(hue: 0.612403, saturation: 0.988506, brightness: 0.341176, alpha: 1), - Color(hue: 0.703704, saturation: 0.915255, brightness: 0.231373, alpha: 1), - Color(hue: 0.787878, saturation: 0.901640, brightness: 0.239216, alpha: 1), - Color(hue: 0.937107, saturation: 0.883333, brightness: 0.235294, alpha: 1), - Color(hue: 0.010989, saturation: 0.989130, brightness: 0.360784, alpha: 1), - Color(hue: 0.051852, saturation: 1.000000, brightness: 0.352941, alpha: 1), - Color(hue: 0.096591, saturation: 1.000000, brightness: 0.345098, alpha: 1), - Color(hue: 0.118217, saturation: 1.000000, brightness: 0.337255, alpha: 1), - Color(hue: 0.158497, saturation: 1.000000, brightness: 0.400000, alpha: 1), - Color(hue: 0.179012, saturation: 0.952941, brightness: 0.333333, alpha: 1), - Color(hue: 0.251773, saturation: 0.758064, brightness: 0.243137, alpha: 1), - ], - [ - Color(hue: 0.539604, saturation: 1.000000, brightness: 0.396078, alpha: 1), - Color(hue: 0.603825, saturation: 0.991870, brightness: 0.482353, alpha: 1), - Color(hue: 0.703704, saturation: 0.878049, brightness: 0.321569, alpha: 1), - Color(hue: 0.789473, saturation: 0.853933, brightness: 0.349020, alpha: 1), - Color(hue: 0.939614, saturation: 0.811765, brightness: 0.333333, alpha: 1), - Color(hue: 0.021629, saturation: 1.000000, brightness: 0.513725, alpha: 1), - Color(hue: 0.055555, saturation: 1.000000, brightness: 0.482353, alpha: 1), - Color(hue: 0.101093, saturation: 1.000000, brightness: 0.478431, alpha: 1), - Color(hue: 0.122222, saturation: 1.000000, brightness: 0.470588, alpha: 1), - Color(hue: 0.158273, saturation: 0.985816, brightness: 0.552941, alpha: 1), - Color(hue: 0.177469, saturation: 0.915254, brightness: 0.462745, alpha: 1), - Color(hue: 0.251366, saturation: 0.701148, brightness: 0.341176, alpha: 1), - ], - [ - Color(hue: 0.538732, saturation: 0.993007, brightness: 0.560784, alpha: 1), - Color(hue: 0.601578, saturation: 1.000000, brightness: 0.662745, alpha: 1), - Color(hue: 0.719697, saturation: 0.924370, brightness: 0.466667, alpha: 1), - Color(hue: 0.788333, saturation: 0.806452, brightness: 0.486275, alpha: 1), - Color(hue: 0.938596, saturation: 0.785124, brightness: 0.474510, alpha: 1), - Color(hue: 0.023941, saturation: 1.000000, brightness: 0.709804, alpha: 1), - Color(hue: 0.059730, saturation: 1.000000, brightness: 0.678431, alpha: 1), - Color(hue: 0.102564, saturation: 1.000000, brightness: 0.662745, alpha: 1), - Color(hue: 0.123232, saturation: 0.993976, brightness: 0.650980, alpha: 1), - Color(hue: 0.159864, saturation: 1.000000, brightness: 0.768627, alpha: 1), - Color(hue: 0.177704, saturation: 0.915151, brightness: 0.647059, alpha: 1), - Color(hue: 0.255020, saturation: 0.680328, brightness: 0.478431, alpha: 1), - ], - [ - Color(hue: 0.537037, saturation: 1.000000, brightness: 0.705882, alpha: 1), - Color(hue: 0.599688, saturation: 1.000000, brightness: 0.839216, alpha: 1), - Color(hue: 0.706284, saturation: 0.824324, brightness: 0.580392, alpha: 1), - Color(hue: 0.785333, saturation: 0.791139, brightness: 0.619608, alpha: 1), - Color(hue: 0.938746, saturation: 0.764707, brightness: 0.600000, alpha: 1), - Color(hue: 0.026549, saturation: 1.000000, brightness: 0.886275, alpha: 1), - Color(hue: 0.061927, saturation: 1.000000, brightness: 0.854902, alpha: 1), - Color(hue: 0.103175, saturation: 0.995261, brightness: 0.827451, alpha: 1), - Color(hue: 0.125000, saturation: 0.995215, brightness: 0.819608, alpha: 1), - Color(hue: 0.160544, saturation: 1.000000, brightness: 0.960784, alpha: 1), - Color(hue: 0.179211, saturation: 0.889952, brightness: 0.819608, alpha: 1), - Color(hue: 0.253968, saturation: 0.668789, brightness: 0.615686, alpha: 1), - ], - [ - Color(hue: 0.542438, saturation: 1.000000, brightness: 0.847059, alpha: 1), - Color(hue: 0.603018, saturation: 1.000000, brightness: 0.996078, alpha: 1), - Color(hue: 0.716435, saturation: 0.808989, brightness: 0.698039, alpha: 1), - Color(hue: 0.792237, saturation: 0.776596, brightness: 0.737255, alpha: 1), - Color(hue: 0.942857, saturation: 0.756756, brightness: 0.725490, alpha: 1), - Color(hue: 0.030627, saturation: 0.917647, brightness: 1.000000, alpha: 1), - Color(hue: 0.069281, saturation: 1.000000, brightness: 1.000000, alpha: 1), - Color(hue: 0.111549, saturation: 0.996078, brightness: 1.000000, alpha: 1), - Color(hue: 0.131093, saturation: 1.000000, brightness: 0.992157, alpha: 1), - Color(hue: 0.164021, saturation: 0.744094, brightness: 0.996078, alpha: 1), - Color(hue: 0.184162, saturation: 0.766949, brightness: 0.925490, alpha: 1), - Color(hue: 0.260163, saturation: 0.657754, brightness: 0.733333, alpha: 1), - ], - [ - Color(hue: 0.535193, saturation: 0.996032, brightness: 0.988235, alpha: 1), - Color(hue: 0.601190, saturation: 0.771653, brightness: 0.996078, alpha: 1), - Color(hue: 0.707665, saturation: 0.795745, brightness: 0.921569, alpha: 1), - Color(hue: 0.786096, saturation: 0.769547, brightness: 0.952941, alpha: 1), - Color(hue: 0.938597, saturation: 0.743478, brightness: 0.901961, alpha: 1), - Color(hue: 0.017143, saturation: 0.686275, brightness: 1.000000, alpha: 1), - Color(hue: 0.056466, saturation: 0.717647, brightness: 1.000000, alpha: 1), - Color(hue: 0.102094, saturation: 0.751968, brightness: 0.996078, alpha: 1), - Color(hue: 0.122396, saturation: 0.755906, brightness: 0.996078, alpha: 1), - Color(hue: 0.157658, saturation: 0.580392, brightness: 1.000000, alpha: 1), - Color(hue: 0.179952, saturation: 0.577406, brightness: 0.937255, alpha: 1), - Color(hue: 0.254310, saturation: 0.549763, brightness: 0.827451, alpha: 1), - ], - [ - Color(hue: 0.537255, saturation: 0.674603, brightness: 0.988235, alpha: 1), - Color(hue: 0.605516, saturation: 0.545098, brightness: 1.000000, alpha: 1), - Color(hue: 0.719048, saturation: 0.688976, brightness: 0.996078, alpha: 1), - Color(hue: 0.790419, saturation: 0.657481, brightness: 0.996078, alpha: 1), - Color(hue: 0.940000, saturation: 0.525210, brightness: 0.933333, alpha: 1), - Color(hue: 0.013333, saturation: 0.490196, brightness: 1.000000, alpha: 1), - Color(hue: 0.051282, saturation: 0.509804, brightness: 1.000000, alpha: 1), - Color(hue: 0.098039, saturation: 0.533333, brightness: 1.000000, alpha: 1), - Color(hue: 0.120098, saturation: 0.533333, brightness: 1.000000, alpha: 1), - Color(hue: 0.157321, saturation: 0.419608, brightness: 1.000000, alpha: 1), - Color(hue: 0.180135, saturation: 0.409091, brightness: 0.949020, alpha: 1), - Color(hue: 0.256097, saturation: 0.371041, brightness: 0.866667, alpha: 1), - ], - [ - Color(hue: 0.540881, saturation: 0.418972, brightness: 0.992157, alpha: 1), - Color(hue: 0.607954, saturation: 0.345098, brightness: 1.000000, alpha: 1), - Color(hue: 0.720760, saturation: 0.448818, brightness: 0.996078, alpha: 1), - Color(hue: 0.790124, saturation: 0.425197, brightness: 0.996078, alpha: 1), - Color(hue: 0.941667, saturation: 0.327869, brightness: 0.956863, alpha: 1), - Color(hue: 0.012500, saturation: 0.313725, brightness: 1.000000, alpha: 1), - Color(hue: 0.051587, saturation: 0.329412, brightness: 1.000000, alpha: 1), - Color(hue: 0.093869, saturation: 0.341176, brightness: 1.000000, alpha: 1), - Color(hue: 0.116279, saturation: 0.338582, brightness: 0.996078, alpha: 1), - Color(hue: 0.157143, saturation: 0.274510, brightness: 1.000000, alpha: 1), - Color(hue: 0.179687, saturation: 0.259109, brightness: 0.968627, alpha: 1), - Color(hue: 0.254902, saturation: 0.219828, brightness: 0.909804, alpha: 1), - ], - [ - Color(hue: 0.548077, saturation: 0.203922, brightness: 1.000000, alpha: 1), - Color(hue: 0.609848, saturation: 0.172549, brightness: 1.000000, alpha: 1), - Color(hue: 0.716981, saturation: 0.208661, brightness: 0.996078, alpha: 1), - Color(hue: 0.783019, saturation: 0.207843, brightness: 1.000000, alpha: 1), - Color(hue: 0.942983, saturation: 0.152611, brightness: 0.976471, alpha: 1), - Color(hue: 0.012821, saturation: 0.152941, brightness: 1.000000, alpha: 1), - Color(hue: 0.048781, saturation: 0.160784, brightness: 1.000000, alpha: 1), - Color(hue: 0.093023, saturation: 0.168627, brightness: 1.000000, alpha: 1), - Color(hue: 0.115080, saturation: 0.164706, brightness: 1.000000, alpha: 1), - Color(hue: 0.156566, saturation: 0.129921, brightness: 0.996078, alpha: 1), - Color(hue: 0.182796, saturation: 0.123999, brightness: 0.980392, alpha: 1), - Color(hue: 0.262820, saturation: 0.109243, brightness: 0.933333, alpha: 1), - ] - ] - - let colors = ColorPickerSwatchViewController.colorSwatch - - private var colorRows = [[ColorLayer]]() - private var colorDict = [String: ColorLayer]() - - var containerView: UIView! - var selectionView: UIView! - var containerViewHeightConstraint: NSLayoutConstraint! - var selectionViewWidthConstraint: NSLayoutConstraint! - var selectionViewXConstraint: NSLayoutConstraint! - var selectionViewYConstraint: NSLayoutConstraint! - - override func viewDidLoad() { - super.viewDidLoad() - - containerView = UIView() - containerView.translatesAutoresizingMaskIntoConstraints = false - containerView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert - view.addSubview(containerView) - - for row in colors { - var colorRow = [ColorLayer]() - for color in row { - let colorLayer = ColorLayer(color: color) - containerView.layer.addSublayer(colorLayer) - colorDict[color.hexString()] = colorLayer - colorRow.append(colorLayer) - } - colorRows.append(colorRow) - } - - view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(gestureRecognizerFired(_:)))) - let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(gestureRecognizerFired(_:))) - panGestureRecognizer.maximumNumberOfTouches = 1 - view.addGestureRecognizer(panGestureRecognizer) - - selectionView = UIView() - selectionView.translatesAutoresizingMaskIntoConstraints = false - selectionView.isUserInteractionEnabled = false - selectionView.layer.borderColor = UIColor.white.cgColor - selectionView.layer.borderWidth = 2 - selectionView.layer.shadowOffset = CGSize(width: 0, height: 0) - selectionView.layer.shadowOpacity = 1 - selectionView.layer.shadowColor = UIColor(white: 0, alpha: 0.1).cgColor - view.addSubview(selectionView) - - containerViewHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: 0) - selectionViewWidthConstraint = selectionView.widthAnchor.constraint(equalToConstant: UIFloat(20)) - let selectionViewBaseXConstraint = selectionView.leftAnchor.constraint(equalTo: view.leftAnchor) - selectionViewBaseXConstraint.priority = .defaultLow - let selectionViewBaseYConstraint = selectionView.topAnchor.constraint(equalTo: view.topAnchor) - selectionViewBaseYConstraint.priority = .defaultLow - selectionViewXConstraint = selectionView.leftAnchor.constraint(equalTo: view.leftAnchor) - selectionViewYConstraint = selectionView.topAnchor.constraint(equalTo: view.topAnchor) - - NSLayoutConstraint.activate([ - containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - containerView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - containerView.topAnchor.constraint(equalTo: view.topAnchor), - containerView.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor), - containerViewHeightConstraint, - - selectionViewWidthConstraint, - selectionView.heightAnchor.constraint(equalTo: selectionView.widthAnchor), - selectionViewBaseXConstraint, - selectionViewBaseYConstraint, - selectionViewXConstraint, - selectionViewYConstraint - ]) - - colorDidChange() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - var x: CGFloat = 0, y: CGFloat = 0 - let size = view.frame.size.width / CGFloat(colors[0].count) - for row in colorRows { - x = 0 - for item in row { - item.frame = CGRect(x: x * size, y: y * size, width: size, height: size) - x += 1 - } - y += 1 - } - - containerViewHeightConstraint.constant = y * size - selectionViewWidthConstraint.constant = size - UIView.performWithoutAnimation { - colorDidChange() - } - } - - @objc private func gestureRecognizerFired(_ sender: UIGestureRecognizer) { - switch sender.state { - case .began, .changed, .ended: - let location = sender.location(in: containerView) - guard let colorView = containerView.layer.hitTest(location) as? ColorLayer else { - return - } - self.setColor(colorView.color) - case .possible, .cancelled, .failed: - break - @unknown default: - break - } - } - - func setSelection(to colorLayer: CALayer?) { - let wasHidden = selectionView.isHidden - selectionView.isHidden = colorLayer == nil - selectionViewXConstraint.constant = colorLayer?.frame.origin.x ?? 0 - selectionViewYConstraint.constant = colorLayer?.frame.origin.y ?? 0 - if wasHidden { - view.layoutIfNeeded() - } else { - UIView.animate(withDuration: 0.2) { - self.view.layoutIfNeeded() - } - } - } - - override func colorDidChange() { - guard selectionView != nil else { return } - setSelection(to: colorDict[color.hexString()]) - } - -} diff --git a/Tweaks/Alderis/Alderis/ColorPickerTabViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerTabViewController.swift deleted file mode 100644 index 3b27951..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerTabViewController.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// ColorPickerTabViewController.swift -// Alderis -// -// Created by Kabir Oberai on 23/03/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal protocol ColorPickerTabDelegate: AnyObject { - func colorPickerTab(_ tab: ColorPickerTabViewControllerBase, didSelect color: Color) -} - -internal class ColorPickerTabViewControllerBase: UIViewController { - - unowned var tabDelegate: ColorPickerTabDelegate - - private(set) var configuration: ColorPickerConfiguration - - private(set) var color: Color { - didSet { colorDidChange() } - } - - func colorDidChange() {} - - func setColor(_ color: Color, shouldBroadcast: Bool = true) { - if self.color == color { - return - } - self.color = color - if shouldBroadcast { - tabDelegate.colorPickerTab(self, didSelect: color) - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - required init(tabDelegate: ColorPickerTabDelegate, configuration: ColorPickerConfiguration, color: Color) { - self.tabDelegate = tabDelegate - self.configuration = configuration - self.color = color - super.init(nibName: nil, bundle: nil) - } - -} - -internal protocol ColorPickerTabViewControllerProtocol: ColorPickerTabViewControllerBase { - static var title: String { get } - static var imageName: String { get } - static var image: UIImage { get } -} - -extension ColorPickerTabViewControllerProtocol { - static var image: UIImage { Assets.systemImage(named: imageName, font: .systemFont(ofSize: UIFloat(20), weight: .medium)) ?? UIImage() } -} - -internal typealias ColorPickerTabViewController = ColorPickerTabViewControllerBase & ColorPickerTabViewControllerProtocol diff --git a/Tweaks/Alderis/Alderis/ColorPickerViewController.swift b/Tweaks/Alderis/Alderis/ColorPickerViewController.swift deleted file mode 100644 index 386d693..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerViewController.swift +++ /dev/null @@ -1,385 +0,0 @@ -// -// ColorPickerViewController.swift -// Alderis -// -// Created by Adam Demasi on 12/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -/// Provides the Color Picker user interface. -/// -/// Present this view controller to display the color picker. Do not push it onto a navigation -/// controller stack. In horizontally and vertically regular size class environments, for instance -/// on iPad and Mac, the picker will be presented as a popover. This means that you must set -/// `sourceView` or other similar properties on the view controller’s `popoverPresentationController` -/// before presentation. -/// -/// To review examples of `ColorPickerViewController` in use, run `pod try Alderis`. -@objc(HBColorPickerViewController) -open class ColorPickerViewController: UIViewController { - - /// Do not rely on this fallback value - always specify a color! - private static let defaultColor = UIColor(white: 0.6, alpha: 1) - - /// Initialise an instance of `ColorPickerViewController` with a configuration object. - /// - /// Remember to set the `delegate` before presenting the view controller. - @objc public init(configuration: ColorPickerConfiguration) { - self.configuration = configuration - super.init(nibName: nil, bundle: nil) - setUp() - } - - /// The delegate that will receive the user’s selection upon tapping the Done button, or a - /// cancellation upon tapping the Cancel button. - @objc open weak var delegate: ColorPickerDelegate? { - didSet { innerViewController?.delegate = delegate } - } - - /// The configuration of the color picker. Use this to set the initially selected color, as well - /// as other behavioral options. - /// - /// Making changes to this value or its properties after the color picker interface has been - /// presented may result in undefined behavior. - /// - /// - see: `ColorPickerConfiguration` - @objc open var configuration: ColorPickerConfiguration! - - /// Deprecated. Set `ColorPickerConfiguration.overrideSmartInvert` instead. - /// - /// - see: `ColorPickerConfiguration.overrideSmartInvert` - @available(*, deprecated, message: "Use ColorPickerConfiguration instead") - @objc open var overrideSmartInvert = true - - /// Deprecated. Set `ColorPickerConfiguration.color` instead. - /// - /// - see: `ColorPickerConfiguration.color` - @available(*, deprecated, message: "Use ColorPickerConfiguration instead") - @objc open var color = ColorPickerViewController.defaultColor - - // A width divisible by 12 (the number of items wide in the swatch). - private var finalWidth: CGFloat { - if modalPresentationStyle == .popover { - return UIFloat(336) - } else { - return floor(min(UIFloat(384), view.frame.size.width - 30) / 12) * 12 - } - } - - private var isFullScreen: Bool { modalPresentationStyle != .popover } - - private var innerViewController: ColorPickerInnerViewController! - - private var backdropView: UIView! - private var backgroundView: UIVisualEffectView! - - private var widthLayoutConstraint: NSLayoutConstraint! - private var bottomLayoutConstraint: NSLayoutConstraint! - private var bottomAnimatingLayoutConstraint: NSLayoutConstraint! - - // swiftlint:disable:next weak_delegate - private lazy var _transitioningDelegate = BottomSheetTransitioningDelegate() - - private var initialBottomSafeAreaInset: CGFloat? - private var isKeyboardVisible = false - - /// :nodoc: - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { - self.configuration = nil - super.init(nibName: nil, bundle: nil) - setUp() - } - - /// :nodoc: - required public init?(coder: NSCoder) { - self.configuration = nil - super.init(coder: coder) - setUp() - } - - private func setUp() { - if traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass == .regular { - modalPresentationStyle = .popover - } else { - modalPresentationStyle = .overCurrentContext - transitioningDelegate = _transitioningDelegate - } - } - - /// :nodoc: - override open func viewDidLoad() { - super.viewDidLoad() - - var compatibilityMode = false - if configuration == nil { - let deprecatedAPI: ColorPickerViewControllerDeprecatedMethods = self - // Yes, Swift, I know my code for handling deprecated API usage uses deprecated API 🙄 - if deprecatedAPI.color == ColorPickerViewController.defaultColor { - fatalError("Alderis: You need to set a configuration. https://hbang.github.io/Alderis/") - } - NSLog("Alderis: Deprecated configuration API in use. This will be removed in a future release. Migrate to using ColorPickerConfiguration. https://hbang.github.io/Alderis/") - compatibilityMode = true - configuration = ColorPickerConfiguration(color: deprecatedAPI.color) - configuration.overrideSmartInvert = deprecatedAPI.overrideSmartInvert - } - - if !configuration.supportsAlpha { - // Force the color to be fully opaque. - configuration.color = configuration.color.withAlphaComponent(1) - } - - navigationController?.isNavigationBarHidden = true - view.backgroundColor = .clear - preferredContentSize = .zero - - if isFullScreen { - backdropView = UIView() - backdropView.translatesAutoresizingMaskIntoConstraints = false - backdropView.backgroundColor = Assets.backdropColor - backdropView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dismissGestureFired(_:)))) - view.addSubview(backdropView) - } - - let containerView = UIView() - containerView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(containerView) - - if isFullScreen { - let style: UIBlurEffect.Style - if #available(iOS 13, *) { - style = .systemThinMaterial - } else { - style = .light - } - backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: style)) - backgroundView.translatesAutoresizingMaskIntoConstraints = false - backgroundView.clipsToBounds = true - backgroundView.layer.cornerRadius = 13 - if #available(iOS 13, *) { - backgroundView.layer.cornerCurve = .continuous - } - containerView.addSubview(backgroundView) - } - - innerViewController = ColorPickerInnerViewController(delegate: delegate, configuration: configuration) - innerViewController.compatibilityMode = compatibilityMode - innerViewController.willMove(toParent: self) - addChild(innerViewController) - innerViewController.view.translatesAutoresizingMaskIntoConstraints = false - - if isFullScreen { - innerViewController.view.clipsToBounds = true - innerViewController.view.layer.cornerRadius = 13 - innerViewController.view.layer.borderWidth = 1 - innerViewController.view.layer.borderColor = Assets.borderColor.cgColor - if #available(iOS 13, *) { - innerViewController.view.layer.cornerCurve = .continuous - } - } else { - popoverPresentationController?.delegate = innerViewController - } - - containerView.addSubview(innerViewController.view) - - widthLayoutConstraint = containerView.widthAnchor.constraint(equalToConstant: finalWidth) - bottomLayoutConstraint = view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0) - bottomAnimatingLayoutConstraint = view.bottomAnchor.constraint(equalTo: containerView.topAnchor) - - NSLayoutConstraint.activate( - [ - widthLayoutConstraint, - innerViewController.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - innerViewController.view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), - innerViewController.view.topAnchor.constraint(equalTo: containerView.topAnchor), - innerViewController.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) - ] + - (isFullScreen ? [ - backdropView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - backdropView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - backdropView.topAnchor.constraint(equalTo: view.topAnchor), - backdropView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - - backgroundView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - backgroundView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), - backgroundView.topAnchor.constraint(equalTo: containerView.topAnchor), - backgroundView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - - containerView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), - bottomLayoutConstraint - ] : [ - containerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), - containerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - containerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - containerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) - ]) - ) - } - - /// :nodoc: - override open func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - widthLayoutConstraint.constant = finalWidth - - if isFullScreen { - innerViewController.view.layer.borderWidth = 1 / (view.window?.screen.scale ?? 1) - } - } - - /// :nodoc: - override open func viewSafeAreaInsetsDidChange() { - super.viewSafeAreaInsetsDidChange() - - if !isKeyboardVisible { - initialBottomSafeAreaInset = view.safeAreaInsets.bottom - bottomLayoutConstraint.constant = initialBottomSafeAreaInset == 0 ? 15 : 0 - } - } - - /// :nodoc: - open override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) { - super.preferredContentSizeDidChange(forChildContentContainer: container) - - if !isFullScreen { - preferredContentSize = CGSize(width: finalWidth, - height: innerViewController.preferredContentSize.height) - } - } - - /// :nodoc: - override open func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - if navigationController != nil && navigationController!.viewControllers.count > 1 { - assertionFailure("Do not push \(String(describing: type(of: self))) onto a navigation controller stack. It must be presented using UIViewController.present(_:animated:completion:).") - } - - if animated && isFullScreen { - backdropView.alpha = 0 - bottomLayoutConstraint.isActive = false - bottomAnimatingLayoutConstraint.isActive = true - view.layoutIfNeeded() - - UIView.animate(withDuration: 0.4, - delay: 0, - usingSpringWithDamping: 2, - initialSpringVelocity: 0.5, - options: [], - animations: { - self.backdropView.alpha = 1 - self.bottomLayoutConstraint.isActive = true - self.bottomAnimatingLayoutConstraint.isActive = false - self.view.layoutIfNeeded() - }, - completion: nil) - } - } - - private let keyboardNotificationNames = [ - UIResponder.keyboardWillShowNotification, - UIResponder.keyboardWillHideNotification, - UIResponder.keyboardWillChangeFrameNotification - ] - - /// :nodoc: - override open func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - for name in keyboardNotificationNames { - NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameWillChange(_:)), name: name, object: nil) - } - } - - /// :nodoc: - override open func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - for name in keyboardNotificationNames { - NotificationCenter.default.removeObserver(self, name: name, object: nil) - } - - if animated && isFullScreen { - backdropView.alpha = 1 - bottomLayoutConstraint.isActive = true - bottomAnimatingLayoutConstraint.isActive = false - view.layoutIfNeeded() - - UIView.animate(withDuration: 0.4, - delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: [], - animations: { - self.backdropView.alpha = 0 - self.bottomLayoutConstraint.isActive = false - self.bottomAnimatingLayoutConstraint.isActive = true - self.view.layoutIfNeeded() - }, - completion: nil) - } - } - - /// :nodoc: - override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - if isFullScreen { - // CGColor doesn’t support dynamic colors, so we need to set this again. - innerViewController.view.layer.borderColor = Assets.borderColor.cgColor - } - } - - @objc private func keyboardFrameWillChange(_ notification: Notification) { - if !isFullScreen { - return - } - - guard let userInfo = notification.userInfo, - let keyboardEndFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect, - let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval, - let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt - else { - return - } - - isKeyboardVisible = notification.name != UIResponder.keyboardWillHideNotification - - var options: UIView.AnimationOptions = .beginFromCurrentState - options.insert(.init(rawValue: curve << 16)) - - UIView.animate(withDuration: duration, - delay: 0, - options: options, - animations: { - let keyboardHeight: CGFloat = (self.isKeyboardVisible ? keyboardEndFrame.size.height : 0) - let keyboardExtraMargin: CGFloat = (self.isKeyboardVisible && self.initialBottomSafeAreaInset != 0 ? 15 : 0) - let bottom = max(keyboardHeight - (self.initialBottomSafeAreaInset ?? 0), 0) + keyboardExtraMargin - self.additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: bottom, right: 0) - self.view.layoutIfNeeded() - }, - completion: nil) - } - - @objc private func dismissGestureFired(_ gestureRecognizer: UITapGestureRecognizer) { - if gestureRecognizer.state == .ended { - if isKeyboardVisible { - view.endEditing(true) - } else { - innerViewController.saveTapped() - dismiss(animated: true, completion: nil) - } - } - } - -} - -/// :nodoc: -private protocol ColorPickerViewControllerDeprecatedMethods { - var color: UIColor { get } - var overrideSmartInvert: Bool { get } -} - -/// :nodoc: -extension ColorPickerViewController: ColorPickerViewControllerDeprecatedMethods {} diff --git a/Tweaks/Alderis/Alderis/ColorPickerWheelView.swift b/Tweaks/Alderis/Alderis/ColorPickerWheelView.swift deleted file mode 100644 index 2f03938..0000000 --- a/Tweaks/Alderis/Alderis/ColorPickerWheelView.swift +++ /dev/null @@ -1,242 +0,0 @@ -// -// ColorPickerMapView.swift -// Alderis -// -// Created by Adam Demasi on 14/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal protocol ColorPickerWheelViewDelegate: AnyObject { - func colorPickerWheelView(didSelectColor color: Color) -} - -internal class ColorPickerWheelView: UIView { - - weak var delegate: ColorPickerWheelViewDelegate? - - var color: Color { - didSet { updateColor() } - } - - private var containerView: UIView! - private var wheelView: ColorPickerWheelInnerView! - private var selectionView: ColorWell! - private var selectionViewXConstraint: NSLayoutConstraint! - private var selectionViewYConstraint: NSLayoutConstraint! - private var selectionViewFingerDownConstraint: NSLayoutConstraint! - - private var isFingerDown = false - private let touchDownFeedbackGenerator = UIImpactFeedbackGenerator(style: .medium) - private let touchUpFeedbackGenerator = UIImpactFeedbackGenerator(style: .light) - - init(color: Color) { - self.color = color - super.init(frame: .zero) - - containerView = UIView() - containerView.translatesAutoresizingMaskIntoConstraints = false - containerView.clipsToBounds = true - addSubview(containerView) - - containerView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(gestureRecognizerFired(_:)))) - containerView.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(gestureRecognizerFired(_:)))) - let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(gestureRecognizerFired(_:))) - panGestureRecognizer.maximumNumberOfTouches = 1 - containerView.addGestureRecognizer(panGestureRecognizer) - - wheelView = ColorPickerWheelInnerView() - wheelView.translatesAutoresizingMaskIntoConstraints = false - wheelView.handleLayout = { [weak self] in self?.setNeedsLayout() } - containerView.addSubview(wheelView) - - selectionView = ColorWell() - selectionView.translatesAutoresizingMaskIntoConstraints = false - selectionView.isDragInteractionEnabled = false - selectionView.isDropInteractionEnabled = false - #if swift(>=5.3) - if #available(iOS 14, *) { - selectionView.isContextMenuInteractionEnabled = false - } - #endif - containerView.addSubview(selectionView) - - selectionViewXConstraint = selectionView.leftAnchor.constraint(equalTo: containerView.leftAnchor) - selectionViewYConstraint = selectionView.topAnchor.constraint(equalTo: containerView.topAnchor) - // https://www.youtube.com/watch?v=Qs8kDiOwPBA - selectionViewFingerDownConstraint = selectionView.widthAnchor.constraint(equalToConstant: 56) - let selectionViewNormalConstraint = selectionView.widthAnchor.constraint(equalToConstant: UIFloat(24)) - selectionViewNormalConstraint.priority = .defaultHigh - - // Remove minimum width constraint configured by ColorWell internally - let selectionWidthConstraint = selectionView.constraints.first { $0.firstAnchor == selectionView.widthAnchor } - selectionWidthConstraint?.isActive = false - - NSLayoutConstraint.activate([ - containerView.centerXAnchor.constraint(equalTo: self.centerXAnchor), - containerView.topAnchor.constraint(equalTo: self.topAnchor), - containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor), - containerView.widthAnchor.constraint(equalTo: containerView.heightAnchor, constant: UIFloat(30)), - - wheelView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: UIFloat(30)), - wheelView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: UIFloat(-30)), - wheelView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: UIFloat(15)), - wheelView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: UIFloat(-15)), - - selectionViewXConstraint, - selectionViewYConstraint, - selectionViewNormalConstraint, - selectionView.heightAnchor.constraint(equalTo: selectionView.widthAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func layoutSubviews() { - super.layoutSubviews() - updateSelectionPoint() - } - - private func updateColor() { - wheelView.brightness = color.brightness - selectionView.backgroundColor = color.uiColor - updateSelectionPoint() - } - - private func updateSelectionPoint() { - let colorPoint = pointForColor(color, in: wheelView.frame.size) - let point = CGPoint(x: wheelView.frame.origin.x + colorPoint.x - (selectionView.frame.size.width / 2), - y: min( - frame.size.height - selectionView.frame.size.height - 1, - max(1, wheelView.frame.origin.y + colorPoint.y - (selectionView.frame.size.height / 2)) - )) - selectionViewXConstraint.constant = point.x - selectionViewYConstraint.constant = point.y - } - - private func colorAt(position: CGPoint, in size: CGSize) -> Color { - let point = CGPoint(x: (size.width / 2) - position.x, - y: (size.height / 2) - position.y) - let h = 180 + round(atan2(point.y, point.x) * (180 / .pi)) - let handleRange = size.width / 2 - let handleDistance = min(sqrt(point.x * point.x + point.y * point.y), handleRange) - let s = round(100 / handleRange * handleDistance) - return Color(hue: h / 360, saturation: s / 100, brightness: color.brightness, alpha: 1) - } - - private func pointForColor(_ color: Color, in size: CGSize) -> CGPoint { - let handleRange = size.width / 2 - let handleAngle = (color.hue * 360) * (.pi / 180) - let handleDistance = color.saturation * handleRange - return CGPoint(x: (size.width / 2) + handleDistance * cos(handleAngle), - y: (size.height / 2) + handleDistance * sin(handleAngle)) - } - - @objc private func gestureRecognizerFired(_ sender: UIGestureRecognizer) { - switch sender.state { - case .began, .changed, .ended: - var location = sender.location(in: containerView) - location.x -= wheelView.frame.origin.x - location.y -= wheelView.frame.origin.y - color = colorAt(position: location, in: wheelView.frame.size) - delegate?.colorPickerWheelView(didSelectColor: color) - case .possible, .cancelled, .failed: - break - @unknown default: - break - } - - if sender is UITapGestureRecognizer { - return - } - - switch sender.state { - case .began, .ended, .cancelled: - isFingerDown = sender.state == .began - selectionViewFingerDownConstraint.isActive = isFingerDown && !isCatalyst - updateSelectionPoint() - UIView.animate(withDuration: 0.2, animations: { - self.containerView.layoutIfNeeded() - self.updateSelectionPoint() - }, completion: { _ in - self.updateSelectionPoint() - }) - if sender.state == .began { - touchDownFeedbackGenerator.impactOccurred() - } else { - touchUpFeedbackGenerator.impactOccurred() - } - case .possible, .changed, .failed: - break - @unknown default: - break - } - } - -} - -private class ColorPickerWheelInnerView: UIView { - private var brightnessView: UIView! - - var brightness: CGFloat { - get { 1 - brightnessView.alpha } - set { brightnessView.alpha = 1 - newValue } - } - - var handleLayout: (() -> Void)! - - private var saturationMask: GradientView! - - override init(frame: CGRect) { - super.init(frame: frame) - - clipsToBounds = true - - let hueView = GradientView() - hueView.translatesAutoresizingMaskIntoConstraints = false - hueView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - hueView.gradientLayer.type = .conic - hueView.gradientLayer.colors = Color.Component.hue.sliderTintColor(for: Color(red: 1, green: 0, blue: 0, alpha: 1)).map(\.uiColor.cgColor) - hueView.gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5) - hueView.gradientLayer.endPoint = CGPoint(x: 0.5, y: 0) - hueView.gradientLayer.transform = CATransform3DMakeRotation(0.5 * .pi, 0, 0, 1) - addSubview(hueView) - - let saturationView = UIView() - saturationView.translatesAutoresizingMaskIntoConstraints = false - saturationView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - saturationView.backgroundColor = .white - addSubview(saturationView) - - saturationMask = GradientView() - saturationMask.gradientLayer.type = .radial - saturationMask.gradientLayer.colors = [UIColor.white.cgColor, UIColor.clear.cgColor] - saturationMask.gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5) - saturationMask.gradientLayer.endPoint = CGPoint(x: 1, y: 1) - saturationView.mask = saturationMask - - brightnessView = UIView() - brightnessView.translatesAutoresizingMaskIntoConstraints = false - brightnessView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - brightnessView.backgroundColor = .black - addSubview(brightnessView) - } - - convenience init() { - self.init(frame: .zero) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func layoutSubviews() { - super.layoutSubviews() - layer.cornerRadius = frame.size.height / 2 - saturationMask.frame = bounds - handleLayout() - } -} diff --git a/Tweaks/Alderis/Alderis/ColorWell.swift b/Tweaks/Alderis/Alderis/ColorWell.swift deleted file mode 100644 index 196cdac..0000000 --- a/Tweaks/Alderis/Alderis/ColorWell.swift +++ /dev/null @@ -1,403 +0,0 @@ -// -// ColorWell.swift -// Alderis -// -// Created by Adam Demasi on 15/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit -import CoreServices - -/// ColorWell can be used to present the user’s color selection in your user interface. It -/// optionally also supports drag-and-drop operations. -/// -/// By default, drop interactions are supported, which causes a `UIControl.Event.valueChanged` event -/// to be emitted. Optionally, drag operations can be enabled, allowing the color to be dropped -/// elsewhere. -/// -/// You can also use `UIControl.Event.touchUpInside` to perform an action, such as to initialise -/// and present an instance of `ColorPickerViewController`. -@objc(HBColorWell) -open class ColorWell: UIControl { - - /// Set the color to be displayed by the view. - @objc open var color: UIColor? { - get { colorView.backgroundColor } - set { colorView.backgroundColor = newValue } - } - - /// Override the default border color if desired. - @objc open var borderColor: UIColor? { - didSet { updateBorderColor() } - } - - /// Whether the user can begin a drag interaction from this view, allowing them to drop the color - /// into a supporting app. The default is `false`. - @objc open var isDragInteractionEnabled = false { - didSet { updateDragDropInteraction() } - } - - /// Whether the user can end a drag interaction by dropping on this view, allowing them to drag a - /// color from a supporting app onto this view. The default is true. - /// - /// To handle a color being dropped on this view, add an action for the `.valueChanged` event. For - /// example: - /// - /// ```swift - /// colorWell.addTarget(self, action: #selector(self.handleColorDidChange(_:)), for: .valueChanged) - /// ``` - @objc open var isDropInteractionEnabled = true { - didSet { updateDragDropInteraction() } - } - - #if swift(>=5.3) - /// Whether the user can long press (iPhone) or right-click (Mac/iPad) the view, allowing them to - /// copy the color in various formats, or paste a color from another source. - /// - /// To handle a color being pasted via the context menu, add an action for the `.valueChanged` - /// event. For example: - /// - /// ```swift - /// colorWell.addTarget(self, action: #selector(self.handleColorDidChange(_:)), for: .valueChanged) - /// ``` - /// - /// Requires iOS 14 or newer. - @available(iOS 14, *) - open override var isContextMenuInteractionEnabled: Bool { - didSet { updateDragDropInteraction() } - } - #endif - - private var colorView: UIView! - private var dragInteraction: UIDragInteraction! - private var dropInteraction: UIDropInteraction! - private var tapGestureRecognizer: UITapGestureRecognizer! - - private var contextMenuTitle: String { - if let color = color { - return "Color: \(Color(uiColor: color).hexString())" - } - return "No color" - } - - /// :nodoc: - override init(frame: CGRect) { - super.init(frame: frame) - setUp() - } - - /// :nodoc: - required public init?(coder: NSCoder) { - super.init(coder: coder) - setUp() - } - - private func setUp() { - clipsToBounds = true - backgroundColor = Assets.checkerboardPatternColor - borderColor = .white - layer.masksToBounds = false - layer.shadowColor = UIColor.black.cgColor - layer.shadowOffset = .zero - layer.shadowOpacity = 0.75 - layer.shadowRadius = 1 - - colorView = UIView() - colorView.translatesAutoresizingMaskIntoConstraints = false - colorView.clipsToBounds = true - addSubview(colorView) - - dragInteraction = UIDragInteraction(delegate: self) - dragInteraction.isEnabled = true - dropInteraction = UIDropInteraction(delegate: self) - updateDragDropInteraction() - - tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapGestureRecognizerFired(_:))) - tapGestureRecognizer.isEnabled = false - addGestureRecognizer(tapGestureRecognizer) - - #if swift(>=5.3) - if #available(iOS 14, *) { - isContextMenuInteractionEnabled = true - } - #endif - - #if swift(>=5.5) - if #available(iOS 15, *) { - toolTip = contextMenuTitle - toolTipInteraction?.delegate = self - } - #endif - - NSLayoutConstraint.activate([ - self.widthAnchor.constraint(greaterThanOrEqualToConstant: UIFloat(32)), - self.heightAnchor.constraint(equalTo: self.widthAnchor), - - colorView.leadingAnchor.constraint(equalTo: self.leadingAnchor), - colorView.trailingAnchor.constraint(equalTo: self.trailingAnchor), - colorView.topAnchor.constraint(equalTo: self.topAnchor), - colorView.bottomAnchor.constraint(equalTo: self.bottomAnchor), - ]) - } - - private func updateTapGestureRecognizer() { - let hasTouchUpActions = allControlEvents.contains(.touchUpInside) - if hasTouchUpActions { - accessibilityTraits.insert(.button) - } else { - accessibilityTraits.remove(.button) - } - tapGestureRecognizer.isEnabled = hasTouchUpActions - } - - private func updateBorderColor() { - layer.borderColor = borderColor?.cgColor - } - - private func updateDragDropInteraction() { - isUserInteractionEnabled = isDragInteractionEnabled || isDropInteractionEnabled - #if swift(>=5.3) - if #available(iOS 14, *) { - isUserInteractionEnabled = isUserInteractionEnabled || isContextMenuInteractionEnabled - } - #endif - - if isDragInteractionEnabled { - addInteraction(dragInteraction) - } else { - removeInteraction(dragInteraction) - } - - if isDropInteractionEnabled { - addInteraction(dropInteraction) - } else { - removeInteraction(dropInteraction) - } - } - - /// :nodoc: - override open func layoutSubviews() { - super.layoutSubviews() - - layer.cornerRadius = frame.size.width / 2 - layer.shadowPath = CGPath(ellipseIn: bounds, transform: nil) - colorView.layer.cornerRadius = layer.cornerRadius - } - - /// :nodoc: - override open func didMoveToWindow() { - super.didMoveToWindow() - let scale = window?.screen.scale ?? 1 - layer.borderWidth = (scale > 2 ? 2 : 1) / scale - } - - /// :nodoc: - override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - updateBorderColor() - } - - /// :nodoc: - open override func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event) { - super.addTarget(target, action: action, for: controlEvents) - updateTapGestureRecognizer() - } - - /// :nodoc: - @available(iOS 14, macCatalyst 14, *) - open override func addAction(_ action: UIAction, for controlEvents: UIControl.Event) { - super.addAction(action, for: controlEvents) - updateTapGestureRecognizer() - } - - /// :nodoc: - open override func removeTarget(_ target: Any?, action: Selector?, for controlEvents: UIControl.Event) { - super.removeTarget(target, action: action, for: controlEvents) - updateTapGestureRecognizer() - } - - /// :nodoc: - @available(iOS 14, macCatalyst 14, *) - open override func removeAction(_ action: UIAction, for controlEvents: UIControl.Event) { - super.removeAction(action, for: controlEvents) - updateTapGestureRecognizer() - } - - /// :nodoc: - @available(iOS 14, macCatalyst 14, *) - open override func removeAction(identifiedBy actionIdentifier: UIAction.Identifier, for controlEvents: UIControl.Event) { - super.removeAction(identifiedBy: actionIdentifier, for: controlEvents) - updateTapGestureRecognizer() - } - - @objc private func handleTapGestureRecognizerFired(_ sender: UITapGestureRecognizer) { - if sender.state == .ended { - sendActions(for: .touchUpInside) - } - } - -} - -/// :nodoc: -extension ColorWell { // UIResponder - - open override var canBecomeFirstResponder: Bool { true } - - open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { - switch action { - case #selector(copy(_:)), #selector(copyHex), #selector(copyRGB), #selector(copyHSL), - #selector(copyObjC), #selector(copySwift): - return color != nil - - case #selector(paste(_:)): - return UIPasteboard.general.hasColors || UIPasteboard.general.hasStrings - - default: - return super.canPerformAction(action, withSender: sender) - } - } - - open override func copy(_ sender: Any?) { - UIPasteboard.general.color = color - } - - open override func paste(_ sender: Any?) { - if let color = UIPasteboard.general.color ?? UIColor(propertyListValue: UIPasteboard.general.string ?? "") { - self.color = color - sendActions(for: .valueChanged) - } - } - - @objc private func copyHex(_ sender: Any?) { - UIPasteboard.general.string = Color(uiColor: color!).hexString - } - - @objc private func copyRGB(_ sender: Any?) { - UIPasteboard.general.string = Color(uiColor: color!).rgbString - } - - @objc private func copyHSL(_ sender: Any?) { - UIPasteboard.general.string = Color(uiColor: color!).hslString - } - - @objc private func copyObjC(_ sender: Any?) { - UIPasteboard.general.string = Color(uiColor: color!).objcString - } - - @objc private func copySwift(_ sender: Any?) { - UIPasteboard.general.string = Color(uiColor: color!).swiftString - } - -} - -/// :nodoc: -extension ColorWell: UIDragInteractionDelegate { - - /// :nodoc: - public func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] { - guard let color = color else { - return [] - } - let provider = NSItemProvider(object: color) - let item = UIDragItem(itemProvider: provider) - item.localObject = color - return [item] - } - -} - -/// :nodoc: -extension ColorWell: UIDropInteractionDelegate { - - /// :nodoc: - public func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { - return session.items.count == 1 && session.canLoadObjects(ofClass: UIColor.self) - } - - /// :nodoc: - public func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal { - return UIDropProposal(operation: .copy) - } - - /// :nodoc: - public func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { - session.loadObjects(ofClass: UIColor.self) { items in - if let color = items.first as? UIColor { - self.color = color - self.sendActions(for: .valueChanged) - } - } - } - -} - -#if swift(>=5.5) -/// :nodoc: -@available(iOS 15, *) -extension ColorWell: UIToolTipInteractionDelegate { - - /// :nodoc: - public func toolTipInteraction(_ interaction: UIToolTipInteraction, configurationAt point: CGPoint) -> UIToolTipConfiguration? { - UIToolTipConfiguration(toolTip: contextMenuTitle) - } - -} -#endif - -#if swift(>=5.3) -/// :nodoc: -@available(iOS 13, *) -extension ColorWell { // UIContextMenuInteractionDelegate - - /// :nodoc: - open override func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { - return UIContextMenuConfiguration(identifier: color, previewProvider: nil) { items in - var children = [UIMenuElement]() - if isCatalyst { - children += [ - UIMenu(title: "", options: .displayInline, children: [ - UICommand(title: self.contextMenuTitle, - action: #selector(self.doesNotRecognizeSelector(_:)), - attributes: .disabled) - ]) - ] - } - children += items - - var objcImageName = "chevron.left.slash.chevron.right" - var swiftImageName = "chevron.left.slash.chevron.right" - if #available(iOS 14, *) { - objcImageName = "curlybraces" - swiftImageName = "swift" - } - children += [ - UIMenu(title: "", options: .displayInline, children: [ - UICommand(title: "Copy as Hex", - image: UIImage(systemName: "number"), - action: #selector(self.copyHex(_:))), - UICommand(title: "Copy as RGB", - image: UIImage(systemName: "r.circle"), - action: #selector(self.copyRGB(_:))), - UICommand(title: "Copy as HSL", - image: UIImage(systemName: "h.circle"), - action: #selector(self.copyHSL(_:))), - UICommand(title: "Copy as Objective-C", - image: UIImage(systemName: objcImageName), - action: #selector(self.copyObjC(_:))), - UICommand(title: "Copy as Swift", - image: UIImage(systemName: swiftImageName), - action: #selector(self.copySwift(_:))), - ]) - ] - return UIMenu(title: self.contextMenuTitle, children: children) - } - } - -} -#endif - -/// Deprecated. Use `ColorWell` instead. -@available(*, deprecated, renamed: "ColorWell") -@objc(HBColorPickerCircleView) -open class ColorPickerCircleView: ColorWell {} diff --git a/Tweaks/Alderis/Alderis/DialogButton.swift b/Tweaks/Alderis/Alderis/DialogButton.swift deleted file mode 100644 index 98d5ba3..0000000 --- a/Tweaks/Alderis/Alderis/DialogButton.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// DialogButton.swift -// Alderis -// -// Created by Adam Demasi on 28/9/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class DialogButton: UIButton { - - var highlightBackgroundColor: UIColor? - - init() { - super.init(frame: .zero) - - addTarget(self, action: #selector(self.handleTouchDown), for: [.touchDown, .touchDragEnter]) - addTarget(self, action: #selector(self.handleTouchUp), for: [.touchUpInside, .touchUpOutside, .touchDragExit, .touchCancel]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc private func handleTouchDown() { - backgroundColor = highlightBackgroundColor - } - - @objc private func handleTouchUp() { - backgroundColor = nil - } - -} diff --git a/Tweaks/Alderis/Alderis/GradientView.swift b/Tweaks/Alderis/Alderis/GradientView.swift deleted file mode 100644 index 532112f..0000000 --- a/Tweaks/Alderis/Alderis/GradientView.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// GradientView.swift -// Alderis -// -// Created by Adam Demasi on 11/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class GradientView: UIView { - - override class var layerClass: AnyClass { CAGradientLayer.self } - - // swiftlint:disable:next force_cast - var gradientLayer: CAGradientLayer { layer as! CAGradientLayer } - -} diff --git a/Tweaks/Alderis/Alderis/Info.plist b/Tweaks/Alderis/Alderis/Info.plist deleted file mode 100644 index c0701c6..0000000 --- a/Tweaks/Alderis/Alderis/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - - diff --git a/Tweaks/Alderis/Alderis/NSBeep.swift b/Tweaks/Alderis/Alderis/NSBeep.swift deleted file mode 100644 index 6cf7a43..0000000 --- a/Tweaks/Alderis/Alderis/NSBeep.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// NSBeep.swift -// Alderis -// -// Created by Adam Demasi on 8/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal typealias NSBeepType = @convention(c) () -> Void - -internal let NSBeep: NSBeepType? = { - if isCatalyst, - let appkit = dlopen("/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit", RTLD_LAZY), - let beep = dlsym(appkit, "NSBeep") { - return unsafeBitCast(beep, to: NSBeepType.self) - } - return nil -}() - -internal func beep() { - if isCatalyst { - NSBeep?() - } else { - let feedbackGenerator = UINotificationFeedbackGenerator() - feedbackGenerator.notificationOccurred(.error) - } -} diff --git a/Tweaks/Alderis/Alderis/SeparatorView.swift b/Tweaks/Alderis/Alderis/SeparatorView.swift deleted file mode 100644 index d279a7d..0000000 --- a/Tweaks/Alderis/Alderis/SeparatorView.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// SeparatorView.swift -// Alderis -// -// Created by Adam Demasi on 12/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal class SeparatorView: UIView { - - enum Direction { - case horizontal, vertical - } - - var direction: Direction { - didSet { updateConstraints() } - } - - private var widthConstraint: NSLayoutConstraint! - private var heightConstraint: NSLayoutConstraint! - - init(direction: Direction) { - self.direction = direction - super.init(frame: .zero) - - backgroundColor = Assets.separatorColor - - widthConstraint = widthAnchor.constraint(equalToConstant: 1) - heightConstraint = heightAnchor.constraint(equalToConstant: 1) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func updateConstraints() { - super.updateConstraints() - - let constant = 1 / (window?.screen.scale ?? 1) - - switch direction { - case .horizontal: - widthConstraint.isActive = false - heightConstraint.isActive = true - heightConstraint.constant = constant - case .vertical: - widthConstraint.isActive = true - heightConstraint.isActive = false - widthConstraint.constant = constant - } - } - - override func didMoveToWindow() { - super.didMoveToWindow() - updateConstraints() - } - -} diff --git a/Tweaks/Alderis/Alderis/TextViewLabel.swift b/Tweaks/Alderis/Alderis/TextViewLabel.swift deleted file mode 100644 index aa539dd..0000000 --- a/Tweaks/Alderis/Alderis/TextViewLabel.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// TextViewLabel.swift -// Alderis -// -// Created by Adam Demasi on 8/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit -import SafariServices - -internal class TextViewLabel: UITextView { - - override init(frame: CGRect, textContainer: NSTextContainer?) { - super.init(frame: frame, textContainer: textContainer) - - delegate = self - backgroundColor = nil - textContainerInset = .zero - self.textContainer.lineFragmentPadding = 0 - isEditable = false - isScrollEnabled = false - adjustsFontForContentSizeCategory = true - } - - convenience init() { - self.init(frame: .zero, textContainer: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - // 🧡 to https://stackoverflow.com/a/44878203/709376 for this - guard super.point(inside: point, with: event), - let position = closestPosition(to: point), - let range = tokenizer.rangeEnclosingPosition(position, - with: .character, - inDirection: .layout(.left)) else { - return false - } - let index = offset(from: beginningOfDocument, to: range.start) - return attributedText.attribute(.link, at: index, effectiveRange: nil) != nil - } - - override var selectedRange: NSRange { - get { NSRange() } - set {} - } - - private var viewController: UIViewController? { - var responder: UIResponder? = self - while responder != nil { - if let viewController = responder as? UIViewController { - return viewController - } - responder = responder?.next - } - return nil - } - -} - -extension TextViewLabel: UITextViewDelegate { - - func textView(_ textView: UITextView, shouldInteractWith url: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { - #if targetEnvironment(macCatalyst) - // No need to do anything custom. - return true - #else - switch interaction { - case .invokeDefaultAction: - let safariViewController = SFSafariViewController(url: url) - safariViewController.modalPresentationStyle = .formSheet - viewController?.present(safariViewController, animated: true) - return false - case .presentActions, .preview: - return true - @unknown default: - return true - } - #endif - } - -} diff --git a/Tweaks/Alderis/Alderis/UIColorAdditions.swift b/Tweaks/Alderis/Alderis/UIColorAdditions.swift deleted file mode 100644 index aa9aacd..0000000 --- a/Tweaks/Alderis/Alderis/UIColorAdditions.swift +++ /dev/null @@ -1,199 +0,0 @@ -// -// UIColorAdditions.swift -// Alderis -// -// Created by Ryan Nair on 10/5/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -/// ColorPropertyListValue is a protocol representing types that can be passed to the\ -/// `UIColor.init(propertyListValue:)` initialiser. `String` and `Array` both conform to this type. -/// -/// - see: `UIColor.init(propertyListValue:)` -public protocol ColorPropertyListValue {} - -/// A string can represent a `ColorPropertyListValue`. -/// -/// - see: `UIColor.init(propertyListValue:)` -extension String: ColorPropertyListValue {} - -/// An array of integers can represent a `ColorPropertyListValue`. -/// -/// - see: `UIColor.init(propertyListValue:)` -extension Array: ColorPropertyListValue where Element: FixedWidthInteger {} - -/// Alderis provides extensions to `UIColor` for the purpose of serializing and deserializing colors -/// into representations that can be stored in property lists, JSON, and similar formats. -public extension UIColor { - - /// Initializes and returns a color object using data from the specified object. - /// - /// The value is expected to be one of: - /// - /// * An array of 3 or 4 integer RGB or RGBA color components, with values between 0 and 255 (e.g. - /// `[218, 192, 222]`) - /// * A CSS-style hex string, with an optional alpha component (e.g. `#DAC0DE` or `#DACODE55`) - /// * A short CSS-style hex string, with an optional alpha component (e.g. `#DC0` or `#DC05`) - /// - /// Use `-[UIColor initWithHbcp_propertyListValue:]` to access this method from Objective-C. - /// - /// - parameter value: The object to retrieve data from. See the discussion for the supported object - /// types. - /// - returns: An initialized color object, or nil if the value does not conform to the expected - /// type. The color information represented by this object is in the device RGB colorspace. - /// - see: `propertyListValue` - @nonobjc convenience init?(propertyListValue: ColorPropertyListValue?) { - if let array = propertyListValue as? [Int], array.count == 3 || array.count == 4 { - let floats = array.map(CGFloat.init(_:)) - self.init(red: floats[0] / 255, - green: floats[1] / 255, - blue: floats[2] / 255, - alpha: array.count == 4 ? floats[3] : 1) - return - } else if var string = propertyListValue as? String { - if string.count == 4 || string.count == 5 { - let r = String(repeating: string[string.index(string.startIndex, offsetBy: 1)], count: 2) - let g = String(repeating: string[string.index(string.startIndex, offsetBy: 2)], count: 2) - let b = String(repeating: string[string.index(string.startIndex, offsetBy: 3)], count: 2) - let a = string.count == 5 ? String(repeating: string[string.index(string.startIndex, offsetBy: 4)], count: 2) : "FF" - string = r + g + b + a - } - - var hex: UInt64 = 0 - let scanner = Scanner(string: string) - guard scanner.scanString("#", into: nil), - scanner.scanHexInt64(&hex) else { - return nil - } - - if string.count == 9 { - self.init(red: CGFloat((hex & 0xFF000000) >> 24) / 255, - green: CGFloat((hex & 0x00FF0000) >> 16) / 255, - blue: CGFloat((hex & 0x0000FF00) >> 8) / 255, - alpha: CGFloat((hex & 0x000000FF) >> 0) / 255) - return - } else { - var alpha: Float = 1 - if scanner.scanString(":", into: nil) { - // Continue scanning to get the alpha component. - scanner.scanFloat(&alpha) - } - - self.init(red: CGFloat((hex & 0xFF0000) >> 16) / 255, - green: CGFloat((hex & 0x00FF00) >> 8) / 255, - blue: CGFloat((hex & 0x0000FF) >> 0) / 255, - alpha: CGFloat(alpha)) - return - } - } - - return nil - } - - /// Maps `init(propertyListValue:)` to Objective-C due to Swift limitations. This is an - /// implementation detail. Ignore this and use `UIColor(propertyListValue:)` or - /// `-[UIColor initWithHbcp_propertyListValue:]` as per usual. - /// - /// - parameter value: The object to retrieve data from. See the discussion for the supported - /// object types. - /// - returns: An initialized color object, or nil if the value does not conform to the expected - /// type. The color information represented by this object is in the device RGB colorspace. - /// device RGB colorspace. - /// - see: `init(propertyListValue:)` - @objc(initWithHbcp_propertyListValue:) - convenience init?(_propertyListValueObjC propertyListValue: Any?) { - if let value = propertyListValue as? String { - self.init(propertyListValue: value) - } else if let value = propertyListValue as? [Int] { - self.init(propertyListValue: value) - } else { - return nil - } - } - - /// Returns a string that represents the color. - /// - /// The output is a string in the format `#AABBCC:0.5`, where the initial `#AABBCC` portion is a - /// 6-character CSS-style hex string, and the final `:0.5` portion represents the alpha value. If - /// the color’s alpha value is `1`, the alpha portion is excluded. - /// - /// If the color is dynamic, for instance if it is a UIKit system color, or initialised via - /// `UIColor(dynamicProvider:)`, the color that matches the current trait collection is used. - /// - /// - returns: A string representing the color, in the format discussed above. - /// - see: `init(propertyListValue:)` - @objc(hbcp_propertyListValue) - var propertyListValue: String { - var alpha: CGFloat = 0 - getRed(nil, green: nil, blue: nil, alpha: &alpha) - - let color = Color(uiColor: self.withAlphaComponent(1)) - let hexString = color.hexString() - let alphaString = alpha == 1 ? "" : String(format: ":%.5G", alpha) - return "\(hexString)\(alphaString)" - } - - /// Returns a hexadecimal string that represents the color. - /// - /// The output is a string in the format `#AABBCCDD`, where the initial `#AABBCC` portion is a - /// 6-character CSS-style hex string, and the final `DD` portion is the hexadecimal representation - /// of the alpha value, supported by [recent web browsers](https://caniuse.com/css-rrggbbaa). - /// - /// If the color is dynamic, for instance if it is a UIKit system color, or initialised via - /// `UIColor(dynamicProvider:)`, the color that matches the current trait collection is used. - /// - /// - returns: A string representing the color, in the format discussed above. - @objc(hbcp_hexString) - var hexString: String { Color(uiColor: self).hexString } - - /// Returns an RGB string that represents the color. - /// - /// The output is a string in the format of `rgba(170, 187, 204, 0.5)`, or `rgb(170, 187, 204)` if - /// the color’s alpha value is `1`. - /// - /// If the color is dynamic, for instance if it is a UIKit system color, or initialised via - /// `UIColor(dynamicProvider:)`, the color that matches the current trait collection is used. - /// - /// - returns: A string representing the color, in the format discussed above. - @objc(hbcp_rgbString) - var rgbString: String { Color(uiColor: self).rgbString } - - /// Returns an HSL string that represents the color. - /// - /// The output is a string in the format of `hsla(170, 187, 204, 0.5)`, or `hsl(170, 187, 204)` if - /// the color’s alpha value is `1`. - /// - /// If the color is dynamic, for instance if it is a UIKit system color, or initialised via - /// `UIColor(dynamicProvider:)`, the color that matches the current trait collection is used. - /// - /// - returns: A string representing the color, in the format discussed above. - @objc(hbcp_hslString) - var hslString: String { Color(uiColor: self).hslString } - - /// Returns an Objective-C UIColor string that represents the color. - /// - /// The output is a string in the format of - /// `[UIColor colorWithRed:0.667 green:0.733 blue:0.800 alpha:1.00]`. - /// - /// If the color is dynamic, for instance if it is a UIKit system color, or initialised via - /// `UIColor(dynamicProvider:)`, the color that matches the current trait collection is used. - /// - /// - returns: A string representing the color, in the format discussed above. - @objc(hbcp_objcString) - var objcString: String { Color(uiColor: self).objcString } - - /// Returns a Swift UIColor string that represents the color. - /// - /// The output is a string in the format of - /// `UIColor(red: 0.667, green: 0.733, blue: 0.800, alpha: 1.00)`. - /// - /// If the color is dynamic, for instance if it is a UIKit system color, or initialised via - /// `UIColor(dynamicProvider:)`, the color that matches the current trait collection is used. - /// - /// - returns: A string representing the color, in the format discussed above. - @objc(hbcp_swiftString) - var swiftString: String { Color(uiColor: self).swiftString } - -} diff --git a/Tweaks/Alderis/Alderis/UIFloat.swift b/Tweaks/Alderis/Alderis/UIFloat.swift deleted file mode 100644 index c2c379a..0000000 --- a/Tweaks/Alderis/Alderis/UIFloat.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// UIFloat.swift -// Alderis -// -// Created by Adam Demasi on 8/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal let isCatalyst: Bool = { - if #available(iOS 13, *) { - return ProcessInfo.processInfo.isMacCatalystApp - } - return false -}() - -// Catalyst iPad mode, with iOS UI at 0.77 scale -internal let isCatalystPad = isCatalyst && UIDevice.current.userInterfaceIdiom == .pad - -// Catalyst Mac mode, with Mac UI at 1.00 scale -internal let isCatalystMac: Bool = { - #if swift(>=5.3) - if #available(iOS 14, *) { - return UIDevice.current.userInterfaceIdiom == .mac - } - #endif - return false -}() - -// Inspired by https://www.highcaffeinecontent.com/blog/20220216-Where-Mac-Catalyst-Falls-Short -internal func UIFloat(_ value: CGFloat) -> CGFloat { - return floor(value * (isCatalystMac ? 0.77 : 1)) -} diff --git a/Tweaks/Alderis/Alderis/UIFontDescriptorAdditions.swift b/Tweaks/Alderis/Alderis/UIFontDescriptorAdditions.swift deleted file mode 100644 index 416b31a..0000000 --- a/Tweaks/Alderis/Alderis/UIFontDescriptorAdditions.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// UIFontDescriptorAdditions.swift -// Alderis -// -// Created by Adam Demasi on 7/5/2022. -// Copyright © 2022 HASHBANG Productions. All rights reserved. -// - -import UIKit - -internal extension UIFontDescriptor.FeatureKey { - - // Abstracts a messy API change made in iOS 15. - static var alderisFeature: Self { - #if swift(>=5.5) - if #available(iOS 15, *) { - return .type - } - #endif - return .featureIdentifier - } - - static var alderisSelector: Self { - #if swift(>=5.5) - if #available(iOS 15, *) { - return .selector - } - #endif - return .typeIdentifier - } - -} diff --git a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.pbxproj b/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.pbxproj deleted file mode 100644 index dc379f3..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,444 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 129B4F59BA5C9D60F07CE7E0 /* libPods-Alderis Demo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ABFF0FA1430DE1F1C311810B /* libPods-Alderis Demo.a */; }; - CF39D44B222BC07E001EF57F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CF39D44A222BC07E001EF57F /* Assets.xcassets */; }; - CF6B3B9E2446A13C000A608B /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF6B3B9D2446A13C000A608B /* FirstViewController.swift */; }; - CF83082423F7819A00157D3F /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CF83082323F7819A00157D3F /* Launch Screen.storyboard */; }; - CFE70278241A593200083903 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE70277241A593200083903 /* AppDelegate.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - CF73D33E241F9C23000B1B10 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 2B5DB4BF0F331C22D5DFB481 /* Pods-Alderis Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Alderis Demo.release.xcconfig"; path = "Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.release.xcconfig"; sourceTree = ""; }; - 9FD89BFF752E9D684C11E887 /* Pods-Alderis Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Alderis Demo.debug.xcconfig"; path = "Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.debug.xcconfig"; sourceTree = ""; }; - ABFF0FA1430DE1F1C311810B /* libPods-Alderis Demo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Alderis Demo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - CF39D43E222BC07C001EF57F /* Alderis Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Alderis Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - CF39D44A222BC07E001EF57F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - CF39D44F222BC07E001EF57F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CF6B3B9D2446A13C000A608B /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = ""; }; - CF83082323F7819A00157D3F /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; - CFCF774D242113EE00379864 /* AlderisDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AlderisDemo.entitlements; sourceTree = ""; }; - CFE70277241A593200083903 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - CF39D43B222BC07C001EF57F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 129B4F59BA5C9D60F07CE7E0 /* libPods-Alderis Demo.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 13755DEE92D2481708433C7E /* Frameworks */ = { - isa = PBXGroup; - children = ( - ABFF0FA1430DE1F1C311810B /* libPods-Alderis Demo.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - AB49FDA0EE3B301C0383D6FF /* Pods */ = { - isa = PBXGroup; - children = ( - 9FD89BFF752E9D684C11E887 /* Pods-Alderis Demo.debug.xcconfig */, - 2B5DB4BF0F331C22D5DFB481 /* Pods-Alderis Demo.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - CF39D435222BC07C001EF57F = { - isa = PBXGroup; - children = ( - CF39D440222BC07C001EF57F /* Alderis Demo */, - CF39D43F222BC07C001EF57F /* Products */, - AB49FDA0EE3B301C0383D6FF /* Pods */, - 13755DEE92D2481708433C7E /* Frameworks */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - usesTabs = 1; - }; - CF39D43F222BC07C001EF57F /* Products */ = { - isa = PBXGroup; - children = ( - CF39D43E222BC07C001EF57F /* Alderis Demo.app */, - ); - name = Products; - sourceTree = ""; - }; - CF39D440222BC07C001EF57F /* Alderis Demo */ = { - isa = PBXGroup; - children = ( - CFCF774D242113EE00379864 /* AlderisDemo.entitlements */, - CF83082323F7819A00157D3F /* Launch Screen.storyboard */, - CFE70277241A593200083903 /* AppDelegate.swift */, - CF6B3B9D2446A13C000A608B /* FirstViewController.swift */, - CF39D44A222BC07E001EF57F /* Assets.xcassets */, - CF39D44F222BC07E001EF57F /* Info.plist */, - ); - path = "Alderis Demo"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - CF39D43D222BC07C001EF57F /* Alderis Demo */ = { - isa = PBXNativeTarget; - buildConfigurationList = CF39D454222BC07E001EF57F /* Build configuration list for PBXNativeTarget "Alderis Demo" */; - buildPhases = ( - B02FB21B4CF370106F8C5ADD /* [CP] Check Pods Manifest.lock */, - CF39D43A222BC07C001EF57F /* Sources */, - CF39D43B222BC07C001EF57F /* Frameworks */, - CF39D43C222BC07C001EF57F /* Resources */, - CF73D33E241F9C23000B1B10 /* Embed Frameworks */, - CF79DA2F25171E2D00F17BCB /* SwiftLint */, - 638C9DB382A92024C20F1301 /* [CP] Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Alderis Demo"; - productName = "Alderis Demo"; - productReference = CF39D43E222BC07C001EF57F /* Alderis Demo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - CF39D436222BC07C001EF57F /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1330; - ORGANIZATIONNAME = "HASHBANG Productions"; - TargetAttributes = { - CF39D43D222BC07C001EF57F = { - CreatedOnToolsVersion = 10.0; - LastSwiftMigration = 1130; - }; - }; - }; - buildConfigurationList = CF39D439222BC07C001EF57F /* Build configuration list for PBXProject "Alderis Demo" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = CF39D435222BC07C001EF57F; - productRefGroup = CF39D43F222BC07C001EF57F /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - CF39D43D222BC07C001EF57F /* Alderis Demo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - CF39D43C222BC07C001EF57F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CF83082423F7819A00157D3F /* Launch Screen.storyboard in Resources */, - CF39D44B222BC07E001EF57F /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 638C9DB382A92024C20F1301 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - B02FB21B4CF370106F8C5ADD /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Alderis Demo-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - CF79DA2F25171E2D00F17BCB /* SwiftLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = SwiftLint; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n\tswiftlint\nelse\n\techo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - CF39D43A222BC07C001EF57F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CFE70278241A593200083903 /* AppDelegate.swift in Sources */, - CF6B3B9E2446A13C000A608B /* FirstViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - CF39D452222BC07E001EF57F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - CF39D453222BC07E001EF57F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - CF39D455222BC07E001EF57F /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9FD89BFF752E9D684C11E887 /* Pods-Alderis Demo.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; - ASSETCATALOG_COMPILER_SKIP_APP_STORE_DEPLOYMENT = YES; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = "Alderis Demo/AlderisDemo.entitlements"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES; - DEVELOPMENT_TEAM = N2LN9ZT493; - INFOPLIST_FILE = "Alderis Demo/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = ws.hbang.AlderisDemo; - PRODUCT_NAME = "Alderis Demo"; - SUPPORTS_MACCATALYST = YES; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,6"; - }; - name = Debug; - }; - CF39D456222BC07E001EF57F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2B5DB4BF0F331C22D5DFB481 /* Pods-Alderis Demo.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; - ASSETCATALOG_COMPILER_SKIP_APP_STORE_DEPLOYMENT = YES; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = "Alderis Demo/AlderisDemo.entitlements"; - CODE_SIGN_STYLE = Automatic; - DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES; - INFOPLIST_FILE = "Alderis Demo/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = ws.hbang.AlderisDemo; - PRODUCT_NAME = "Alderis Demo"; - SUPPORTS_MACCATALYST = YES; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,6"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - CF39D439222BC07C001EF57F /* Build configuration list for PBXProject "Alderis Demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF39D452222BC07E001EF57F /* Debug */, - CF39D453222BC07E001EF57F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CF39D454222BC07E001EF57F /* Build configuration list for PBXNativeTarget "Alderis Demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF39D455222BC07E001EF57F /* Debug */, - CF39D456222BC07E001EF57F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = CF39D436222BC07C001EF57F /* Project object */; -} diff --git a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index e210b76..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/xcshareddata/xcschemes/Alderis Demo.xcscheme b/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/xcshareddata/xcschemes/Alderis Demo.xcscheme deleted file mode 100644 index 24f8b16..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo.xcodeproj/xcshareddata/xcschemes/Alderis Demo.xcscheme +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo.xcworkspace/contents.xcworkspacedata b/Tweaks/Alderis/Demo/Alderis Demo.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 870adfc..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tweaks/Alderis/Demo/Alderis Demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo/AlderisDemo.entitlements b/Tweaks/Alderis/Demo/Alderis Demo/AlderisDemo.entitlements deleted file mode 100644 index ee95ab7..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/AlderisDemo.entitlements +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.network.client - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo/AppDelegate.swift b/Tweaks/Alderis/Demo/Alderis Demo/AppDelegate.swift deleted file mode 100644 index cbd357f..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/AppDelegate.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// AppDelegate.swift -// Alderis Demo -// -// Created by Adam Demasi on 12/3/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - // swiftlint:disable:next line_length - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { - window = UIWindow(frame: UIScreen.main.bounds) - window!.tintColor = UIColor(hue: 0.939614, saturation: 0.811765, brightness: 0.333333, alpha: 1) - - let tabBarController = UITabBarController() - let viewController = UINavigationController(rootViewController: FirstViewController()) - if #available(iOS 13, *) { - let tabIcon = UIImage(systemName: "paintbrush.fill")?.withBaselineOffset(fromBottom: 2) - viewController.tabBarItem = UITabBarItem(title: "Alderis Demo", image: tabIcon, tag: 0) - } - tabBarController.viewControllers = [viewController] - - window!.rootViewController = tabBarController - window!.makeKeyAndVisible() - - return true - } - -} diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon120x120.png b/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon120x120.png deleted file mode 100644 index f27b7ab..0000000 Binary files a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon120x120.png and /dev/null differ diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon152x152.png b/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon152x152.png deleted file mode 100644 index 25d48de..0000000 Binary files a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon152x152.png and /dev/null differ diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon167x167.png b/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon167x167.png deleted file mode 100644 index 3d96ee3..0000000 Binary files a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon167x167.png and /dev/null differ diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon180x180.png b/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon180x180.png deleted file mode 100644 index 031e9f8..0000000 Binary files a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/AppIcon180x180.png and /dev/null differ diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 352a52d..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "AppIcon120x120.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "AppIcon180x180.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "AppIcon152x152.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "AppIcon167x167.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/Contents.json b/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Base.lproj/LaunchScreen.storyboard b/Tweaks/Alderis/Demo/Alderis Demo/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index bfa3612..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo/FirstViewController.swift b/Tweaks/Alderis/Demo/Alderis Demo/FirstViewController.swift deleted file mode 100644 index 3018f73..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/FirstViewController.swift +++ /dev/null @@ -1,321 +0,0 @@ -// -// FirstViewController.swift -// Alderis Demo -// -// Created by Adam Demasi on 15/4/20. -// Copyright © 2020 HASHBANG Productions. All rights reserved. -// - -import UIKit -import Alderis - -class FirstViewController: UIViewController { - - private var color = UIColor(hue: 0.939614, saturation: 0.811765, brightness: 0.333333, alpha: 1) - - private var colorWell: ColorWell! - private var uikitWell: UIView? - - // swiftlint:disable:next function_body_length - override func viewDidLoad() { - super.viewDidLoad() - - title = "Alderis Demo" - if #available(iOS 13, *) { - view.backgroundColor = .systemBackground - } else { - view.backgroundColor = .white - } - - #if targetEnvironment(macCatalyst) - navigationController?.isNavigationBarHidden = true - #endif - - let stackView = UIStackView() - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.axis = .vertical - stackView.alignment = .center - stackView.spacing = 10 - view.addSubview(stackView) - - let mainButton = UIButton(type: .system) - if #available(iOS 15, *) { - var config = UIButton.Configuration.filled() - config.buttonSize = .large - mainButton.configuration = config - } else { - mainButton.titleLabel!.font = UIFont.systemFont(ofSize: 34, weight: .semibold) - } - mainButton.setTitle("Present", for: .normal) - mainButton.addTarget(self, action: #selector(self.presentColorPicker), for: .touchUpInside) - stackView.addArrangedSubview(mainButton) - - // swiftlint:disable comma - let buttons: [(title: String, action: Selector)] = [ - ("Present with customised title", #selector(presentColorPickerCustomisedTitle)), - ("Present with customised initial tab", #selector(presentColorPickerCustomisedInitialTab)), - ("Present with customised tabs", #selector(presentColorPickerCustomisedTabs)), - ("Present with tabs hidden", #selector(presentColorPickerNoTabs)), - ("Present with customised title, tabs hidden", #selector(presentColorPickerCustomisedTitleNoTabs)), - ("Present without alpha", #selector(presentColorPickerNoAlpha)), - ("Present without overriding Smart Invert", #selector(presentColorPickerNoOverrideSmartInvert)), - ("Present using deprecated API", #selector(presentColorPickerDeprecatedAPI)), - ("Present UIKit Color Picker", #selector(presentUIKitColorPicker)) - ] - // swiftlint:enable comma - - for item in buttons { - let button = UIButton(type: .system) - if #available(iOS 15, *) { - var config = UIButton.Configuration.plain() - config.buttonSize = .mini - config.macIdiomStyle = .borderlessTinted - button.configuration = config - } - button.setTitle(item.title, for: .normal) - button.addTarget(self, action: item.action, for: .touchUpInside) - stackView.addArrangedSubview(button) - } - - let spacerView = UIView() - stackView.addArrangedSubview(spacerView) - - let wellsLabel = UILabel() - wellsLabel.font = UIFont.preferredFont(forTextStyle: .headline) - wellsLabel.textAlignment = .center - wellsLabel.text = "Color wells (try out drag and drop!)" - stackView.addArrangedSubview(wellsLabel) - - colorWell = ColorWell() - colorWell.isDragInteractionEnabled = true - colorWell.isDropInteractionEnabled = true - colorWell.addTarget(self, action: #selector(self.colorWellValueChanged(_:)), for: .valueChanged) - colorWell.addTarget(self, action: #selector(self.presentColorPicker), for: .touchUpInside) - - let dragOrDropColorWell = ColorWell() - dragOrDropColorWell.isDragInteractionEnabled = true - dragOrDropColorWell.isDropInteractionEnabled = true - dragOrDropColorWell.color = .systemPurple - - let nonDraggableWell = ColorWell() - nonDraggableWell.isDragInteractionEnabled = false - nonDraggableWell.isDropInteractionEnabled = true - nonDraggableWell.color = .systemOrange - - let nonDroppableWell = ColorWell() - nonDroppableWell.isDragInteractionEnabled = true - nonDroppableWell.isDropInteractionEnabled = false - nonDroppableWell.color = .systemTeal - - let nonDragOrDropWell = ColorWell() - nonDragOrDropWell.isDragInteractionEnabled = false - nonDragOrDropWell.isDropInteractionEnabled = false - nonDragOrDropWell.color = .systemGreen - - let wellsStackView = UIStackView(arrangedSubviews: [colorWell, - dragOrDropColorWell, - nonDraggableWell, - nonDroppableWell, - nonDragOrDropWell]) - wellsStackView.translatesAutoresizingMaskIntoConstraints = false - wellsStackView.axis = .horizontal - wellsStackView.alignment = .center - wellsStackView.spacing = 10 - - if #available(iOS 14, *) { - let uikitWell = UIColorWell() - uikitWell.addTarget(self, action: #selector(self.uikitColorWellValueChanged(_:)), for: .valueChanged) - wellsStackView.addArrangedSubview(uikitWell) - self.uikitWell = uikitWell - } - - stackView.addArrangedSubview(wellsStackView) - - NSLayoutConstraint.activate([ - stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15), - stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15), - stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor), - - spacerView.heightAnchor.constraint(equalToConstant: 0) - ]) - - var isMac = false - if #available(iOS 14, *) { - isMac = UIDevice.current.userInterfaceIdiom == .mac - } - - NSLayoutConstraint.activate(wellsStackView.arrangedSubviews.flatMap { view in - [ - view.widthAnchor.constraint(equalToConstant: isMac ? 24 : 32), - view.heightAnchor.constraint(equalTo: view.widthAnchor) - ] - }) - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - view.window!.tintColor = color - colorWell.color = color - if #available(iOS 14, *), - let uikitWell = uikitWell as? UIColorWell { - uikitWell.selectedColor = color - } - } - - @objc func colorWellValueChanged(_ sender: ColorWell) { - NSLog("Color well value changed with value %@", String(describing: sender.color)) - view.window!.tintColor = sender.color - if #available(iOS 14, *), - let uikitWell = uikitWell as? UIColorWell { - uikitWell.selectedColor = sender.color - } - } - - @available(iOS 14, *) - @objc func uikitColorWellValueChanged(_ sender: UIColorWell) { - NSLog("UIKit color well value changed with value %@", String(describing: sender.selectedColor)) - view.window!.tintColor = sender.selectedColor - colorWell.color = sender.selectedColor - } - - @objc func presentColorPicker(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerCustomisedTitle(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - configuration.title = "Select an Awesome Color" - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerCustomisedInitialTab(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - configuration.initialTab = .map - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerCustomisedTabs(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - configuration.visibleTabs = [.map, .sliders] - configuration.initialTab = .sliders - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerNoAlpha(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color.withAlphaComponent(0.5)) - configuration.supportsAlpha = false - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerNoTabs(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - configuration.showTabs = false - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerCustomisedTitleNoTabs(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - configuration.title = "Select an Awesome Color" - configuration.showTabs = false - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerNoOverrideSmartInvert(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: color) - configuration.overrideSmartInvert = false - - let colorPickerViewController = ColorPickerViewController(configuration: configuration) - colorPickerViewController.delegate = self - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentColorPickerDeprecatedAPI(_ sender: UIView) { - let colorPickerViewController = ColorPickerViewController() - colorPickerViewController.delegate = self - colorPickerViewController.color = color - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } - - @objc func presentUIKitColorPicker(_ sender: UIView) { - if #available(iOS 14, *) { - let colorPickerViewController = UIColorPickerViewController() - colorPickerViewController.delegate = self - colorPickerViewController.selectedColor = color - colorPickerViewController.popoverPresentationController?.sourceView = sender - tabBarController!.present(colorPickerViewController, animated: true) - } else { - fatalError("UIColorPickerViewController is only available as of iOS 14") - } - } - -} - -extension FirstViewController: ColorPickerDelegate { - - func colorPicker(_ colorPicker: ColorPickerViewController, didSelect color: UIColor) { - NSLog("User selected color %@ (%@)", color.propertyListValue, String(describing: color)) - self.color = color - view.window!.tintColor = color - colorWell.color = color - } - - func colorPicker(_ colorPicker: ColorPickerViewController, didAccept color: UIColor) { - NSLog("User accepted color %@ (%@)", color.propertyListValue, String(describing: color)) - } - - func colorPickerDidCancel(_ colorPicker: ColorPickerViewController) { - NSLog("Color picker cancelled") - } - -} - -@available(iOS 14, *) -extension FirstViewController: UIColorPickerViewControllerDelegate { - - func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) { - NSLog("UIKit color picker value changed with color %@ (%@)", - viewController.selectedColor.propertyListValue, - String(describing: viewController.selectedColor)) - color = viewController.selectedColor - view.window!.tintColor = viewController.selectedColor - if let uikitWell = uikitWell as? UIColorWell { - uikitWell.selectedColor = viewController.selectedColor - } - } - - func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) { - NSLog("UIKit color picker finished") - } - -} diff --git a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSectionHeaderView.h b/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSectionHeaderView.h deleted file mode 100644 index 33d3631..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSectionHeaderView.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// HBColorPickerSectionHeaderView.h -// Alderis Demo -// -// Created by Adam Demasi on 31/3/19. -// Copyright © 2019 HASHBANG Productions. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface HBColorPickerSectionHeaderView : UICollectionReusableView - -@property (nonatomic, strong) UILabel *titleLabel; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSectionHeaderView.m b/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSectionHeaderView.m deleted file mode 100644 index 5bc241b..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSectionHeaderView.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// HBColorPickerSectionHeaderView.m -// Alderis Demo -// -// Created by Adam Demasi on 31/3/19. -// Copyright © 2019 HASHBANG Productions. All rights reserved. -// - -#import "HBColorPickerSectionHeaderView.h" -#import "CompactConstraint.h" - -@implementation HBColorPickerSectionHeaderView - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - - if (self) { - _titleLabel = [[UILabel alloc] init]; - _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; - _titleLabel.font = [UIFont boldSystemFontOfSize:18.f]; - [self addSubview:_titleLabel]; - - [self hb_addCompactConstraints:@[ - @"titleLabel.left = self.left + horizontalMargin", - @"titleLabel.right = self.right - horizontalMargin", - @"titleLabel.top = self.top + topMargin", - @"titleLabel.bottom = self.bottom - bottomMargin" - ] - metrics:@{ - @"horizontalMargin": @15.f, - @"topMargin": @10.f, - @"bottomMargin": @0.f - } - views:@{ - @"self": self, - @"titleLabel": _titleLabel - }]; - } - - return self; -} - -@end diff --git a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSwatchCell.h b/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSwatchCell.h deleted file mode 100644 index 6cb6071..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSwatchCell.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// HBColorPickerSwatchCell.h -// Alderis Demo -// -// Created by Adam Demasi on 4/3/19. -// Copyright © 2019 HASHBANG Productions. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface HBColorPickerSwatchCell : UICollectionViewCell - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSwatchCell.m b/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSwatchCell.m deleted file mode 100644 index 40031a8..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/HBColorPickerSwatchCell.m +++ /dev/null @@ -1,32 +0,0 @@ -// -// HBColorPickerSwatchCell.m -// Alderis Demo -// -// Created by Adam Demasi on 4/3/19. -// Copyright © 2019 HASHBANG Productions. All rights reserved. -// - -#import "HBColorPickerSwatchCell.h" - -@implementation HBColorPickerSwatchCell - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - - if (self) { - self.clipsToBounds = YES; -// self.layer.cornerRadius = 22.f; -// self.layer.borderColor = [UIColor grayColor].CGColor; - } - - return self; -} - -- (void)didMoveToWindow { - [super didMoveToWindow]; - -// CGFloat scale = self.window.screen.scale ?: 1.f; -// self.layer.borderWidth = scale > 2.f ? 2.f / scale : 1.f / scale; -} - -@end diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Info.plist b/Tweaks/Alderis/Demo/Alderis Demo/Info.plist deleted file mode 100644 index 247a221..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Alderis Demo - CFBundleDisplayName - Alderis Demo - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - Launch Screen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/Tweaks/Alderis/Demo/Alderis Demo/Launch Screen.storyboard b/Tweaks/Alderis/Demo/Alderis Demo/Launch Screen.storyboard deleted file mode 100644 index 2cb83b5..0000000 --- a/Tweaks/Alderis/Demo/Alderis Demo/Launch Screen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tweaks/Alderis/Demo/Podfile b/Tweaks/Alderis/Demo/Podfile deleted file mode 100644 index b1d2d98..0000000 --- a/Tweaks/Alderis/Demo/Podfile +++ /dev/null @@ -1,5 +0,0 @@ -platform :ios, '12.0' - -target 'Alderis Demo' do - pod 'Alderis', :path => '..' -end diff --git a/Tweaks/Alderis/Demo/Podfile.lock b/Tweaks/Alderis/Demo/Podfile.lock deleted file mode 100644 index d737eea..0000000 --- a/Tweaks/Alderis/Demo/Podfile.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - Alderis (1.1.2) - -DEPENDENCIES: - - Alderis (from `..`) - -EXTERNAL SOURCES: - Alderis: - :path: ".." - -SPEC CHECKSUMS: - Alderis: 847a404817e585ac7dae36904d7591405520534f - -PODFILE CHECKSUM: ec7a2ee9a64089a4374e61824363ea96330e7a8a - -COCOAPODS: 1.11.3 diff --git a/Tweaks/Alderis/Demo/Pods/Headers/Private/Alderis/Alderis.h b/Tweaks/Alderis/Demo/Pods/Headers/Private/Alderis/Alderis.h deleted file mode 120000 index 8bf4bb3..0000000 --- a/Tweaks/Alderis/Demo/Pods/Headers/Private/Alderis/Alderis.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Alderis/Alderis.h \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Headers/Private/Alderis/AlderisSDKCompatibility.h b/Tweaks/Alderis/Demo/Pods/Headers/Private/Alderis/AlderisSDKCompatibility.h deleted file mode 120000 index 3e24d10..0000000 --- a/Tweaks/Alderis/Demo/Pods/Headers/Private/Alderis/AlderisSDKCompatibility.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Alderis/AlderisSDKCompatibility.h \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis-umbrella.h b/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis-umbrella.h deleted file mode 120000 index f7d2fbd..0000000 --- a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis-umbrella.h +++ /dev/null @@ -1 +0,0 @@ -../../../Target Support Files/Alderis/Alderis-umbrella.h \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis.h b/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis.h deleted file mode 120000 index 8bf4bb3..0000000 --- a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Alderis/Alderis.h \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis.modulemap b/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis.modulemap deleted file mode 120000 index 03e68ee..0000000 --- a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/Alderis.modulemap +++ /dev/null @@ -1 +0,0 @@ -../../../Target Support Files/Alderis/Alderis.modulemap \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/AlderisSDKCompatibility.h b/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/AlderisSDKCompatibility.h deleted file mode 120000 index 3e24d10..0000000 --- a/Tweaks/Alderis/Demo/Pods/Headers/Public/Alderis/AlderisSDKCompatibility.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../Alderis/AlderisSDKCompatibility.h \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Local Podspecs/Alderis.podspec.json b/Tweaks/Alderis/Demo/Pods/Local Podspecs/Alderis.podspec.json deleted file mode 100644 index 8230522..0000000 --- a/Tweaks/Alderis/Demo/Pods/Local Podspecs/Alderis.podspec.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "Alderis", - "version": "1.1.2", - "summary": "A fresh new color picker, with a gentle, fun, and dead simple user interface.", - "description": "Alderis is a fresh new color picker, with a gentle, fun, and dead simple user\ninterface. It aims to incorporate the usual elements of a color picker, in a way\nthat users will find easy and fun to use.\n\nThe user can start by selecting a color they like on the initial color palette\ntab, and either accept it, or refine it using the color wheel and adjustment\nsliders found on the two other tabs.", - "homepage": "https://github.com/hbang/Alderis", - "screenshots": [ - "https://github.com/hbang/Alderis/raw/main/screenshots/alderis-1.jpg", - "https://github.com/hbang/Alderis/raw/main/screenshots/alderis-2.jpg", - "https://github.com/hbang/Alderis/raw/main/screenshots/alderis-3.jpg", - "https://github.com/hbang/Alderis/raw/main/screenshots/alderis-4.jpg" - ], - "license": "Apache License, Version 2.0", - "authors": "HASHBANG Productions", - "social_media_url": "https://twitter.com/hashbang", - "swift_versions": "5.0", - "platforms": { - "ios": "12.0" - }, - "source": { - "git": "https://github.com/hbang/Alderis.git", - "tag": "1.1.2" - }, - "requires_arc": true, - "source_files": [ - "Alderis/*.swift", - "Alderis/*.h" - ], - "resource_bundles": { - "Alderis": "Alderis/Assets-ios12.xcassets" - }, - "swift_version": "5.0" -} diff --git a/Tweaks/Alderis/Demo/Pods/Manifest.lock b/Tweaks/Alderis/Demo/Pods/Manifest.lock deleted file mode 100644 index d737eea..0000000 --- a/Tweaks/Alderis/Demo/Pods/Manifest.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - Alderis (1.1.2) - -DEPENDENCIES: - - Alderis (from `..`) - -EXTERNAL SOURCES: - Alderis: - :path: ".." - -SPEC CHECKSUMS: - Alderis: 847a404817e585ac7dae36904d7591405520534f - -PODFILE CHECKSUM: ec7a2ee9a64089a4374e61824363ea96330e7a8a - -COCOAPODS: 1.11.3 diff --git a/Tweaks/Alderis/Demo/Pods/Pods.xcodeproj/project.pbxproj b/Tweaks/Alderis/Demo/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index 07d1a0c..0000000 --- a/Tweaks/Alderis/Demo/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,922 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 05103D0E4FCCCF239AD0A0B6BC8BF438 /* AlderisSDKCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 33AF563198A93F314C97104EA7E89655 /* AlderisSDKCompatibility.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0D8BF7C4464C83EF0B028B01A78AEDD6 /* ColorPickerAccessibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 895BC4B0779E64166AAFB40F10B8C78C /* ColorPickerAccessibilityViewController.swift */; }; - 1249F0A1123D8CD9B892BBC474175825 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98BA600B082CA0F5CE446945D05C3FED /* Color.swift */; }; - 135D3BAA68E17A0AC6B3667951342ED9 /* ColorPickerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E33FF69927289707F0B298D6590DE7F /* ColorPickerConfiguration.swift */; }; - 1EAAE13CA289E1465B194A38124C4D5F /* ColorWell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F57C4296EB375AC2FAD236F6F8D89677 /* ColorWell.swift */; }; - 2939CFC7F4E151B8BA170E2718FE5C2D /* ColorPickerInnerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE38B60A89EFE92ABBBD9B9DC6B76B9E /* ColorPickerInnerViewController.swift */; }; - 37F5ABFCFA0B0D72CAEFBDFA3B5ED787 /* Alderis-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 97CE419BD858D6FE5C2D08A274A5FCC4 /* Alderis-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4CB88CD902C9400106C9CDC4C3BADDD9 /* Alderis.h in Headers */ = {isa = PBXBuildFile; fileRef = CA71B8BBD169668C8D0BC006FB4A5EBB /* Alderis.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 50DCDD2604D2D2195B7FE86549C8C60A /* ColorPickerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE27FA6F4BFD5E6412B78F11FE678C3 /* ColorPickerDelegate.swift */; }; - 53966AFCE54B78B4BEFD48FF19423AC2 /* TextViewLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412F9DA6B91118873136801E797D0D53 /* TextViewLabel.swift */; }; - 5B575D82A33FC6ADA46F8463ECD56545 /* ColorPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EF72B33574BD440D1C8476026F3DEE /* ColorPickerViewController.swift */; }; - 612EFA95A4DD8D4015CF8FA9A1878399 /* ColorPickerSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA93ECBA0BF9F1EDB0DF41B1F6BB122 /* ColorPickerSlider.swift */; }; - 61BC805E3601DBC8943B104CE9DAB27D /* BottomSheetTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C58F11F0D4691B733DF3C64E9CAA22C /* BottomSheetTransition.swift */; }; - 6309E88FA19CA2C7E1397C854EF70D66 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A7B12A211D20F3215B791362C4A167 /* Assets.swift */; }; - 65FF5EEC743492FF458C8C511687895F /* Alderis-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 25FF3569DF1635C4D4EFDBE3EC713871 /* Alderis-dummy.m */; }; - 675572C2B585A87F28A077B811DA8FA5 /* ColorPickerWheelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38BF69FA9AA99E27F929AA33A622BC50 /* ColorPickerWheelView.swift */; }; - 69E9416DB84F9C1578C79463C00F1034 /* AccessibilityComplianceLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CB3607C30014F8358C3875AF8F0A7C3 /* AccessibilityComplianceLabel.swift */; }; - 6A38E3A03B08C4DB4E72A35AF6C42293 /* SeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6656E3EB483BC4EFB619B8B7DAA8A9D9 /* SeparatorView.swift */; }; - 7AE2A9360F7B1AFEF18CA72FAB8E47CA /* DialogButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57A8871167DE887D9D09AAEFB7FF3A37 /* DialogButton.swift */; }; - 7C15B0F74C21E30A6D2FE833A039C6A5 /* ColorPickerSlidersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22A1DF5EB1BEC3637C580A1C8270A196 /* ColorPickerSlidersViewController.swift */; }; - 815F9C399ED6E92FB5C7CBA666339C43 /* UIFontDescriptorAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ABB5DB2028B61124D7915C993C57531 /* UIFontDescriptorAdditions.swift */; }; - 854293819B45401802BEBE4DAE9593D5 /* AccessibilityContrastSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B1B52CBBF19B2BB0FA72B98D54EB376 /* AccessibilityContrastSelector.swift */; }; - 8E81254A16B7C247CF0DEBA561FFFBBF /* Pods-Alderis Demo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E0B28B43B7BC45127DE1EA921314EAA /* Pods-Alderis Demo-dummy.m */; }; - A27A1ADC9991A8C08AE350860C1B4894 /* NSBeep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DB8593FFDFFE77DA2BC61903E23688 /* NSBeep.swift */; }; - A4B55DD8DF7981D5348FED7150137FD4 /* ColorPickerMapSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CA6996BA5910AA62E840ECDAC8A311D /* ColorPickerMapSlider.swift */; }; - B07A5681AD8C8E562F7768F8687EA98D /* ColorPickerNumericSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C96783D143FBCCA45297A1B50D52C6 /* ColorPickerNumericSlider.swift */; }; - B622882FF8E7B4CCFFB32813BDCB2D34 /* UIFloat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193C648A76B81FC98BAD74C9D92EE779 /* UIFloat.swift */; }; - BA43D3FA7CD5A3F1F61BB205626EE7F7 /* UIColorAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F684AF5C41A475CC3FB2946E5DF2ED /* UIColorAdditions.swift */; }; - BC1230C95F458765C8CEBDF80109609B /* ColorPickerSwatchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFE5AC5F8B2C3F386620685EAF5D2739 /* ColorPickerSwatchViewController.swift */; }; - D951C553E2937D74043A298EFD7BC0BA /* Pods-Alderis Demo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 16A2838DE41B9772EA81132CE1FE138B /* Pods-Alderis Demo-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; - DCF8E0093062AD806401B93579A00946 /* Assets-ios12.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BDC12530AEE0050A48E2C0437FFE7BA /* Assets-ios12.xcassets */; }; - E5F02AF27C52B7EEDFA8F5CE568058FC /* ColorPickerMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32455B59318B845D222D6DD4C86D0F14 /* ColorPickerMapViewController.swift */; }; - EB32A80054921FB5EEECD0B2C1BA1FB8 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8EDAAEA299AE2C5EB2BB7172634E896 /* GradientView.swift */; }; - F8144CFF31B54A06D202B96AA7FA0CF1 /* ColorPickerTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B1135B4A039DE8DAA72EEA1D127815 /* ColorPickerTabViewController.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 406A8A6B603CDE598EAB01818A637160 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = E06BFBDAEB84B8EBA0D1A8B43D16EF27; - remoteInfo = "Alderis-Alderis"; - }; - EE5F7F514D1321804708AF70F97259CC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0BF6D5F4E6EC1CF170610CBAB0F6CEF2; - remoteInfo = Alderis; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 02B116C65675DAEA942559AE27E67F15 /* highlight.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = highlight.css; path = docs/css/highlight.css; sourceTree = ""; }; - 02F847ACA8E7B867DD5935F065F04DD4 /* jazzy.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jazzy.js; path = docs/js/jazzy.js; sourceTree = ""; }; - 04C96783D143FBCCA45297A1B50D52C6 /* ColorPickerNumericSlider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerNumericSlider.swift; path = Alderis/ColorPickerNumericSlider.swift; sourceTree = ""; }; - 08E8A13AC29E80A401DF99D68805957A /* Alderis-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alderis-prefix.pch"; sourceTree = ""; }; - 0974F2B8473A65FEDBC4983C7BE0D053 /* UI Components.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "UI Components.html"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/UI Components.html"; sourceTree = ""; }; - 09DB8593FFDFFE77DA2BC61903E23688 /* NSBeep.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSBeep.swift; path = Alderis/NSBeep.swift; sourceTree = ""; }; - 0BB90EF60C711FCDCD835AC9AB34EF94 /* dash.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = dash.png; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/img/dash.png; sourceTree = ""; }; - 0E81A451910A2F39C165935A61188DD7 /* Alderis */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = Alderis; path = libAlderis.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0EBF7EA81D2DEA250A5A1C0522E8D7A3 /* jazzy.search.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jazzy.search.js; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/js/jazzy.search.js; sourceTree = ""; }; - 11B1135B4A039DE8DAA72EEA1D127815 /* ColorPickerTabViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerTabViewController.swift; path = Alderis/ColorPickerTabViewController.swift; sourceTree = ""; }; - 12CF8765DD7A138CB9A12850F4F4AF9A /* alderis-2.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-2.jpg"; path = "docs/screenshots/alderis-2.jpg"; sourceTree = ""; }; - 135BC3D71ADFA71F8713F5F29FB7D3D2 /* ColorPickerTab.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ColorPickerTab.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Enums/ColorPickerTab.html; sourceTree = ""; }; - 16A2838DE41B9772EA81132CE1FE138B /* Pods-Alderis Demo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Alderis Demo-umbrella.h"; sourceTree = ""; }; - 193C648A76B81FC98BAD74C9D92EE779 /* UIFloat.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIFloat.swift; path = Alderis/UIFloat.swift; sourceTree = ""; }; - 2073961377AA380E66ADD8B2B1414B70 /* logo.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = logo.jpg; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/logo.jpg; sourceTree = ""; }; - 2100D41A9E3FA821A631CC2A8231B340 /* carat.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = carat.png; path = docs/img/carat.png; sourceTree = ""; }; - 229FF675CBC5FBD3E5814D3A434BEE86 /* logo.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = logo.jpg; path = docs/screenshots/logo.jpg; sourceTree = ""; }; - 22A1DF5EB1BEC3637C580A1C8270A196 /* ColorPickerSlidersViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerSlidersViewController.swift; path = Alderis/ColorPickerSlidersViewController.swift; sourceTree = ""; }; - 2393CC4938AC17F8A44EA2F5850A9F7C /* lunr.min.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = lunr.min.js; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/js/lunr.min.js; sourceTree = ""; }; - 2442B5DB4407D4A13C865A36A51ECE46 /* Pods-Alderis Demo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Alderis Demo-acknowledgements.plist"; sourceTree = ""; }; - 25FF3569DF1635C4D4EFDBE3EC713871 /* Alderis-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alderis-dummy.m"; sourceTree = ""; }; - 2CB3607C30014F8358C3875AF8F0A7C3 /* AccessibilityComplianceLabel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityComplianceLabel.swift; path = Alderis/AccessibilityComplianceLabel.swift; sourceTree = ""; }; - 3176D00931C79BF799AF1F6717276229 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = docs/docsets/Alderis.docset/Contents/Info.plist; sourceTree = ""; }; - 32455B59318B845D222D6DD4C86D0F14 /* ColorPickerMapViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerMapViewController.swift; path = Alderis/ColorPickerMapViewController.swift; sourceTree = ""; }; - 32B2DF317783C03E472F09C6A18A2137 /* Deprecated.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Deprecated.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Deprecated.html; sourceTree = ""; }; - 33AF563198A93F314C97104EA7E89655 /* AlderisSDKCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AlderisSDKCompatibility.h; path = Alderis/AlderisSDKCompatibility.h; sourceTree = ""; }; - 346A89CF7100B245C0D8FFBB735BA330 /* alderis-1.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-1.jpg"; path = "docs/screenshots/alderis-1.jpg"; sourceTree = ""; }; - 34B81EA50C950B2A5BB60792DF6C2321 /* alderis-4.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-4.jpg"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/alderis-4.jpg"; sourceTree = ""; }; - 36E2384C9860D24702DA564950E42638 /* ColorPickerViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ColorPickerViewController.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Classes/ColorPickerViewController.html; sourceTree = ""; }; - 38BF69FA9AA99E27F929AA33A622BC50 /* ColorPickerWheelView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerWheelView.swift; path = Alderis/ColorPickerWheelView.swift; sourceTree = ""; }; - 390A3C384514B2A881E2611AA3A7AFAF /* Guides.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Guides.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Guides.html; sourceTree = ""; }; - 39151D3F804E2ACE7EB4A41F0519640F /* preference-bundles.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "preference-bundles.html"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/preference-bundles.html"; sourceTree = ""; }; - 39CCC3F183B912E6298F07E239499149 /* typeahead.jquery.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = typeahead.jquery.js; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/js/typeahead.jquery.js; sourceTree = ""; }; - 3BE1332117E0FB3058648B05E510FC05 /* jazzy.search.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jazzy.search.js; path = docs/js/jazzy.search.js; sourceTree = ""; }; - 3F26A160257BC65D007E7AC9351E1F46 /* Pods-Alderis Demo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Alderis Demo.modulemap"; sourceTree = ""; }; - 408B7D127DAD5D88CCD0B96EBF7E1740 /* jazzy.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = jazzy.css; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/css/jazzy.css; sourceTree = ""; }; - 412F9DA6B91118873136801E797D0D53 /* TextViewLabel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextViewLabel.swift; path = Alderis/TextViewLabel.swift; sourceTree = ""; }; - 426F13D795E5EEB02FFB85344C6E177B /* alderis-4.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-4.jpg"; path = "docs/screenshots/alderis-4.jpg"; sourceTree = ""; }; - 427B5E705542B1CB268BA88393B7E81C /* typeahead.jquery.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = typeahead.jquery.js; path = docs/js/typeahead.jquery.js; sourceTree = ""; }; - 42D5D9AC25A2A1829039F043ACC13982 /* UI Components.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "UI Components.html"; path = "docs/UI Components.html"; sourceTree = ""; }; - 4339F8A837B317D1831C93FD9779103A /* Pods-Alderis Demo */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "Pods-Alderis Demo"; path = "libPods-Alderis Demo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 456BDD346100CE3A8518F4826FB3407E /* UIColor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = UIColor.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Extensions/UIColor.html; sourceTree = ""; }; - 46B301E1CAEEF9AC54CE7AB98AE94FF8 /* jazzy.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jazzy.js; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/js/jazzy.js; sourceTree = ""; }; - 490D4F0EB791E3F5DCFE8DA18519BCE9 /* ColorPickerViewController.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ColorPickerViewController.html; path = docs/Classes/ColorPickerViewController.html; sourceTree = ""; }; - 4ABB5DB2028B61124D7915C993C57531 /* UIFontDescriptorAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIFontDescriptorAdditions.swift; path = Alderis/UIFontDescriptorAdditions.swift; sourceTree = ""; }; - 4BDC12530AEE0050A48E2C0437FFE7BA /* Assets-ios12.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; name = "Assets-ios12.xcassets"; path = "Alderis/Assets-ios12.xcassets"; sourceTree = ""; }; - 4D7238C16049AC7D52380A3F0F037DA1 /* Alderis.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alderis.release.xcconfig; sourceTree = ""; }; - 4DAF9BE7C45EEC6325555273285DBCFF /* Pods-Alderis Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Alderis Demo.debug.xcconfig"; sourceTree = ""; }; - 56A04476FF0C6D9343BC0479260BF23C /* spinner.gif */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.gif; name = spinner.gif; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/img/spinner.gif; sourceTree = ""; }; - 56C95B256105E52E1EBED49808BA072D /* gh.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = gh.png; path = docs/img/gh.png; sourceTree = ""; }; - 57A8871167DE887D9D09AAEFB7FF3A37 /* DialogButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DialogButton.swift; path = Alderis/DialogButton.swift; sourceTree = ""; }; - 5BFEDA5074456612DCD226636CB27A97 /* ColorPickerDelegate.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ColorPickerDelegate.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Protocols/ColorPickerDelegate.html; sourceTree = ""; }; - 5C53194D55F86B1096691514B424C4B6 /* ColorPickerDelegate.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ColorPickerDelegate.html; path = docs/Protocols/ColorPickerDelegate.html; sourceTree = ""; }; - 5DFA99D99F720D80A8C0F3CBA36A6722 /* alderis-2.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-2.jpg"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/alderis-2.jpg"; sourceTree = ""; }; - 6085501632610BFE778FFF92DF0A5748 /* preference-bundles.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "preference-bundles.html"; path = "docs/preference-bundles.html"; sourceTree = ""; }; - 60B41A93CBFB859E0CC522EAEF362A58 /* ColorPickerConfiguration.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ColorPickerConfiguration.html; path = docs/Classes/ColorPickerConfiguration.html; sourceTree = ""; }; - 61B0B4CC82C04F8049F6D13378E10D29 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 61BCC763200E79B1A67858928D3BFF6D /* dash.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = dash.png; path = docs/img/dash.png; sourceTree = ""; }; - 655E41783F73F7420DA545011AE41E59 /* Alderis.tgz */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file; name = Alderis.tgz; path = docs/docsets/Alderis.tgz; sourceTree = ""; }; - 65F7A4EE3B7BC951DCA59097E498A594 /* gh.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = gh.png; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/img/gh.png; sourceTree = ""; }; - 6656E3EB483BC4EFB619B8B7DAA8A9D9 /* SeparatorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SeparatorView.swift; path = Alderis/SeparatorView.swift; sourceTree = ""; }; - 6B1B52CBBF19B2BB0FA72B98D54EB376 /* AccessibilityContrastSelector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AccessibilityContrastSelector.swift; path = Alderis/AccessibilityContrastSelector.swift; sourceTree = ""; }; - 6E0B28B43B7BC45127DE1EA921314EAA /* Pods-Alderis Demo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Alderis Demo-dummy.m"; sourceTree = ""; }; - 6E11449DA1AF7B8354272EA71429E6DF /* search.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = search.json; path = docs/search.json; sourceTree = ""; }; - 6FE4AFB52F6E21D973EB81FA5D47DE99 /* spinner.gif */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.gif; name = spinner.gif; path = docs/img/spinner.gif; sourceTree = ""; }; - 7C3BAA2B975E5AB6E45B7501A38D0E50 /* jquery.min.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jquery.min.js; path = docs/js/jquery.min.js; sourceTree = ""; }; - 7C4AEA4097E03F8F1E1FF76936BFC278 /* alderis-demo.mp4 */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file; name = "alderis-demo.mp4"; path = "docs/screenshots/alderis-demo.mp4"; sourceTree = ""; }; - 7CA6996BA5910AA62E840ECDAC8A311D /* ColorPickerMapSlider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerMapSlider.swift; path = Alderis/ColorPickerMapSlider.swift; sourceTree = ""; }; - 81C90428B5B99754A43DA6313C54EA89 /* ColorWell.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ColorWell.html; path = docs/Classes/ColorWell.html; sourceTree = ""; }; - 86AD6BD58D889622FFD4FFAB222FB92F /* Deprecated.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Deprecated.html; path = docs/Deprecated.html; sourceTree = ""; }; - 895BC4B0779E64166AAFB40F10B8C78C /* ColorPickerAccessibilityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerAccessibilityViewController.swift; path = Alderis/ColorPickerAccessibilityViewController.swift; sourceTree = ""; }; - 8ACDBAED02C2312FD0DDD22FF5C8F90C /* lunr.min.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = lunr.min.js; path = docs/js/lunr.min.js; sourceTree = ""; }; - 8BEDC7D63209B1F7C6891F0A83428EC0 /* Pods-Alderis Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Alderis Demo.release.xcconfig"; sourceTree = ""; }; - 8E33FF69927289707F0B298D6590DE7F /* ColorPickerConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerConfiguration.swift; path = Alderis/ColorPickerConfiguration.swift; sourceTree = ""; }; - 909F399540F2BEB7DC4E5B64D2D23826 /* Alderis.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = Alderis.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 90A7B12A211D20F3215B791362C4A167 /* Assets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Assets.swift; path = Alderis/Assets.swift; sourceTree = ""; }; - 922CFAFDF66D62804DBB612073906B88 /* index.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = index.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/index.html; sourceTree = ""; }; - 92B1C7079B2E8A4A28B8E33816D706EB /* index.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = index.html; path = docs/index.html; sourceTree = ""; }; - 92C09CC7B803B95560EB8939CC6E04F4 /* ColorWell.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ColorWell.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Classes/ColorWell.html; sourceTree = ""; }; - 96A206F94AE69D710EB7B7C8762C8A62 /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = ""; }; - 96D71531FEDE7846F4A8F71D072D1591 /* Alderis.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Alderis.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 97CE419BD858D6FE5C2D08A274A5FCC4 /* Alderis-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alderis-umbrella.h"; sourceTree = ""; }; - 98BA600B082CA0F5CE446945D05C3FED /* Color.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Color.swift; path = Alderis/Color.swift; sourceTree = ""; }; - 9C58F11F0D4691B733DF3C64E9CAA22C /* BottomSheetTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BottomSheetTransition.swift; path = Alderis/BottomSheetTransition.swift; sourceTree = ""; }; - 9C59604B7017DD6EE566A7E63D207201 /* jazzy.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = jazzy.css; path = docs/css/jazzy.css; sourceTree = ""; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9DE62A37068140A5FCA8272D4E7A546B /* ResourceBundle-Alderis-Alderis-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-Alderis-Alderis-Info.plist"; sourceTree = ""; }; - 9F8B0A840EE850B85532904D3477EA6C /* migrating-to-11.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "migrating-to-11.html"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/migrating-to-11.html"; sourceTree = ""; }; - A00D32F1DB750C7A433206BB9423273C /* jquery.min.js */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.javascript; name = jquery.min.js; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/js/jquery.min.js; sourceTree = ""; }; - A11066E4ED4E95D10035D29173139102 /* ColorPickerTab.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = ColorPickerTab.html; path = docs/Enums/ColorPickerTab.html; sourceTree = ""; }; - A4CAB22104CFE97E066C888EA84A1FB5 /* Extensions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Extensions.html; path = docs/Extensions.html; sourceTree = ""; }; - ADC5E34B53A672560E13EAF0D89BA5F6 /* alderis-1.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-1.jpg"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/alderis-1.jpg"; sourceTree = ""; }; - AE38B60A89EFE92ABBBD9B9DC6B76B9E /* ColorPickerInnerViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerInnerViewController.swift; path = Alderis/ColorPickerInnerViewController.swift; sourceTree = ""; }; - B2E0D7FED34ACD1971214E2CE7A0916F /* alderis-3.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-3.jpg"; path = "docs/screenshots/alderis-3.jpg"; sourceTree = ""; }; - B3128C93A74BE7F8CE1FC5D5717740D7 /* Pods-Alderis Demo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Alderis Demo-acknowledgements.markdown"; sourceTree = ""; }; - B49DA50C46A4E7E3D74A2BA21F4E972D /* alderis-demo.gif */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.gif; name = "alderis-demo.gif"; path = "docs/screenshots/alderis-demo.gif"; sourceTree = ""; }; - C6E7523EE0A4CF72A207ADDD734DEE45 /* Pods-Alderis Demo-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Alderis Demo-resources.sh"; sourceTree = ""; }; - C72FB199C848386888B509700DC92309 /* Color Picker.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "Color Picker.html"; path = "docs/Color Picker.html"; sourceTree = ""; }; - C94AE49628F942E40E6FC907AF341F0C /* UIColor.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = UIColor.html; path = docs/Extensions/UIColor.html; sourceTree = ""; }; - CA71B8BBD169668C8D0BC006FB4A5EBB /* Alderis.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Alderis.h; path = Alderis/Alderis.h; sourceTree = ""; }; - CD75327C7B0D6532BB1C51ADF5E5F5C1 /* alderis-3.jpg */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.jpeg; name = "alderis-3.jpg"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/alderis-3.jpg"; sourceTree = ""; }; - CF1C0CA74112CFEF515F9B106B84EED3 /* Color Picker.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = "Color Picker.html"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/Color Picker.html"; sourceTree = ""; }; - D3193B5C2AFD71349D8FE05C8859B534 /* ColorPickerConfiguration.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = ColorPickerConfiguration.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Classes/ColorPickerConfiguration.html; sourceTree = ""; }; - DA583C23AB5145F55CE214AAA9F21D69 /* Guides.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = Guides.html; path = docs/Guides.html; sourceTree = ""; }; - DDB4D91E9BF02F44556BF6B3E8AECE44 /* highlight.css */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.css; name = highlight.css; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/css/highlight.css; sourceTree = ""; }; - DF3AF36BDEB0B6B51C5330F99693D3D8 /* alderis-demo.gif */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.gif; name = "alderis-demo.gif"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/alderis-demo.gif"; sourceTree = ""; }; - E09142CF0722BCBDFF7C6EF2C6E3C5AD /* Alderis.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Alderis.modulemap; sourceTree = ""; }; - E7DCD05E0FBC03FB1CB46C061461DCE4 /* Extensions.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html.documentation; name = Extensions.html; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/Extensions.html; sourceTree = ""; }; - EBC28A5101D4B8328FB9CB18F7370042 /* docSet.dsidx */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file; name = docSet.dsidx; path = docs/docsets/Alderis.docset/Contents/Resources/docSet.dsidx; sourceTree = ""; }; - EF35F95BEC555044C7C3CBBC6AF054FB /* migrating-to-11.html */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.html; name = "migrating-to-11.html"; path = "docs/migrating-to-11.html"; sourceTree = ""; }; - EFE5AC5F8B2C3F386620685EAF5D2739 /* ColorPickerSwatchViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerSwatchViewController.swift; path = Alderis/ColorPickerSwatchViewController.swift; sourceTree = ""; }; - F15D960A598C031F6A6BF1896262FA7B /* Alderis.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Alderis.debug.xcconfig; sourceTree = ""; }; - F4758ABB829DE115D62896232DB57BAC /* search.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = search.json; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/search.json; sourceTree = ""; }; - F57C4296EB375AC2FAD236F6F8D89677 /* ColorWell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorWell.swift; path = Alderis/ColorWell.swift; sourceTree = ""; }; - F5F684AF5C41A475CC3FB2946E5DF2ED /* UIColorAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIColorAdditions.swift; path = Alderis/UIColorAdditions.swift; sourceTree = ""; }; - F7EF72B33574BD440D1C8476026F3DEE /* ColorPickerViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerViewController.swift; path = Alderis/ColorPickerViewController.swift; sourceTree = ""; }; - F8EDAAEA299AE2C5EB2BB7172634E896 /* GradientView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = Alderis/GradientView.swift; sourceTree = ""; }; - FDA93ECBA0BF9F1EDB0DF41B1F6BB122 /* ColorPickerSlider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerSlider.swift; path = Alderis/ColorPickerSlider.swift; sourceTree = ""; }; - FDB1859B2497FB32CBD6018DA07E3903 /* Alderis.xml */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = Alderis.xml; path = docs/docsets/Alderis.xml; sourceTree = ""; }; - FDC0B355146987F48BAC2F801702D175 /* alderis-demo.mp4 */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file; name = "alderis-demo.mp4"; path = "docs/docsets/Alderis.docset/Contents/Resources/Documents/screenshots/alderis-demo.mp4"; sourceTree = ""; }; - FE815F230EB0E506A0E93FC9B05DEF16 /* carat.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = carat.png; path = docs/docsets/Alderis.docset/Contents/Resources/Documents/img/carat.png; sourceTree = ""; }; - FEE27FA6F4BFD5E6412B78F11FE678C3 /* ColorPickerDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColorPickerDelegate.swift; path = Alderis/ColorPickerDelegate.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 093A79D3DC07E777E846D998AB14C931 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B383053112517B152D012AEDB5956A0 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DA7ECD0D42EFE4684D076E810F8EDFF5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 197C13DD8906A694068BF18639FCC930 /* Development Pods */ = { - isa = PBXGroup; - children = ( - 899E89AB43D963792788E66158E22535 /* Alderis */, - ); - name = "Development Pods"; - sourceTree = ""; - }; - 887692E1D0CD32ADA45C133CE07E5777 /* Products */ = { - isa = PBXGroup; - children = ( - 0E81A451910A2F39C165935A61188DD7 /* Alderis */, - 96D71531FEDE7846F4A8F71D072D1591 /* Alderis.bundle */, - 4339F8A837B317D1831C93FD9779103A /* Pods-Alderis Demo */, - ); - name = Products; - sourceTree = ""; - }; - 899E89AB43D963792788E66158E22535 /* Alderis */ = { - isa = PBXGroup; - children = ( - 2CB3607C30014F8358C3875AF8F0A7C3 /* AccessibilityComplianceLabel.swift */, - 6B1B52CBBF19B2BB0FA72B98D54EB376 /* AccessibilityContrastSelector.swift */, - CA71B8BBD169668C8D0BC006FB4A5EBB /* Alderis.h */, - 33AF563198A93F314C97104EA7E89655 /* AlderisSDKCompatibility.h */, - 90A7B12A211D20F3215B791362C4A167 /* Assets.swift */, - 4BDC12530AEE0050A48E2C0437FFE7BA /* Assets-ios12.xcassets */, - 9C58F11F0D4691B733DF3C64E9CAA22C /* BottomSheetTransition.swift */, - 98BA600B082CA0F5CE446945D05C3FED /* Color.swift */, - 895BC4B0779E64166AAFB40F10B8C78C /* ColorPickerAccessibilityViewController.swift */, - 8E33FF69927289707F0B298D6590DE7F /* ColorPickerConfiguration.swift */, - FEE27FA6F4BFD5E6412B78F11FE678C3 /* ColorPickerDelegate.swift */, - AE38B60A89EFE92ABBBD9B9DC6B76B9E /* ColorPickerInnerViewController.swift */, - 7CA6996BA5910AA62E840ECDAC8A311D /* ColorPickerMapSlider.swift */, - 32455B59318B845D222D6DD4C86D0F14 /* ColorPickerMapViewController.swift */, - 04C96783D143FBCCA45297A1B50D52C6 /* ColorPickerNumericSlider.swift */, - FDA93ECBA0BF9F1EDB0DF41B1F6BB122 /* ColorPickerSlider.swift */, - 22A1DF5EB1BEC3637C580A1C8270A196 /* ColorPickerSlidersViewController.swift */, - EFE5AC5F8B2C3F386620685EAF5D2739 /* ColorPickerSwatchViewController.swift */, - 11B1135B4A039DE8DAA72EEA1D127815 /* ColorPickerTabViewController.swift */, - F7EF72B33574BD440D1C8476026F3DEE /* ColorPickerViewController.swift */, - 38BF69FA9AA99E27F929AA33A622BC50 /* ColorPickerWheelView.swift */, - F57C4296EB375AC2FAD236F6F8D89677 /* ColorWell.swift */, - 57A8871167DE887D9D09AAEFB7FF3A37 /* DialogButton.swift */, - F8EDAAEA299AE2C5EB2BB7172634E896 /* GradientView.swift */, - 09DB8593FFDFFE77DA2BC61903E23688 /* NSBeep.swift */, - 6656E3EB483BC4EFB619B8B7DAA8A9D9 /* SeparatorView.swift */, - 412F9DA6B91118873136801E797D0D53 /* TextViewLabel.swift */, - F5F684AF5C41A475CC3FB2946E5DF2ED /* UIColorAdditions.swift */, - 193C648A76B81FC98BAD74C9D92EE779 /* UIFloat.swift */, - 4ABB5DB2028B61124D7915C993C57531 /* UIFontDescriptorAdditions.swift */, - BCB9C80F62D03A4D91FB7BDD74E87218 /* Pod */, - EC4B0BEA27DDFEE43BB8A01A8A88802E /* Support Files */, - ); - name = Alderis; - path = ../..; - sourceTree = ""; - }; - A1837F8ECDB0D608D38E29E5F08D2348 /* Pods-Alderis Demo */ = { - isa = PBXGroup; - children = ( - 3F26A160257BC65D007E7AC9351E1F46 /* Pods-Alderis Demo.modulemap */, - B3128C93A74BE7F8CE1FC5D5717740D7 /* Pods-Alderis Demo-acknowledgements.markdown */, - 2442B5DB4407D4A13C865A36A51ECE46 /* Pods-Alderis Demo-acknowledgements.plist */, - 6E0B28B43B7BC45127DE1EA921314EAA /* Pods-Alderis Demo-dummy.m */, - C6E7523EE0A4CF72A207ADDD734DEE45 /* Pods-Alderis Demo-resources.sh */, - 16A2838DE41B9772EA81132CE1FE138B /* Pods-Alderis Demo-umbrella.h */, - 4DAF9BE7C45EEC6325555273285DBCFF /* Pods-Alderis Demo.debug.xcconfig */, - 8BEDC7D63209B1F7C6891F0A83428EC0 /* Pods-Alderis Demo.release.xcconfig */, - ); - name = "Pods-Alderis Demo"; - path = "Target Support Files/Pods-Alderis Demo"; - sourceTree = ""; - }; - BCB9C80F62D03A4D91FB7BDD74E87218 /* Pod */ = { - isa = PBXGroup; - children = ( - 909F399540F2BEB7DC4E5B64D2D23826 /* Alderis.podspec */, - 655E41783F73F7420DA545011AE41E59 /* Alderis.tgz */, - FDB1859B2497FB32CBD6018DA07E3903 /* Alderis.xml */, - ADC5E34B53A672560E13EAF0D89BA5F6 /* alderis-1.jpg */, - 346A89CF7100B245C0D8FFBB735BA330 /* alderis-1.jpg */, - 5DFA99D99F720D80A8C0F3CBA36A6722 /* alderis-2.jpg */, - 12CF8765DD7A138CB9A12850F4F4AF9A /* alderis-2.jpg */, - CD75327C7B0D6532BB1C51ADF5E5F5C1 /* alderis-3.jpg */, - B2E0D7FED34ACD1971214E2CE7A0916F /* alderis-3.jpg */, - 34B81EA50C950B2A5BB60792DF6C2321 /* alderis-4.jpg */, - 426F13D795E5EEB02FFB85344C6E177B /* alderis-4.jpg */, - DF3AF36BDEB0B6B51C5330F99693D3D8 /* alderis-demo.gif */, - B49DA50C46A4E7E3D74A2BA21F4E972D /* alderis-demo.gif */, - FDC0B355146987F48BAC2F801702D175 /* alderis-demo.mp4 */, - 7C4AEA4097E03F8F1E1FF76936BFC278 /* alderis-demo.mp4 */, - FE815F230EB0E506A0E93FC9B05DEF16 /* carat.png */, - 2100D41A9E3FA821A631CC2A8231B340 /* carat.png */, - C72FB199C848386888B509700DC92309 /* Color Picker.html */, - CF1C0CA74112CFEF515F9B106B84EED3 /* Color Picker.html */, - 60B41A93CBFB859E0CC522EAEF362A58 /* ColorPickerConfiguration.html */, - D3193B5C2AFD71349D8FE05C8859B534 /* ColorPickerConfiguration.html */, - 5BFEDA5074456612DCD226636CB27A97 /* ColorPickerDelegate.html */, - 5C53194D55F86B1096691514B424C4B6 /* ColorPickerDelegate.html */, - 135BC3D71ADFA71F8713F5F29FB7D3D2 /* ColorPickerTab.html */, - A11066E4ED4E95D10035D29173139102 /* ColorPickerTab.html */, - 490D4F0EB791E3F5DCFE8DA18519BCE9 /* ColorPickerViewController.html */, - 36E2384C9860D24702DA564950E42638 /* ColorPickerViewController.html */, - 81C90428B5B99754A43DA6313C54EA89 /* ColorWell.html */, - 92C09CC7B803B95560EB8939CC6E04F4 /* ColorWell.html */, - 0BB90EF60C711FCDCD835AC9AB34EF94 /* dash.png */, - 61BCC763200E79B1A67858928D3BFF6D /* dash.png */, - 86AD6BD58D889622FFD4FFAB222FB92F /* Deprecated.html */, - 32B2DF317783C03E472F09C6A18A2137 /* Deprecated.html */, - EBC28A5101D4B8328FB9CB18F7370042 /* docSet.dsidx */, - E7DCD05E0FBC03FB1CB46C061461DCE4 /* Extensions.html */, - A4CAB22104CFE97E066C888EA84A1FB5 /* Extensions.html */, - 65F7A4EE3B7BC951DCA59097E498A594 /* gh.png */, - 56C95B256105E52E1EBED49808BA072D /* gh.png */, - 390A3C384514B2A881E2611AA3A7AFAF /* Guides.html */, - DA583C23AB5145F55CE214AAA9F21D69 /* Guides.html */, - 02B116C65675DAEA942559AE27E67F15 /* highlight.css */, - DDB4D91E9BF02F44556BF6B3E8AECE44 /* highlight.css */, - 922CFAFDF66D62804DBB612073906B88 /* index.html */, - 92B1C7079B2E8A4A28B8E33816D706EB /* index.html */, - 3176D00931C79BF799AF1F6717276229 /* Info.plist */, - 9C59604B7017DD6EE566A7E63D207201 /* jazzy.css */, - 408B7D127DAD5D88CCD0B96EBF7E1740 /* jazzy.css */, - 46B301E1CAEEF9AC54CE7AB98AE94FF8 /* jazzy.js */, - 02F847ACA8E7B867DD5935F065F04DD4 /* jazzy.js */, - 0EBF7EA81D2DEA250A5A1C0522E8D7A3 /* jazzy.search.js */, - 3BE1332117E0FB3058648B05E510FC05 /* jazzy.search.js */, - A00D32F1DB750C7A433206BB9423273C /* jquery.min.js */, - 7C3BAA2B975E5AB6E45B7501A38D0E50 /* jquery.min.js */, - 96A206F94AE69D710EB7B7C8762C8A62 /* LICENSE.md */, - 2073961377AA380E66ADD8B2B1414B70 /* logo.jpg */, - 229FF675CBC5FBD3E5814D3A434BEE86 /* logo.jpg */, - 2393CC4938AC17F8A44EA2F5850A9F7C /* lunr.min.js */, - 8ACDBAED02C2312FD0DDD22FF5C8F90C /* lunr.min.js */, - 9F8B0A840EE850B85532904D3477EA6C /* migrating-to-11.html */, - EF35F95BEC555044C7C3CBBC6AF054FB /* migrating-to-11.html */, - 39151D3F804E2ACE7EB4A41F0519640F /* preference-bundles.html */, - 6085501632610BFE778FFF92DF0A5748 /* preference-bundles.html */, - 61B0B4CC82C04F8049F6D13378E10D29 /* README.md */, - F4758ABB829DE115D62896232DB57BAC /* search.json */, - 6E11449DA1AF7B8354272EA71429E6DF /* search.json */, - 56A04476FF0C6D9343BC0479260BF23C /* spinner.gif */, - 6FE4AFB52F6E21D973EB81FA5D47DE99 /* spinner.gif */, - 39CCC3F183B912E6298F07E239499149 /* typeahead.jquery.js */, - 427B5E705542B1CB268BA88393B7E81C /* typeahead.jquery.js */, - 0974F2B8473A65FEDBC4983C7BE0D053 /* UI Components.html */, - 42D5D9AC25A2A1829039F043ACC13982 /* UI Components.html */, - 456BDD346100CE3A8518F4826FB3407E /* UIColor.html */, - C94AE49628F942E40E6FC907AF341F0C /* UIColor.html */, - ); - name = Pod; - sourceTree = ""; - }; - BDF19F2547EA527C68B46E462B39F6D6 /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - A1837F8ECDB0D608D38E29E5F08D2348 /* Pods-Alderis Demo */, - ); - name = "Targets Support Files"; - sourceTree = ""; - }; - CF1408CF629C7361332E53B88F7BD30C = { - isa = PBXGroup; - children = ( - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - 197C13DD8906A694068BF18639FCC930 /* Development Pods */, - D89477F20FB1DE18A04690586D7808C4 /* Frameworks */, - 887692E1D0CD32ADA45C133CE07E5777 /* Products */, - BDF19F2547EA527C68B46E462B39F6D6 /* Targets Support Files */, - ); - sourceTree = ""; - }; - D89477F20FB1DE18A04690586D7808C4 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; - EC4B0BEA27DDFEE43BB8A01A8A88802E /* Support Files */ = { - isa = PBXGroup; - children = ( - E09142CF0722BCBDFF7C6EF2C6E3C5AD /* Alderis.modulemap */, - 25FF3569DF1635C4D4EFDBE3EC713871 /* Alderis-dummy.m */, - 08E8A13AC29E80A401DF99D68805957A /* Alderis-prefix.pch */, - 97CE419BD858D6FE5C2D08A274A5FCC4 /* Alderis-umbrella.h */, - F15D960A598C031F6A6BF1896262FA7B /* Alderis.debug.xcconfig */, - 4D7238C16049AC7D52380A3F0F037DA1 /* Alderis.release.xcconfig */, - 9DE62A37068140A5FCA8272D4E7A546B /* ResourceBundle-Alderis-Alderis-Info.plist */, - ); - name = "Support Files"; - path = "Demo/Pods/Target Support Files/Alderis"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 51A2924DCFAFC3B05542EA589886B1C6 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CB88CD902C9400106C9CDC4C3BADDD9 /* Alderis.h in Headers */, - 37F5ABFCFA0B0D72CAEFBDFA3B5ED787 /* Alderis-umbrella.h in Headers */, - 05103D0E4FCCCF239AD0A0B6BC8BF438 /* AlderisSDKCompatibility.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 98EEA9AFD506EEC0E957CF8454860A08 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - D951C553E2937D74043A298EFD7BC0BA /* Pods-Alderis Demo-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0BF6D5F4E6EC1CF170610CBAB0F6CEF2 /* Alderis */ = { - isa = PBXNativeTarget; - buildConfigurationList = C437B582C0CD78FA49BA3C9157B57927 /* Build configuration list for PBXNativeTarget "Alderis" */; - buildPhases = ( - 51A2924DCFAFC3B05542EA589886B1C6 /* Headers */, - 8B61953302CC432EB3F74A8EC097B279 /* Sources */, - 7B383053112517B152D012AEDB5956A0 /* Frameworks */, - D84A6533DC71D25B63EED5E38DCCF222 /* Copy generated compatibility header */, - ); - buildRules = ( - ); - dependencies = ( - D321C14625B095BD1368B46D005293EF /* PBXTargetDependency */, - ); - name = Alderis; - productName = Alderis; - productReference = 0E81A451910A2F39C165935A61188DD7 /* Alderis */; - productType = "com.apple.product-type.library.static"; - }; - 9E56E22F79A7CE7FED2693342F797A57 /* Pods-Alderis Demo */ = { - isa = PBXNativeTarget; - buildConfigurationList = B5722471F152263BB3FE3DEF51C789D0 /* Build configuration list for PBXNativeTarget "Pods-Alderis Demo" */; - buildPhases = ( - 98EEA9AFD506EEC0E957CF8454860A08 /* Headers */, - 96050FC4E13B8F5C9F1D8D224D1953EC /* Sources */, - 093A79D3DC07E777E846D998AB14C931 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 55B65CD199127E2795039C1DB95BFB0C /* PBXTargetDependency */, - ); - name = "Pods-Alderis Demo"; - productName = "Pods-Alderis Demo"; - productReference = 4339F8A837B317D1831C93FD9779103A /* Pods-Alderis Demo */; - productType = "com.apple.product-type.library.static"; - }; - E06BFBDAEB84B8EBA0D1A8B43D16EF27 /* Alderis-Alderis */ = { - isa = PBXNativeTarget; - buildConfigurationList = 126BE766A5469BB6DD9826BB45369530 /* Build configuration list for PBXNativeTarget "Alderis-Alderis" */; - buildPhases = ( - C568396AF857A063AA905A65555EAE01 /* Sources */, - DA7ECD0D42EFE4684D076E810F8EDFF5 /* Frameworks */, - F92A57EF1BCA2E27937952913AF9DD9B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Alderis-Alderis"; - productName = Alderis; - productReference = 96D71531FEDE7846F4A8F71D072D1591 /* Alderis.bundle */; - productType = "com.apple.product-type.bundle"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - BFDFE7DC352907FC980B868725387E98 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1240; - LastUpgradeCheck = 1240; - }; - buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 10.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - Base, - en, - ); - mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 887692E1D0CD32ADA45C133CE07E5777 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 0BF6D5F4E6EC1CF170610CBAB0F6CEF2 /* Alderis */, - E06BFBDAEB84B8EBA0D1A8B43D16EF27 /* Alderis-Alderis */, - 9E56E22F79A7CE7FED2693342F797A57 /* Pods-Alderis Demo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - F92A57EF1BCA2E27937952913AF9DD9B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DCF8E0093062AD806401B93579A00946 /* Assets-ios12.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - D84A6533DC71D25B63EED5E38DCCF222 /* Copy generated compatibility header */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h", - "${PODS_ROOT}/Headers/Public/Alderis/Alderis.modulemap", - "${PODS_ROOT}/Headers/Public/Alderis/Alderis-umbrella.h", - ); - name = "Copy generated compatibility header"; - outputFileListPaths = ( - ); - outputPaths = ( - "${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap", - "${BUILT_PRODUCTS_DIR}/Alderis-umbrella.h", - "${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "COMPATIBILITY_HEADER_PATH=\"${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h\"\nMODULE_MAP_PATH=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap\"\n\nditto \"${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h\" \"${COMPATIBILITY_HEADER_PATH}\"\nditto \"${PODS_ROOT}/Headers/Public/Alderis/Alderis.modulemap\" \"${MODULE_MAP_PATH}\"\nditto \"${PODS_ROOT}/Headers/Public/Alderis/Alderis-umbrella.h\" \"${BUILT_PRODUCTS_DIR}\"\nprintf \"\\n\\nmodule ${PRODUCT_MODULE_NAME}.Swift {\\n header \\\"${COMPATIBILITY_HEADER_PATH}\\\"\\n requires objc\\n}\\n\" >> \"${MODULE_MAP_PATH}\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 8B61953302CC432EB3F74A8EC097B279 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 69E9416DB84F9C1578C79463C00F1034 /* AccessibilityComplianceLabel.swift in Sources */, - 854293819B45401802BEBE4DAE9593D5 /* AccessibilityContrastSelector.swift in Sources */, - 65FF5EEC743492FF458C8C511687895F /* Alderis-dummy.m in Sources */, - 6309E88FA19CA2C7E1397C854EF70D66 /* Assets.swift in Sources */, - 61BC805E3601DBC8943B104CE9DAB27D /* BottomSheetTransition.swift in Sources */, - 1249F0A1123D8CD9B892BBC474175825 /* Color.swift in Sources */, - 0D8BF7C4464C83EF0B028B01A78AEDD6 /* ColorPickerAccessibilityViewController.swift in Sources */, - 135D3BAA68E17A0AC6B3667951342ED9 /* ColorPickerConfiguration.swift in Sources */, - 50DCDD2604D2D2195B7FE86549C8C60A /* ColorPickerDelegate.swift in Sources */, - 2939CFC7F4E151B8BA170E2718FE5C2D /* ColorPickerInnerViewController.swift in Sources */, - A4B55DD8DF7981D5348FED7150137FD4 /* ColorPickerMapSlider.swift in Sources */, - E5F02AF27C52B7EEDFA8F5CE568058FC /* ColorPickerMapViewController.swift in Sources */, - B07A5681AD8C8E562F7768F8687EA98D /* ColorPickerNumericSlider.swift in Sources */, - 612EFA95A4DD8D4015CF8FA9A1878399 /* ColorPickerSlider.swift in Sources */, - 7C15B0F74C21E30A6D2FE833A039C6A5 /* ColorPickerSlidersViewController.swift in Sources */, - BC1230C95F458765C8CEBDF80109609B /* ColorPickerSwatchViewController.swift in Sources */, - F8144CFF31B54A06D202B96AA7FA0CF1 /* ColorPickerTabViewController.swift in Sources */, - 5B575D82A33FC6ADA46F8463ECD56545 /* ColorPickerViewController.swift in Sources */, - 675572C2B585A87F28A077B811DA8FA5 /* ColorPickerWheelView.swift in Sources */, - 1EAAE13CA289E1465B194A38124C4D5F /* ColorWell.swift in Sources */, - 7AE2A9360F7B1AFEF18CA72FAB8E47CA /* DialogButton.swift in Sources */, - EB32A80054921FB5EEECD0B2C1BA1FB8 /* GradientView.swift in Sources */, - A27A1ADC9991A8C08AE350860C1B4894 /* NSBeep.swift in Sources */, - 6A38E3A03B08C4DB4E72A35AF6C42293 /* SeparatorView.swift in Sources */, - 53966AFCE54B78B4BEFD48FF19423AC2 /* TextViewLabel.swift in Sources */, - BA43D3FA7CD5A3F1F61BB205626EE7F7 /* UIColorAdditions.swift in Sources */, - B622882FF8E7B4CCFFB32813BDCB2D34 /* UIFloat.swift in Sources */, - 815F9C399ED6E92FB5C7CBA666339C43 /* UIFontDescriptorAdditions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 96050FC4E13B8F5C9F1D8D224D1953EC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8E81254A16B7C247CF0DEBA561FFFBBF /* Pods-Alderis Demo-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C568396AF857A063AA905A65555EAE01 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 55B65CD199127E2795039C1DB95BFB0C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Alderis; - target = 0BF6D5F4E6EC1CF170610CBAB0F6CEF2 /* Alderis */; - targetProxy = EE5F7F514D1321804708AF70F97259CC /* PBXContainerItemProxy */; - }; - D321C14625B095BD1368B46D005293EF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "Alderis-Alderis"; - target = E06BFBDAEB84B8EBA0D1A8B43D16EF27 /* Alderis-Alderis */; - targetProxy = 406A8A6B603CDE598EAB01818A637160 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 09F3B7AD1520CE6F6C0A503058268F79 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8BEDC7D63209B1F7C6891F0A83428EC0 /* Pods-Alderis Demo.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 243AD1FF67BA11AD2C1237B6D72C1AEA /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4DAF9BE7C45EEC6325555273285DBCFF /* Pods-Alderis Demo.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 2B9E26EAE2CD392AD762421F663075A1 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 32C472C250AD6233A5A55B5200970444 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F15D960A598C031F6A6BF1896262FA7B /* Alderis.debug.xcconfig */; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Alderis"; - DEVELOPMENT_TEAM = N2LN9ZT493; - IBSC_MODULE = Alderis; - INFOPLIST_FILE = "Target Support Files/Alderis/ResourceBundle-Alderis-Alderis-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - PRODUCT_NAME = Alderis; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - 48E2F0964C45ACF1380D5197F8C8A485 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F15D960A598C031F6A6BF1896262FA7B /* Alderis.debug.xcconfig */; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/Alderis/Alderis-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MODULEMAP_FILE = Headers/Public/Alderis/Alderis.modulemap; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = Alderis; - PRODUCT_NAME = Alderis; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 63FAF33E1C55B71A5F5A8B3CC8749F99 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Release; - }; - ED8FFBDEE9F6373244786C888DEDA0C6 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4D7238C16049AC7D52380A3F0F037DA1 /* Alderis.release.xcconfig */; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/Alderis/Alderis-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MODULEMAP_FILE = Headers/Public/Alderis/Alderis.modulemap; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = Alderis; - PRODUCT_NAME = Alderis; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - FCFAE712F7B981CE1EF4FAB963869E91 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4D7238C16049AC7D52380A3F0F037DA1 /* Alderis.release.xcconfig */; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Alderis"; - DEVELOPMENT_TEAM = N2LN9ZT493; - IBSC_MODULE = Alderis; - INFOPLIST_FILE = "Target Support Files/Alderis/ResourceBundle-Alderis-Alderis-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - PRODUCT_NAME = Alderis; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 126BE766A5469BB6DD9826BB45369530 /* Build configuration list for PBXNativeTarget "Alderis-Alderis" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 32C472C250AD6233A5A55B5200970444 /* Debug */, - FCFAE712F7B981CE1EF4FAB963869E91 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2B9E26EAE2CD392AD762421F663075A1 /* Debug */, - 63FAF33E1C55B71A5F5A8B3CC8749F99 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B5722471F152263BB3FE3DEF51C789D0 /* Build configuration list for PBXNativeTarget "Pods-Alderis Demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 243AD1FF67BA11AD2C1237B6D72C1AEA /* Debug */, - 09F3B7AD1520CE6F6C0A503058268F79 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C437B582C0CD78FA49BA3C9157B57927 /* Build configuration list for PBXNativeTarget "Alderis" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 48E2F0964C45ACF1380D5197F8C8A485 /* Debug */, - ED8FFBDEE9F6373244786C888DEDA0C6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; -} diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-dummy.m b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-dummy.m deleted file mode 100644 index cc0acd6..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Alderis : NSObject -@end -@implementation PodsDummy_Alderis -@end diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-prefix.pch b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-prefix.pch deleted file mode 100644 index beb2a24..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-umbrella.h b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-umbrella.h deleted file mode 100644 index 9e9378d..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis-umbrella.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "Alderis.h" -#import "AlderisSDKCompatibility.h" - -FOUNDATION_EXPORT double AlderisVersionNumber; -FOUNDATION_EXPORT const unsigned char AlderisVersionString[]; - diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.debug.xcconfig b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.debug.xcconfig deleted file mode 100644 index 8db202b..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.debug.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alderis -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Alderis" "${PODS_ROOT}/Headers/Public" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.modulemap b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.modulemap deleted file mode 100644 index 042d2a0..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module Alderis { - umbrella header "Alderis-umbrella.h" - - export * - module * { export * } -} diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.release.xcconfig b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.release.xcconfig deleted file mode 100644 index 8db202b..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/Alderis.release.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alderis -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Alderis" "${PODS_ROOT}/Headers/Public" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/ResourceBundle-Alderis-Alderis-Info.plist b/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/ResourceBundle-Alderis-Alderis-Info.plist deleted file mode 100644 index 146e63e..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Alderis/ResourceBundle-Alderis-Alderis-Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.1.2 - CFBundleSignature - ???? - CFBundleVersion - 1 - NSPrincipalClass - - - diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-acknowledgements.markdown b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-acknowledgements.markdown deleted file mode 100644 index 9ae34b8..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-acknowledgements.markdown +++ /dev/null @@ -1,209 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## Alderis - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -Generated by CocoaPods - https://cocoapods.org diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-acknowledgements.plist b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-acknowledgements.plist deleted file mode 100644 index 3cbb799..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-acknowledgements.plist +++ /dev/null @@ -1,241 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - License - Apache License, Version 2.0 - Title - Alderis - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - https://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-dummy.m b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-dummy.m deleted file mode 100644 index bdfd81c..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_Alderis_Demo : NSObject -@end -@implementation PodsDummy_Pods_Alderis_Demo -@end diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Debug-input-files.xcfilelist b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Debug-input-files.xcfilelist deleted file mode 100644 index 1df96fb..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Debug-input-files.xcfilelist +++ /dev/null @@ -1,2 +0,0 @@ -${PODS_ROOT}/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources.sh -${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.bundle \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Debug-output-files.xcfilelist b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Debug-output-files.xcfilelist deleted file mode 100644 index 60900db..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Debug-output-files.xcfilelist +++ /dev/null @@ -1 +0,0 @@ -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Alderis.bundle \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Release-input-files.xcfilelist b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Release-input-files.xcfilelist deleted file mode 100644 index 1df96fb..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Release-input-files.xcfilelist +++ /dev/null @@ -1,2 +0,0 @@ -${PODS_ROOT}/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources.sh -${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.bundle \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Release-output-files.xcfilelist b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Release-output-files.xcfilelist deleted file mode 100644 index 60900db..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources-Release-output-files.xcfilelist +++ /dev/null @@ -1 +0,0 @@ -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Alderis.bundle \ No newline at end of file diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources.sh b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources.sh deleted file mode 100755 index 79e5f3c..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-resources.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/sh -set -e -set -u -set -o pipefail - -function on_error { - echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" -} -trap 'on_error $LINENO' ERR - -if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then - # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy - # resources to, so exit 0 (signalling the script phase was successful). - exit 0 -fi - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -# This protects against multiple targets copying the same framework dependency at the same time. The solution -# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html -RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") - -case "${TARGETED_DEVICE_FAMILY:-}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - 3) - TARGET_DEVICE_ARGS="--target-device tv" - ;; - 4) - TARGET_DEVICE_ARGS="--target-device watch" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; -esac - -install_resource() -{ - if [[ "$1" = /* ]] ; then - RESOURCE_PATH="$1" - else - RESOURCE_PATH="${PODS_ROOT}/$1" - fi - if [[ ! -e "$RESOURCE_PATH" ]] ; then - cat << EOM -error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. -EOM - exit 1 - fi - case $RESOURCE_PATH in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true - mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true - xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - *) - echo "$RESOURCE_PATH" || true - echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" - ;; - esac -} -if [[ "$CONFIGURATION" == "Debug" ]]; then - install_resource "${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.bundle" -fi -if [[ "$CONFIGURATION" == "Release" ]]; then - install_resource "${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.bundle" -fi - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] -then - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find -L "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "${PODS_ROOT}*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - else - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" - fi -fi diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-umbrella.h b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-umbrella.h deleted file mode 100644 index 5a0ea94..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double Pods_Alderis_DemoVersionNumber; -FOUNDATION_EXPORT const unsigned char Pods_Alderis_DemoVersionString[]; - diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.debug.xcconfig b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.debug.xcconfig deleted file mode 100644 index ada2059..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.debug.xcconfig +++ /dev/null @@ -1,15 +0,0 @@ -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Alderis" -LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Alderis" /usr/lib/swift -OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.modulemap" -OTHER_LDFLAGS = $(inherited) -ObjC -l"Alderis" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.modulemap" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_PODFILE_DIR_PATH = ${SRCROOT}/. -PODS_ROOT = ${SRCROOT}/Pods -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alderis" -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.modulemap b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.modulemap deleted file mode 100644 index c1a6429..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module Pods_Alderis_Demo { - umbrella header "Pods-Alderis Demo-umbrella.h" - - export * - module * { export * } -} diff --git a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.release.xcconfig b/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.release.xcconfig deleted file mode 100644 index ada2059..0000000 --- a/Tweaks/Alderis/Demo/Pods/Target Support Files/Pods-Alderis Demo/Pods-Alderis Demo.release.xcconfig +++ /dev/null @@ -1,15 +0,0 @@ -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Alderis" -LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Alderis" /usr/lib/swift -OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.modulemap" -OTHER_LDFLAGS = $(inherited) -ObjC -l"Alderis" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alderis/Alderis.modulemap" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_PODFILE_DIR_PATH = ${SRCROOT}/. -PODS_ROOT = ${SRCROOT}/Pods -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alderis" -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tweaks/Alderis/LICENSE.md b/Tweaks/Alderis/LICENSE.md deleted file mode 100644 index d645695..0000000 --- a/Tweaks/Alderis/LICENSE.md +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/Tweaks/Alderis/Makefile b/Tweaks/Alderis/Makefile deleted file mode 100644 index 7d86e1a..0000000 --- a/Tweaks/Alderis/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -export TARGET = iphone:latest:14.0 - -FRAMEWORK_OUTPUT_DIR = $(THEOS_OBJ_DIR)/xcode_derived/install/Library/Frameworks -ALDERIS_SDK_DIR = $(THEOS_OBJ_DIR)/alderis_sdk_$(THEOS_PACKAGE_BASE_VERSION) - -export ADDITIONAL_CFLAGS = -fobjc-arc -Wextra -Wno-unused-parameter -F$(FRAMEWORK_OUTPUT_DIR) -export ADDITIONAL_LDFLAGS = -F$(FRAMEWORK_OUTPUT_DIR) - -INSTALL_TARGET_PROCESSES = Preferences - -include $(THEOS)/makefiles/common.mk - -XCODEPROJ_NAME = Alderis - -FINALPACKAGE = 1 - -Alderis_XCODEFLAGS = DYLIB_INSTALL_NAME_BASE=/Library/Frameworks BUILD_LIBRARY_FOR_DISTRIBUTION=YES ARCHS="$(ARCHS)" -quiet - -SUBPROJECTS = lcpshim - -include $(THEOS_MAKE_PATH)/xcodeproj.mk -include $(THEOS_MAKE_PATH)/aggregate.mk - diff --git a/Tweaks/Alderis/Package.swift b/Tweaks/Alderis/Package.swift deleted file mode 100644 index 297fb87..0000000 --- a/Tweaks/Alderis/Package.swift +++ /dev/null @@ -1,16 +0,0 @@ -// swift-tools-version:5.2 - -import PackageDescription - -let package = Package( - name: "Alderis", - platforms: [ - .iOS(.v12) - ], - products: [ - .library(name: "Alderis", targets: ["Alderis"]), - ], - targets: [ - .target(name: "Alderis", path: "Alderis") - ] -) diff --git a/Tweaks/Alderis/README.md b/Tweaks/Alderis/README.md deleted file mode 100644 index 5d4322c..0000000 --- a/Tweaks/Alderis/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# ![Alderis Color Picker](screenshots/logo.jpg) - -**
Try it yourself: `pod try Alderis`
** - -Alderis is a fresh new color picker, with a gentle, fun, and dead simple user interface. It aims to incorporate the usual elements of a color picker, in a way that users will find easy and fun to use. - -The user can start by selecting a color they like on the initial color palette tab, and either accept it, or refine it using the color wheel and adjustment sliders found on the two other tabs. - -Alderis is named for the Alderamin (Alpha) star in the Cepheus (Cephei) constellation. (There is no dependency on the [Cephei](https://hbang.github.io/libcephei/) project.) - -## Why do I want this? Isn’t there already a color picker in iOS? -Alderis was [originally released](https://twitter.com/hbkirb/status/1239332547437326337) before iOS 14 was unveiled with a built-in [color picker](https://developer.apple.com/design/human-interface-guidelines/ios/controls/color-wells/) feature, which seems to be heavily inspired by Alderis. However, rather than throw in the towel here, I’m considering this an opportunity to continue building what I feel is a better, less cluttered user experience, with more configuration options for apps to fine-tune a color picker UI suitable for each use case and target market. - -If this doesn’t seem important to you, the answer is simple: skip Alderis and use [UIColorPickerViewController](https://developer.apple.com/documentation/uikit/uicolorpickerviewcontroller). If it does, read on. - -### Feature Comparison - - - - - - - - - - - - - - - - - - - - - - - - - - -
Alderis UIKit
Minimal UI ✔️ ✖️
Drag and drop colors within app ✔️ ✔️ *
Drag and drop colors across apps ✔️ ✖️
Color grid ✔️ ✔️
Color spectrum/wheel ✔️ ✔️
RGB sliders ✔️ ✔️
HSB sliders ✔️ ✖️
Grayscale slider ✔️ ✖️
Opacity slider ✔️ ✔️
Hex color code support ✔️ ✔️
Color space support (Display P3) ✖️ ✔️
Save favorite colors ✖️ ✔️
Saved colors shared across apps ✖️ ✔️
Grab color from screen (eyedropper) ✖️ ✔️
Customise title label ✔️ ✖️
Customise tab row visibility ✔️ ✖️
Customise visible tabs ✔️ ✖️
Customise initially selected tab ✔️ ✖️
Customise opacity slider visibility ✔️ ✔️
Customise color grid ✖️ ✖️
Interface Builder support ✖️ ✖️
SwiftUI support w/o UIKit bridging ✖️ ✖️
Observe value change with KVO ✖️ ✔️
- -\* UIColorWell supports dragging colors *onto* it, but not *out* of it. Alderis supports both directions, which are separately configurable. The default Alderis ColorWell behavior matches UIColorWell. Alderis supports drag and drop on the color picker window; UIKit does not. - -## Installation - -### CocoaPods -Add to your Podfile: - -```ruby -pod 'Alderis', '~> 1.2.0' -``` - -And then run `pod install`. - -### Carthage -Add to your Cartfile: - -```ruby -github 'hbang/Alderis' ~> 1.2.0 -``` - -And then run `carthage update`. - -### Swift Package Manager -1. Click File → Swift Packages → Add Package Dependency. -2. Enter `http://github.com/hbang/Alderis.git`. -3. Specify `1.2` as the version filter. - -Or, manually add it to your Package.swift: - -```swift -dependencies: [ - .package(url: "http://github.com/hbang/Alderis.git", from: "1.2.0") -] -``` - -And then run `swift package update`. - -### Jailbreak packages -Add `ws.hbang.alderis (>= 1.2)` to your `Depends:` list. - -#### Preference Bundles and libcolorpicker Compatibility -Alderis acts as a drop-in replacement for [libcolorpicker](https://github.com/atomikpanda/libcolorpicker), an abandoned but still very popular color picker library on jailbroken iOS. Packages can simply change their dependencies list to replace `org.thebigboss.libcolorpicker` with `ws.hbang.alderis (>= 1.2)` to switch their color picker to Alderis. No other changes required! - -For more information, refer to [the docs](https://hbang.github.io/Alderis/preference-bundles.html). - -## License -Licensed under the Apache License, version 2.0. Refer to [LICENSE.md](https://github.com/hbang/Alderis/blob/main/LICENSE.md). - -Header backdrop photo credit: [John-Mark Smith](https://unsplash.com/@mrrrk_smith) on Unsplash diff --git a/Tweaks/Alderis/build-fat.sh b/Tweaks/Alderis/build-fat.sh deleted file mode 100755 index e8d22ec..0000000 --- a/Tweaks/Alderis/build-fat.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# This makes me sad 🙁 - -set -e - -if [[ $(arch) != i386 ]]; then - echo "Not working on ARM. Try Rosetta instead?" - exit 1 -fi - -PROJECT_DIR=$(realpath $(dirname $0)) - -THEOS_OBJ_DIR=$PROJECT_DIR/.theos/obj -THEOS_STAGING_DIR=$PROJECT_DIR/.theos/_ -FRAMEWORK_OUTPUT_DIR=$THEOS_OBJ_DIR/install/Library/Frameworks - -echo -echo Building modern -echo -make clean -sudo xcode-select -switch /Applications/Xcode-13.4.0.app/Contents/Developer -make package \ - FINALPACKAGE=1 -cp $FRAMEWORK_OUTPUT_DIR/Alderis.framework/Alderis Alderis-ios14 - -echo -echo Building legacy -echo -make clean -mkdir -p $THEOS_OBJ_DIR -mv Alderis-ios14 $THEOS_OBJ_DIR -sudo xcode-select -switch /Applications/Xcode-11.7.app/Contents/Developer -make package \ - BUILD_LEGACY_ARM64E=1 \ - THEOS_PLATFORM_SDK_ROOT=/Applications/Xcode-11.7.app/Contents/Developer \ - FINALPACKAGE=1 -cp $FRAMEWORK_OUTPUT_DIR/Alderis.framework/Alderis $THEOS_OBJ_DIR/Alderis-ios12 - -echo -cp $THEOS_OBJ_DIR/Alderis-ios{12,14} $THEOS_STAGING_DIR/Library/Frameworks/Alderis.framework -sudo xcode-select -switch /Applications/Xcode-13.4.0.app/Contents/Developer -echo Alderis-ios12: -otool -h $THEOS_STAGING_DIR/Library/Frameworks/Alderis.framework/Alderis-ios12 -echo -echo Alderis-ios14: -otool -h $THEOS_STAGING_DIR/Library/Frameworks/Alderis.framework/Alderis-ios14 -echo -echo libcolorpicker.dylib: -otool -h $THEOS_STAGING_DIR/usr/lib/libcolorpicker.dylib - -echo -echo Packaging -echo -rm $THEOS_STAGING_DIR/Library/Frameworks/Alderis.framework/Alderis -ln -s Alderis-ios12 $THEOS_STAGING_DIR/Library/Frameworks/Alderis.framework/Alderis -$THEOS/bin/dm.pl -b -Zlzma -z9 .theos/_ packages/ diff --git a/Tweaks/Alderis/control b/Tweaks/Alderis/control deleted file mode 100644 index 65b8187..0000000 --- a/Tweaks/Alderis/control +++ /dev/null @@ -1,16 +0,0 @@ -Package: ws.hbang.alderis -Name: Alderis Color Picker -Depends: firmware (>= 12.0), firmware (>= 12.2) | ${LIBSWIFT}, uikittools -Replaces: org.thebigboss.libcolorpicker, me.nepeta.libcolorpicker -Provides: org.thebigboss.libcolorpicker (= 99.0), me.nepeta.libcolorpicker (= 99.0) -Version: 1.2 -Architecture: iphoneos-arm -Description: Color picker support library for tweaks -Maintainer: HASHBANG Productions -Author: HASHBANG Productions -Section: Development -Depiction: https://chariz.com/get/alderis -Icon: https://img.chariz.cloud/icon/alderis/icon@3x.png -Support: https://hashbang.productions/support/ -Tag: role::developer, compatible_min::ios12.0 -dev: hbang diff --git a/Tweaks/Alderis/info/Migrating to 1.1.md b/Tweaks/Alderis/info/Migrating to 1.1.md deleted file mode 100644 index 158bea5..0000000 --- a/Tweaks/Alderis/info/Migrating to 1.1.md +++ /dev/null @@ -1,42 +0,0 @@ -## Migrating to 1.1 - -### ColorPickerConfiguration -A variety of configuration options have been added, configured on a new `ColorPickerConfiguration` class. - -Code that looks like this: - -```swift -let colorPicker = ColorPickerViewController() -colorPicker.color = UIColor(red: 1, green: 0, blue: 1, alpha: 0) -present(colorPicker, animated: true, completion: nil) -``` - -Should now become: - -```swift -let configuration = ColorPickerConfiguration(color: UIColor(red: 1, green: 0, blue: 1, alpha: 0)) -// Do any other configuration you want here… -let colorPicker = ColorPickerViewController(configuration: configuration) -present(colorPicker, animated: true, completion: nil) -``` - -### Delegate changes -`ColorPickerDelegate.colorPicker(_:didSelect:)` is now fired with every change made within the color picker interface. Ensure any work done in this method does not assume the value is the user’s final selection. You might use this to update your user interface based on the current selection. If there is nothing useful you can do to improve the user experience, don’t implement this method. - -The new `ColorPickerDelegate.colorPicker(_:didAccept:)` method is now used to signal the user dismissing the color picker with a positive response, by tapping the Done button or dismissing the popover. - -For compatibility, if the color is set via the deprecated `ColorPickerViewController.color` API, the delegate behaves as it did in Alderis 1.0. - -### Popover style -Alderis now uses popovers, providing a more integrated interface design on iPad and Mac Catalyst. In order to support this, some popover presentation parameters must be set. If they are not set, UIKit throws an exception on presenting the view controller. - -For example: - -```swift -@IBAction func presentColorPicker(_ sender: UIView) { - let configuration = ColorPickerConfiguration(color: UIColor(red: 1, green: 0, blue: 1, alpha: 0)) - let colorPicker = ColorPickerViewController(configuration: configuration) - colorPicker.popoverPresentationController?.sourceView = sender - present(colorPicker, animated: true, completion: nil) -} -``` diff --git a/Tweaks/Alderis/info/Preference Bundles.md b/Tweaks/Alderis/info/Preference Bundles.md deleted file mode 100644 index bcc67ad..0000000 --- a/Tweaks/Alderis/info/Preference Bundles.md +++ /dev/null @@ -1,33 +0,0 @@ -## Alderis with Preference Bundles -Alderis acts as a drop-in replacement for [libcolorpicker](https://github.com/atomikpanda/libcolorpicker), an abandoned but still very popular color picker library on jailbroken iOS. Packages can simply change their dependencies list to replace `org.thebigboss.libcolorpicker` with `ws.hbang.alderis (>= 1.1)` to switch the color picker to Alderis. No other changes required! - -Alderis also provides a replacement, cleaner interface for preference bundles. Example usage: - -```xml - - cell - PSLinkCell - cellClass - HBColorPickerTableCell - defaults - com.example.myawesomething - default - #33b5e5 - label - Tint Color - showAlphaSlider - - PostNotification - com.example.myawesomething/ReloadPrefs - -``` - -Compared to libcolorpicker’s API design, this leans on the fundamentals of Preferences.framework, including using the framework’s built-in preference value getters/setters system. In fact, the only two distinct parts are the `cellClass` and the `showAlphaSlider` key. The rest should seem natural to typical Preference specifier plist usage. - -Remember to link against the `libcolorpicker` library from the preference bundle. With Theos, this might look like: - -```make -MyAwesomeThing_LIBRARIES = colorpicker -``` - -The functionality described in this section is only available in the jailbreak package for Alderis, specifically in the `libcolorpicker.dylib` binary ([lcpshim](https://github.com/hbang/Alderis/tree/main/lcpshim)), and is not included in the App Store (CocoaPods/Carthage) version. diff --git a/Tweaks/Alderis/lcpshim/ColorFunctions.m b/Tweaks/Alderis/lcpshim/ColorFunctions.m deleted file mode 100644 index 25d3015..0000000 --- a/Tweaks/Alderis/lcpshim/ColorFunctions.m +++ /dev/null @@ -1,18 +0,0 @@ -@import Alderis; -#import "libcolorpicker.h" - -UIColor *LCPParseColorString(NSString *hexString, NSString *fallback) { - UIColor *result = [[UIColor alloc] initWithHbcp_propertyListValue:hexString]; - if (result == nil && fallback != nil) { - result = [[UIColor alloc] initWithHbcp_propertyListValue:fallback]; - } - return result; -} - -UIColor *colorFromDefaultsWithKey(NSString *identifier, NSString *key, NSString *fallback) { - id result = CFBridgingRelease(CFPreferencesCopyValue((__bridge CFStringRef)key, (__bridge CFStringRef)identifier, CFSTR("mobile"), kCFPreferencesCurrentHost)); - if ([result isKindOfClass:NSString.class]) { - return LCPParseColorString((NSString *)result, fallback); - } - return LCPParseColorString(fallback, nil); -} diff --git a/Tweaks/Alderis/lcpshim/HBColorPickerTableCell+Private.h b/Tweaks/Alderis/lcpshim/HBColorPickerTableCell+Private.h deleted file mode 100644 index ee220ad..0000000 --- a/Tweaks/Alderis/lcpshim/HBColorPickerTableCell+Private.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "libcolorpicker.h" - -@interface HBColorPickerTableCell () - -- (UIColor *)_colorValue; -- (void)_setColorValue:(UIColor *)color; -- (void)_updateValue; - -- (void)_present; - -@end diff --git a/Tweaks/Alderis/lcpshim/HBColorPickerTableCell.h b/Tweaks/Alderis/lcpshim/HBColorPickerTableCell.h deleted file mode 100644 index 9394306..0000000 --- a/Tweaks/Alderis/lcpshim/HBColorPickerTableCell.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface HBColorPickerTableCell : PSTableCell - -@end diff --git a/Tweaks/Alderis/lcpshim/HBColorPickerTableCell.m b/Tweaks/Alderis/lcpshim/HBColorPickerTableCell.m deleted file mode 100644 index 043043b..0000000 --- a/Tweaks/Alderis/lcpshim/HBColorPickerTableCell.m +++ /dev/null @@ -1,127 +0,0 @@ -@import Alderis; -#import "libcolorpicker.h" -#import - -@interface UIView () -- (UIViewController *)_viewControllerForAncestor; -@end - -@interface HBColorPickerTableCell () -@end - -@implementation HBColorPickerTableCell { - HBColorWell *_colorWell; - HBColorPickerViewController *_viewController; -} - -#pragma mark - PSTableCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier specifier:(PSSpecifier *)specifier { - specifier.cellType = PSButtonCell; - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier specifier:specifier]; - if (self) { - self.textLabel.textColor = self.tintColor; - self.textLabel.highlightedTextColor = self.tintColor; - - _colorWell = [[HBColorWell alloc] initWithFrame:CGRectMake(0, 0, 32, 32)]; - _colorWell.isDragInteractionEnabled = YES; - _colorWell.isDropInteractionEnabled = YES; - [_colorWell addTarget:self action:@selector(_present) forControlEvents:UIControlEventTouchUpInside]; - [_colorWell addTarget:self action:@selector(_colorWellValueChanged:) forControlEvents:UIControlEventValueChanged]; - self.accessoryView = _colorWell; - - // This relies on an implementation detail - do not do this yourself! - [self addInteraction:[[UIDropInteraction alloc] initWithDelegate:_colorWell]]; - - [self _updateValue]; - } - return self; -} - -- (void)refreshCellContentsWithSpecifier:(PSSpecifier *)specifier { - specifier.cellType = PSButtonCell; - [super refreshCellContentsWithSpecifier:specifier]; - [self _updateValue]; - self.textLabel.textColor = self.tintColor; - self.textLabel.highlightedTextColor = self.tintColor; -} - -- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { - UIColor *color = _colorWell.color; - [super setHighlighted:highlighted animated:animated]; - // stop deleting my background color Apple!!! - _colorWell.color = color; -} - -- (void)setSelected:(BOOL)selected animated:(BOOL)animated { - if (selected) { - [self _present]; - } -} - -- (void)tintColorDidChange { - [super tintColorDidChange]; - self.textLabel.textColor = self.tintColor; - self.textLabel.highlightedTextColor = self.tintColor; -} - -#pragma mark - Properties - -- (NSString *)_hbcp_defaults { - return self.specifier.properties[@"defaults"]; -} - -- (NSString *)_hbcp_key { - return self.specifier.properties[@"key"]; -} - -- (NSString *)_hbcp_default { - return self.specifier.properties[@"default"]; -} - -- (BOOL)_hbcp_supportsAlpha { - return self.specifier.properties[@"showAlphaSlider"] ? ((NSNumber *)self.specifier.properties[@"showAlphaSlider"]).boolValue : NO; -} - -#pragma mark - Getters/setters - -- (UIColor *)_colorValue { - return LCPParseColorString([self.specifier performGetter], self._hbcp_default) ?: [UIColor colorWithWhite:0.6 alpha:1]; -} - -- (void)_setColorValue:(UIColor *)color { - [self.specifier performSetterWithValue:color.hbcp_propertyListValue]; - [self _updateValue]; -} - -- (void)_updateValue { - _colorWell.color = self._colorValue; -} - -#pragma mark - Actions - -- (void)_present { - _viewController = [[HBColorPickerViewController alloc] init]; - _viewController.delegate = self; - _viewController.popoverPresentationController.sourceView = self; - - HBColorPickerConfiguration *configuration = [[HBColorPickerConfiguration alloc] initWithColor:self._colorValue]; - configuration.title = self.textLabel.text; - configuration.supportsAlpha = self._hbcp_supportsAlpha; - _viewController.configuration = configuration; - - UIViewController *rootViewController = self._viewControllerForAncestor ?: [UIApplication sharedApplication].keyWindow.rootViewController; - [rootViewController presentViewController:_viewController animated:YES completion:nil]; -} - -- (void)_colorWellValueChanged:(HBColorWell *)sender { - [self _setColorValue:sender.color]; -} - -#pragma mark - HBColorPickerDelegate - -- (void)colorPicker:(HBColorPickerViewController *)colorPicker didSelectColor:(UIColor *)color { - [self _setColorValue:color]; -} - -@end diff --git a/Tweaks/Alderis/lcpshim/Makefile b/Tweaks/Alderis/lcpshim/Makefile deleted file mode 100644 index 38a9b34..0000000 --- a/Tweaks/Alderis/lcpshim/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -TARGET = iphone:clang:15.5:13.0 -ARCHS = arm64 -FINALPACKAGE = 1 -include $(THEOS)/makefiles/common.mk - -LIBRARY_NAME = libcolorpicker - -libcolorpicker_FILES = $(wildcard *.m) -libcolorpicker_PRIVATE_FRAMEWORKS = Preferences -libcolorpicker_EXTRA_FRAMEWORKS = Alderis -libcolorpicker_CFLAGS = -Wno-unguarded-availability -Wno-deprecated-declarations -fmodules - -include $(THEOS_MAKE_PATH)/library.mk diff --git a/Tweaks/Alderis/lcpshim/PFColorAlert.m b/Tweaks/Alderis/lcpshim/PFColorAlert.m deleted file mode 100644 index cb8db07..0000000 --- a/Tweaks/Alderis/lcpshim/PFColorAlert.m +++ /dev/null @@ -1,66 +0,0 @@ -@import Alderis; -#import "libcolorpicker.h" - -@interface PFColorAlert () - -@end - -@implementation PFColorAlert { - PFColorAlert *_strongSelf; - HBColorPickerViewController *_viewController; - UIColor *_color; - BOOL _showAlpha; - PFColorAlertCompletion _completion; -} - -+ (PFColorAlert *)colorAlertWithStartColor:(UIColor *)startColor showAlpha:(BOOL)showAlpha { - return [[self.class alloc] initWithStartColor:startColor showAlpha:showAlpha]; -} - -- (PFColorAlert *)initWithStartColor:(UIColor *)startColor showAlpha:(BOOL)showAlpha { - self = [super init]; - if (self) { - _color = startColor; - _showAlpha = showAlpha; - } - return self; -} - -- (void)displayWithCompletion:(PFColorAlertCompletion)completion { - _completion = [completion copy]; - _viewController = [[HBColorPickerViewController alloc] init]; - _viewController.delegate = self; - - UIColor *color = _color ?: [UIColor colorWithWhite:0.6 alpha:1]; - HBColorPickerConfiguration *configuration = [[HBColorPickerConfiguration alloc] initWithColor:color]; - configuration.supportsAlpha = _showAlpha; - _viewController.configuration = configuration; - - UIWindow *window = [UIApplication sharedApplication].keyWindow; - _viewController.popoverPresentationController.sourceView = window; - _viewController.popoverPresentationController.sourceRect = window.bounds; - _viewController.popoverPresentationController.permittedArrowDirections = 0; - [window.rootViewController presentViewController:_viewController animated:YES completion:nil]; - - // Keep a strong reference to ourself. The color picker delegate is weakly stored by - // HBColorPickerViewController, but some users of PFColorAlert do not keep a strong reference to - // the PFColorAlert instance after calling displayWithCompletion:, causing this class to get - // deallocated and the delegate never called. - _strongSelf = self; -} - -- (void)close { - _completion(_color); - _strongSelf = nil; -} - -- (void)colorPicker:(HBColorPickerViewController *)colorPicker didSelectColor:(UIColor *)color { - _color = [color copy]; - [self close]; -} - -- (void)colorPickerDidCancel:(HBColorPickerViewController *)colorPicker { - [self close]; -} - -@end diff --git a/Tweaks/Alderis/lcpshim/PFColorCell.m b/Tweaks/Alderis/lcpshim/PFColorCell.m deleted file mode 100644 index a5bc6dc..0000000 --- a/Tweaks/Alderis/lcpshim/PFColorCell.m +++ /dev/null @@ -1,30 +0,0 @@ -#import "libcolorpicker.h" -#import - -@interface PFColorCell : PFLiteColorCell - -@end - -@implementation PFColorCell - -- (NSString *)_hbcp_defaults { - return self.specifier.properties[@"color_defaults"]; -} - -- (NSString *)_hbcp_key { - return self.specifier.properties[@"color_key"]; -} - -- (NSString *)_hbcp_default { - return self.specifier.properties[@"color_fallback"]; -} - -- (NSString *)_hbcp_postNotification { - return self.specifier.properties[@"color_postNotification"]; -} - -- (BOOL)_hbcp_supportsAlpha { - return self.specifier.properties[@"usesAlpha"] ? ((NSNumber *)self.specifier.properties[@"usesAlpha"]).boolValue : NO; -} - -@end diff --git a/Tweaks/Alderis/lcpshim/PFLiteColorCell.m b/Tweaks/Alderis/lcpshim/PFLiteColorCell.m deleted file mode 100644 index d3a7605..0000000 --- a/Tweaks/Alderis/lcpshim/PFLiteColorCell.m +++ /dev/null @@ -1,71 +0,0 @@ -@import Alderis; -#import "libcolorpicker.h" -#import "HBColorPickerTableCell+Private.h" -#import - -@implementation PFLiteColorCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier specifier:(PSSpecifier *)specifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier specifier:specifier]; - if (self) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSLog(@"Alderis: %@: Using libcolorpicker compatibility class. Please consider switching to HBColorPickerTableCell. This warning will only be logged once.", self.class); - }); - } - return self; -} - -#pragma mark - Properties - -- (NSString *)_hbcp_defaults { - return self.specifier.properties[@"libcolorpicker"][@"defaults"]; -} - -- (NSString *)_hbcp_key { - return self.specifier.properties[@"libcolorpicker"][@"key"]; -} - -- (NSString *)_hbcp_default { - return self.specifier.properties[@"libcolorpicker"][@"fallback"]; -} - -- (NSString *)_hbcp_postNotification { - return self.specifier.properties[@"libcolorpicker"][@"PostNotification"]; -} - -- (BOOL)_hbcp_supportsAlpha { - return self.specifier.properties[@"libcolorpicker"][@"alpha"] ? ((NSNumber *)self.specifier.properties[@"libcolorpicker"][@"alpha"]).boolValue : NO; -} - -#pragma mark - Getters/setters - -- (UIColor *)_colorValue { - if (self._hbcp_defaults != nil && self._hbcp_key != nil) { - // libcolorpicker compatibility - NSString *path = [NSString stringWithFormat:@"/var/mobile/Library/Preferences/%@.plist", self._hbcp_defaults]; - NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:path]; - return LCPParseColorString(dictionary[self._hbcp_key], self._hbcp_default); - } - return [super _colorValue]; -} - -- (void)_setColorValue:(UIColor *)color { - // libcolorpicker compatibility - if (self._hbcp_defaults != nil && self._hbcp_key != nil) { - NSLog(@"Alderis: %@: Writing directly to plist file (libcolorpicker compatibility). I’m going to do it since it seems to be somewhat common, but you should be ashamed of yourself. https://hbang.github.io/Alderis/preference-bundles.html", self.class); - - NSString *path = [NSString stringWithFormat:@"/var/mobile/Library/Preferences/%@.plist", self._hbcp_defaults]; - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:path] ?: [NSMutableDictionary dictionary]; - dictionary[self._hbcp_key] = color.hbcp_propertyListValue; - [dictionary writeToFile:path atomically:YES]; - if (self._hbcp_postNotification != nil) { - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)self._hbcp_postNotification, nil, nil, YES); - } - [self _updateValue]; - } else { - [super _setColorValue:color]; - } -} - -@end diff --git a/Tweaks/Alderis/lcpshim/PFSimpleLiteColorCell.m b/Tweaks/Alderis/lcpshim/PFSimpleLiteColorCell.m deleted file mode 100644 index a87c7f1..0000000 --- a/Tweaks/Alderis/lcpshim/PFSimpleLiteColorCell.m +++ /dev/null @@ -1,5 +0,0 @@ -#import "libcolorpicker.h" - -@implementation PFSimpleLiteColorCell - -@end diff --git a/Tweaks/Alderis/lcpshim/UIColor+PFColor.m b/Tweaks/Alderis/lcpshim/UIColor+PFColor.m deleted file mode 100644 index af85b99..0000000 --- a/Tweaks/Alderis/lcpshim/UIColor+PFColor.m +++ /dev/null @@ -1,19 +0,0 @@ -@import Alderis; -#import "libcolorpicker.h" - -@implementation UIColor (PFColor) - -+ (UIColor *)PF_colorWithHex:(NSString *)hexString { - return [[self.class alloc] initWithHbcp_propertyListValue:hexString]; -} - -+ (NSString *)PF_hexFromColor:(UIColor *)color { - return color.hbcp_propertyListValue; -} - -+ (NSString *)hexFromColor:(UIColor *)color { - NSLog(@"Alderis: +[UIColor(PFColor) hexFromColor:]: Please migrate to +[UIColor(PFColor) PF_hexFromColor:]. This unprefixed method will be removed in future."); - return [self PF_hexFromColor:color]; -} - -@end diff --git a/Tweaks/Alderis/lcpshim/libcolorpicker.h b/Tweaks/Alderis/lcpshim/libcolorpicker.h deleted file mode 100644 index 8c26f3c..0000000 --- a/Tweaks/Alderis/lcpshim/libcolorpicker.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Alderis libcolorpicker Compatibility -// https://github.com/hbang/Alderis -// -// All interfaces declared in this file are deprecated and only provided for out-of-the-box -// compatibility with libcolorpicker. Do not write new code that uses these interfaces. -// - -@import UIKit; -#import -#import - -__BEGIN_DECLS -extern UIColor *LCPParseColorString(NSString *hexString, NSString *fallback); - -__attribute__((__deprecated__)) -extern UIColor *colorFromDefaultsWithKey(NSString *identifier, NSString *key, NSString *fallback); -__END_DECLS - -@interface UIColor (PFColor) - -+ (UIColor *)PF_colorWithHex:(NSString *)hexString; -+ (NSString *)PF_hexFromColor:(UIColor *)color; - -/// Do not use this unprefixed method. Migrate to +[UIColor PF_hexFromColor:] immediately. It will -/// be removed in a future release. -+ (NSString *)hexFromColor:(UIColor *)color __deprecated_msg("Use +[UIColor PF_hexFromColor:]"); - -@end - -typedef void (^PFColorAlertCompletion)(UIColor *color); - -@interface PFColorAlert : NSObject - -+ (instancetype)colorAlertWithStartColor:(UIColor *)startColor showAlpha:(BOOL)showAlpha; -- (instancetype)initWithStartColor:(UIColor *)startColor showAlpha:(BOOL)showAlpha; - -- (void)displayWithCompletion:(PFColorAlertCompletion)completion; -- (void)close; - -@end - -@interface HBColorPickerTableCell : PSTableCell - -@end - -@interface PFLiteColorCell : HBColorPickerTableCell - -@end - -@interface PFSimpleLiteColorCell : PFLiteColorCell - -@end diff --git a/Tweaks/Alderis/postinst b/Tweaks/Alderis/postinst deleted file mode 100755 index 30c9d43..0000000 --- a/Tweaks/Alderis/postinst +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -set -e - -# Install the right version 🙁 -cf_version=$(printf "%.0f" $(cfversion)) -if [ $cf_version -ge 1750 ]; then - tag=ios14 -else - tag=ios12 -fi - -if [ -e /Library/Frameworks/Alderis.framework/Alderis ]; then - rm /Library/Frameworks/Alderis.framework/Alderis -fi -ln -s Alderis-$tag /Library/Frameworks/Alderis.framework/Alderis - -# Tell the package manager to restart system app (SpringBoard) after installation. -if ! [ -z "$CYDIA" ]; then - read -r fd ver <&$fd - fi -fi - -exit 0 diff --git a/Tweaks/Alderis/screenshots/alderis-1.jpg b/Tweaks/Alderis/screenshots/alderis-1.jpg deleted file mode 100644 index f6ff201..0000000 Binary files a/Tweaks/Alderis/screenshots/alderis-1.jpg and /dev/null differ diff --git a/Tweaks/Alderis/screenshots/alderis-2.jpg b/Tweaks/Alderis/screenshots/alderis-2.jpg deleted file mode 100644 index 903d3e6..0000000 Binary files a/Tweaks/Alderis/screenshots/alderis-2.jpg and /dev/null differ diff --git a/Tweaks/Alderis/screenshots/alderis-3.jpg b/Tweaks/Alderis/screenshots/alderis-3.jpg deleted file mode 100644 index 5def6d6..0000000 Binary files a/Tweaks/Alderis/screenshots/alderis-3.jpg and /dev/null differ diff --git a/Tweaks/Alderis/screenshots/alderis-4.jpg b/Tweaks/Alderis/screenshots/alderis-4.jpg deleted file mode 100644 index 92e32bc..0000000 Binary files a/Tweaks/Alderis/screenshots/alderis-4.jpg and /dev/null differ diff --git a/Tweaks/Alderis/screenshots/logo.jpg b/Tweaks/Alderis/screenshots/logo.jpg deleted file mode 100644 index 7bf3b8d..0000000 Binary files a/Tweaks/Alderis/screenshots/logo.jpg and /dev/null differ diff --git a/Tweaks/DontEatMyContent b/Tweaks/DontEatMyContent new file mode 160000 index 0000000..2ea5e7b --- /dev/null +++ b/Tweaks/DontEatMyContent @@ -0,0 +1 @@ +Subproject commit 2ea5e7b3d992b7380fee5f816e38bb8c6cd5fae3 diff --git a/Tweaks/DontEatMyContent/.gitignore b/Tweaks/DontEatMyContent/.gitignore deleted file mode 100644 index 075ed95..0000000 --- a/Tweaks/DontEatMyContent/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -.theos/ -packages/ -.test/ - -# Temporary files -*~ -~$*.doc* -~$*.xls* -~$*.ppt* -*.xlk -*.pdf - -# .DS_Store files -*.DS_Store - -# Preference files -.vscode/ \ No newline at end of file diff --git a/Tweaks/DontEatMyContent/DontEatMyContent.plist b/Tweaks/DontEatMyContent/DontEatMyContent.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/DontEatMyContent/DontEatMyContent.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/DontEatMyContent/LICENSE.md b/Tweaks/DontEatMyContent/LICENSE.md deleted file mode 100644 index 831fc80..0000000 --- a/Tweaks/DontEatMyContent/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Foxster - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Tweaks/DontEatMyContent/Makefile b/Tweaks/DontEatMyContent/Makefile deleted file mode 100644 index 10cb52a..0000000 --- a/Tweaks/DontEatMyContent/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -TARGET := iphone:clang:latest:14.0 -ARCHS = arm64 - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = DontEatMyContent - -DontEatMyContent_FILES = Tweak.x Settings.x -DontEatMyContent_CFLAGS = -fobjc-arc -DontEatMyContent_FRAMEWORKS = UIKit - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/DontEatMyContent/README.md b/Tweaks/DontEatMyContent/README.md deleted file mode 100644 index 28ed3b1..0000000 --- a/Tweaks/DontEatMyContent/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# DontEatMyContent -Prevent the notch/Dynamic Island from munching on 2:1 video content in YouTube - -

- -

- -## How It Works -The rendering view is constrained to the safe area layout guide of its container so it will always be below the notch and Dynamic Island. These constraints are only activated for videos with 2:1 aspect ratio or wider to prevent unintended effects on videos with smaller aspect ratios. - -## Compatibility -Supports iPhone 12 mini, iPhone 13 series and newer **except** iPhone SE 3rd generation, iPhone 13 Pro Max and iPhone 14 Plus. - -> **Note**: From [v1.0.4](https://github.com/therealFoxster/DontEatMyContent/releases/tag/v1.0.4) onwards, the tweak only supports YouTube versions that got the [October 2022 redesign](https://blog.youtube/news-and-events/an-updated-look-and-feel-for-youtube/). v1.0.4 was tested and confirmed to be working with YouTube v17.43.1. - -## Grab It -- IPA file: https://therealfoxster.github.io/altsource-viewer/app?source=https://therealfoxster.github.io/altsource/apps.json&id=com.google.ios.youtube -- DEB file: https://github.com/therealFoxster/DontEatMyContent/releases/latest - -## Preview (iPhone 13 mini) -### Original Implementation -

- -

- -### Tweaked Implementation -

- -

- -### Zoomed to Fill -

- -

- -## License -[The MIT License](LICENSE.md) diff --git a/Tweaks/DontEatMyContent/Settings.x b/Tweaks/DontEatMyContent/Settings.x deleted file mode 100644 index 79fc50c..0000000 --- a/Tweaks/DontEatMyContent/Settings.x +++ /dev/null @@ -1,167 +0,0 @@ -#import "Tweak.h" - -// Adapted from -// https://github.com/PoomSmart/YouPiP/blob/bd04bf37be3d01540db418061164ae17a8f0298e/Settings.x -// https://github.com/qnblackcat/uYouPlus/blob/265927b3900d886e2085d05bfad7cd4157be87d2/Settings.xm - -extern void DEMC_showSnackBar(NSString *text); -extern NSBundle *DEMC_getTweakBundle(); -extern CGFloat constant; - -static const NSInteger sectionId = 517; // DontEatMyContent's section ID (just a random number) - -// Category for additional functions -@interface YTSettingsSectionItemManager (_DEMC) -- (void)updateDEMCSectionWithEntry:(id)entry; -@end - -%group DEMC_Settings - -%hook YTAppSettingsPresentationData -+ (NSArray *)settingsCategoryOrder { - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - NSUInteger insertIndex = [order indexOfObject:@(1)]; // Index of Settings > General - if (insertIndex != NSNotFound) - [mutableOrder insertObject:@(sectionId) atIndex:insertIndex + 1]; // Insert DontEatMyContent settings under General - return mutableOrder; -} -%end - -%hook YTSettingsSectionItemManager -%new -- (void)updateDEMCSectionWithEntry:(id)entry { - YTSettingsViewController *delegate = [self valueForKey:@"_dataDelegate"]; - NSMutableArray *sectionItems = [NSMutableArray array]; // Create autoreleased array - NSBundle *bundle = DEMC_getTweakBundle(); - - // Enabled - YTSettingsSectionItem *enabled = [%c(YTSettingsSectionItem) switchItemWithTitle:LOCALIZED_STRING(@"ENABLED") - titleDescription:LOCALIZED_STRING(@"TWEAK_DESC") - accessibilityIdentifier:nil - switchOn:IS_TWEAK_ENABLED - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:ENABLED_KEY]; - - YTAlertView *alert = [%c(YTAlertView) confirmationDialogWithAction:^ - { - // https://stackoverflow.com/a/17802404/19227228 - [[UIApplication sharedApplication] performSelector:@selector(suspend)]; - [NSThread sleepForTimeInterval:0.5]; - exit(0); - } - actionTitle:LOCALIZED_STRING(@"EXIT") - cancelTitle:LOCALIZED_STRING(@"LATER") - ]; - alert.title = DEMC; - alert.subtitle = LOCALIZED_STRING(@"EXIT_YT_DESC"); - [alert show]; - - return YES; - } - settingItemId:0 - ]; - [sectionItems addObject:enabled]; - - // Safe area constant - YTSettingsSectionItem *constraintConstant = [%c(YTSettingsSectionItem) itemWithTitle:LOCALIZED_STRING(@"SAFE_AREA_CONST") - titleDescription:LOCALIZED_STRING(@"SAFE_AREA_CONST_DESC") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return [NSString stringWithFormat:@"%.1f", constant]; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) { - __block YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; - NSMutableArray *rows = [NSMutableArray array]; - - float currentConstant = 20.0; - float storedConstant = [[NSUserDefaults standardUserDefaults] floatForKey:SAFE_AREA_CONSTANT_KEY];; - UInt8 index = 0, selectedIndex = 0; - while (currentConstant <= 25.0) { - NSString *title = [NSString stringWithFormat:@"%.1f", currentConstant]; - if (currentConstant == DEFAULT_CONSTANT) - title = [NSString stringWithFormat:@"%.1f (%@)", currentConstant, LOCALIZED_STRING(@"DEFAULT")]; - if (currentConstant == storedConstant) - selectedIndex = index; - [rows addObject:[%c(YTSettingsSectionItem) checkmarkItemWithTitle:title - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) { - [[NSUserDefaults standardUserDefaults] setFloat:currentConstant forKey:SAFE_AREA_CONSTANT_KEY]; - constant = currentConstant; - [settingsViewController reloadData]; // Refresh section's detail text (constant) - DEMC_showSnackBar(LOCALIZED_STRING(@"SAFE_AREA_CONST_MESSAGE")); - return YES; - } - ]]; - currentConstant += 0.5; index++; - } - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOCALIZED_STRING(@"SAFE_AREA_CONST") - pickerSectionTitle:nil - rows:rows - selectedItemIndex:selectedIndex - parentResponder:[self parentResponder] - ]; - - [settingsViewController pushViewController:picker]; - return YES; - } - ]; - if (IS_TWEAK_ENABLED) [sectionItems addObject:constraintConstant]; - - // Color views - YTSettingsSectionItem *colorViews = [%c(YTSettingsSectionItem) switchItemWithTitle:LOCALIZED_STRING(@"COLOR_VIEWS") - titleDescription:LOCALIZED_STRING(@"COLOR_VIEWS_DESC") - accessibilityIdentifier:nil - switchOn:IS_COLOR_VIEWS_ENABLED - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:COLOR_VIEWS_ENABLED_KEY]; - DEMC_showSnackBar(LOCALIZED_STRING(@"CHANGES_SAVED")); - return YES; - } - settingItemId:0 - ]; - if (IS_TWEAK_ENABLED) [sectionItems addObject:colorViews]; - - // Report an issue - YTSettingsSectionItem *reportIssue = [%c(YTSettingsSectionItem) itemWithTitle:LOCALIZED_STRING(@"REPORT_ISSUE") - titleDescription:nil - accessibilityIdentifier:nil - detailTextBlock:nil - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) { - return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/therealFoxster/DontEatMyContent/issues/new"]]; - } - ]; - [sectionItems addObject:reportIssue]; - - // View source code - YTSettingsSectionItem *sourceCode = [%c(YTSettingsSectionItem) itemWithTitle:LOCALIZED_STRING(@"SOURCE_CODE") - titleDescription:nil - accessibilityIdentifier:nil - detailTextBlock:nil - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) { - return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/therealFoxster/DontEatMyContent"]]; - } - ]; - [sectionItems addObject:sourceCode]; - - [delegate setSectionItems:sectionItems - forCategory:sectionId - title:DEMC - titleDescription:nil - headerHidden:NO - ]; -} -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { - if (category == sectionId) { - [self updateDEMCSectionWithEntry:entry]; - return; - } - %orig; -} -%end - -%end // group DEMC_Settings - -%ctor { - %init(DEMC_Settings); -} \ No newline at end of file diff --git a/Tweaks/DontEatMyContent/Tweak.h b/Tweaks/DontEatMyContent/Tweak.h deleted file mode 100644 index c8d3ef0..0000000 --- a/Tweaks/DontEatMyContent/Tweak.h +++ /dev/null @@ -1,108 +0,0 @@ -#import - -#define DEMC @"DontEatMyContent" - -// Keys -#define ENABLED_KEY @"DEMC_enabled" -#define COLOR_VIEWS_ENABLED_KEY @"DEMC_colorViewsEnabled" -#define SAFE_AREA_CONSTANT_KEY @"DEMC_safeAreaConstant" - -#define DEFAULT_CONSTANT 22.0 -#define IS_TWEAK_ENABLED [[NSUserDefaults standardUserDefaults] boolForKey:ENABLED_KEY] -#define IS_COLOR_VIEWS_ENABLED [[NSUserDefaults standardUserDefaults] boolForKey:COLOR_VIEWS_ENABLED_KEY] -#define LOCALIZED_STRING(s) [bundle localizedStringForKey:s value:nil table:nil] - -@interface YTPlayerViewController : UIViewController -- (id)activeVideoPlayerOverlay; -- (id)playerView; -- (BOOL)isCurrentVideoVertical; -@end - -@interface YTPlayerView : UIView -- (id)renderingView; -@end - -@interface YTMainAppVideoPlayerOverlayViewController : UIViewController -- (BOOL)isFullscreen; -@end - -@interface MLHAMSBDLSampleBufferRenderingView : UIView -@end - -@interface YTMainAppEngagementPanelViewController : UIViewController -- (BOOL)isLandscapeEngagementPanel; -- (BOOL)isPeekingSupported; -@end - -@interface YTEngagementPanelContainerViewController : UIViewController -- (BOOL)isLandscapeEngagementPanel; -- (BOOL)isPeekingSupported; -@end - -@interface YTLabel : UILabel -@property (nonatomic, copy, readwrite) NSString *text; -@end - -@interface YTSettingsCell : UICollectionViewCell -@end - -@interface YTSettingsSectionItemManager : NSObject -- (id)parentResponder; -@end - -@interface YTSettingsPickerViewController : UIViewController -- (instancetype)initWithNavTitle:(NSString *)navTitle - pickerSectionTitle:(NSString *)pickerSectionTitle - rows:(NSArray *)rows - selectedItemIndex:(NSUInteger)selectedItemIndex - parentResponder:(id)parentResponder; -@end - -@interface YTSettingsSectionItem : NSObject -+ (instancetype)switchItemWithTitle:(NSString *)title - titleDescription:(NSString *)titleDescription - accessibilityIdentifier:(NSString *)accessibilityIdentifier - switchOn:(BOOL)switchOn - switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock - settingItemId:(int)settingItemId; -+ (instancetype)itemWithTitle:(NSString *)title - titleDescription:(NSString *)titleDescription - accessibilityIdentifier:(NSString *)accessibilityIdentifier - detailTextBlock:(id)detailTextBlock - selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title - selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -@end - -@interface YTSettingsViewController : UIViewController -- (void)setSectionItems:(NSMutableArray *)sectionItems - forCategory:(NSInteger)category - title:(NSString *)title - titleDescription:(NSString *)titleDescription - headerHidden:(BOOL)headerHidden; -- (void)pushViewController:(UIViewController *)viewController; -- (void)reloadData; -@end - -// Alert -@interface YTAlertView : UIView -@property (nonatomic, copy, readwrite) NSString *title; -@property (nonatomic, copy, readwrite) NSString *subtitle; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action - actionTitle:(NSString *)actionTitle - cancelTitle:(NSString *)cancelTitle; -- (void)show; -@end - -// Snack bar -@interface YTHUDMessage : NSObject -+ (id)messageWithText:(id)text; -@end -@interface GOOHUDManagerInternal : NSObject -- (void)showMessageMainThread:(id)message; -+ (id)sharedInstance; -@end - -@interface YTUIUtils : NSObject -+ (BOOL)openURL:(NSURL *)url; -@end \ No newline at end of file diff --git a/Tweaks/DontEatMyContent/Tweak.x b/Tweaks/DontEatMyContent/Tweak.x deleted file mode 100644 index 2d648a6..0000000 --- a/Tweaks/DontEatMyContent/Tweak.x +++ /dev/null @@ -1,279 +0,0 @@ -#import -#import -#import "Tweak.h" - -#define UNSUPPORTED_DEVICES @[@"iPhone14,3", @"iPhone14,6", @"iPhone14,8"] -#define THRESHOLD 1.99 - -CGFloat constant; // Makes rendering view a bit larger since constraining to safe area leaves a gap between the notch/Dynamic Island and video -static CGFloat videoAspectRatio = 16/9; -static BOOL isZoomedToFill = NO; -static BOOL isEngagementPanelVisible = NO; -static BOOL isRemoveEngagementPanelViewControllerWithIdentifierCalled = NO; - -static MLHAMSBDLSampleBufferRenderingView *renderingView; -static NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstraint, *centerYConstraint; - -static BOOL DEMC_isDeviceSupported(); -static void DEMC_activateConstraints(); -static void DEMC_deactivateConstraints(); -static void DEMC_centerRenderingView(); -void DEMC_showSnackBar(NSString *text); -NSBundle *DEMC_getTweakBundle(); - -%group DEMC_Tweak - -// Retrieve video aspect ratio -%hook YTPlayerView -- (void)setAspectRatio:(CGFloat)aspectRatio { - %orig(aspectRatio); - videoAspectRatio = aspectRatio; -} -%end - -%hook YTPlayerViewController -- (void)viewDidAppear:(BOOL)animated { - YTPlayerView *playerView = [self playerView]; - UIView *renderingViewContainer = [playerView valueForKey:@"_renderingViewContainer"]; - renderingView = [playerView renderingView]; - - widthConstraint = [renderingView.widthAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.widthAnchor constant:constant]; - heightConstraint = [renderingView.heightAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.heightAnchor constant:constant]; - centerXConstraint = [renderingView.centerXAnchor constraintEqualToAnchor:renderingViewContainer.centerXAnchor]; - centerYConstraint = [renderingView.centerYAnchor constraintEqualToAnchor:renderingViewContainer.centerYAnchor]; - - if (IS_COLOR_VIEWS_ENABLED) { - playerView.backgroundColor = [UIColor blueColor]; - renderingViewContainer.backgroundColor = [UIColor greenColor]; - renderingView.backgroundColor = [UIColor redColor]; - } else { - playerView.backgroundColor = nil; - renderingViewContainer.backgroundColor = nil; - renderingView.backgroundColor = [UIColor blackColor]; - } - - YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay]; - - // Must check class since YTInlineMutedPlaybackPlayerOverlayViewController doesn't have -(BOOL)isFullscreen - if ([activeVideoPlayerOverlay isKindOfClass:%c(YTMainAppVideoPlayerOverlayViewController)] && - [activeVideoPlayerOverlay isFullscreen] && !isZoomedToFill && !isEngagementPanelVisible) - DEMC_activateConstraints(); - - %orig(animated); -} -// New video played -- (void)playbackController:(id)playbackController didActivateVideo:(id)video withPlaybackData:(id)playbackData { - %orig(playbackController, video, playbackData); - - isEngagementPanelVisible = NO; - isRemoveEngagementPanelViewControllerWithIdentifierCalled = NO; - - if ([[self activeVideoPlayerOverlay] isFullscreen]) - // New video played while in full screen (landscape) - // Activate since new videos played in full screen aren't zoomed-to-fill by default - // (i.e. the notch/Dynamic Island will cut into content when playing a new video in full screen) - DEMC_activateConstraints(); - else if (![self isCurrentVideoVertical] && ((YTPlayerView *)[self playerView]).userInteractionEnabled) - DEMC_deactivateConstraints(); -} -- (void)setPlayerViewLayout:(int)layout { - %orig(layout); - - if (![[self activeVideoPlayerOverlay] isKindOfClass:%c(YTMainAppVideoPlayerOverlayViewController)]) return; - - switch (layout) { - case 1: // Mini bar - break; - case 2: - DEMC_deactivateConstraints(); - break; - case 3: // Fullscreen - if (!isZoomedToFill && !isEngagementPanelVisible) DEMC_activateConstraints(); - break; - default: - break; - } -} -%end - -// Pinch to zoom -%hook YTVideoFreeZoomOverlayView -- (void)didRecognizePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer { - DEMC_deactivateConstraints(); - %orig(pinchGestureRecognizer); -} -// Detect zoom to fill -- (void)showLabelForSnapState:(NSInteger)snapState { - if (snapState == 0) { // Original - isZoomedToFill = NO; - DEMC_activateConstraints(); - } else if (snapState == 1) { // Zoomed to fill - isZoomedToFill = YES; - // No need to deactivate constraints as it's already done in -(void)didRecognizePinch:(UIPinchGestureRecognizer *) - } - %orig(snapState); -} -%end - -// Mini bar dismiss -%hook YTWatchMiniBarViewController -- (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType { - %orig(velocity, gestureType); - isZoomedToFill = NO; // YouTube undoes zoom-to-fill when mini bar is dismissed -} -- (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType skipShouldDismissCheck:(BOOL)skipShouldDismissCheck { - %orig(velocity, gestureType, skipShouldDismissCheck); - isZoomedToFill = NO; -} -%end - -%hook YTMainAppEngagementPanelViewController -// Engagement panel (comment, description, etc.) about to show up -- (void)viewWillAppear:(BOOL)animated { - if ([self isPeekingSupported]) { - // Shorts (only Shorts support peeking, I think) - } else { - // Everything else - isEngagementPanelVisible = YES; - if ([self isLandscapeEngagementPanel]) { - DEMC_deactivateConstraints(); - } - } - %orig(animated); -} -%end - -%hook YTEngagementPanelContainerViewController -// Engagement panel about to dismiss -- (void)notifyEngagementPanelContainerControllerWillHideFinalPanel { - // Crashes if plays new video while in full screen causing engagement panel dismissal - // Must check if engagement panel was dismissed because new video played - // (i.e. if -(void)removeEngagementPanelViewControllerWithIdentifier:(id) was called prior) - if (![self isPeekingSupported] && !isRemoveEngagementPanelViewControllerWithIdentifierCalled) { - isEngagementPanelVisible = NO; - if ([self isLandscapeEngagementPanel] && !isZoomedToFill) { - DEMC_activateConstraints(); - } - } - %orig; -} -- (void)removeEngagementPanelViewControllerWithIdentifier:(id)identifier { - // Usually called when engagement panel is open & new video is played or mini bar is dismissed - isRemoveEngagementPanelViewControllerWithIdentifierCalled = YES; - %orig(identifier); -} -%end - -%end // group DEMC_Tweak - -%group DEMC_UnsupportedDevice - -// Get tweak settings' index path & prevent it from being opened on unsupported devices -id settingsCollectionView; -NSIndexPath *tweakIndexPath; -%hook YTCollectionViewController -- (id)collectionView:(id)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - YTSettingsCell *cell = %orig; - if ([cell isKindOfClass:%c(YTSettingsCell)]) { - YTLabel *title = [cell valueForKey:@"_titleLabel"]; - if ([title.text isEqualToString:DEMC]) { - settingsCollectionView = collectionView; - tweakIndexPath = indexPath; - } - } - return cell; -} -- (BOOL)collectionView:(id)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath { - if (collectionView == settingsCollectionView && indexPath == tweakIndexPath) { - NSBundle *bundle = DEMC_getTweakBundle(); - DEMC_showSnackBar(LOCALIZED_STRING(@"UNSUPPORTED_DEVICE")); - return NO; - } - return %orig; -} -%end - -%end // group DEMC_UnsupportedDevice - -%ctor { - if (!DEMC_isDeviceSupported()) { - [[NSUserDefaults standardUserDefaults] setBool:NO forKey:ENABLED_KEY]; - %init(DEMC_UnsupportedDevice); - return; - } - - constant = [[NSUserDefaults standardUserDefaults] floatForKey:SAFE_AREA_CONSTANT_KEY]; - if (constant == 0) { // First launch probably - constant = DEFAULT_CONSTANT; - [[NSUserDefaults standardUserDefaults] setFloat:constant forKey:SAFE_AREA_CONSTANT_KEY]; - } - if (IS_TWEAK_ENABLED) %init(DEMC_Tweak); -} - -static BOOL DEMC_isDeviceSupported() { - // Get device model identifier (e.g. iPhone14,4) - // https://stackoverflow.com/a/11197770/19227228 - struct utsname systemInfo; - uname(&systemInfo); - NSString *deviceModelId = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; - - NSArray *unsupportedModelIds = UNSUPPORTED_DEVICES; - for (NSString *identifier in unsupportedModelIds) { - if ([deviceModelId isEqualToString:identifier]) { - return NO; - } - } - - if ([deviceModelId containsString:@"iPhone"]) { - if ([deviceModelId isEqualToString:@"iPhone13,1"]) { - // iPhone 12 mini - return YES; - } - NSString *modelNumber = [[deviceModelId stringByReplacingOccurrencesOfString:@"iPhone" withString:@""] stringByReplacingOccurrencesOfString:@"," withString:@"."]; - if ([modelNumber floatValue] >= 14.0) { - // iPhone 13 series and newer - return YES; - } else return NO; - } else return NO; -} - -static void DEMC_activateConstraints() { - if (videoAspectRatio < THRESHOLD) { - DEMC_deactivateConstraints(); - return; - } - // NSLog(@"activate"); - DEMC_centerRenderingView(); - renderingView.translatesAutoresizingMaskIntoConstraints = NO; - widthConstraint.active = YES; - heightConstraint.active = YES; -} - -static void DEMC_deactivateConstraints() { - // NSLog(@"deactivate"); - renderingView.translatesAutoresizingMaskIntoConstraints = YES; -} - -static void DEMC_centerRenderingView() { - centerXConstraint.active = YES; - centerYConstraint.active = YES; -} - -void DEMC_showSnackBar(NSString *text) { - YTHUDMessage *message = [%c(YTHUDMessage) messageWithText:text]; - GOOHUDManagerInternal *manager = [%c(GOOHUDManagerInternal) sharedInstance]; - [manager showMessageMainThread:message]; -} - -NSBundle *DEMC_getTweakBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"DontEatMyContent" ofType:@"bundle"]; - if (bundlePath) - bundle = [NSBundle bundleWithPath:bundlePath]; - else // Rootless - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/DontEatMyContent.bundle")]; - }); - return bundle; -} \ No newline at end of file diff --git a/Tweaks/DontEatMyContent/control b/Tweaks/DontEatMyContent/control deleted file mode 100644 index 64b908a..0000000 --- a/Tweaks/DontEatMyContent/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: me.foxster.donteatmycontent -Name: DontEatMyContent -Version: 1.0.10 -Architecture: iphoneos-arm -Description: Prevent the notch/Dynamic Island from munching on 2:1 video content in YouTube -Maintainer: Foxster -Author: Foxster -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 14.0) diff --git a/Tweaks/DontEatMyContent/layout/Library/Application Support/DontEatMyContent.bundle/Info.plist b/Tweaks/DontEatMyContent/layout/Library/Application Support/DontEatMyContent.bundle/Info.plist deleted file mode 100644 index 00c6803..0000000 --- a/Tweaks/DontEatMyContent/layout/Library/Application Support/DontEatMyContent.bundle/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - - CFBundleIdentifier - me.foxster.donteatmycontent - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - NSPrincipalClass - DontEatMyContent - - \ No newline at end of file diff --git a/Tweaks/DontEatMyContent/layout/Library/Application Support/DontEatMyContent.bundle/en.lproj/Localizable.strings b/Tweaks/DontEatMyContent/layout/Library/Application Support/DontEatMyContent.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 3ddf947..0000000 --- a/Tweaks/DontEatMyContent/layout/Library/Application Support/DontEatMyContent.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,21 +0,0 @@ -"ENABLED" = "Enabled"; -"TWEAK_DESC" = "Prevents the notch/Dynamic Island from cutting into 2:1 videos (e.g., MKBHD's videos)"; - -"SAFE_AREA_CONST" = "Safe area constant"; -"SAFE_AREA_CONST_DESC" = "Customize this constant to push the video closer to or further away from the notch/Dynamic Island. The larger the constant, the closer the video will be to the notch/Dynamic Island, and vice versa"; -"DEFAULT" = "default"; -"SAFE_AREA_CONST_MESSAGE" = "Your changes were saved. If a video is currently playing, dismiss it for changes to take effect"; - -"COLOR_VIEWS" = "Colored views"; -"COLOR_VIEWS_DESC" = "Sets a red background for the rendering view, green for the rendering view container, and blue for the player view; useful for debugging"; - -"REPORT_ISSUE" = "Report an issue"; -"SOURCE_CODE" = "View source code"; - -"CHANGES_SAVED" = "Your changes were saved"; - -"EXIT" = "Exit"; -"LATER" = "Later"; -"EXIT_YT_DESC" = "Relaunch YouTube to apply changes"; - -"UNSUPPORTED_DEVICE" = "This device is not supported"; \ No newline at end of file diff --git a/Tweaks/FLEX b/Tweaks/FLEX new file mode 160000 index 0000000..2083017 --- /dev/null +++ b/Tweaks/FLEX @@ -0,0 +1 @@ +Subproject commit 20830170bfe50659de36eace461fd95ebdb16cba diff --git a/Tweaks/FLEX/.gitignore b/Tweaks/FLEX/.gitignore deleted file mode 100644 index 496ee2c..0000000 --- a/Tweaks/FLEX/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store \ No newline at end of file diff --git a/Tweaks/FLEX/Core/Controllers/FLEXFilteringTableViewController.h b/Tweaks/FLEX/Core/Controllers/FLEXFilteringTableViewController.h deleted file mode 100644 index f0488a1..0000000 --- a/Tweaks/FLEX/Core/Controllers/FLEXFilteringTableViewController.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// FLEXFilteringTableViewController.h -// FLEX -// -// Created by Tanner on 3/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" - -#pragma mark - FLEXTableViewFiltering -@protocol FLEXTableViewFiltering - -/// An array of visible, "filtered" sections. For example, -/// if you have 3 sections in \c allSections and the user searches -/// for something that matches rows in only one section, then -/// this property would only contain that on matching section. -@property (nonatomic, copy) NSArray *sections; -/// An array of all possible sections. Empty sections are to be removed -/// and the resulting array stored in the \c section property. Setting -/// this property should immediately set \c sections to \c nonemptySections -/// -/// Do not manually initialize this property, it will be -/// initialized for you using the result of \c makeSections. -@property (nonatomic, copy) NSArray *allSections; - -/// This computed property should filter \c allSections for assignment to \c sections -@property (nonatomic, readonly, copy) NSArray *nonemptySections; - -/// This should be able to re-initialize \c allSections -- (NSArray *)makeSections; - -@end - - -#pragma mark - FLEXFilteringTableViewController -/// A table view which implements \c UITableView* methods using arrays of -/// \c FLEXTableViewSection objects provied by a special delegate. -@interface FLEXFilteringTableViewController : FLEXTableViewController - -/// Stores the current search query. -@property (nonatomic, copy) NSString *filterText; - -/// This property is set to \c self by default. -/// -/// This property is used to power almost all of the table view's data source -/// and delegate methods automatically, including row and section filtering -/// when the user searches, 3D Touch context menus, row selection, etc. -/// -/// Setting this property will also set \c searchDelegate to that object. -@property (nonatomic, weak) id filterDelegate; - -/// Defaults to \c NO. If enabled, all filtering will be done by calling -/// \c onBackgroundQueue:thenOnMainQueue: with the UI updated on the main queue. -@property (nonatomic) BOOL filterInBackground; - -/// Defaults to \c NO. If enabled, one • will be supplied as an index title for each section. -@property (nonatomic) BOOL wantsSectionIndexTitles; - -/// Recalculates the non-empty sections and reloads the table view. -/// -/// Subclasses may override to perform additional reloading logic, -/// such as calling \c -reloadSections if needed. Be sure to call -/// \c super after any logic that would affect the appearance of -/// the table view, since the table view is reloaded last. -/// -/// Called at the end of this class's implementation of \c updateSearchResults: -- (void)reloadData; - -/// Invoke this method to call \c -reloadData on each section -/// in \c self.filterDelegate.allSections. -- (void)reloadSections; - -#pragma mark FLEXTableViewFiltering - -@property (nonatomic, copy) NSArray *sections; -@property (nonatomic, copy) NSArray *allSections; - -/// Subclasses can override to hide specific sections under certain conditions -/// if using \c self as the \c filterDelegate, as is the default. -/// -/// For example, the object explorer hides the description section when searching. -@property (nonatomic, readonly, copy) NSArray *nonemptySections; - -/// If using \c self as the \c filterDelegate, as is the default, -/// subclasses should override to provide the sections for the table view. -- (NSArray *)makeSections; - -@end diff --git a/Tweaks/FLEX/Core/Controllers/FLEXFilteringTableViewController.m b/Tweaks/FLEX/Core/Controllers/FLEXFilteringTableViewController.m deleted file mode 100644 index b9cd17e..0000000 --- a/Tweaks/FLEX/Core/Controllers/FLEXFilteringTableViewController.m +++ /dev/null @@ -1,209 +0,0 @@ -// -// FLEXFilteringTableViewController.m -// FLEX -// -// Created by Tanner on 3/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" -#import "FLEXTableViewSection.h" -#import "NSArray+FLEX.h" -#import "FLEXMacros.h" - -@interface FLEXFilteringTableViewController () - -@end - -@implementation FLEXFilteringTableViewController -@synthesize allSections = _allSections; - -#pragma mark - View controller lifecycle - -- (void)loadView { - [super loadView]; - - if (!self.filterDelegate) { - self.filterDelegate = self; - } else { - [self _registerCellsForReuse]; - } -} - -- (void)_registerCellsForReuse { - for (FLEXTableViewSection *section in self.filterDelegate.allSections) { - if (section.cellRegistrationMapping) { - [self.tableView registerCells:section.cellRegistrationMapping]; - } - } -} - - -#pragma mark - Public - -- (void)setFilterDelegate:(id)filterDelegate { - _filterDelegate = filterDelegate; - filterDelegate.allSections = [filterDelegate makeSections]; - - if (self.isViewLoaded) { - [self _registerCellsForReuse]; - } -} - -- (void)reloadData { - [self reloadData:self.nonemptySections]; -} - -- (void)reloadData:(NSArray *)nonemptySections { - // Recalculate displayed sections - self.filterDelegate.sections = nonemptySections; - - // Refresh table view - if (self.isViewLoaded) { - [self.tableView reloadData]; - } -} - -- (void)reloadSections { - for (FLEXTableViewSection *section in self.filterDelegate.allSections) { - [section reloadData]; - } -} - - -#pragma mark - Search - -- (void)updateSearchResults:(NSString *)newText { - NSArray *(^filter)(void) = ^NSArray *{ - self.filterText = newText; - - // Sections will adjust data based on this property - for (FLEXTableViewSection *section in self.filterDelegate.allSections) { - section.filterText = newText; - } - - return nil; - }; - - if (self.filterInBackground) { - [self onBackgroundQueue:filter thenOnMainQueue:^(NSArray *unused) { - if ([self.searchText isEqualToString:newText]) { - [self reloadData]; - } - }]; - } else { - filter(); - [self reloadData]; - } -} - - -#pragma mark Filtering - -- (NSArray *)nonemptySections { - return [self.filterDelegate.allSections flex_filtered:^BOOL(FLEXTableViewSection *section, NSUInteger idx) { - return section.numberOfRows > 0; - }]; -} - -- (NSArray *)makeSections { - return @[]; -} - -- (void)setAllSections:(NSArray *)allSections { - _allSections = allSections.copy; - // Only display nonempty sections - self.sections = self.nonemptySections; -} - -- (void)setSections:(NSArray *)sections { - // Allow sections to reload a portion of the table view at will - [sections enumerateObjectsUsingBlock:^(FLEXTableViewSection *s, NSUInteger idx, BOOL *stop) { - [s setTable:self.tableView section:idx]; - }]; - _sections = sections.copy; -} - - -#pragma mark - UITableViewDataSource - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.filterDelegate.sections.count; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.filterDelegate.sections[section].numberOfRows; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return self.filterDelegate.sections[section].title; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *reuse = [self.filterDelegate.sections[indexPath.section] reuseIdentifierForRow:indexPath.row]; - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuse forIndexPath:indexPath]; - [self.filterDelegate.sections[indexPath.section] configureCell:cell forRow:indexPath.row]; - return cell; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return UITableViewAutomaticDimension; -} - -- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { - if (self.wantsSectionIndexTitles) { - return [NSArray flex_forEachUpTo:self.filterDelegate.sections.count map:^id(NSUInteger i) { - return @"⦁"; - }]; - } - - return nil; -} - - -#pragma mark - UITableViewDelegate - -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { - return [self.filterDelegate.sections[indexPath.section] canSelectRow:indexPath.row]; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXTableViewSection *section = self.filterDelegate.sections[indexPath.section]; - - void (^action)(UIViewController *) = [section didSelectRowAction:indexPath.row]; - UIViewController *details = [section viewControllerToPushForRow:indexPath.row]; - - if (action) { - action(self); - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - } else if (details) { - [self.navigationController pushViewController:details animated:YES]; - } else { - [NSException raise:NSInternalInconsistencyException - format:@"Row is selectable but has no action or view controller"]; - } -} - -- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - [self.filterDelegate.sections[indexPath.section] didPressInfoButtonAction:indexPath.row](self); -} - -- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __IOS_AVAILABLE(13.0) { - FLEXTableViewSection *section = self.filterDelegate.sections[indexPath.section]; - NSString *title = [section menuTitleForRow:indexPath.row]; - NSArray *menuItems = [section menuItemsForRow:indexPath.row sender:self]; - - if (menuItems.count) { - return [UIContextMenuConfiguration - configurationWithIdentifier:nil - previewProvider:nil - actionProvider:^UIMenu *(NSArray *suggestedActions) { - return [UIMenu menuWithTitle:title children:menuItems]; - } - ]; - } - - return nil; -} - -@end diff --git a/Tweaks/FLEX/Core/Controllers/FLEXNavigationController.h b/Tweaks/FLEX/Core/Controllers/FLEXNavigationController.h deleted file mode 100644 index f0533a8..0000000 --- a/Tweaks/FLEX/Core/Controllers/FLEXNavigationController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXNavigationController.h -// FLEX -// -// Created by Tanner on 1/30/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXNavigationController : UINavigationController - -+ (instancetype)withRootViewController:(UIViewController *)rootVC; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Core/Controllers/FLEXNavigationController.m b/Tweaks/FLEX/Core/Controllers/FLEXNavigationController.m deleted file mode 100644 index d460fdd..0000000 --- a/Tweaks/FLEX/Core/Controllers/FLEXNavigationController.m +++ /dev/null @@ -1,196 +0,0 @@ -// -// FLEXNavigationController.m -// FLEX -// -// Created by Tanner on 1/30/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXNavigationController.h" -#import "FLEXExplorerViewController.h" -#import "FLEXTabList.h" - -@interface UINavigationController (Private) -- (void)_gestureRecognizedInteractiveHide:(UIGestureRecognizer *)sender; -@end -@interface UIPanGestureRecognizer (Private) -- (void)_setDelegate:(id)delegate; -@end - -@interface FLEXNavigationController () -@property (nonatomic, readonly) BOOL toolbarWasHidden; -@property (nonatomic) BOOL waitingToAddTab; -@property (nonatomic, readonly) BOOL canShowToolbar; -@property (nonatomic) BOOL didSetupPendingDismissButtons; -@property (nonatomic) UISwipeGestureRecognizer *navigationBarSwipeGesture; -@end - -@implementation FLEXNavigationController - -+ (instancetype)withRootViewController:(UIViewController *)rootVC { - return [[self alloc] initWithRootViewController:rootVC]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.waitingToAddTab = YES; - - // Add gesture to reveal toolbar if hidden - UITapGestureRecognizer *navbarTapGesture = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleNavigationBarTap:) - ]; - - // Don't cancel touches to work around bug on versions of iOS prior to 13 - navbarTapGesture.cancelsTouchesInView = NO; - [self.navigationBar addGestureRecognizer:navbarTapGesture]; - - // Add gesture to dismiss if not presented with a sheet style - if (@available(iOS 13, *)) { - switch (self.modalPresentationStyle) { - case UIModalPresentationAutomatic: - case UIModalPresentationPageSheet: - case UIModalPresentationFormSheet: - break; - - default: - [self addNavigationBarSwipeGesture]; - break; - } - } else { - [self addNavigationBarSwipeGesture]; - } -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - if (self.beingPresented && !self.didSetupPendingDismissButtons) { - for (UIViewController *vc in self.viewControllers) { - [self addNavigationBarItemsToViewController:vc.navigationItem]; - } - - self.didSetupPendingDismissButtons = YES; - } -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - if (self.waitingToAddTab) { - // Only add new tab if we're presented properly - if ([self.presentingViewController isKindOfClass:[FLEXExplorerViewController class]]) { - // New navigation controllers always add themselves as new tabs, - // tabs are closed by FLEXExplorerViewController - [FLEXTabList.sharedList addTab:self]; - self.waitingToAddTab = NO; - } - } -} - -- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { - [super pushViewController:viewController animated:animated]; - [self addNavigationBarItemsToViewController:viewController.navigationItem]; -} - -- (void)dismissAnimated { - // Tabs are only closed if the done button is pressed; this - // allows you to leave a tab open by dragging down to dismiss - if ([self.presentingViewController isKindOfClass:[FLEXExplorerViewController class]]) { - [FLEXTabList.sharedList closeTab:self]; - } - - [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; -} - -- (BOOL)canShowToolbar { - return self.topViewController.toolbarItems.count > 0; -} - -- (void)addNavigationBarItemsToViewController:(UINavigationItem *)navigationItem { - if (!self.presentingViewController) { - return; - } - - // Check if a done item already exists - for (UIBarButtonItem *item in navigationItem.rightBarButtonItems) { - if (item.style == UIBarButtonItemStyleDone) { - return; - } - } - - // Give root view controllers a Done button if it does not already have one - UIBarButtonItem *done = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self - action:@selector(dismissAnimated) - ]; - - // Prepend the button if other buttons exist already - NSArray *existingItems = navigationItem.rightBarButtonItems; - if (existingItems.count) { - navigationItem.rightBarButtonItems = [@[done] arrayByAddingObjectsFromArray:existingItems]; - } else { - navigationItem.rightBarButtonItem = done; - } - - // Keeps us from calling this method again on - // the same view controllers in -viewWillAppear: - self.didSetupPendingDismissButtons = YES; -} - -- (void)addNavigationBarSwipeGesture { - UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] - initWithTarget:self action:@selector(handleNavigationBarSwipe:) - ]; - swipe.direction = UISwipeGestureRecognizerDirectionDown; - swipe.delegate = self; - self.navigationBarSwipeGesture = swipe; - [self.navigationBar addGestureRecognizer:swipe]; -} - -- (void)handleNavigationBarSwipe:(UISwipeGestureRecognizer *)sender { - if (sender.state == UIGestureRecognizerStateRecognized) { - [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; - } -} - -- (void)handleNavigationBarTap:(UIGestureRecognizer *)sender { - // Don't reveal the toolbar if we were just tapping a button - CGPoint location = [sender locationInView:self.navigationBar]; - UIView *hitView = [self.navigationBar hitTest:location withEvent:nil]; - if ([hitView isKindOfClass:[UIControl class]]) { - return; - } - - if (sender.state == UIGestureRecognizerStateRecognized) { - if (self.toolbarHidden && self.canShowToolbar) { - [self setToolbarHidden:NO animated:YES]; - } - } -} - -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)g1 shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)g2 { - if (g1 == self.navigationBarSwipeGesture && g2 == self.barHideOnSwipeGestureRecognizer) { - return YES; - } - - return NO; -} - -- (void)_gestureRecognizedInteractiveHide:(UIPanGestureRecognizer *)sender { - if (sender.state == UIGestureRecognizerStateRecognized) { - BOOL show = self.canShowToolbar; - CGFloat yTranslation = [sender translationInView:self.view].y; - CGFloat yVelocity = [sender velocityInView:self.view].y; - if (yVelocity > 2000) { - [self setToolbarHidden:YES animated:YES]; - } else if (show && yTranslation > 20 && yVelocity > 250) { - [self setToolbarHidden:NO animated:YES]; - } else if (yTranslation < -20) { - [self setToolbarHidden:YES animated:YES]; - } - } -} - -@end diff --git a/Tweaks/FLEX/Core/Controllers/FLEXTableViewController.h b/Tweaks/FLEX/Core/Controllers/FLEXTableViewController.h deleted file mode 100644 index 762c815..0000000 --- a/Tweaks/FLEX/Core/Controllers/FLEXTableViewController.h +++ /dev/null @@ -1,153 +0,0 @@ -// -// FLEXTableViewController.h -// FLEX -// -// Created by Tanner on 7/5/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import "FLEXTableView.h" -@class FLEXScopeCarousel, FLEXWindow, FLEXTableViewSection; - -typedef CGFloat FLEXDebounceInterval; -/// No delay, all events delivered -extern CGFloat const kFLEXDebounceInstant; -/// Small delay which makes UI seem smoother by avoiding rapid events -extern CGFloat const kFLEXDebounceFast; -/// Slower than Fast, faster than ExpensiveIO -extern CGFloat const kFLEXDebounceForAsyncSearch; -/// The least frequent, at just over once per second; for I/O or other expensive operations -extern CGFloat const kFLEXDebounceForExpensiveIO; - -@protocol FLEXSearchResultsUpdating -/// A method to handle search query update events. -/// -/// \c searchBarDebounceInterval is used to reduce the frequency at which this -/// method is called. This method is also called when the search bar becomes -/// the first responder, and when the selected search bar scope index changes. -- (void)updateSearchResults:(NSString *)newText; -@end - -@interface FLEXTableViewController : UITableViewController < - UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate -> - -/// A grouped table view. Inset on iOS 13. -/// -/// Simply calls into \c initWithStyle: -- (id)init; - -/// Subclasses may override to configure the controller before \c viewDidLoad: -- (id)initWithStyle:(UITableViewStyle)style; - -@property (nonatomic) FLEXTableView *tableView; - -/// If your subclass conforms to \c FLEXSearchResultsUpdating -/// then this property is assigned to \c self automatically. -/// -/// Setting \c filterDelegate will also set this property to that object. -@property (nonatomic, weak) id searchDelegate; - -/// Defaults to NO. -/// -/// Setting this to YES will initialize the carousel and the view. -@property (nonatomic) BOOL showsCarousel; -/// A horizontally scrolling list with functionality similar to -/// that of a search bar's scope bar. You'd want to use this when -/// you have potentially more than 4 scope options. -@property (nonatomic) FLEXScopeCarousel *carousel; - -/// Defaults to NO. -/// -/// Setting this to YES will initialize searchController and the view. -@property (nonatomic) BOOL showsSearchBar; -/// Defaults to NO. -/// -/// Setting this to YES will make the search bar appear whenever the view appears. -/// Otherwise, iOS will only show the search bar when you scroll up. -@property (nonatomic) BOOL showSearchBarInitially; -/// Defaults to NO. -/// -/// Setting this to YES will make the search bar activate whenever the view appears. -@property (nonatomic) BOOL activatesSearchBarAutomatically; - -/// nil unless showsSearchBar is set to YES. -/// -/// self is used as the default search results updater and delegate. -/// The search bar will not dim the background or hide the navigation bar by default. -/// On iOS 11 and up, the search bar will appear in the navigation bar below the title. -@property (nonatomic) UISearchController *searchController; -/// Used to initialize the search controller. Defaults to nil. -@property (nonatomic) UIViewController *searchResultsController; -/// Defaults to "Fast" -/// -/// Determines how often search bar results will be "debounced." -/// Empty query events are always sent instantly. Query events will -/// be sent when the user has not changed the query for this interval. -@property (nonatomic) FLEXDebounceInterval searchBarDebounceInterval; -/// Whether the search bar stays at the top of the view while scrolling. -/// -/// Calls into self.navigationItem.hidesSearchBarWhenScrolling. -/// Do not change self.navigationItem.hidesSearchBarWhenScrolling directly, -/// or it will not be respsected. Use this instead. -/// Defaults to NO. -@property (nonatomic) BOOL pinSearchBar; -/// By default, we will show the search bar's cancel button when -/// search becomes active and hide it when search is dismissed. -/// -/// Do not set the showsCancelButton property on the searchController's -/// searchBar manually. Set this property after turning on showsSearchBar. -/// -/// Does nothing pre-iOS 13, safe to call on any version. -@property (nonatomic) BOOL automaticallyShowsSearchBarCancelButton; - -/// If using the scope bar, self.searchController.searchBar.selectedScopeButtonIndex. -/// Otherwise, this is the selected index of the carousel, or NSNotFound if using neither. -@property (nonatomic) NSInteger selectedScope; -/// self.searchController.searchBar.text -@property (nonatomic, readonly, copy) NSString *searchText; - -/// A totally optional delegate to forward search results updater calls to. -/// If a delegate is set, updateSearchResults: is not called on this view controller. -@property (nonatomic, weak) id searchResultsUpdater; - -/// self.view.window as a \c FLEXWindow -@property (nonatomic, readonly) FLEXWindow *window; - -/// Convenient for doing some async processor-intensive searching -/// in the background before updating the UI back on the main queue. -- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock; - -/// Adds up to 3 additional items to the toolbar in right-to-left order. -/// -/// That is, the first item in the given array will be the rightmost item behind -/// any existing toolbar items. By default, buttons for bookmarks and tabs are shown. -/// -/// If you wish to have more control over how the buttons are arranged or which -/// buttons are displayed, you can access the properties for the pre-existing -/// toolbar items directly and manually set \c self.toolbarItems by overriding -/// the \c setupToolbarItems method below. -- (void)addToolbarItems:(NSArray *)items; - -/// Subclasses may override. You should not need to call this method directly. -- (void)setupToolbarItems; - -@property (nonatomic, readonly) UIBarButtonItem *shareToolbarItem; -@property (nonatomic, readonly) UIBarButtonItem *bookmarksToolbarItem; -@property (nonatomic, readonly) UIBarButtonItem *openTabsToolbarItem; - -/// Whether or not to display the "share" icon in the middle of the toolbar. NO by default. -/// -/// Turning this on after you have added custom toolbar items will -/// push off the leftmost toolbar item and shift the others leftward. -@property (nonatomic) BOOL showsShareToolbarItem; -/// Called when the share button is pressed. -/// Default implementation does nothign. Subclasses may override. -- (void)shareButtonPressed:(UIBarButtonItem *)sender; - -/// Subclasses may call this to opt-out of all toolbar related behavior. -/// This is necessary if you want to disable the gesture which reveals the toolbar. -- (void)disableToolbar; - -@end diff --git a/Tweaks/FLEX/Core/Controllers/FLEXTableViewController.m b/Tweaks/FLEX/Core/Controllers/FLEXTableViewController.m deleted file mode 100644 index 70baf3b..0000000 --- a/Tweaks/FLEX/Core/Controllers/FLEXTableViewController.m +++ /dev/null @@ -1,618 +0,0 @@ -// -// FLEXTableViewController.m -// FLEX -// -// Created by Tanner on 7/5/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" -#import "FLEXExplorerViewController.h" -#import "FLEXBookmarksViewController.h" -#import "FLEXTabsViewController.h" -#import "FLEXScopeCarousel.h" -#import "FLEXTableView.h" -#import "FLEXUtility.h" -#import "FLEXResources.h" -#import "UIBarButtonItem+FLEX.h" -#import - -@interface Block : NSObject -- (void)invoke; -@end - -CGFloat const kFLEXDebounceInstant = 0.f; -CGFloat const kFLEXDebounceFast = 0.05; -CGFloat const kFLEXDebounceForAsyncSearch = 0.15; -CGFloat const kFLEXDebounceForExpensiveIO = 0.5; - -@interface FLEXTableViewController () -@property (nonatomic) NSTimer *debounceTimer; -@property (nonatomic) BOOL didInitiallyRevealSearchBar; -@property (nonatomic) UITableViewStyle style; - -@property (nonatomic) BOOL hasAppeared; -@property (nonatomic, readonly) UIView *tableHeaderViewContainer; - -@property (nonatomic, readonly) BOOL manuallyDeactivateSearchOnDisappear; - -@property (nonatomic) UIBarButtonItem *middleToolbarItem; -@property (nonatomic) UIBarButtonItem *middleLeftToolbarItem; -@property (nonatomic) UIBarButtonItem *leftmostToolbarItem; -@end - -@implementation FLEXTableViewController -@dynamic tableView; -@synthesize showsShareToolbarItem = _showsShareToolbarItem; -@synthesize tableHeaderViewContainer = _tableHeaderViewContainer; -@synthesize automaticallyShowsSearchBarCancelButton = _automaticallyShowsSearchBarCancelButton; - -#pragma mark - Initialization - -- (id)init { - if (@available(iOS 13.0, *)) { - self = [self initWithStyle:UITableViewStyleInsetGrouped]; - } else { - self = [self initWithStyle:UITableViewStyleGrouped]; - } - - return self; -} - -- (id)initWithStyle:(UITableViewStyle)style { - self = [super initWithStyle:style]; - - if (self) { - _searchBarDebounceInterval = kFLEXDebounceFast; - _showSearchBarInitially = YES; - _style = style; - _manuallyDeactivateSearchOnDisappear = ( - NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11 - ); - - // We will be our own search delegate if we implement this method - if ([self respondsToSelector:@selector(updateSearchResults:)]) { - self.searchDelegate = (id)self; - } - } - - return self; -} - - -#pragma mark - Public - -- (FLEXWindow *)window { - return (id)self.view.window; -} - -- (void)setShowsSearchBar:(BOOL)showsSearchBar { - if (_showsSearchBar == showsSearchBar) return; - _showsSearchBar = showsSearchBar; - - if (showsSearchBar) { - UIViewController *results = self.searchResultsController; - self.searchController = [[UISearchController alloc] initWithSearchResultsController:results]; - self.searchController.searchBar.placeholder = @"Filter"; - self.searchController.searchResultsUpdater = (id)self; - self.searchController.delegate = (id)self; - self.searchController.dimsBackgroundDuringPresentation = NO; - self.searchController.hidesNavigationBarDuringPresentation = NO; - /// Not necessary in iOS 13; remove this when iOS 13 is the minimum deployment target - self.searchController.searchBar.delegate = self; - - self.automaticallyShowsSearchBarCancelButton = YES; - - if (@available(iOS 13, *)) { - self.searchController.automaticallyShowsScopeBar = NO; - } - - [self addSearchController:self.searchController]; - } else { - // Search already shown and just set to NO, so remove it - [self removeSearchController:self.searchController]; - } -} - -- (void)setShowsCarousel:(BOOL)showsCarousel { - if (_showsCarousel == showsCarousel) return; - _showsCarousel = showsCarousel; - - if (showsCarousel) { - _carousel = ({ weakify(self) - - FLEXScopeCarousel *carousel = [FLEXScopeCarousel new]; - carousel.selectedIndexChangedAction = ^(NSInteger idx) { strongify(self); - [self.searchDelegate updateSearchResults:self.searchText]; - }; - - // UITableView won't update the header size unless you reset the header view - [carousel registerBlockForDynamicTypeChanges:^(FLEXScopeCarousel *_) { strongify(self); - [self layoutTableHeaderIfNeeded]; - }]; - - carousel; - }); - [self addCarousel:_carousel]; - } else { - // Carousel already shown and just set to NO, so remove it - [self removeCarousel:_carousel]; - } -} - -- (NSInteger)selectedScope { - if (self.searchController.searchBar.showsScopeBar) { - return self.searchController.searchBar.selectedScopeButtonIndex; - } else if (self.showsCarousel) { - return self.carousel.selectedIndex; - } else { - return 0; - } -} - -- (void)setSelectedScope:(NSInteger)selectedScope { - if (self.searchController.searchBar.showsScopeBar) { - self.searchController.searchBar.selectedScopeButtonIndex = selectedScope; - } else if (self.showsCarousel) { - self.carousel.selectedIndex = selectedScope; - } - - [self.searchDelegate updateSearchResults:self.searchText]; -} - -- (NSString *)searchText { - return self.searchController.searchBar.text; -} - -- (BOOL)automaticallyShowsSearchBarCancelButton { - if (@available(iOS 13, *)) { - return self.searchController.automaticallyShowsCancelButton; - } - - return _automaticallyShowsSearchBarCancelButton; -} - -- (void)setAutomaticallyShowsSearchBarCancelButton:(BOOL)value { - if (@available(iOS 13, *)) { - self.searchController.automaticallyShowsCancelButton = value; - } - - _automaticallyShowsSearchBarCancelButton = value; -} - -- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSArray *items = backgroundBlock(); - dispatch_async(dispatch_get_main_queue(), ^{ - mainBlock(items); - }); - }); -} - -- (void)setsShowsShareToolbarItem:(BOOL)showsShareToolbarItem { - _showsShareToolbarItem = showsShareToolbarItem; - if (self.isViewLoaded) { - [self setupToolbarItems]; - } -} - -- (void)disableToolbar { - self.navigationController.toolbarHidden = YES; - self.navigationController.hidesBarsOnSwipe = NO; - self.toolbarItems = nil; -} - - -#pragma mark - View Controller Lifecycle - -- (void)loadView { - self.view = [FLEXTableView style:self.style]; - self.tableView.dataSource = self; - self.tableView.delegate = self; - - _shareToolbarItem = FLEXBarButtonItemSystem(Action, self, @selector(shareButtonPressed:)); - _bookmarksToolbarItem = [UIBarButtonItem - flex_itemWithImage:FLEXResources.bookmarksIcon target:self action:@selector(showBookmarks) - ]; - _openTabsToolbarItem = [UIBarButtonItem - flex_itemWithImage:FLEXResources.openTabsIcon target:self action:@selector(showTabSwitcher) - ]; - - self.leftmostToolbarItem = UIBarButtonItem.flex_fixedSpace; - self.middleLeftToolbarItem = UIBarButtonItem.flex_fixedSpace; - self.middleToolbarItem = UIBarButtonItem.flex_fixedSpace; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; - - // Toolbar - self.navigationController.toolbarHidden = self.toolbarItems.count > 0; - self.navigationController.hidesBarsOnSwipe = YES; - - // On iOS 13, the root view controller shows it's search bar no matter what. - // Turning this off avoids some weird flash the navigation bar does when we - // toggle navigationItem.hidesSearchBarWhenScrolling on and off. The flash - // will still happen on subsequent view controllers, but we can at least - // avoid it for the root view controller - if (@available(iOS 13, *)) { - if (self.navigationController.viewControllers.firstObject == self) { - _showSearchBarInitially = NO; - } - } -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - if (@available(iOS 11.0, *)) { - // When going back, make the search bar reappear instead of hiding - if ((self.pinSearchBar || self.showSearchBarInitially) && !self.didInitiallyRevealSearchBar) { - self.navigationItem.hidesSearchBarWhenScrolling = NO; - } - } - - // Make the keyboard seem to appear faster - if (self.activatesSearchBarAutomatically) { - [self makeKeyboardAppearNow]; - } - - [self setupToolbarItems]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - // Allow scrolling to collapse the search bar, only if we don't want it pinned - if (@available(iOS 11.0, *)) { - if (self.showSearchBarInitially && !self.pinSearchBar && !self.didInitiallyRevealSearchBar) { - // All this mumbo jumbo is necessary to work around a bug in iOS 13 up to 13.2 - // wherein quickly toggling navigationItem.hidesSearchBarWhenScrolling to make - // the search bar appear initially results in a bugged search bar that - // becomes transparent and floats over the screen as you scroll - [UIView animateWithDuration:0.2 animations:^{ - self.navigationItem.hidesSearchBarWhenScrolling = YES; - [self.navigationController.view setNeedsLayout]; - [self.navigationController.view layoutIfNeeded]; - }]; - } - } - - if (self.activatesSearchBarAutomatically) { - // Keyboard has appeared, now we call this as we soon present our search bar - [self removeDummyTextField]; - - // Activate the search bar - dispatch_async(dispatch_get_main_queue(), ^{ - // This doesn't work unless it's wrapped in this dispatch_async call - [self.searchController.searchBar becomeFirstResponder]; - }); - } - - // We only want to reveal the search bar when the view controller first appears. - self.didInitiallyRevealSearchBar = YES; -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - if (self.manuallyDeactivateSearchOnDisappear && self.searchController.isActive) { - self.searchController.active = NO; - } -} - -- (void)didMoveToParentViewController:(UIViewController *)parent { - [super didMoveToParentViewController:parent]; - // Reset this since we are re-appearing under a new - // parent view controller and need to show it again - self.didInitiallyRevealSearchBar = NO; -} - - -#pragma mark - Toolbar, Public - -- (void)setupToolbarItems { - if (!self.isViewLoaded) { - return; - } - - self.toolbarItems = @[ - self.leftmostToolbarItem, - UIBarButtonItem.flex_flexibleSpace, - self.middleLeftToolbarItem, - UIBarButtonItem.flex_flexibleSpace, - self.middleToolbarItem, - UIBarButtonItem.flex_flexibleSpace, - self.bookmarksToolbarItem, - UIBarButtonItem.flex_flexibleSpace, - self.openTabsToolbarItem, - ]; - - for (UIBarButtonItem *item in self.toolbarItems) { - [item _setWidth:60]; - // This does not work for anything but fixed spaces for some reason - // item.width = 60; - } - - // Disable tabs entirely when not presented by FLEXExplorerViewController - UIViewController *presenter = self.navigationController.presentingViewController; - if (![presenter isKindOfClass:[FLEXExplorerViewController class]]) { - self.openTabsToolbarItem.enabled = NO; - } -} - -- (void)addToolbarItems:(NSArray *)items { - if (self.showsShareToolbarItem) { - // Share button is in the middle, skip middle button - if (items.count > 0) { - self.middleLeftToolbarItem = items[0]; - } - if (items.count > 1) { - self.leftmostToolbarItem = items[1]; - } - } else { - // Add buttons right-to-left - if (items.count > 0) { - self.middleToolbarItem = items[0]; - } - if (items.count > 1) { - self.middleLeftToolbarItem = items[1]; - } - if (items.count > 2) { - self.leftmostToolbarItem = items[2]; - } - } - - [self setupToolbarItems]; -} - -- (void)setShowsShareToolbarItem:(BOOL)showShare { - if (_showsShareToolbarItem != showShare) { - _showsShareToolbarItem = showShare; - - if (showShare) { - // Push out leftmost item - self.leftmostToolbarItem = self.middleLeftToolbarItem; - self.middleLeftToolbarItem = self.middleToolbarItem; - - // Use share for middle - self.middleToolbarItem = self.shareToolbarItem; - } else { - // Remove share, shift custom items rightward - self.middleToolbarItem = self.middleLeftToolbarItem; - self.middleLeftToolbarItem = self.leftmostToolbarItem; - self.leftmostToolbarItem = UIBarButtonItem.flex_fixedSpace; - } - } - - [self setupToolbarItems]; -} - -- (void)shareButtonPressed:(UIBarButtonItem *)sender { - -} - - -#pragma mark - Private - -- (void)debounce:(void(^)(void))block { - [self.debounceTimer invalidate]; - - self.debounceTimer = [NSTimer - scheduledTimerWithTimeInterval:self.searchBarDebounceInterval - target:block - selector:@selector(invoke) - userInfo:nil - repeats:NO - ]; -} - -- (void)layoutTableHeaderIfNeeded { - if (self.showsCarousel) { - self.carousel.frame = FLEXRectSetHeight( - self.carousel.frame, self.carousel.intrinsicContentSize.height - ); - } - - self.tableView.tableHeaderView = self.tableView.tableHeaderView; -} - -- (void)addCarousel:(FLEXScopeCarousel *)carousel { - if (@available(iOS 11.0, *)) { - self.tableView.tableHeaderView = carousel; - } else { - carousel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - - CGRect frame = self.tableHeaderViewContainer.frame; - CGRect subviewFrame = carousel.frame; - subviewFrame.origin.y = 0; - - // Put the carousel below the search bar if it's already there - if (self.showsSearchBar) { - carousel.frame = subviewFrame = FLEXRectSetY( - subviewFrame, self.searchController.searchBar.frame.size.height - ); - frame.size.height += carousel.intrinsicContentSize.height; - } else { - frame.size.height = carousel.intrinsicContentSize.height; - } - - self.tableHeaderViewContainer.frame = frame; - [self.tableHeaderViewContainer addSubview:carousel]; - } - - [self layoutTableHeaderIfNeeded]; -} - -- (void)removeCarousel:(FLEXScopeCarousel *)carousel { - [carousel removeFromSuperview]; - - if (@available(iOS 11.0, *)) { - self.tableView.tableHeaderView = nil; - } else { - if (self.showsSearchBar) { - [self removeSearchController:self.searchController]; - [self addSearchController:self.searchController]; - } else { - self.tableView.tableHeaderView = nil; - _tableHeaderViewContainer = nil; - } - } -} - -- (void)addSearchController:(UISearchController *)controller { - if (@available(iOS 11.0, *)) { - self.navigationItem.searchController = controller; - } else { - controller.searchBar.autoresizingMask |= UIViewAutoresizingFlexibleBottomMargin; - [self.tableHeaderViewContainer addSubview:controller.searchBar]; - CGRect subviewFrame = controller.searchBar.frame; - CGRect frame = self.tableHeaderViewContainer.frame; - frame.size.width = MAX(frame.size.width, subviewFrame.size.width); - frame.size.height = subviewFrame.size.height; - - // Move the carousel down if it's already there - if (self.showsCarousel) { - self.carousel.frame = FLEXRectSetY( - self.carousel.frame, subviewFrame.size.height - ); - frame.size.height += self.carousel.frame.size.height; - } - - self.tableHeaderViewContainer.frame = frame; - [self layoutTableHeaderIfNeeded]; - } -} - -- (void)removeSearchController:(UISearchController *)controller { - if (@available(iOS 11.0, *)) { - self.navigationItem.searchController = nil; - } else { - [controller.searchBar removeFromSuperview]; - - if (self.showsCarousel) { -// self.carousel.frame = FLEXRectRemake(CGPointZero, self.carousel.frame.size); - [self removeCarousel:self.carousel]; - [self addCarousel:self.carousel]; - } else { - self.tableView.tableHeaderView = nil; - _tableHeaderViewContainer = nil; - } - } -} - -- (UIView *)tableHeaderViewContainer { - if (!_tableHeaderViewContainer) { - _tableHeaderViewContainer = [UIView new]; - self.tableView.tableHeaderView = self.tableHeaderViewContainer; - } - - return _tableHeaderViewContainer; -} - -- (void)showBookmarks { - UINavigationController *nav = [[UINavigationController alloc] - initWithRootViewController:[FLEXBookmarksViewController new] - ]; - [self presentViewController:nav animated:YES completion:nil]; -} - -- (void)showTabSwitcher { - UINavigationController *nav = [[UINavigationController alloc] - initWithRootViewController:[FLEXTabsViewController new] - ]; - [self presentViewController:nav animated:YES completion:nil]; -} - - -#pragma mark - Search Bar - -#pragma mark Faster keyboard - -static UITextField *kDummyTextField = nil; - -/// Make the keyboard appear instantly. We use this to make the -/// keyboard appear faster when the search bar is set to appear initially. -/// You must call \c -removeDummyTextField before your search bar is to appear. -- (void)makeKeyboardAppearNow { - if (!kDummyTextField) { - kDummyTextField = [UITextField new]; - kDummyTextField.autocorrectionType = UITextAutocorrectionTypeNo; - } - - kDummyTextField.inputAccessoryView = self.searchController.searchBar.inputAccessoryView; - [UIApplication.sharedApplication.keyWindow addSubview:kDummyTextField]; - [kDummyTextField becomeFirstResponder]; -} - -- (void)removeDummyTextField { - if (kDummyTextField.superview) { - [kDummyTextField removeFromSuperview]; - } -} - -#pragma mark UISearchResultsUpdating - -- (void)updateSearchResultsForSearchController:(UISearchController *)searchController { - [self.debounceTimer invalidate]; - NSString *text = searchController.searchBar.text; - - void (^updateSearchResults)(void) = ^{ - if (self.searchResultsUpdater) { - [self.searchResultsUpdater updateSearchResults:text]; - } else { - [self.searchDelegate updateSearchResults:text]; - } - }; - - // Only debounce if we want to, and if we have a non-empty string - // Empty string events are sent instantly - if (text.length && self.searchBarDebounceInterval > kFLEXDebounceInstant) { - [self debounce:updateSearchResults]; - } else { - updateSearchResults(); - } -} - - -#pragma mark UISearchControllerDelegate - -- (void)willPresentSearchController:(UISearchController *)searchController { - // Manually show cancel button for < iOS 13 - if (!@available(iOS 13, *) && self.automaticallyShowsSearchBarCancelButton) { - [searchController.searchBar setShowsCancelButton:YES animated:YES]; - } -} - -- (void)willDismissSearchController:(UISearchController *)searchController { - // Manually hide cancel button for < iOS 13 - if (!@available(iOS 13, *) && self.automaticallyShowsSearchBarCancelButton) { - [searchController.searchBar setShowsCancelButton:NO animated:YES]; - } -} - - -#pragma mark UISearchBarDelegate - -/// Not necessary in iOS 13; remove this when iOS 13 is the deployment target -- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope { - [self updateSearchResultsForSearchController:self.searchController]; -} - - -#pragma mark Table View - -/// Not having a title in the first section looks weird with a rounded-corner table view style -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (@available(iOS 13, *)) { - if (self.style == UITableViewStyleInsetGrouped) { - return @" "; - } - } - - return nil; // For plain/gropued style -} - -@end diff --git a/Tweaks/FLEX/Core/FLEXSingleRowSection.h b/Tweaks/FLEX/Core/FLEXSingleRowSection.h deleted file mode 100644 index 6b04a0e..0000000 --- a/Tweaks/FLEX/Core/FLEXSingleRowSection.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// FLEXSingleRowSection.h -// FLEX -// -// Created by Tanner Bennett on 9/25/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewSection.h" - -/// A section providing a specific single row. -/// -/// You may optionally provide a view controller to push when the row -/// is selected, or an action to perform when it is selected. -/// Which one is used first is up to the table view data source. -@interface FLEXSingleRowSection : FLEXTableViewSection - -/// @param reuseIdentifier if nil, kFLEXDefaultCell is used. -+ (instancetype)title:(NSString *)sectionTitle - reuse:(NSString *)reuseIdentifier - cell:(void(^)(__kindof UITableViewCell *cell))cellConfiguration; - -@property (nonatomic) UIViewController *pushOnSelection; -@property (nonatomic) void (^selectionAction)(UIViewController *host); -/// Called to determine whether the single row should display itself or not. -@property (nonatomic) BOOL (^filterMatcher)(NSString *filterText); - -@end diff --git a/Tweaks/FLEX/Core/FLEXSingleRowSection.m b/Tweaks/FLEX/Core/FLEXSingleRowSection.m deleted file mode 100644 index 7940941..0000000 --- a/Tweaks/FLEX/Core/FLEXSingleRowSection.m +++ /dev/null @@ -1,87 +0,0 @@ -// -// FLEXSingleRowSection.m -// FLEX -// -// Created by Tanner Bennett on 9/25/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSingleRowSection.h" -#import "FLEXTableView.h" - -@interface FLEXSingleRowSection () -@property (nonatomic, readonly) NSString *reuseIdentifier; -@property (nonatomic, readonly) void (^cellConfiguration)(__kindof UITableViewCell *cell); - -@property (nonatomic) NSString *lastTitle; -@property (nonatomic) NSString *lastSubitle; -@end - -@implementation FLEXSingleRowSection - -#pragma mark - Public - -+ (instancetype)title:(NSString *)title - reuse:(NSString *)reuse - cell:(void (^)(__kindof UITableViewCell *))config { - return [[self alloc] initWithTitle:title reuse:reuse cell:config]; -} - -- (id)initWithTitle:(NSString *)sectionTitle - reuse:(NSString *)reuseIdentifier - cell:(void (^)(__kindof UITableViewCell *))cellConfiguration { - self = [super init]; - if (self) { - _title = sectionTitle; - _reuseIdentifier = reuseIdentifier ?: kFLEXDefaultCell; - _cellConfiguration = cellConfiguration; - } - - return self; -} - -#pragma mark - Overrides - -- (NSInteger)numberOfRows { - if (self.filterMatcher && self.filterText.length) { - return self.filterMatcher(self.filterText) ? 1 : 0; - } - - return 1; -} - -- (BOOL)canSelectRow:(NSInteger)row { - return self.pushOnSelection || self.selectionAction; -} - -- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row { - return self.selectionAction; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - return self.pushOnSelection; -} - -- (NSString *)reuseIdentifierForRow:(NSInteger)row { - return self.reuseIdentifier; -} - -- (void)configureCell:(__kindof UITableViewCell *)cell forRow:(NSInteger)row { - cell.textLabel.text = nil; - cell.detailTextLabel.text = nil; - cell.accessoryType = UITableViewCellAccessoryNone; - - self.cellConfiguration(cell); - self.lastTitle = cell.textLabel.text; - self.lastSubitle = cell.detailTextLabel.text; -} - -- (NSString *)titleForRow:(NSInteger)row { - return self.lastTitle; -} - -- (NSString *)subtitleForRow:(NSInteger)row { - return self.lastSubitle; -} - -@end diff --git a/Tweaks/FLEX/Core/FLEXTableViewSection.h b/Tweaks/FLEX/Core/FLEXTableViewSection.h deleted file mode 100644 index f43e7d7..0000000 --- a/Tweaks/FLEX/Core/FLEXTableViewSection.h +++ /dev/null @@ -1,146 +0,0 @@ -// -// FLEXTableViewSection.h -// FLEX -// -// Created by Tanner on 1/29/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import "NSArray+FLEX.h" -@class FLEXTableView; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark FLEXTableViewSection - -/// An abstract base class for table view sections. -/// -/// Many properties or methods here return nil or some logical equivalent by default. -/// Even so, most of the methods with defaults are intended to be overriden by subclasses. -/// Some methods are not implemented at all and MUST be implemented by a subclass. -@interface FLEXTableViewSection : NSObject { - @protected - /// Unused by default, use if you want - NSString *_title; - - @private - __weak UITableView *_tableView; - NSInteger _sectionIndex; -} - -#pragma mark - Data - -/// A title to be displayed for the custom section. -/// Subclasses may override or use the \c _title ivar. -@property (nonatomic, readonly, nullable, copy) NSString *title; -/// The number of rows in this section. Subclasses must override. -/// This should not change until \c filterText is changed or \c reloadData is called. -@property (nonatomic, readonly) NSInteger numberOfRows; -/// A map of reuse identifiers to \c UITableViewCell (sub)class objects. -/// Subclasses \e may override this as necessary, but are not required to. -/// See \c FLEXTableView.h for more information. -/// @return nil by default. -@property (nonatomic, readonly, nullable) NSDictionary *cellRegistrationMapping; - -/// The section should filter itself based on the contents of this property -/// as it is set. If it is set to nil or an empty string, it should not filter. -/// Subclasses should override or observe this property and react to changes. -/// -/// It is common practice to use two arrays for the underlying model: -/// One to hold all rows, and one to hold unfiltered rows. When \c setFilterText: -/// is called, call \c super to store the new value, and re-filter your model accordingly. -@property (nonatomic, nullable) NSString *filterText; - -/// Provides an avenue for the section to refresh data or change the number of rows. -/// -/// This is called before reloading the table view itself. If your section pulls data -/// from an external data source, this is a good place to refresh that data entirely. -/// If your section does not, then it might be simpler for you to just override -/// \c setFilterText: to call \c super and call \c reloadData. -- (void)reloadData; - -/// Like \c reloadData, but optionally reloads the table view section -/// associated with this section object, if any. Do not override. -/// Do not call outside of the main thread. -- (void)reloadData:(BOOL)updateTable; - -/// Provide a table view and section index to allow the section to efficiently reload -/// its own section of the table when something changes it. The table reference is -/// held weakly, and subclasses cannot access it or the index. Call this method again -/// if the section numbers have changed since you last called it. -- (void)setTable:(UITableView *)tableView section:(NSInteger)index; - -#pragma mark - Row Selection - -/// Whether the given row should be selectable, such as if tapping the cell -/// should take the user to a new screen or trigger an action. -/// Subclasses \e may override this as necessary, but are not required to. -/// @return \c NO by default -- (BOOL)canSelectRow:(NSInteger)row; - -/// An action "future" to be triggered when the row is selected, if the row -/// supports being selected as indicated by \c canSelectRow:. Subclasses -/// must implement this in accordance with how they implement \c canSelectRow: -/// if they do not implement \c viewControllerToPushForRow: -/// @return This returns \c nil if no view controller is provided by -/// \c viewControllerToPushForRow: — otherwise it pushes that view controller -/// onto \c host.navigationController -- (nullable void(^)(__kindof UIViewController *host))didSelectRowAction:(NSInteger)row; - -/// A view controller to display when the row is selected, if the row -/// supports being selected as indicated by \c canSelectRow:. Subclasses -/// must implement this in accordance with how they implement \c canSelectRow: -/// if they do not implement \c didSelectRowAction: -/// @return \c nil by default -- (nullable UIViewController *)viewControllerToPushForRow:(NSInteger)row; - -/// Called when the accessory view's detail button is pressed. -/// @return \c nil by default. -- (nullable void(^)(__kindof UIViewController *host))didPressInfoButtonAction:(NSInteger)row; - -#pragma mark - Context Menus - -/// By default, this is the title of the row. -/// @return The title of the context menu, if any. -- (nullable NSString *)menuTitleForRow:(NSInteger)row API_AVAILABLE(ios(13.0)); -/// Protected, not intended for public use. \c menuTitleForRow: -/// already includes the value returned from this method. -/// -/// By default, this returns \c @"". Subclasses may override to -/// provide a detailed description of the target of the context menu. -- (NSString *)menuSubtitleForRow:(NSInteger)row API_AVAILABLE(ios(13.0)); -/// The context menu items, if any. Subclasses may override. -/// By default, only inludes items for \c copyMenuItemsForRow:. -- (nullable NSArray *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender API_AVAILABLE(ios(13.0)); -/// Subclasses may override to return a list of copiable items. -/// -/// Every two elements in the list compose a key-value pair, where the key -/// should be a description of what will be copied, and the values should be -/// the strings to copy. Return an empty string as a value to show a disabled action. -- (nullable NSArray *)copyMenuItemsForRow:(NSInteger)row API_AVAILABLE(ios(13.0)); - -#pragma mark - Cell Configuration - -/// Provide a reuse identifier for the given row. Subclasses should override. -/// -/// Custom reuse identifiers should be specified in \c cellRegistrationMapping. -/// You may return any of the identifiers in \c FLEXTableView.h -/// without including them in the \c cellRegistrationMapping. -/// @return \c kFLEXDefaultCell by default. -- (NSString *)reuseIdentifierForRow:(NSInteger)row; -/// Configure a cell for the given row. Subclasses must override. -- (void)configureCell:(__kindof UITableViewCell *)cell forRow:(NSInteger)row; - -#pragma mark - External Convenience - -/// For use by whatever view controller uses your section. Not required. -/// @return An optional title. -- (nullable NSString *)titleForRow:(NSInteger)row; -/// For use by whatever view controller uses your section. Not required. -/// @return An optional subtitle. -- (nullable NSString *)subtitleForRow:(NSInteger)row; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Core/FLEXTableViewSection.m b/Tweaks/FLEX/Core/FLEXTableViewSection.m deleted file mode 100644 index 3fcd96b..0000000 --- a/Tweaks/FLEX/Core/FLEXTableViewSection.m +++ /dev/null @@ -1,137 +0,0 @@ -// -// FLEXTableViewSection.m -// FLEX -// -// Created by Tanner on 1/29/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewSection.h" -#import "FLEXTableView.h" -#import "FLEXUtility.h" -#import "UIMenu+FLEX.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wincomplete-implementation" - -@implementation FLEXTableViewSection - -- (NSInteger)numberOfRows { - return 0; -} - -- (void)reloadData { } - -- (void)reloadData:(BOOL)updateTable { - [self reloadData]; - if (updateTable) { - NSIndexSet *index = [NSIndexSet indexSetWithIndex:_sectionIndex]; - [_tableView reloadSections:index withRowAnimation:UITableViewRowAnimationNone]; - } -} - -- (void)setTable:(UITableView *)tableView section:(NSInteger)index { - _tableView = tableView; - _sectionIndex = index; -} - -- (NSDictionary *)cellRegistrationMapping { - return nil; -} - -- (BOOL)canSelectRow:(NSInteger)row { return NO; } - -- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row { - UIViewController *toPush = [self viewControllerToPushForRow:row]; - if (toPush) { - return ^(UIViewController *host) { - [host.navigationController pushViewController:toPush animated:YES]; - }; - } - - return nil; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - return nil; -} - -- (void (^)(__kindof UIViewController *))didPressInfoButtonAction:(NSInteger)row { - return nil; -} - -- (NSString *)reuseIdentifierForRow:(NSInteger)row { - return kFLEXDefaultCell; -} - -- (NSString *)menuTitleForRow:(NSInteger)row { - NSString *title = [self titleForRow:row]; - NSString *subtitle = [self menuSubtitleForRow:row]; - - if (subtitle.length) { - return [NSString stringWithFormat:@"%@\n\n%@", title, subtitle]; - } - - return title; -} - -- (NSString *)menuSubtitleForRow:(NSInteger)row { - return @""; -} - -- (NSArray *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender API_AVAILABLE(ios(13)) { - NSArray *copyItems = [self copyMenuItemsForRow:row]; - NSAssert(copyItems.count % 2 == 0, @"copyMenuItemsForRow: should return an even list"); - - if (copyItems.count) { - NSInteger numberOfActions = copyItems.count / 2; - BOOL collapseMenu = numberOfActions > 4; - UIImage *copyIcon = [UIImage systemImageNamed:@"doc.on.doc"]; - - NSMutableArray *actions = [NSMutableArray new]; - - for (NSInteger i = 0; i < copyItems.count; i += 2) { - NSString *key = copyItems[i], *value = copyItems[i+1]; - NSString *title = collapseMenu ? key : [@"Copy " stringByAppendingString:key]; - - UIAction *copy = [UIAction - actionWithTitle:title - image:copyIcon - identifier:nil - handler:^(__kindof UIAction *action) { - UIPasteboard.generalPasteboard.string = value; - } - ]; - if (!value.length) { - copy.attributes = UIMenuElementAttributesDisabled; - } - - [actions addObject:copy]; - } - - UIMenu *copyMenu = [UIMenu - flex_inlineMenuWithTitle:@"Copy…" - image:copyIcon - children:actions - ]; - - if (collapseMenu) { - return @[[copyMenu flex_collapsed]]; - } else { - return @[copyMenu]; - } - } - - return @[]; -} - -- (NSArray *)copyMenuItemsForRow:(NSInteger)row { - return nil; -} - -- (NSString *)titleForRow:(NSInteger)row { return nil; } -- (NSString *)subtitleForRow:(NSInteger)row { return nil; } - -@end - -#pragma clang diagnostic pop diff --git a/Tweaks/FLEX/Core/Views/Carousel/FLEXCarouselCell.h b/Tweaks/FLEX/Core/Views/Carousel/FLEXCarouselCell.h deleted file mode 100644 index d8afbd0..0000000 --- a/Tweaks/FLEX/Core/Views/Carousel/FLEXCarouselCell.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// FLEXCarouselCell.h -// FLEX -// -// Created by Tanner Bennett on 7/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXCarouselCell : UICollectionViewCell - -@property (nonatomic, copy) NSString *title; - -@end diff --git a/Tweaks/FLEX/Core/Views/Carousel/FLEXCarouselCell.m b/Tweaks/FLEX/Core/Views/Carousel/FLEXCarouselCell.m deleted file mode 100644 index aabfbec..0000000 --- a/Tweaks/FLEX/Core/Views/Carousel/FLEXCarouselCell.m +++ /dev/null @@ -1,93 +0,0 @@ -// -// FLEXCarouselCell.m -// FLEX -// -// Created by Tanner Bennett on 7/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXCarouselCell.h" -#import "FLEXColor.h" -#import "UIView+FLEX_Layout.h" - -@interface FLEXCarouselCell () -@property (nonatomic, readonly) UILabel *titleLabel; -@property (nonatomic, readonly) UIView *selectionIndicatorStripe; -@property (nonatomic) BOOL constraintsInstalled; -@end - -@implementation FLEXCarouselCell - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _titleLabel = [UILabel new]; - _selectionIndicatorStripe = [UIView new]; - - self.titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - self.selectionIndicatorStripe.backgroundColor = self.tintColor; - if (@available(iOS 10, *)) { - self.titleLabel.adjustsFontForContentSizeCategory = YES; - } - - [self.contentView addSubview:self.titleLabel]; - [self.contentView addSubview:self.selectionIndicatorStripe]; - - [self installConstraints]; - - [self updateAppearance]; - } - - return self; -} - -- (void)updateAppearance { - self.selectionIndicatorStripe.hidden = !self.selected; - - if (self.selected) { - self.titleLabel.textColor = self.tintColor; - } else { - self.titleLabel.textColor = FLEXColor.deemphasizedTextColor; - } -} - -#pragma mark Public - -- (NSString *)title { - return self.titleLabel.text; -} - -- (void)setTitle:(NSString *)title { - self.titleLabel.text = title; - [self.titleLabel sizeToFit]; - [self setNeedsLayout]; -} - -#pragma mark Overrides - -- (void)prepareForReuse { - [super prepareForReuse]; - [self updateAppearance]; -} - -- (void)installConstraints { - CGFloat stripeHeight = 2; - - self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; - self.selectionIndicatorStripe.translatesAutoresizingMaskIntoConstraints = NO; - - UIView *superview = self.contentView; - [self.titleLabel flex_pinEdgesToSuperviewWithInsets:UIEdgeInsetsMake(10, 15, 8 + stripeHeight, 15)]; - - [self.selectionIndicatorStripe.leadingAnchor constraintEqualToAnchor:superview.leadingAnchor].active = YES; - [self.selectionIndicatorStripe.bottomAnchor constraintEqualToAnchor:superview.bottomAnchor].active = YES; - [self.selectionIndicatorStripe.trailingAnchor constraintEqualToAnchor:superview.trailingAnchor].active = YES; - [self.selectionIndicatorStripe.heightAnchor constraintEqualToConstant:stripeHeight].active = YES; -} - -- (void)setSelected:(BOOL)selected { - super.selected = selected; - [self updateAppearance]; -} - -@end diff --git a/Tweaks/FLEX/Core/Views/Carousel/FLEXScopeCarousel.h b/Tweaks/FLEX/Core/Views/Carousel/FLEXScopeCarousel.h deleted file mode 100644 index fb03676..0000000 --- a/Tweaks/FLEX/Core/Views/Carousel/FLEXScopeCarousel.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FLEXScopeCarousel.h -// FLEX -// -// Created by Tanner Bennett on 7/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -/// Only use on iOS 10 and up. Requires iOS 10 APIs for calculating row sizes. -@interface FLEXScopeCarousel : UIControl - -@property (nonatomic, copy) NSArray *items; -@property (nonatomic) NSInteger selectedIndex; -@property (nonatomic) void(^selectedIndexChangedAction)(NSInteger idx); - -- (void)registerBlockForDynamicTypeChanges:(void(^)(FLEXScopeCarousel *))handler; - -@end diff --git a/Tweaks/FLEX/Core/Views/Carousel/FLEXScopeCarousel.m b/Tweaks/FLEX/Core/Views/Carousel/FLEXScopeCarousel.m deleted file mode 100644 index daf967d..0000000 --- a/Tweaks/FLEX/Core/Views/Carousel/FLEXScopeCarousel.m +++ /dev/null @@ -1,204 +0,0 @@ -// -// FLEXScopeCarousel.m -// FLEX -// -// Created by Tanner Bennett on 7/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXScopeCarousel.h" -#import "FLEXCarouselCell.h" -#import "FLEXColor.h" -#import "FLEXMacros.h" -#import "UIView+FLEX_Layout.h" - -const CGFloat kCarouselItemSpacing = 0; -NSString * const kCarouselCellReuseIdentifier = @"kCarouselCellReuseIdentifier"; - -@interface FLEXScopeCarousel () -@property (nonatomic, readonly) UICollectionView *collectionView; -@property (nonatomic, readonly) FLEXCarouselCell *sizingCell; - -@property (nonatomic, readonly) id dynamicTypeObserver; -@property (nonatomic, readonly) NSMutableArray *dynamicTypeHandlers; - -@property (nonatomic) BOOL constraintsInstalled; -@end - -@implementation FLEXScopeCarousel - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.backgroundColor = FLEXColor.primaryBackgroundColor; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth; - self.translatesAutoresizingMaskIntoConstraints = YES; - _dynamicTypeHandlers = [NSMutableArray new]; - - CGSize itemSize = CGSizeZero; - if (@available(iOS 10.0, *)) { - itemSize = UICollectionViewFlowLayoutAutomaticSize; - } - - // Collection view layout - UICollectionViewFlowLayout *layout = ({ - UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new]; - layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; - layout.sectionInset = UIEdgeInsetsZero; - layout.minimumLineSpacing = kCarouselItemSpacing; - layout.itemSize = itemSize; - layout.estimatedItemSize = itemSize; - layout; - }); - - // Collection view - _collectionView = ({ - UICollectionView *cv = [[UICollectionView alloc] - initWithFrame:CGRectZero - collectionViewLayout:layout - ]; - cv.showsHorizontalScrollIndicator = NO; - cv.backgroundColor = UIColor.clearColor; - cv.delegate = self; - cv.dataSource = self; - [cv registerClass:[FLEXCarouselCell class] forCellWithReuseIdentifier:kCarouselCellReuseIdentifier]; - - [self addSubview:cv]; - cv; - }); - - - // Sizing cell - _sizingCell = [FLEXCarouselCell new]; - self.sizingCell.title = @"NSObject"; - - // Dynamic type - weakify(self); - _dynamicTypeObserver = [NSNotificationCenter.defaultCenter - addObserverForName:UIContentSizeCategoryDidChangeNotification - object:nil queue:nil usingBlock:^(NSNotification *note) { strongify(self) - [self.collectionView setNeedsLayout]; - [self setNeedsUpdateConstraints]; - - // Notify observers - for (void (^block)(FLEXScopeCarousel *) in self.dynamicTypeHandlers) { - block(self); - } - } - ]; - } - - return self; -} - -- (void)dealloc { - [NSNotificationCenter.defaultCenter removeObserver:self.dynamicTypeObserver]; -} - -#pragma mark - Overrides - -- (void)drawRect:(CGRect)rect { - [super drawRect:rect]; - - CGFloat width = 1.f / UIScreen.mainScreen.scale; - - // Draw hairline - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetStrokeColorWithColor(context, FLEXColor.hairlineColor.CGColor); - CGContextSetLineWidth(context, width); - CGContextMoveToPoint(context, 0, rect.size.height - width); - CGContextAddLineToPoint(context, rect.size.width, rect.size.height - width); - CGContextStrokePath(context); -} - -+ (BOOL)requiresConstraintBasedLayout { - return YES; -} - -- (void)updateConstraints { - if (!self.constraintsInstalled) { - self.collectionView.translatesAutoresizingMaskIntoConstraints = NO; - [self.collectionView flex_pinEdgesToSuperview]; - - self.constraintsInstalled = YES; - } - - [super updateConstraints]; -} - -- (CGSize)intrinsicContentSize { - return CGSizeMake( - UIViewNoIntrinsicMetric, - [self.sizingCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height - ); -} - -#pragma mark - Public - -- (void)setItems:(NSArray *)items { - NSParameterAssert(items.count); - - _items = items.copy; - - // Refresh list, select first item initially - [self.collectionView reloadData]; - self.selectedIndex = 0; -} - -- (void)setSelectedIndex:(NSInteger)idx { - NSParameterAssert(idx < self.items.count); - - _selectedIndex = idx; - NSIndexPath *path = [NSIndexPath indexPathForItem:idx inSection:0]; - [self.collectionView selectItemAtIndexPath:path - animated:YES - scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; - [self collectionView:self.collectionView didSelectItemAtIndexPath:path]; -} - -- (void)registerBlockForDynamicTypeChanges:(void (^)(FLEXScopeCarousel *))handler { - [self.dynamicTypeHandlers addObject:handler]; -} - -#pragma mark - UICollectionView - -- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { -// if (@available(iOS 10.0, *)) { -// return UICollectionViewFlowLayoutAutomaticSize; -// } - - self.sizingCell.title = self.items[indexPath.item]; - return [self.sizingCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; -} - -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { - return self.items.count; -} - -- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView - cellForItemAtIndexPath:(NSIndexPath *)indexPath { - FLEXCarouselCell *cell = (id)[collectionView dequeueReusableCellWithReuseIdentifier:kCarouselCellReuseIdentifier - forIndexPath:indexPath]; - cell.title = self.items[indexPath.row]; - return cell; -} - -- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - _selectedIndex = indexPath.item; // In case self.selectedIndex didn't trigger this call - - if (self.selectedIndexChangedAction) { - self.selectedIndexChangedAction(indexPath.row); - } - - // TODO: dynamically choose a scroll position. Very wide items should - // get "Left" while smaller items should not scroll at all, unless - // they are only partially on the screen, in which case they - // should get "HorizontallyCentered" to bring them onto the screen. - // For now, everything goes to the left, as this has a similar effect. - [collectionView scrollToItemAtIndexPath:indexPath - atScrollPosition:UICollectionViewScrollPositionLeft - animated:YES]; - [self sendActionsForControlEvents:UIControlEventValueChanged]; -} - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXCodeFontCell.h b/Tweaks/FLEX/Core/Views/Cells/FLEXCodeFontCell.h deleted file mode 100644 index c4afbf7..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXCodeFontCell.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXCodeFontCell.h -// FLEX -// -// Created by Tanner on 12/27/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMultilineTableViewCell.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXCodeFontCell : FLEXMultilineDetailTableViewCell - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXCodeFontCell.m b/Tweaks/FLEX/Core/Views/Cells/FLEXCodeFontCell.m deleted file mode 100644 index aff1730..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXCodeFontCell.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// FLEXCodeFontCell.m -// FLEX -// -// Created by Tanner on 12/27/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXCodeFontCell.h" -#import "UIFont+FLEX.h" - -@implementation FLEXCodeFontCell - -- (void)postInit { - [super postInit]; - - self.titleLabel.font = UIFont.flex_codeFont; - self.subtitleLabel.font = UIFont.flex_codeFont; - - self.titleLabel.adjustsFontSizeToFitWidth = YES; - self.titleLabel.minimumScaleFactor = 0.9; - self.subtitleLabel.adjustsFontSizeToFitWidth = YES; - self.subtitleLabel.minimumScaleFactor = 0.75; - - // Disable mutli-line pre iOS 11 - if (@available(iOS 11, *)) { - self.subtitleLabel.numberOfLines = 5; - } else { - self.titleLabel.numberOfLines = 1; - self.subtitleLabel.numberOfLines = 1; - } -} - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXKeyValueTableViewCell.h b/Tweaks/FLEX/Core/Views/Cells/FLEXKeyValueTableViewCell.h deleted file mode 100644 index 7e3074c..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXKeyValueTableViewCell.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXKeyValueTableViewCell.h -// FLEX -// -// Created by Tanner Bennett on 1/23/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewCell.h" - -@interface FLEXKeyValueTableViewCell : FLEXTableViewCell - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXKeyValueTableViewCell.m b/Tweaks/FLEX/Core/Views/Cells/FLEXKeyValueTableViewCell.m deleted file mode 100644 index 28ca502..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXKeyValueTableViewCell.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXKeyValueTableViewCell.m -// FLEX -// -// Created by Tanner Bennett on 1/23/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXKeyValueTableViewCell.h" - -@implementation FLEXKeyValueTableViewCell - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - return [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier]; -} - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXMultilineTableViewCell.h b/Tweaks/FLEX/Core/Views/Cells/FLEXMultilineTableViewCell.h deleted file mode 100644 index 914cf23..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXMultilineTableViewCell.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// FLEXMultilineTableViewCell.h -// FLEX -// -// Created by Ryan Olson on 2/13/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewCell.h" - -/// A cell with both labels set to be multi-line capable. -@interface FLEXMultilineTableViewCell : FLEXTableViewCell - -+ (CGFloat)preferredHeightWithAttributedText:(NSAttributedString *)attributedText - maxWidth:(CGFloat)contentViewWidth - style:(UITableViewStyle)style - showsAccessory:(BOOL)showsAccessory; - -@end - -/// A \c FLEXMultilineTableViewCell initialized with \c UITableViewCellStyleSubtitle -@interface FLEXMultilineDetailTableViewCell : FLEXMultilineTableViewCell - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXMultilineTableViewCell.m b/Tweaks/FLEX/Core/Views/Cells/FLEXMultilineTableViewCell.m deleted file mode 100644 index 58f008c..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXMultilineTableViewCell.m +++ /dev/null @@ -1,67 +0,0 @@ -// -// FLEXMultilineTableViewCell.m -// FLEX -// -// Created by Ryan Olson on 2/13/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMultilineTableViewCell.h" -#import "UIView+FLEX_Layout.h" -#import "FLEXUtility.h" - -@interface FLEXMultilineTableViewCell () -@property (nonatomic, readonly) UILabel *_titleLabel; -@property (nonatomic, readonly) UILabel *_subtitleLabel; -@property (nonatomic) BOOL constraintsUpdated; -@end - -@implementation FLEXMultilineTableViewCell - -- (void)postInit { - [super postInit]; - - self.titleLabel.numberOfLines = 0; - self.subtitleLabel.numberOfLines = 0; -} - -+ (UIEdgeInsets)labelInsets { - return UIEdgeInsetsMake(10.0, 16.0, 10.0, 8.0); -} - -+ (CGFloat)preferredHeightWithAttributedText:(NSAttributedString *)attributedText - maxWidth:(CGFloat)contentViewWidth - style:(UITableViewStyle)style - showsAccessory:(BOOL)showsAccessory { - CGFloat labelWidth = contentViewWidth; - - // Content view inset due to accessory view observed on iOS 8.1 iPhone 6. - if (showsAccessory) { - labelWidth -= 34.0; - } - - UIEdgeInsets labelInsets = [self labelInsets]; - labelWidth -= (labelInsets.left + labelInsets.right); - - CGSize constrainSize = CGSizeMake(labelWidth, CGFLOAT_MAX); - CGRect boundingBox = [attributedText - boundingRectWithSize:constrainSize - options:NSStringDrawingUsesLineFragmentOrigin - context:nil - ]; - CGFloat preferredLabelHeight = FLEXFloor(boundingBox.size.height); - CGFloat preferredCellHeight = preferredLabelHeight + labelInsets.top + labelInsets.bottom + 1.0; - - return preferredCellHeight; -} - -@end - - -@implementation FLEXMultilineDetailTableViewCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier]; -} - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXSubtitleTableViewCell.h b/Tweaks/FLEX/Core/Views/Cells/FLEXSubtitleTableViewCell.h deleted file mode 100644 index 26858ab..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXSubtitleTableViewCell.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXSubtitleTableViewCell.h -// FLEX -// -// Created by Tanner on 4/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewCell.h" - -/// A cell initialized with \c UITableViewCellStyleSubtitle -@interface FLEXSubtitleTableViewCell : FLEXTableViewCell - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXSubtitleTableViewCell.m b/Tweaks/FLEX/Core/Views/Cells/FLEXSubtitleTableViewCell.m deleted file mode 100644 index b1bb3ad..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXSubtitleTableViewCell.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXSubtitleTableViewCell.m -// FLEX -// -// Created by Tanner on 4/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSubtitleTableViewCell.h" - -@implementation FLEXSubtitleTableViewCell - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier]; -} - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXTableViewCell.h b/Tweaks/FLEX/Core/Views/Cells/FLEXTableViewCell.h deleted file mode 100644 index 6d06598..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXTableViewCell.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// FLEXTableViewCell.h -// FLEX -// -// Created by Tanner on 4/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXTableViewCell : UITableViewCell - -/// Use this instead of .textLabel -@property (nonatomic, readonly) UILabel *titleLabel; -/// Use this instead of .detailTextLabel -@property (nonatomic, readonly) UILabel *subtitleLabel; - -/// Subclasses can override this instead of initializers to -/// perform additional initialization without lots of boilerplate. -/// Remember to call super! -- (void)postInit; - -@end diff --git a/Tweaks/FLEX/Core/Views/Cells/FLEXTableViewCell.m b/Tweaks/FLEX/Core/Views/Cells/FLEXTableViewCell.m deleted file mode 100644 index ceb4752..0000000 --- a/Tweaks/FLEX/Core/Views/Cells/FLEXTableViewCell.m +++ /dev/null @@ -1,57 +0,0 @@ -// -// FLEXTableViewCell.m -// FLEX -// -// Created by Tanner on 4/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewCell.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" -#import "FLEXTableView.h" - -@interface UITableView (Internal) -// Exists at least since iOS 5 -- (BOOL)_canPerformAction:(SEL)action forCell:(UITableViewCell *)cell sender:(id)sender; -- (void)_performAction:(SEL)action forCell:(UITableViewCell *)cell sender:(id)sender; -@end - -@interface UITableViewCell (Internal) -// Exists at least since iOS 5 -@property (nonatomic, readonly) FLEXTableView *_tableView; -@end - -@implementation FLEXTableViewCell - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - [self postInit]; - } - - return self; -} - -- (void)postInit { - UIFont *cellFont = UIFont.flex_defaultTableCellFont; - self.titleLabel.font = cellFont; - self.subtitleLabel.font = cellFont; - self.subtitleLabel.textColor = FLEXColor.deemphasizedTextColor; - - self.titleLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - self.subtitleLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - - self.titleLabel.numberOfLines = 1; - self.subtitleLabel.numberOfLines = 1; -} - -- (UILabel *)titleLabel { - return self.textLabel; -} - -- (UILabel *)subtitleLabel { - return self.detailTextLabel; -} - -@end diff --git a/Tweaks/FLEX/Core/Views/FLEXTableView.h b/Tweaks/FLEX/Core/Views/FLEXTableView.h deleted file mode 100644 index 9479b52..0000000 --- a/Tweaks/FLEX/Core/Views/FLEXTableView.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// FLEXTableView.h -// FLEX -// -// Created by Tanner on 4/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark Reuse identifiers - -typedef NSString * FLEXTableViewCellReuseIdentifier; - -/// A regular \c FLEXTableViewCell initialized with \c UITableViewCellStyleDefault -extern FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell; -/// A \c FLEXSubtitleTableViewCell initialized with \c UITableViewCellStyleSubtitle -extern FLEXTableViewCellReuseIdentifier const kFLEXDetailCell; -/// A \c FLEXMultilineTableViewCell initialized with \c UITableViewCellStyleDefault -extern FLEXTableViewCellReuseIdentifier const kFLEXMultilineCell; -/// A \c FLEXMultilineTableViewCell initialized with \c UITableViewCellStyleSubtitle -extern FLEXTableViewCellReuseIdentifier const kFLEXMultilineDetailCell; -/// A \c FLEXTableViewCell initialized with \c UITableViewCellStyleValue1 -extern FLEXTableViewCellReuseIdentifier const kFLEXKeyValueCell; -/// A \c FLEXSubtitleTableViewCell which uses monospaced fonts for both labels -extern FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell; - -#pragma mark - FLEXTableView -@interface FLEXTableView : UITableView - -+ (instancetype)flexDefaultTableView; -+ (instancetype)groupedTableView; -+ (instancetype)plainTableView; -+ (instancetype)style:(UITableViewStyle)style; - -/// You do not need to register classes for any of the default reuse identifiers above -/// (annotated as \c FLEXTableViewCellReuseIdentifier types) unless you wish to provide -/// a custom cell for any of those reuse identifiers. By default, \c FLEXTableViewCell, -/// \c FLEXSubtitleTableViewCell, and \c FLEXMultilineTableViewCell are used, respectively. -/// -/// @param registrationMapping A map of reuse identifiers to \c UITableViewCell (sub)class objects. -- (void)registerCells:(NSDictionary *)registrationMapping; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Core/Views/FLEXTableView.m b/Tweaks/FLEX/Core/Views/FLEXTableView.m deleted file mode 100644 index 09973de..0000000 --- a/Tweaks/FLEX/Core/Views/FLEXTableView.m +++ /dev/null @@ -1,83 +0,0 @@ -// -// FLEXTableView.m -// FLEX -// -// Created by Tanner on 4/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableView.h" -#import "FLEXUtility.h" -#import "FLEXSubtitleTableViewCell.h" -#import "FLEXMultilineTableViewCell.h" -#import "FLEXKeyValueTableViewCell.h" -#import "FLEXCodeFontCell.h" - -FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell = @"kFLEXDefaultCell"; -FLEXTableViewCellReuseIdentifier const kFLEXDetailCell = @"kFLEXDetailCell"; -FLEXTableViewCellReuseIdentifier const kFLEXMultilineCell = @"kFLEXMultilineCell"; -FLEXTableViewCellReuseIdentifier const kFLEXMultilineDetailCell = @"kFLEXMultilineDetailCell"; -FLEXTableViewCellReuseIdentifier const kFLEXKeyValueCell = @"kFLEXKeyValueCell"; -FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell = @"kFLEXCodeFontCell"; - -#pragma mark Private - -@interface UITableView (Private) -- (CGFloat)_heightForHeaderInSection:(NSInteger)section; -- (NSString *)_titleForHeaderInSection:(NSInteger)section; -@end - -@implementation FLEXTableView - -+ (instancetype)flexDefaultTableView { - if (@available(iOS 13.0, *)) { - return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped]; - } else { - return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; - } -} - -#pragma mark - Initialization - -+ (id)groupedTableView { - if (@available(iOS 13.0, *)) { - return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped]; - } else { - return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; - } -} - -+ (id)plainTableView { - return [[self alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; -} - -+ (id)style:(UITableViewStyle)style { - return [[self alloc] initWithFrame:CGRectZero style:style]; -} - -- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style { - self = [super initWithFrame:frame style:style]; - if (self) { - [self registerCells:@{ - kFLEXDefaultCell : [FLEXTableViewCell class], - kFLEXDetailCell : [FLEXSubtitleTableViewCell class], - kFLEXMultilineCell : [FLEXMultilineTableViewCell class], - kFLEXMultilineDetailCell : [FLEXMultilineDetailTableViewCell class], - kFLEXKeyValueCell : [FLEXKeyValueTableViewCell class], - kFLEXCodeFontCell : [FLEXCodeFontCell class], - }]; - } - - return self; -} - - -#pragma mark - Public - -- (void)registerCells:(NSDictionary *)registrationMapping { - [registrationMapping enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, Class cellClass, BOOL *stop) { - [self registerClass:cellClass forCellReuseIdentifier:identifier]; - }]; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.h deleted file mode 100644 index 961caa1..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputColorView.h -// Flipboard -// -// Created by Ryan Olson on 6/30/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputView.h" - -@interface FLEXArgumentInputColorView : FLEXArgumentInputView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m deleted file mode 100644 index 7f10130..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputColorView.m +++ /dev/null @@ -1,311 +0,0 @@ -// -// FLEXArgumentInputColorView.m -// Flipboard -// -// Created by Ryan Olson on 6/30/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputColorView.h" -#import "FLEXUtility.h" -#import "FLEXRuntimeUtility.h" - -@protocol FLEXColorComponentInputViewDelegate; - -@interface FLEXColorComponentInputView : UIView - -@property (nonatomic) UISlider *slider; -@property (nonatomic) UILabel *valueLabel; - -@property (nonatomic, weak) id delegate; - -@end - -@protocol FLEXColorComponentInputViewDelegate - -- (void)colorComponentInputViewValueDidChange:(FLEXColorComponentInputView *)colorComponentInputView; - -@end - - -@implementation FLEXColorComponentInputView - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.slider = [UISlider new]; - [self.slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged]; - [self addSubview:self.slider]; - - self.valueLabel = [UILabel new]; - self.valueLabel.backgroundColor = self.backgroundColor; - self.valueLabel.font = [UIFont systemFontOfSize:14.0]; - self.valueLabel.textAlignment = NSTextAlignmentRight; - [self addSubview:self.valueLabel]; - - [self updateValueLabel]; - } - return self; -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor { - [super setBackgroundColor:backgroundColor]; - self.slider.backgroundColor = backgroundColor; - self.valueLabel.backgroundColor = backgroundColor; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - const CGFloat kValueLabelWidth = 50.0; - - [self.slider sizeToFit]; - CGFloat sliderWidth = self.bounds.size.width - kValueLabelWidth; - self.slider.frame = CGRectMake(0, 0, sliderWidth, self.slider.frame.size.height); - - [self.valueLabel sizeToFit]; - CGFloat valueLabelOriginX = CGRectGetMaxX(self.slider.frame); - CGFloat valueLabelOriginY = FLEXFloor((self.slider.frame.size.height - self.valueLabel.frame.size.height) / 2.0); - self.valueLabel.frame = CGRectMake(valueLabelOriginX, valueLabelOriginY, kValueLabelWidth, self.valueLabel.frame.size.height); -} - -- (void)sliderChanged:(id)sender { - [self.delegate colorComponentInputViewValueDidChange:self]; - [self updateValueLabel]; -} - -- (void)updateValueLabel { - self.valueLabel.text = [NSString stringWithFormat:@"%.3f", self.slider.value]; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat height = [self.slider sizeThatFits:size].height; - return CGSizeMake(size.width, height); -} - -@end - -@interface FLEXColorPreviewBox : UIView - -@property (nonatomic) UIColor *color; - -@property (nonatomic) UIView *colorOverlayView; - -@end - -@implementation FLEXColorPreviewBox - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.layer.borderWidth = 1.0; - self.layer.borderColor = UIColor.blackColor.CGColor; - self.backgroundColor = [UIColor colorWithPatternImage:[[self class] backgroundPatternImage]]; - - self.colorOverlayView = [[UIView alloc] initWithFrame:self.bounds]; - self.colorOverlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.colorOverlayView.backgroundColor = UIColor.clearColor; - [self addSubview:self.colorOverlayView]; - } - return self; -} - -- (void)setColor:(UIColor *)color { - self.colorOverlayView.backgroundColor = color; -} - -- (UIColor *)color { - return self.colorOverlayView.backgroundColor; -} - -+ (UIImage *)backgroundPatternImage { - const CGFloat kSquareDimension = 5.0; - CGSize squareSize = CGSizeMake(kSquareDimension, kSquareDimension); - CGSize imageSize = CGSizeMake(2.0 * kSquareDimension, 2.0 * kSquareDimension); - - UIGraphicsBeginImageContextWithOptions(imageSize, YES, UIScreen.mainScreen.scale); - - [UIColor.whiteColor setFill]; - UIRectFill(CGRectMake(0, 0, imageSize.width, imageSize.height)); - - [UIColor.grayColor setFill]; - UIRectFill(CGRectMake(squareSize.width, 0, squareSize.width, squareSize.height)); - UIRectFill(CGRectMake(0, squareSize.height, squareSize.width, squareSize.height)); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; -} - -@end - -@interface FLEXArgumentInputColorView () - -@property (nonatomic) FLEXColorPreviewBox *colorPreviewBox; -@property (nonatomic) UILabel *hexLabel; -@property (nonatomic) FLEXColorComponentInputView *alphaInput; -@property (nonatomic) FLEXColorComponentInputView *redInput; -@property (nonatomic) FLEXColorComponentInputView *greenInput; -@property (nonatomic) FLEXColorComponentInputView *blueInput; - -@end - -@implementation FLEXArgumentInputColorView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.colorPreviewBox = [FLEXColorPreviewBox new]; - [self addSubview:self.colorPreviewBox]; - - self.hexLabel = [UILabel new]; - self.hexLabel.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.9]; - self.hexLabel.textAlignment = NSTextAlignmentCenter; - self.hexLabel.font = [UIFont systemFontOfSize:12.0]; - [self addSubview:self.hexLabel]; - - self.alphaInput = [FLEXColorComponentInputView new]; - self.alphaInput.slider.minimumTrackTintColor = UIColor.blackColor; - self.alphaInput.delegate = self; - [self addSubview:self.alphaInput]; - - self.redInput = [FLEXColorComponentInputView new]; - self.redInput.slider.minimumTrackTintColor = UIColor.redColor; - self.redInput.delegate = self; - [self addSubview:self.redInput]; - - self.greenInput = [FLEXColorComponentInputView new]; - self.greenInput.slider.minimumTrackTintColor = UIColor.greenColor; - self.greenInput.delegate = self; - [self addSubview:self.greenInput]; - - self.blueInput = [FLEXColorComponentInputView new]; - self.blueInput.slider.minimumTrackTintColor = UIColor.blueColor; - self.blueInput.delegate = self; - [self addSubview:self.blueInput]; - } - return self; -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor { - [super setBackgroundColor:backgroundColor]; - self.alphaInput.backgroundColor = backgroundColor; - self.redInput.backgroundColor = backgroundColor; - self.greenInput.backgroundColor = backgroundColor; - self.blueInput.backgroundColor = backgroundColor; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGFloat runningOriginY = 0; - CGSize constrainSize = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX); - - self.colorPreviewBox.frame = CGRectMake(0, runningOriginY, self.bounds.size.width, [[self class] colorPreviewBoxHeight]); - runningOriginY = CGRectGetMaxY(self.colorPreviewBox.frame) + [[self class] inputViewVerticalPadding]; - - [self.hexLabel sizeToFit]; - const CGFloat kLabelVerticalOutsetAmount = 0.0; - const CGFloat kLabelHorizontalOutsetAmount = 2.0; - UIEdgeInsets labelOutset = UIEdgeInsetsMake(-kLabelVerticalOutsetAmount, -kLabelHorizontalOutsetAmount, -kLabelVerticalOutsetAmount, -kLabelHorizontalOutsetAmount); - self.hexLabel.frame = UIEdgeInsetsInsetRect(self.hexLabel.frame, labelOutset); - CGFloat hexLabelOriginX = self.colorPreviewBox.layer.borderWidth; - CGFloat hexLabelOriginY = CGRectGetMaxY(self.colorPreviewBox.frame) - self.colorPreviewBox.layer.borderWidth - self.hexLabel.frame.size.height; - self.hexLabel.frame = CGRectMake(hexLabelOriginX, hexLabelOriginY, self.hexLabel.frame.size.width, self.hexLabel.frame.size.height); - - NSArray *colorComponentInputViews = @[self.alphaInput, self.redInput, self.greenInput, self.blueInput]; - for (FLEXColorComponentInputView *inputView in colorComponentInputViews) { - CGSize fitSize = [inputView sizeThatFits:constrainSize]; - inputView.frame = CGRectMake(0, runningOriginY, fitSize.width, fitSize.height); - runningOriginY = CGRectGetMaxY(inputView.frame) + [[self class] inputViewVerticalPadding]; - } -} - -- (void)setInputValue:(id)inputValue { - if ([inputValue isKindOfClass:[UIColor class]]) { - [self updateWithColor:inputValue]; - } else if ([inputValue isKindOfClass:[NSValue class]]) { - const char *type = [inputValue objCType]; - if (strcmp(type, @encode(CGColorRef)) == 0) { - CGColorRef colorRef; - [inputValue getValue:&colorRef]; - UIColor *color = [[UIColor alloc] initWithCGColor:colorRef]; - [self updateWithColor:color]; - } - } else { - [self updateWithColor:UIColor.clearColor]; - } -} - -- (id)inputValue { - return [UIColor colorWithRed:self.redInput.slider.value green:self.greenInput.slider.value blue:self.blueInput.slider.value alpha:self.alphaInput.slider.value]; -} - -- (void)colorComponentInputViewValueDidChange:(FLEXColorComponentInputView *)colorComponentInputView { - [self updateColorPreview]; -} - -- (void)updateWithColor:(UIColor *)color { - CGFloat red, green, blue, white, alpha; - if ([color getRed:&red green:&green blue:&blue alpha:&alpha]) { - self.alphaInput.slider.value = alpha; - [self.alphaInput updateValueLabel]; - self.redInput.slider.value = red; - [self.redInput updateValueLabel]; - self.greenInput.slider.value = green; - [self.greenInput updateValueLabel]; - self.blueInput.slider.value = blue; - [self.blueInput updateValueLabel]; - } else if ([color getWhite:&white alpha:&alpha]) { - self.alphaInput.slider.value = alpha; - [self.alphaInput updateValueLabel]; - self.redInput.slider.value = white; - [self.redInput updateValueLabel]; - self.greenInput.slider.value = white; - [self.greenInput updateValueLabel]; - self.blueInput.slider.value = white; - [self.blueInput updateValueLabel]; - } - [self updateColorPreview]; -} - -- (void)updateColorPreview { - self.colorPreviewBox.color = self.inputValue; - unsigned char redByte = self.redInput.slider.value * 255; - unsigned char greenByte = self.greenInput.slider.value * 255; - unsigned char blueByte = self.blueInput.slider.value * 255; - self.hexLabel.text = [NSString stringWithFormat:@"#%02X%02X%02X", redByte, greenByte, blueByte]; - [self setNeedsLayout]; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat height = 0; - height += [[self class] colorPreviewBoxHeight]; - height += [[self class] inputViewVerticalPadding]; - height += [self.alphaInput sizeThatFits:size].height; - height += [[self class] inputViewVerticalPadding]; - height += [self.redInput sizeThatFits:size].height; - height += [[self class] inputViewVerticalPadding]; - height += [self.greenInput sizeThatFits:size].height; - height += [[self class] inputViewVerticalPadding]; - height += [self.blueInput sizeThatFits:size].height; - return CGSizeMake(size.width, height); -} - -+ (CGFloat)inputViewVerticalPadding { - return 10.0; -} - -+ (CGFloat)colorPreviewBoxHeight { - return 40.0; -} - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - - // We don't care if currentValue is a color or not; we will default to +clearColor - return (strcmp(type, @encode(CGColorRef)) == 0) || (strcmp(type, FLEXEncodeClass(UIColor)) == 0); -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.h deleted file mode 100644 index bbfdb66..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputDataView.h -// Flipboard -// -// Created by Daniel Rodriguez Troitino on 2/14/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputView.h" - -@interface FLEXArgumentInputDateView : FLEXArgumentInputView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m deleted file mode 100644 index b144210..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputDateView.m +++ /dev/null @@ -1,58 +0,0 @@ -// -// FLEXArgumentInputDataView.m -// Flipboard -// -// Created by Daniel Rodriguez Troitino on 2/14/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputDateView.h" -#import "FLEXRuntimeUtility.h" - -@interface FLEXArgumentInputDateView () - -@property (nonatomic) UIDatePicker *datePicker; - -@end - -@implementation FLEXArgumentInputDateView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.datePicker = [UIDatePicker new]; - self.datePicker.datePickerMode = UIDatePickerModeDateAndTime; - // Using UTC, because that's what the NSDate description prints - self.datePicker.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; - self.datePicker.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; - [self addSubview:self.datePicker]; - } - return self; -} - -- (void)setInputValue:(id)inputValue { - if ([inputValue isKindOfClass:[NSDate class]]) { - self.datePicker.date = inputValue; - } -} - -- (id)inputValue { - return self.datePicker.date; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - self.datePicker.frame = self.bounds; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat height = [self.datePicker sizeThatFits:size].height; - return CGSizeMake(size.width, height); -} - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - return strcmp(type, FLEXEncodeClass(NSDate)) == 0; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.h deleted file mode 100644 index 7183f28..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputFontView.h -// Flipboard -// -// Created by Ryan Olson on 6/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputView.h" - -@interface FLEXArgumentInputFontView : FLEXArgumentInputView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m deleted file mode 100644 index d8b2432..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontView.m +++ /dev/null @@ -1,109 +0,0 @@ -// -// FLEXArgumentInputFontView.m -// Flipboard -// -// Created by Ryan Olson on 6/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputFontView.h" -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXArgumentInputFontsPickerView.h" - -@interface FLEXArgumentInputFontView () - -@property (nonatomic) FLEXArgumentInputView *fontNameInput; -@property (nonatomic) FLEXArgumentInputView *pointSizeInput; - -@end - -@implementation FLEXArgumentInputFontView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.fontNameInput = [[FLEXArgumentInputFontsPickerView alloc] initWithArgumentTypeEncoding:FLEXEncodeClass(NSString)]; - self.fontNameInput.targetSize = FLEXArgumentInputViewSizeSmall; - self.fontNameInput.title = @"Font Name:"; - [self addSubview:self.fontNameInput]; - - self.pointSizeInput = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:@encode(CGFloat)]; - self.pointSizeInput.targetSize = FLEXArgumentInputViewSizeSmall; - self.pointSizeInput.title = @"Point Size:"; - [self addSubview:self.pointSizeInput]; - } - return self; -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor { - [super setBackgroundColor:backgroundColor]; - self.fontNameInput.backgroundColor = backgroundColor; - self.pointSizeInput.backgroundColor = backgroundColor; -} - -- (void)setInputValue:(id)inputValue { - if ([inputValue isKindOfClass:[UIFont class]]) { - UIFont *font = (UIFont *)inputValue; - self.fontNameInput.inputValue = font.fontName; - self.pointSizeInput.inputValue = @(font.pointSize); - } -} - -- (id)inputValue { - CGFloat pointSize = 0; - if ([self.pointSizeInput.inputValue isKindOfClass:[NSValue class]]) { - NSValue *pointSizeValue = (NSValue *)self.pointSizeInput.inputValue; - if (strcmp([pointSizeValue objCType], @encode(CGFloat)) == 0) { - [pointSizeValue getValue:&pointSize]; - } - } - return [UIFont fontWithName:self.fontNameInput.inputValue size:pointSize]; -} - -- (BOOL)inputViewIsFirstResponder { - return [self.fontNameInput inputViewIsFirstResponder] || [self.pointSizeInput inputViewIsFirstResponder]; -} - - -#pragma mark - Layout and Sizing - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGFloat runningOriginY = self.topInputFieldVerticalLayoutGuide; - - CGSize fontNameFitSize = [self.fontNameInput sizeThatFits:self.bounds.size]; - self.fontNameInput.frame = CGRectMake(0, runningOriginY, fontNameFitSize.width, fontNameFitSize.height); - runningOriginY = CGRectGetMaxY(self.fontNameInput.frame) + [[self class] verticalPaddingBetweenFields]; - - CGSize pointSizeFitSize = [self.pointSizeInput sizeThatFits:self.bounds.size]; - self.pointSizeInput.frame = CGRectMake(0, runningOriginY, pointSizeFitSize.width, pointSizeFitSize.height); -} - -+ (CGFloat)verticalPaddingBetweenFields { - return 10.0; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGSize fitSize = [super sizeThatFits:size]; - - CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX); - - CGFloat height = fitSize.height; - height += [self.fontNameInput sizeThatFits:constrainSize].height; - height += [[self class] verticalPaddingBetweenFields]; - height += [self.pointSizeInput sizeThatFits:constrainSize].height; - - return CGSizeMake(fitSize.width, height); -} - - -#pragma mark - - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - return strcmp(type, FLEXEncodeClass(UIFont)) == 0; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.h deleted file mode 100644 index a8bcb68..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// FLEXArgumentInputFontsPickerView.h -// FLEX -// -// Created by 啟倫 陳 on 2014/7/27. -// Copyright (c) 2014年 f. All rights reserved. -// - -#import "FLEXArgumentInputTextView.h" - -@interface FLEXArgumentInputFontsPickerView : FLEXArgumentInputTextView -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m deleted file mode 100644 index f280be0..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.m +++ /dev/null @@ -1,96 +0,0 @@ -// -// FLEXArgumentInputFontsPickerView.m -// FLEX -// -// Created by 啟倫 陳 on 2014/7/27. -// Copyright (c) 2014年 f. All rights reserved. -// - -#import "FLEXArgumentInputFontsPickerView.h" -#import "FLEXRuntimeUtility.h" - -@interface FLEXArgumentInputFontsPickerView () - -@property (nonatomic) NSMutableArray *availableFonts; - -@end - - -@implementation FLEXArgumentInputFontsPickerView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.targetSize = FLEXArgumentInputViewSizeSmall; - [self createAvailableFonts]; - self.inputTextView.inputView = [self createFontsPicker]; - } - return self; -} - -- (void)setInputValue:(id)inputValue { - self.inputTextView.text = inputValue; - if ([self.availableFonts indexOfObject:inputValue] == NSNotFound) { - [self.availableFonts insertObject:inputValue atIndex:0]; - } - [(UIPickerView *)self.inputTextView.inputView selectRow:[self.availableFonts indexOfObject:inputValue] inComponent:0 animated:NO]; -} - -- (id)inputValue { - return self.inputTextView.text.length > 0 ? [self.inputTextView.text copy] : nil; -} - -#pragma mark - private - -- (UIPickerView*)createFontsPicker { - UIPickerView *fontsPicker = [UIPickerView new]; - fontsPicker.dataSource = self; - fontsPicker.delegate = self; - fontsPicker.showsSelectionIndicator = YES; - return fontsPicker; -} - -- (void)createAvailableFonts { - NSMutableArray *unsortedFontsArray = [NSMutableArray new]; - for (NSString *eachFontFamily in UIFont.familyNames) { - for (NSString *eachFontName in [UIFont fontNamesForFamilyName:eachFontFamily]) { - [unsortedFontsArray addObject:eachFontName]; - } - } - self.availableFonts = [NSMutableArray arrayWithArray:[unsortedFontsArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]]; -} - -#pragma mark - UIPickerViewDataSource - -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { - return 1; -} - -- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { - return self.availableFonts.count; -} - -#pragma mark - UIPickerViewDelegate - -- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { - UILabel *fontLabel; - if (!view) { - fontLabel = [UILabel new]; - fontLabel.backgroundColor = UIColor.clearColor; - fontLabel.textAlignment = NSTextAlignmentCenter; - } else { - fontLabel = (UILabel*)view; - } - UIFont *font = [UIFont fontWithName:self.availableFonts[row] size:15.0]; - NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; - NSAttributedString *attributesString = [[NSAttributedString alloc] initWithString:self.availableFonts[row] attributes:attributesDictionary]; - fontLabel.attributedText = attributesString; - [fontLabel sizeToFit]; - return fontLabel; -} - -- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - self.inputTextView.text = self.availableFonts[row]; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.h deleted file mode 100644 index 9d2b39c..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputNotSupportedView.h -// Flipboard -// -// Created by Ryan Olson on 6/18/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputTextView.h" - -@interface FLEXArgumentInputNotSupportedView : FLEXArgumentInputTextView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.m deleted file mode 100644 index a7fd152..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// FLEXArgumentInputNotSupportedView.m -// Flipboard -// -// Created by Ryan Olson on 6/18/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputNotSupportedView.h" -#import "FLEXColor.h" - -@implementation FLEXArgumentInputNotSupportedView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.inputTextView.userInteractionEnabled = NO; - self.inputTextView.backgroundColor = [FLEXColor secondaryGroupedBackgroundColorWithAlpha:0.5]; - self.inputPlaceholderText = @"nil (type not supported)"; - self.targetSize = FLEXArgumentInputViewSizeSmall; - } - return self; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.h deleted file mode 100644 index 5d08897..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputNumberView.h -// Flipboard -// -// Created by Ryan Olson on 6/15/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputTextView.h" - -@interface FLEXArgumentInputNumberView : FLEXArgumentInputTextView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m deleted file mode 100644 index 6f6a48a..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.m +++ /dev/null @@ -1,62 +0,0 @@ -// -// FLEXArgumentInputNumberView.m -// Flipboard -// -// Created by Ryan Olson on 6/15/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputNumberView.h" -#import "FLEXRuntimeUtility.h" - -@implementation FLEXArgumentInputNumberView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.inputTextView.keyboardType = UIKeyboardTypeNumbersAndPunctuation; - self.targetSize = FLEXArgumentInputViewSizeSmall; - } - - return self; -} - -- (void)setInputValue:(id)inputValue { - if ([inputValue respondsToSelector:@selector(stringValue)]) { - self.inputTextView.text = [inputValue stringValue]; - } -} - -- (id)inputValue { - return [FLEXRuntimeUtility valueForNumberWithObjCType:self.typeEncoding.UTF8String fromInputString:self.inputTextView.text]; -} - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - - static NSArray *supportedTypes = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - supportedTypes = @[ - @FLEXEncodeClass(NSNumber), - @FLEXEncodeClass(NSDecimalNumber), - @(@encode(char)), - @(@encode(int)), - @(@encode(short)), - @(@encode(long)), - @(@encode(long long)), - @(@encode(unsigned char)), - @(@encode(unsigned int)), - @(@encode(unsigned short)), - @(@encode(unsigned long)), - @(@encode(unsigned long long)), - @(@encode(float)), - @(@encode(double)), - @(@encode(long double)) - ]; - }); - - return type && [supportedTypes containsObject:@(type)]; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.h deleted file mode 100644 index df2f7e6..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputObjectView.h -// Flipboard -// -// Created by Ryan Olson on 6/15/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputTextView.h" - -@interface FLEXArgumentInputObjectView : FLEXArgumentInputTextView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m deleted file mode 100644 index 0eddf86..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m +++ /dev/null @@ -1,232 +0,0 @@ -// -// FLEXArgumentInputJSONObjectView.m -// Flipboard -// -// Created by Ryan Olson on 6/15/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputObjectView.h" -#import "FLEXRuntimeUtility.h" - -static const CGFloat kSegmentInputMargin = 10; - -typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) { - FLEXArgInputObjectTypeJSON, - FLEXArgInputObjectTypeAddress -}; - -@interface FLEXArgumentInputObjectView () - -@property (nonatomic) UISegmentedControl *objectTypeSegmentControl; -@property (nonatomic) FLEXArgInputObjectType inputType; - -@end - -@implementation FLEXArgumentInputObjectView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - // Start with the numbers and punctuation keyboard since quotes, curly braces, or - // square brackets are likely to be the first characters type for the JSON. - self.inputTextView.keyboardType = UIKeyboardTypeNumbersAndPunctuation; - self.targetSize = FLEXArgumentInputViewSizeLarge; - - self.objectTypeSegmentControl = [[UISegmentedControl alloc] initWithItems:@[@"Value", @"Address"]]; - [self.objectTypeSegmentControl addTarget:self action:@selector(didChangeType) forControlEvents:UIControlEventValueChanged]; - self.objectTypeSegmentControl.selectedSegmentIndex = 0; - [self addSubview:self.objectTypeSegmentControl]; - - self.inputType = [[self class] preferredDefaultTypeForObjCType:typeEncoding withCurrentValue:nil]; - self.objectTypeSegmentControl.selectedSegmentIndex = self.inputType; - } - - return self; -} - -- (void)didChangeType { - self.inputType = self.objectTypeSegmentControl.selectedSegmentIndex; - - if (super.inputValue) { - // Trigger an update to the text field to show - // the address of the stored object we were given, - // or to show a JSON representation of the object - [self populateTextAreaFromValue:super.inputValue]; - } else { - // Clear the text field - [self populateTextAreaFromValue:nil]; - } -} - -- (void)setInputType:(FLEXArgInputObjectType)inputType { - if (_inputType == inputType) return; - - _inputType = inputType; - - // Resize input view - switch (inputType) { - case FLEXArgInputObjectTypeJSON: - self.targetSize = FLEXArgumentInputViewSizeLarge; - break; - case FLEXArgInputObjectTypeAddress: - self.targetSize = FLEXArgumentInputViewSizeSmall; - break; - } - - // Change placeholder - switch (inputType) { - case FLEXArgInputObjectTypeJSON: - self.inputPlaceholderText = - @"You can put any valid JSON here, such as a string, number, array, or dictionary:" - "\n\"This is a string\"" - "\n1234" - "\n{ \"name\": \"Bob\", \"age\": 47 }" - "\n[" - "\n 1, 2, 3" - "\n]"; - break; - case FLEXArgInputObjectTypeAddress: - self.inputPlaceholderText = @"0x0000deadb33f"; - break; - } - - [self setNeedsLayout]; - [self.superview setNeedsLayout]; -} - -- (void)setInputValue:(id)inputValue { - super.inputValue = inputValue; - [self populateTextAreaFromValue:inputValue]; -} - -- (id)inputValue { - switch (self.inputType) { - case FLEXArgInputObjectTypeJSON: - return [FLEXRuntimeUtility objectValueFromEditableJSONString:self.inputTextView.text]; - case FLEXArgInputObjectTypeAddress: { - NSScanner *scanner = [NSScanner scannerWithString:self.inputTextView.text]; - - unsigned long long objectPointerValue; - if ([scanner scanHexLongLong:&objectPointerValue]) { - return (__bridge id)(void *)objectPointerValue; - } - - return nil; - } - } -} - -- (void)populateTextAreaFromValue:(id)value { - if (!value) { - self.inputTextView.text = nil; - } else { - if (self.inputType == FLEXArgInputObjectTypeJSON) { - self.inputTextView.text = [FLEXRuntimeUtility editableJSONStringForObject:value]; - } else if (self.inputType == FLEXArgInputObjectTypeAddress) { - self.inputTextView.text = [NSString stringWithFormat:@"%p", value]; - } - } - - // Delegate methods are not called for programmatic changes - [self textViewDidChange:self.inputTextView]; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGSize fitSize = [super sizeThatFits:size]; - fitSize.height += [self.objectTypeSegmentControl sizeThatFits:size].height + kSegmentInputMargin; - - return fitSize; -} - -- (void)layoutSubviews { - CGFloat segmentHeight = [self.objectTypeSegmentControl sizeThatFits:self.frame.size].height; - self.objectTypeSegmentControl.frame = CGRectMake( - 0.0, - // Our segmented control is taking the position - // of the text view, as far as super is concerned, - // and we override this property to be different - super.topInputFieldVerticalLayoutGuide, - self.frame.size.width, - segmentHeight - ); - - [super layoutSubviews]; -} - -- (CGFloat)topInputFieldVerticalLayoutGuide { - // Our text view is offset from the segmented control - CGFloat segmentHeight = [self.objectTypeSegmentControl sizeThatFits:self.frame.size].height; - return segmentHeight + super.topInputFieldVerticalLayoutGuide + kSegmentInputMargin; -} - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - // Must be object type - return type[0] == FLEXTypeEncodingObjcObject || type[0] == FLEXTypeEncodingObjcClass; -} - -+ (FLEXArgInputObjectType)preferredDefaultTypeForObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type[0] == FLEXTypeEncodingObjcObject || type[0] == FLEXTypeEncodingObjcClass); - - if (value) { - // If there's a current value, it must be serializable to JSON - // to display the JSON editor. Otherwise display the address field. - if ([FLEXRuntimeUtility editableJSONStringForObject:value]) { - return FLEXArgInputObjectTypeJSON; - } else { - return FLEXArgInputObjectTypeAddress; - } - } else { - // Otherwise, see if we have more type information than just 'id'. - // If we do, make sure the encoding is something serializable to JSON. - // Properties and ivars keep more detailed type encoding information than method arguments. - if (strcmp(type, @encode(id)) != 0) { - BOOL isJSONSerializableType = NO; - - // Parse class name out of the string, - // which is in the form `@"ClassName"` - Class cls = NSClassFromString(({ - NSString *className = nil; - NSScanner *scan = [NSScanner scannerWithString:@(type)]; - NSCharacterSet *allowed = [NSCharacterSet - characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$" - ]; - - // Skip over the @" then scan the name - if ([scan scanString:@"@\"" intoString:nil]) { - [scan scanCharactersFromSet:allowed intoString:&className]; - } - - className; - })); - - // Note: we can't use @encode(NSString) here because that drops - // the class information and just goes to @encode(id). - NSArray *jsonTypes = @[ - [NSString class], - [NSNumber class], - [NSArray class], - [NSDictionary class], - ]; - - // Look for matching types - for (Class jsonClass in jsonTypes) { - if ([cls isSubclassOfClass:jsonClass]) { - isJSONSerializableType = YES; - break; - } - } - - if (isJSONSerializableType) { - return FLEXArgInputObjectTypeJSON; - } else { - return FLEXArgInputObjectTypeAddress; - } - } else { - return FLEXArgInputObjectTypeAddress; - } - } -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.h deleted file mode 100644 index e17a26b..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputStringView.h -// Flipboard -// -// Created by Ryan Olson on 6/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputTextView.h" - -@interface FLEXArgumentInputStringView : FLEXArgumentInputTextView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m deleted file mode 100644 index 5329bee..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStringView.m +++ /dev/null @@ -1,129 +0,0 @@ -// -// FLEXArgumentInputStringView.m -// Flipboard -// -// Created by Ryan Olson on 6/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputStringView.h" -#import "FLEXRuntimeUtility.h" - -@implementation FLEXArgumentInputStringView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - FLEXTypeEncoding type = typeEncoding[0]; - if (type == FLEXTypeEncodingConst) { - // A crash here would mean an invalid type encoding string - type = typeEncoding[1]; - } - - // Selectors don't need a multi-line text box - if (type == FLEXTypeEncodingSelector) { - self.targetSize = FLEXArgumentInputViewSizeSmall; - } else { - self.targetSize = FLEXArgumentInputViewSizeLarge; - } - } - return self; -} - -- (void)setInputValue:(id)inputValue { - if ([inputValue isKindOfClass:[NSString class]]) { - self.inputTextView.text = inputValue; - } else if ([inputValue isKindOfClass:[NSValue class]]) { - NSValue *value = (id)inputValue; - NSParameterAssert(strlen(value.objCType) == 1); - - // C-String or SEL from NSValue - FLEXTypeEncoding type = value.objCType[0]; - if (type == FLEXTypeEncodingConst) { - // A crash here would mean an invalid type encoding string - type = value.objCType[1]; - } - - if (type == FLEXTypeEncodingCString) { - self.inputTextView.text = @((const char *)value.pointerValue); - } else if (type == FLEXTypeEncodingSelector) { - self.inputTextView.text = NSStringFromSelector((SEL)value.pointerValue); - } - } -} - -- (id)inputValue { - NSString *text = self.inputTextView.text; - // Interpret empty string as nil. We loose the ability to set empty string as a string value, - // but we accept that tradeoff in exchange for not having to type quotes for every string. - if (!text.length) { - return nil; - } - - // Case: C-strings and SELs - if (self.typeEncoding.length <= 2) { - FLEXTypeEncoding type = [self.typeEncoding characterAtIndex:0]; - if (type == FLEXTypeEncodingConst) { - // A crash here would mean an invalid type encoding string - type = [self.typeEncoding characterAtIndex:1]; - } - - if (type == FLEXTypeEncodingCString || type == FLEXTypeEncodingSelector) { - const char *encoding = self.typeEncoding.UTF8String; - SEL selector = NSSelectorFromString(text); - return [NSValue valueWithBytes:&selector objCType:encoding]; - } - } - - // Case: NSStrings - return self.inputTextView.text.copy; -} - -// TODO: Support using object address for strings, as in the object arg view. - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - unsigned long len = strlen(type); - - BOOL isConst = type[0] == FLEXTypeEncodingConst; - NSInteger i = isConst ? 1 : 0; - - BOOL typeIsString = strcmp(type, FLEXEncodeClass(NSString)) == 0; - BOOL typeIsCString = len <= 2 && type[i] == FLEXTypeEncodingCString; - BOOL typeIsSEL = len <= 2 && type[i] == FLEXTypeEncodingSelector; - BOOL valueIsString = [value isKindOfClass:[NSString class]]; - - BOOL typeIsPrimitiveString = typeIsSEL || typeIsCString; - BOOL typeIsSupported = typeIsString || typeIsCString || typeIsSEL; - - BOOL valueIsNSValueWithCorrectType = NO; - if ([value isKindOfClass:[NSValue class]]) { - NSValue *v = (id)value; - len = strlen(v.objCType); - if (len == 1) { - FLEXTypeEncoding type = v.objCType[i]; - if (type == FLEXTypeEncodingCString && typeIsCString) { - valueIsNSValueWithCorrectType = YES; - } else if (type == FLEXTypeEncodingSelector && typeIsSEL) { - valueIsNSValueWithCorrectType = YES; - } - } - } - - if (!value && typeIsSupported) { - return YES; - } - - if (typeIsString && valueIsString) { - return YES; - } - - // Primitive strings can be input as NSStrings or NSValues - if (typeIsPrimitiveString && (valueIsString || valueIsNSValueWithCorrectType)) { - return YES; - } - - return NO; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h deleted file mode 100644 index 82270ae..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputStructView.h -// Flipboard -// -// Created by Ryan Olson on 6/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputView.h" - -@interface FLEXArgumentInputStructView : FLEXArgumentInputView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m deleted file mode 100644 index 2479d6a..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m +++ /dev/null @@ -1,220 +0,0 @@ -// -// FLEXArgumentInputStructView.m -// Flipboard -// -// Created by Ryan Olson on 6/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputStructView.h" -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXTypeEncodingParser.h" - -@interface FLEXArgumentInputStructView () - -@property (nonatomic) NSArray *argumentInputViews; - -@end - -@implementation FLEXArgumentInputStructView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - NSMutableArray *inputViews = [NSMutableArray new]; - NSArray *customTitles = [[self class] customFieldTitlesForTypeEncoding:typeEncoding]; - [FLEXRuntimeUtility enumerateTypesInStructEncoding:typeEncoding usingBlock:^(NSString *structName, - const char *fieldTypeEncoding, - NSString *prettyTypeEncoding, - NSUInteger fieldIndex, - NSUInteger fieldOffset) { - - FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:fieldTypeEncoding]; - inputView.targetSize = FLEXArgumentInputViewSizeSmall; - - if (fieldIndex < customTitles.count) { - inputView.title = customTitles[fieldIndex]; - } else { - inputView.title = [NSString stringWithFormat:@"%@ field %lu (%@)", - structName, (unsigned long)fieldIndex, prettyTypeEncoding - ]; - } - - [inputViews addObject:inputView]; - [self addSubview:inputView]; - }]; - self.argumentInputViews = inputViews; - } - return self; -} - - -#pragma mark - Superclass Overrides - -- (void)setBackgroundColor:(UIColor *)backgroundColor { - [super setBackgroundColor:backgroundColor]; - for (FLEXArgumentInputView *inputView in self.argumentInputViews) { - inputView.backgroundColor = backgroundColor; - } -} - -- (void)setInputValue:(id)inputValue { - if ([inputValue isKindOfClass:[NSValue class]]) { - const char *structTypeEncoding = [inputValue objCType]; - if (strcmp(self.typeEncoding.UTF8String, structTypeEncoding) == 0) { - NSUInteger valueSize = 0; - - if (FLEXGetSizeAndAlignment(structTypeEncoding, &valueSize, NULL)) { - void *unboxedValue = malloc(valueSize); - [inputValue getValue:unboxedValue]; - [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName, - const char *fieldTypeEncoding, - NSString *prettyTypeEncoding, - NSUInteger fieldIndex, - NSUInteger fieldOffset) { - - void *fieldPointer = unboxedValue + fieldOffset; - FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex]; - - if (fieldTypeEncoding[0] == FLEXTypeEncodingObjcObject || fieldTypeEncoding[0] == FLEXTypeEncodingObjcClass) { - inputView.inputValue = (__bridge id)fieldPointer; - } else { - NSValue *boxedField = [FLEXRuntimeUtility valueForPrimitivePointer:fieldPointer objCType:fieldTypeEncoding]; - inputView.inputValue = boxedField; - } - }]; - free(unboxedValue); - } - } - } -} - -- (id)inputValue { - NSValue *boxedStruct = nil; - const char *structTypeEncoding = self.typeEncoding.UTF8String; - NSUInteger structSize = 0; - - if (FLEXGetSizeAndAlignment(structTypeEncoding, &structSize, NULL)) { - void *unboxedStruct = malloc(structSize); - [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName, - const char *fieldTypeEncoding, - NSString *prettyTypeEncoding, - NSUInteger fieldIndex, - NSUInteger fieldOffset) { - - void *fieldPointer = unboxedStruct + fieldOffset; - FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex]; - - if (fieldTypeEncoding[0] == FLEXTypeEncodingObjcObject || fieldTypeEncoding[0] == FLEXTypeEncodingObjcClass) { - // Object fields - memcpy(fieldPointer, (__bridge void *)inputView.inputValue, sizeof(id)); - } else { - // Boxed primitive/struct fields - id inputValue = inputView.inputValue; - if ([inputValue isKindOfClass:[NSValue class]] && strcmp([inputValue objCType], fieldTypeEncoding) == 0) { - [inputValue getValue:fieldPointer]; - } - } - }]; - - boxedStruct = [NSValue value:unboxedStruct withObjCType:structTypeEncoding]; - free(unboxedStruct); - } - - return boxedStruct; -} - -- (BOOL)inputViewIsFirstResponder { - BOOL isFirstResponder = NO; - for (FLEXArgumentInputView *inputView in self.argumentInputViews) { - if ([inputView inputViewIsFirstResponder]) { - isFirstResponder = YES; - break; - } - } - return isFirstResponder; -} - - -#pragma mark - Layout and Sizing - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGFloat runningOriginY = self.topInputFieldVerticalLayoutGuide; - - for (FLEXArgumentInputView *inputView in self.argumentInputViews) { - CGSize inputFitSize = [inputView sizeThatFits:self.bounds.size]; - inputView.frame = CGRectMake(0, runningOriginY, inputFitSize.width, inputFitSize.height); - runningOriginY = CGRectGetMaxY(inputView.frame) + [[self class] verticalPaddingBetweenFields]; - } -} - -+ (CGFloat)verticalPaddingBetweenFields { - return 10.0; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGSize fitSize = [super sizeThatFits:size]; - - CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX); - CGFloat height = fitSize.height; - - for (FLEXArgumentInputView *inputView in self.argumentInputViews) { - height += [inputView sizeThatFits:constrainSize].height; - height += [[self class] verticalPaddingBetweenFields]; - } - - return CGSizeMake(fitSize.width, height); -} - - -#pragma mark - Class Helpers - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - if (type[0] == FLEXTypeEncodingStructBegin) { - return FLEXGetSizeAndAlignment(type, nil, nil); - } - - return NO; -} - -+ (NSArray *)customFieldTitlesForTypeEncoding:(const char *)typeEncoding { - NSArray *customTitles = nil; - if (strcmp(typeEncoding, @encode(CGRect)) == 0) { - customTitles = @[@"CGPoint origin", @"CGSize size"]; - } else if (strcmp(typeEncoding, @encode(CGPoint)) == 0) { - customTitles = @[@"CGFloat x", @"CGFloat y"]; - } else if (strcmp(typeEncoding, @encode(CGSize)) == 0) { - customTitles = @[@"CGFloat width", @"CGFloat height"]; - } else if (strcmp(typeEncoding, @encode(CGVector)) == 0) { - customTitles = @[@"CGFloat dx", @"CGFloat dy"]; - } else if (strcmp(typeEncoding, @encode(UIEdgeInsets)) == 0) { - customTitles = @[@"CGFloat top", @"CGFloat left", @"CGFloat bottom", @"CGFloat right"]; - } else if (strcmp(typeEncoding, @encode(UIOffset)) == 0) { - customTitles = @[@"CGFloat horizontal", @"CGFloat vertical"]; - } else if (strcmp(typeEncoding, @encode(NSRange)) == 0) { - customTitles = @[@"NSUInteger location", @"NSUInteger length"]; - } else if (strcmp(typeEncoding, @encode(CATransform3D)) == 0) { - customTitles = @[@"CGFloat m11", @"CGFloat m12", @"CGFloat m13", @"CGFloat m14", - @"CGFloat m21", @"CGFloat m22", @"CGFloat m23", @"CGFloat m24", - @"CGFloat m31", @"CGFloat m32", @"CGFloat m33", @"CGFloat m34", - @"CGFloat m41", @"CGFloat m42", @"CGFloat m43", @"CGFloat m44"]; - } else if (strcmp(typeEncoding, @encode(CGAffineTransform)) == 0) { - customTitles = @[@"CGFloat a", @"CGFloat b", - @"CGFloat c", @"CGFloat d", - @"CGFloat tx", @"CGFloat ty"]; - } else { - if (@available(iOS 11.0, *)) { - if (strcmp(typeEncoding, @encode(NSDirectionalEdgeInsets)) == 0) { - customTitles = @[@"CGFloat top", @"CGFloat leading", - @"CGFloat bottom", @"CGFloat trailing"]; - } - } - } - return customTitles; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h deleted file mode 100644 index 26d2f31..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXArgumentInputSwitchView.h -// Flipboard -// -// Created by Ryan Olson on 6/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputView.h" - -@interface FLEXArgumentInputSwitchView : FLEXArgumentInputView - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m deleted file mode 100644 index 9380823..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.m +++ /dev/null @@ -1,81 +0,0 @@ -// -// FLEXArgumentInputSwitchView.m -// Flipboard -// -// Created by Ryan Olson on 6/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputSwitchView.h" - -@interface FLEXArgumentInputSwitchView () - -@property (nonatomic) UISwitch *inputSwitch; - -@end - -@implementation FLEXArgumentInputSwitchView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.inputSwitch = [UISwitch new]; - [self.inputSwitch addTarget:self action:@selector(switchValueDidChange:) forControlEvents:UIControlEventValueChanged]; - [self.inputSwitch sizeToFit]; - [self addSubview:self.inputSwitch]; - } - return self; -} - - -#pragma mark Input/Output - -- (void)setInputValue:(id)inputValue { - BOOL on = NO; - if ([inputValue isKindOfClass:[NSNumber class]]) { - NSNumber *number = (NSNumber *)inputValue; - on = [number boolValue]; - } else if ([inputValue isKindOfClass:[NSValue class]]) { - NSValue *value = (NSValue *)inputValue; - if (strcmp([value objCType], @encode(BOOL)) == 0) { - [value getValue:&on]; - } - } - self.inputSwitch.on = on; -} - -- (id)inputValue { - BOOL isOn = [self.inputSwitch isOn]; - NSValue *boxedBool = [NSValue value:&isOn withObjCType:@encode(BOOL)]; - return boxedBool; -} - -- (void)switchValueDidChange:(id)sender { - [self.delegate argumentInputViewValueDidChange:self]; -} - - -#pragma mark - Layout and Sizing - -- (void)layoutSubviews { - [super layoutSubviews]; - - self.inputSwitch.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.inputSwitch.frame.size.width, self.inputSwitch.frame.size.height); -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGSize fitSize = [super sizeThatFits:size]; - fitSize.height += self.inputSwitch.frame.size.height; - return fitSize; -} - - -#pragma mark - Class Helpers - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - NSParameterAssert(type); - // Only BOOLs. Current value is irrelevant. - return strcmp(type, @encode(BOOL)) == 0; -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h deleted file mode 100644 index 5bb8ec8..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXArgumentInputTextView.h -// FLEXInjected -// -// Created by Ryan Olson on 6/15/14. -// -// - -#import "FLEXArgumentInputView.h" - -@interface FLEXArgumentInputTextView : FLEXArgumentInputView - -// For subclass eyes only - -@property (nonatomic, readonly) UITextView *inputTextView; -@property (nonatomic) NSString *inputPlaceholderText; - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m deleted file mode 100644 index 4ea2b05..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m +++ /dev/null @@ -1,155 +0,0 @@ -// -// FLEXArgumentInputTextView.m -// FLEXInjected -// -// Created by Ryan Olson on 6/15/14. -// -// - -#import "FLEXColor.h" -#import "FLEXArgumentInputTextView.h" -#import "FLEXUtility.h" - -@interface FLEXArgumentInputTextView () - -@property (nonatomic) UITextView *inputTextView; -@property (nonatomic) UILabel *placeholderLabel; -@property (nonatomic, readonly) NSUInteger numberOfInputLines; - -@end - -@implementation FLEXArgumentInputTextView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithArgumentTypeEncoding:typeEncoding]; - if (self) { - self.inputTextView = [UITextView new]; - self.inputTextView.font = [[self class] inputFont]; - self.inputTextView.backgroundColor = FLEXColor.secondaryGroupedBackgroundColor; - self.inputTextView.layer.cornerRadius = 10.f; - self.inputTextView.contentInset = UIEdgeInsetsMake(0, 5, 0, 0); - self.inputTextView.autocapitalizationType = UITextAutocapitalizationTypeNone; - self.inputTextView.autocorrectionType = UITextAutocorrectionTypeNo; - self.inputTextView.delegate = self; - self.inputTextView.inputAccessoryView = [self createToolBar]; - if (@available(iOS 11, *)) { - self.inputTextView.smartQuotesType = UITextSmartQuotesTypeNo; - [self.inputTextView.layer setValue:@YES forKey:@"continuousCorners"]; - } else { - self.inputTextView.layer.borderWidth = 1.f; - self.inputTextView.layer.borderColor = FLEXColor.borderColor.CGColor; - } - - self.placeholderLabel = [UILabel new]; - self.placeholderLabel.font = self.inputTextView.font; - self.placeholderLabel.textColor = FLEXColor.deemphasizedTextColor; - self.placeholderLabel.numberOfLines = 0; - - [self addSubview:self.inputTextView]; - [self.inputTextView addSubview:self.placeholderLabel]; - - } - return self; -} - -#pragma mark - Private - -- (UIToolbar *)createToolBar { - UIToolbar *toolBar = [UIToolbar new]; - [toolBar sizeToFit]; - UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace - target:nil action:nil - ]; - UIBarButtonItem *pasteItem = [[UIBarButtonItem alloc] - initWithTitle:@"Paste" style:UIBarButtonItemStyleDone - target:self.inputTextView action:@selector(paste:) - ]; - UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self.inputTextView action:@selector(resignFirstResponder) - ]; - toolBar.items = @[spaceItem, pasteItem, doneItem]; - return toolBar; -} - -- (void)setInputPlaceholderText:(NSString *)placeholder { - self.placeholderLabel.text = placeholder; - if (placeholder.length) { - if (!self.inputTextView.text.length) { - self.placeholderLabel.hidden = NO; - } else { - self.placeholderLabel.hidden = YES; - } - } else { - self.placeholderLabel.hidden = YES; - } - - [self setNeedsLayout]; -} - -- (NSString *)inputPlaceholderText { - return self.placeholderLabel.text; -} - - -#pragma mark - Superclass Overrides - -- (BOOL)inputViewIsFirstResponder { - return self.inputTextView.isFirstResponder; -} - - -#pragma mark - Layout and Sizing - -- (void)layoutSubviews { - [super layoutSubviews]; - - self.inputTextView.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.bounds.size.width, [self inputTextViewHeight]); - // Placeholder label is positioned by insetting then origin - // by the content inset then the text container inset - CGSize s = self.inputTextView.frame.size; - self.placeholderLabel.frame = CGRectMake(0, 0, s.width, s.height); - self.placeholderLabel.frame = UIEdgeInsetsInsetRect( - UIEdgeInsetsInsetRect(self.placeholderLabel.frame, self.inputTextView.contentInset), - self.inputTextView.textContainerInset - ); -} - -- (NSUInteger)numberOfInputLines { - switch (self.targetSize) { - case FLEXArgumentInputViewSizeDefault: - return 2; - case FLEXArgumentInputViewSizeSmall: - return 1; - case FLEXArgumentInputViewSizeLarge: - return 8; - } -} - -- (CGFloat)inputTextViewHeight { - return ceil([[self class] inputFont].lineHeight * self.numberOfInputLines) + 16.0; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGSize fitSize = [super sizeThatFits:size]; - fitSize.height += [self inputTextViewHeight]; - return fitSize; -} - - -#pragma mark - Class Helpers - -+ (UIFont *)inputFont { - return [UIFont systemFontOfSize:14.0]; -} - - -#pragma mark - UITextViewDelegate - -- (void)textViewDidChange:(UITextView *)textView { - [self.delegate argumentInputViewValueDidChange:self]; - self.placeholderLabel.hidden = !(self.inputPlaceholderText.length && !textView.text.length); -} - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.h b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.h deleted file mode 100644 index 171139e..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// FLEXArgumentInputView.h -// Flipboard -// -// Created by Ryan Olson on 5/30/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -typedef NS_ENUM(NSUInteger, FLEXArgumentInputViewSize) { - /// 2 lines, medium-sized - FLEXArgumentInputViewSizeDefault = 0, - /// One line - FLEXArgumentInputViewSizeSmall, - /// Several lines - FLEXArgumentInputViewSizeLarge -}; - -@protocol FLEXArgumentInputViewDelegate; - -@interface FLEXArgumentInputView : UIView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding; - -/// The name of the field. Optional (can be nil). -@property (nonatomic, copy) NSString *title; - -/// To populate the filed with an initial value, set this property. -/// To reteive the value input by the user, access the property. -/// Primitive types and structs should/will be boxed in NSValue containers. -/// Concrete subclasses should override both the setter and getter for this property. -/// Subclasses can call super.inputValue to access a backing store for the value. -@property (nonatomic) id inputValue; - -/// Setting this value to large will make some argument input views increase the size of their input field(s). -/// Useful to increase the use of space if there is only one input view on screen (i.e. for property and ivar editing). -@property (nonatomic) FLEXArgumentInputViewSize targetSize; - -/// Users of the input view can get delegate callbacks for incremental changes in user input. -@property (nonatomic, weak) id delegate; - -// Subclasses can override - -/// If the input view has one or more text views, returns YES when one of them is focused. -@property (nonatomic, readonly) BOOL inputViewIsFirstResponder; - -/// For subclasses to indicate that they can handle editing a field the give type and value. -/// Used by FLEXArgumentInputViewFactory to create appropriate input views. -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value; - -// For subclass eyes only - -@property (nonatomic, readonly) UILabel *titleLabel; -@property (nonatomic, readonly) NSString *typeEncoding; -@property (nonatomic, readonly) CGFloat topInputFieldVerticalLayoutGuide; - -@end - -@protocol FLEXArgumentInputViewDelegate - -- (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputView; - -@end diff --git a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.m b/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.m deleted file mode 100644 index f991e52..0000000 --- a/Tweaks/FLEX/Editing/ArgumentInputViews/FLEXArgumentInputView.m +++ /dev/null @@ -1,114 +0,0 @@ -// -// FLEXArgumentInputView.m -// Flipboard -// -// Created by Ryan Olson on 5/30/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXArgumentInputView.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" - -@interface FLEXArgumentInputView () - -@property (nonatomic) UILabel *titleLabel; -@property (nonatomic) NSString *typeEncoding; - -@end - -@implementation FLEXArgumentInputView - -- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding { - self = [super initWithFrame:CGRectZero]; - if (self) { - self.typeEncoding = typeEncoding != NULL ? @(typeEncoding) : nil; - } - return self; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - if (self.showsTitle) { - CGSize constrainSize = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX); - CGSize labelSize = [self.titleLabel sizeThatFits:constrainSize]; - self.titleLabel.frame = CGRectMake(0, 0, labelSize.width, labelSize.height); - } -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor { - [super setBackgroundColor:backgroundColor]; - self.titleLabel.backgroundColor = backgroundColor; -} - -- (void)setTitle:(NSString *)title { - if (![_title isEqual:title]) { - _title = title; - self.titleLabel.text = title; - [self setNeedsLayout]; - } -} - -- (UILabel *)titleLabel { - if (!_titleLabel) { - _titleLabel = [UILabel new]; - _titleLabel.font = [[self class] titleFont]; - _titleLabel.textColor = FLEXColor.primaryTextColor; - _titleLabel.numberOfLines = 0; - [self addSubview:_titleLabel]; - } - return _titleLabel; -} - -- (BOOL)showsTitle { - return self.title.length > 0; -} - -- (CGFloat)topInputFieldVerticalLayoutGuide { - CGFloat verticalLayoutGuide = 0; - if (self.showsTitle) { - CGFloat titleHeight = [self.titleLabel sizeThatFits:self.bounds.size].height; - verticalLayoutGuide = titleHeight + [[self class] titleBottomPadding]; - } - return verticalLayoutGuide; -} - - -#pragma mark - Subclasses Can Override - -- (BOOL)inputViewIsFirstResponder { - return NO; -} - -+ (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value { - return NO; -} - - -#pragma mark - Class Helpers - -+ (UIFont *)titleFont { - return [UIFont systemFontOfSize:12.0]; -} - -+ (CGFloat)titleBottomPadding { - return 4.0; -} - - -#pragma mark - Sizing - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat height = 0; - - if (self.title.length > 0) { - CGSize constrainSize = CGSizeMake(size.width, CGFLOAT_MAX); - height += ceil([self.titleLabel sizeThatFits:constrainSize].height); - height += [[self class] titleBottomPadding]; - } - - return CGSizeMake(size.width, height); -} - -@end diff --git a/Tweaks/FLEX/Editing/FLEXArgumentInputViewFactory.h b/Tweaks/FLEX/Editing/FLEXArgumentInputViewFactory.h deleted file mode 100644 index f72e907..0000000 --- a/Tweaks/FLEX/Editing/FLEXArgumentInputViewFactory.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// FLEXArgumentInputViewFactory.h -// FLEXInjected -// -// Created by Ryan Olson on 6/15/14. -// -// - -#import -#import "FLEXArgumentInputSwitchView.h" - -@interface FLEXArgumentInputViewFactory : NSObject - -/// Forwards to argumentInputViewForTypeEncoding:currentValue: with a nil currentValue. -+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding; - -/// The main factory method for making argument input view subclasses that are the best fit for the type. -+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue; - -/// A way to check if we should try editing a filed given its type encoding and value. -/// Useful when deciding whether to edit or explore a property, ivar, or NSUserDefaults value. -+ (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue; - -@end diff --git a/Tweaks/FLEX/Editing/FLEXArgumentInputViewFactory.m b/Tweaks/FLEX/Editing/FLEXArgumentInputViewFactory.m deleted file mode 100644 index fde1c8f..0000000 --- a/Tweaks/FLEX/Editing/FLEXArgumentInputViewFactory.m +++ /dev/null @@ -1,70 +0,0 @@ -// -// FLEXArgumentInputViewFactory.m -// FLEXInjected -// -// Created by Ryan Olson on 6/15/14. -// -// - -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXArgumentInputView.h" -#import "FLEXArgumentInputObjectView.h" -#import "FLEXArgumentInputNumberView.h" -#import "FLEXArgumentInputSwitchView.h" -#import "FLEXArgumentInputStructView.h" -#import "FLEXArgumentInputNotSupportedView.h" -#import "FLEXArgumentInputStringView.h" -#import "FLEXArgumentInputFontView.h" -#import "FLEXArgumentInputColorView.h" -#import "FLEXArgumentInputDateView.h" -#import "FLEXRuntimeUtility.h" - -@implementation FLEXArgumentInputViewFactory - -+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding { - return [self argumentInputViewForTypeEncoding:typeEncoding currentValue:nil]; -} - -+ (FLEXArgumentInputView *)argumentInputViewForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue { - Class subclass = [self argumentInputViewSubclassForTypeEncoding:typeEncoding currentValue:currentValue]; - if (!subclass) { - // Fall back to a FLEXArgumentInputNotSupportedView if we can't find a subclass that fits the type encoding. - // The unsupported view shows "nil" and does not allow user input. - subclass = [FLEXArgumentInputNotSupportedView class]; - } - // Remove the field name if there is any (e.g. \"width\"d -> d) - const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:typeEncoding]; - return [[subclass alloc] initWithArgumentTypeEncoding:typeEncoding + fieldNameOffset]; -} - -+ (Class)argumentInputViewSubclassForTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue { - // Remove the field name if there is any (e.g. \"width\"d -> d) - const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:typeEncoding]; - Class argumentInputViewSubclass = nil; - NSArray *inputViewClasses = @[[FLEXArgumentInputColorView class], - [FLEXArgumentInputFontView class], - [FLEXArgumentInputStringView class], - [FLEXArgumentInputStructView class], - [FLEXArgumentInputSwitchView class], - [FLEXArgumentInputDateView class], - [FLEXArgumentInputNumberView class], - [FLEXArgumentInputObjectView class]]; - - // Note that order is important here since multiple subclasses may support the same type. - // An example is the number subclass and the bool subclass for the type @encode(BOOL). - // Both work, but we'd prefer to use the bool subclass. - for (Class inputViewClass in inputViewClasses) { - if ([inputViewClass supportsObjCType:typeEncoding + fieldNameOffset withCurrentValue:currentValue]) { - argumentInputViewSubclass = inputViewClass; - break; - } - } - - return argumentInputViewSubclass; -} - -+ (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue { - return [self argumentInputViewSubclassForTypeEncoding:typeEncoding currentValue:currentValue] != nil; -} - -@end diff --git a/Tweaks/FLEX/Editing/FLEXDefaultEditorViewController.h b/Tweaks/FLEX/Editing/FLEXDefaultEditorViewController.h deleted file mode 100644 index 5d6ae4c..0000000 --- a/Tweaks/FLEX/Editing/FLEXDefaultEditorViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// FLEXDefaultEditorViewController.h -// Flipboard -// -// Created by Ryan Olson on 5/23/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFieldEditorViewController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXDefaultEditorViewController : FLEXVariableEditorViewController - -+ (instancetype)target:(NSUserDefaults *)defaults key:(NSString *)key commitHandler:(void(^_Nullable)(void))onCommit; - -+ (BOOL)canEditDefaultWithValue:(nullable id)currentValue; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Editing/FLEXDefaultEditorViewController.m b/Tweaks/FLEX/Editing/FLEXDefaultEditorViewController.m deleted file mode 100644 index f368b7f..0000000 --- a/Tweaks/FLEX/Editing/FLEXDefaultEditorViewController.m +++ /dev/null @@ -1,80 +0,0 @@ -// -// FLEXDefaultEditorViewController.m -// Flipboard -// -// Created by Ryan Olson on 5/23/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXDefaultEditorViewController.h" -#import "FLEXFieldEditorView.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXArgumentInputView.h" -#import "FLEXArgumentInputViewFactory.h" - -@interface FLEXDefaultEditorViewController () - -@property (nonatomic, readonly) NSUserDefaults *defaults; -@property (nonatomic, readonly) NSString *key; - -@end - -@implementation FLEXDefaultEditorViewController - -+ (instancetype)target:(NSUserDefaults *)defaults key:(NSString *)key commitHandler:(void(^_Nullable)(void))onCommit { - FLEXDefaultEditorViewController *editor = [self target:defaults data:key commitHandler:onCommit]; - editor.title = @"Edit Default"; - return editor; -} - -- (NSUserDefaults *)defaults { - return [_target isKindOfClass:[NSUserDefaults class]] ? _target : nil; -} - -- (NSString *)key { - return _data; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.fieldEditorView.fieldDescription = self.key; - - id currentValue = [self.defaults objectForKey:self.key]; - FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory - argumentInputViewForTypeEncoding:FLEXEncodeObject(currentValue) - currentValue:currentValue - ]; - inputView.backgroundColor = self.view.backgroundColor; - inputView.inputValue = currentValue; - self.fieldEditorView.argumentInputViews = @[inputView]; -} - -- (void)actionButtonPressed:(id)sender { - id value = self.firstInputView.inputValue; - if (value) { - [self.defaults setObject:value forKey:self.key]; - } else { - [self.defaults removeObjectForKey:self.key]; - } - [self.defaults synchronize]; - - // Dismiss keyboard and handle committed changes - [super actionButtonPressed:sender]; - - // Go back after setting, but not for switches. - if (sender) { - [self.navigationController popViewControllerAnimated:YES]; - } else { - self.firstInputView.inputValue = [self.defaults objectForKey:self.key]; - } -} - -+ (BOOL)canEditDefaultWithValue:(id)currentValue { - return [FLEXArgumentInputViewFactory - canEditFieldWithTypeEncoding:FLEXEncodeObject(currentValue) - currentValue:currentValue - ]; -} - -@end diff --git a/Tweaks/FLEX/Editing/FLEXFieldEditorView.h b/Tweaks/FLEX/Editing/FLEXFieldEditorView.h deleted file mode 100644 index 19c0e63..0000000 --- a/Tweaks/FLEX/Editing/FLEXFieldEditorView.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FLEXFieldEditorView.h -// Flipboard -// -// Created by Ryan Olson on 5/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@class FLEXArgumentInputView; - -@interface FLEXFieldEditorView : UIView - -@property (nonatomic, copy) NSString *targetDescription; -@property (nonatomic, copy) NSString *fieldDescription; - -@property (nonatomic, copy) NSArray *argumentInputViews; - -@end diff --git a/Tweaks/FLEX/Editing/FLEXFieldEditorView.m b/Tweaks/FLEX/Editing/FLEXFieldEditorView.m deleted file mode 100644 index 229f75e..0000000 --- a/Tweaks/FLEX/Editing/FLEXFieldEditorView.m +++ /dev/null @@ -1,172 +0,0 @@ -// -// FLEXFieldEditorView.m -// Flipboard -// -// Created by Ryan Olson on 5/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFieldEditorView.h" -#import "FLEXArgumentInputView.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" - -@interface FLEXFieldEditorView () - -@property (nonatomic) UILabel *targetDescriptionLabel; -@property (nonatomic) UIView *targetDescriptionDivider; -@property (nonatomic) UILabel *fieldDescriptionLabel; -@property (nonatomic) UIView *fieldDescriptionDivider; - -@end - -@implementation FLEXFieldEditorView - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.targetDescriptionLabel = [UILabel new]; - self.targetDescriptionLabel.numberOfLines = 0; - self.targetDescriptionLabel.font = [[self class] labelFont]; - [self addSubview:self.targetDescriptionLabel]; - - self.targetDescriptionDivider = [[self class] dividerView]; - [self addSubview:self.targetDescriptionDivider]; - - self.fieldDescriptionLabel = [UILabel new]; - self.fieldDescriptionLabel.numberOfLines = 0; - self.fieldDescriptionLabel.font = [[self class] labelFont]; - [self addSubview:self.fieldDescriptionLabel]; - - self.fieldDescriptionDivider = [[self class] dividerView]; - [self addSubview:self.fieldDescriptionDivider]; - } - return self; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGFloat horizontalPadding = [[self class] horizontalPadding]; - CGFloat verticalPadding = [[self class] verticalPadding]; - CGFloat dividerLineHeight = [[self class] dividerLineHeight]; - - CGFloat originY = verticalPadding; - CGFloat originX = horizontalPadding; - CGFloat contentWidth = self.bounds.size.width - 2.0 * horizontalPadding; - CGSize constrainSize = CGSizeMake(contentWidth, CGFLOAT_MAX); - - CGSize instanceDescriptionSize = [self.targetDescriptionLabel sizeThatFits:constrainSize]; - self.targetDescriptionLabel.frame = CGRectMake(originX, originY, instanceDescriptionSize.width, instanceDescriptionSize.height); - originY = CGRectGetMaxY(self.targetDescriptionLabel.frame) + verticalPadding; - - self.targetDescriptionDivider.frame = CGRectMake(originX, originY, contentWidth, dividerLineHeight); - originY = CGRectGetMaxY(self.targetDescriptionDivider.frame) + verticalPadding; - - CGSize fieldDescriptionSize = [self.fieldDescriptionLabel sizeThatFits:constrainSize]; - self.fieldDescriptionLabel.frame = CGRectMake(originX, originY, fieldDescriptionSize.width, fieldDescriptionSize.height); - originY = CGRectGetMaxY(self.fieldDescriptionLabel.frame) + verticalPadding; - - self.fieldDescriptionDivider.frame = CGRectMake(originX, originY, contentWidth, dividerLineHeight); - originY = CGRectGetMaxY(self.fieldDescriptionDivider.frame) + verticalPadding; - - for (UIView *argumentInputView in self.argumentInputViews) { - CGSize inputViewSize = [argumentInputView sizeThatFits:constrainSize]; - argumentInputView.frame = CGRectMake(originX, originY, inputViewSize.width, inputViewSize.height); - originY = CGRectGetMaxY(argumentInputView.frame) + verticalPadding; - } -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor { - [super setBackgroundColor:backgroundColor]; - self.targetDescriptionLabel.backgroundColor = backgroundColor; - self.fieldDescriptionLabel.backgroundColor = backgroundColor; -} - -- (void)setTargetDescription:(NSString *)targetDescription { - if (![_targetDescription isEqual:targetDescription]) { - _targetDescription = targetDescription; - self.targetDescriptionLabel.text = targetDescription; - [self setNeedsLayout]; - } -} - -- (void)setFieldDescription:(NSString *)fieldDescription { - if (![_fieldDescription isEqual:fieldDescription]) { - _fieldDescription = fieldDescription; - self.fieldDescriptionLabel.text = fieldDescription; - [self setNeedsLayout]; - } -} - -- (void)setArgumentInputViews:(NSArray *)argumentInputViews { - if (![_argumentInputViews isEqual:argumentInputViews]) { - - for (FLEXArgumentInputView *inputView in _argumentInputViews) { - [inputView removeFromSuperview]; - } - - _argumentInputViews = argumentInputViews; - - for (FLEXArgumentInputView *newInputView in argumentInputViews) { - [self addSubview:newInputView]; - } - - [self setNeedsLayout]; - } -} - -+ (UIView *)dividerView { - UIView *dividerView = [UIView new]; - dividerView.backgroundColor = [self dividerColor]; - return dividerView; -} - -+ (UIColor *)dividerColor { - return FLEXColor.tertiaryBackgroundColor; -} - -+ (CGFloat)horizontalPadding { - return 10.0; -} - -+ (CGFloat)verticalPadding { - return 20.0; -} - -+ (UIFont *)labelFont { - return [UIFont systemFontOfSize:14.0]; -} - -+ (CGFloat)dividerLineHeight { - return 1.0; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat horizontalPadding = [[self class] horizontalPadding]; - CGFloat verticalPadding = [[self class] verticalPadding]; - CGFloat dividerLineHeight = [[self class] dividerLineHeight]; - - CGFloat height = 0; - CGFloat availableWidth = size.width - 2.0 * horizontalPadding; - CGSize constrainSize = CGSizeMake(availableWidth, CGFLOAT_MAX); - - height += verticalPadding; - height += ceil([self.targetDescriptionLabel sizeThatFits:constrainSize].height); - height += verticalPadding; - height += dividerLineHeight; - height += verticalPadding; - height += ceil([self.fieldDescriptionLabel sizeThatFits:constrainSize].height); - height += verticalPadding; - height += dividerLineHeight; - height += verticalPadding; - - for (FLEXArgumentInputView *inputView in self.argumentInputViews) { - height += [inputView sizeThatFits:constrainSize].height; - height += verticalPadding; - } - - return CGSizeMake(size.width, height); -} - -@end diff --git a/Tweaks/FLEX/Editing/FLEXFieldEditorViewController.h b/Tweaks/FLEX/Editing/FLEXFieldEditorViewController.h deleted file mode 100644 index c0250af..0000000 --- a/Tweaks/FLEX/Editing/FLEXFieldEditorViewController.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// FLEXFieldEditorViewController.h -// FLEX -// -// Created by Tanner on 11/22/18. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXVariableEditorViewController.h" -#import "FLEXProperty.h" -#import "FLEXIvar.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXFieldEditorViewController : FLEXVariableEditorViewController - -/// @return nil if the property is readonly or if the type is unsupported -+ (nullable instancetype)target:(id)target property:(FLEXProperty *)property commitHandler:(void(^_Nullable)(void))onCommit; -/// @return nil if the ivar type is unsupported -+ (nullable instancetype)target:(id)target ivar:(FLEXIvar *)ivar commitHandler:(void(^_Nullable)(void))onCommit; - -/// Subclasses can change the button title via the \c title property -@property (nonatomic, readonly) UIBarButtonItem *getterButton; - -- (void)getterButtonPressed:(id)sender; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Editing/FLEXFieldEditorViewController.m b/Tweaks/FLEX/Editing/FLEXFieldEditorViewController.m deleted file mode 100644 index ed5e629..0000000 --- a/Tweaks/FLEX/Editing/FLEXFieldEditorViewController.m +++ /dev/null @@ -1,149 +0,0 @@ -// -// FLEXFieldEditorViewController.m -// FLEX -// -// Created by Tanner on 11/22/18. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFieldEditorViewController.h" -#import "FLEXFieldEditorView.h" -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" -#import "UIBarButtonItem+FLEX.h" - -@interface FLEXFieldEditorViewController () - -@property (nonatomic) FLEXProperty *property; -@property (nonatomic) FLEXIvar *ivar; - -@property (nonatomic, readonly) id currentValue; -@property (nonatomic, readonly) const FLEXTypeEncoding *typeEncoding; -@property (nonatomic, readonly) NSString *fieldDescription; - -@end - -@implementation FLEXFieldEditorViewController - -#pragma mark - Initialization - -+ (instancetype)target:(id)target property:(nonnull FLEXProperty *)property commitHandler:(void(^_Nullable)(void))onCommit { - FLEXFieldEditorViewController *editor = [self target:target data:property commitHandler:onCommit]; - editor.title = [@"Property: " stringByAppendingString:property.name]; - editor.property = property; - return editor; -} - -+ (instancetype)target:(id)target ivar:(nonnull FLEXIvar *)ivar commitHandler:(void(^_Nullable)(void))onCommit { - FLEXFieldEditorViewController *editor = [self target:target data:ivar commitHandler:onCommit]; - editor.title = [@"Ivar: " stringByAppendingString:ivar.name]; - editor.ivar = ivar; - return editor; -} - -#pragma mark - Overrides - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.view.backgroundColor = FLEXColor.groupedBackgroundColor; - - // Create getter button - _getterButton = [[UIBarButtonItem alloc] - initWithTitle:@"Get" - style:UIBarButtonItemStyleDone - target:self - action:@selector(getterButtonPressed:) - ]; - self.toolbarItems = @[ - UIBarButtonItem.flex_flexibleSpace, self.getterButton, self.actionButton - ]; - - // Configure input view - self.fieldEditorView.fieldDescription = self.fieldDescription; - FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:self.typeEncoding]; - inputView.inputValue = self.currentValue; - inputView.delegate = self; - self.fieldEditorView.argumentInputViews = @[inputView]; - - // Don't show a "set" button for switches; we mutate when the switch is flipped - if ([inputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) { - self.actionButton.enabled = NO; - self.actionButton.title = @"Flip the switch to call the setter"; - // Put getter button before setter button - self.toolbarItems = @[ - UIBarButtonItem.flex_flexibleSpace, self.actionButton, self.getterButton - ]; - } -} - -- (void)actionButtonPressed:(id)sender { - if (self.property) { - id userInputObject = self.firstInputView.inputValue; - NSArray *arguments = userInputObject ? @[userInputObject] : nil; - SEL setterSelector = self.property.likelySetter; - NSError *error = nil; - [FLEXRuntimeUtility performSelector:setterSelector onObject:self.target withArguments:arguments error:&error]; - if (error) { - [FLEXAlert showAlert:@"Property Setter Failed" message:error.localizedDescription from:self]; - sender = nil; // Don't pop back - } - } else { - // TODO: check mutability and use mutableCopy if necessary; - // this currently could and would assign NSArray to NSMutableArray - [self.ivar setValue:self.firstInputView.inputValue onObject:self.target]; - } - - // Dismiss keyboard and handle committed changes - [super actionButtonPressed:sender]; - - // Go back after setting, but not for switches. - if (sender) { - [self.navigationController popViewControllerAnimated:YES]; - } else { - self.firstInputView.inputValue = self.currentValue; - } -} - -- (void)getterButtonPressed:(id)sender { - [self.fieldEditorView endEditing:YES]; - - [self exploreObjectOrPopViewController:self.currentValue]; -} - -- (void)argumentInputViewValueDidChange:(FLEXArgumentInputView *)argumentInputView { - if ([argumentInputView isKindOfClass:[FLEXArgumentInputSwitchView class]]) { - [self actionButtonPressed:nil]; - } -} - -#pragma mark - Private - -- (id)currentValue { - if (self.property) { - return [self.property getValue:self.target]; - } else { - return [self.ivar getValue:self.target]; - } -} - -- (const FLEXTypeEncoding *)typeEncoding { - if (self.property) { - return self.property.attributes.typeEncoding.UTF8String; - } else { - return self.ivar.typeEncoding.UTF8String; - } -} - -- (NSString *)fieldDescription { - if (self.property) { - return self.property.fullDescription; - } else { - return self.ivar.description; - } -} - -@end diff --git a/Tweaks/FLEX/Editing/FLEXMethodCallingViewController.h b/Tweaks/FLEX/Editing/FLEXMethodCallingViewController.h deleted file mode 100644 index 6dc77a5..0000000 --- a/Tweaks/FLEX/Editing/FLEXMethodCallingViewController.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// FLEXMethodCallingViewController.h -// Flipboard -// -// Created by Ryan Olson on 5/23/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXVariableEditorViewController.h" -#import "FLEXMethod.h" - -@interface FLEXMethodCallingViewController : FLEXVariableEditorViewController - -+ (instancetype)target:(id)target method:(FLEXMethod *)method; - -@end diff --git a/Tweaks/FLEX/Editing/FLEXMethodCallingViewController.m b/Tweaks/FLEX/Editing/FLEXMethodCallingViewController.m deleted file mode 100644 index 9e25e6e..0000000 --- a/Tweaks/FLEX/Editing/FLEXMethodCallingViewController.m +++ /dev/null @@ -1,110 +0,0 @@ -// -// FLEXMethodCallingViewController.m -// Flipboard -// -// Created by Ryan Olson on 5/23/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMethodCallingViewController.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXFieldEditorView.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXArgumentInputView.h" -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXUtility.h" - -@interface FLEXMethodCallingViewController () -@property (nonatomic, readonly) FLEXMethod *method; -@end - -@implementation FLEXMethodCallingViewController - -+ (instancetype)target:(id)target method:(FLEXMethod *)method { - return [[self alloc] initWithTarget:target method:method]; -} - -- (id)initWithTarget:(id)target method:(FLEXMethod *)method { - NSParameterAssert(method.isInstanceMethod == !object_isClass(target)); - - self = [super initWithTarget:target data:method commitHandler:nil]; - if (self) { - self.title = method.isInstanceMethod ? @"Method: " : @"Class Method: "; - self.title = [self.title stringByAppendingString:method.selectorString]; - } - - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.actionButton.title = @"Call"; - - // Configure field editor view - self.fieldEditorView.argumentInputViews = [self argumentInputViews]; - self.fieldEditorView.fieldDescription = [NSString stringWithFormat: - @"Signature:\n%@\n\nReturn Type:\n%s", - self.method.description, (char *)self.method.returnType - ]; -} - -- (NSArray *)argumentInputViews { - Method method = self.method.objc_method; - NSArray *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:method]; - NSMutableArray *argumentInputViews = [NSMutableArray new]; - unsigned int argumentIndex = kFLEXNumberOfImplicitArgs; - - for (NSString *methodComponent in methodComponents) { - char *argumentTypeEncoding = method_copyArgumentType(method, argumentIndex); - FLEXArgumentInputView *inputView = [FLEXArgumentInputViewFactory argumentInputViewForTypeEncoding:argumentTypeEncoding]; - free(argumentTypeEncoding); - - inputView.backgroundColor = self.view.backgroundColor; - inputView.title = methodComponent; - [argumentInputViews addObject:inputView]; - argumentIndex++; - } - - return argumentInputViews; -} - -- (void)actionButtonPressed:(id)sender { - // Gather arguments - NSMutableArray *arguments = [NSMutableArray new]; - for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) { - // Use NSNull as a nil placeholder; it will be interpreted as nil - [arguments addObject:inputView.inputValue ?: NSNull.null]; - } - - // Call method - NSError *error = nil; - id returnValue = [FLEXRuntimeUtility - performSelector:self.method.selector - onObject:self.target - withArguments:arguments - error:&error - ]; - - // Dismiss keyboard and handle committed changes - [super actionButtonPressed:sender]; - - // Display return value or error - if (error) { - [FLEXAlert showAlert:@"Method Call Failed" message:error.localizedDescription from:self]; - } else if (returnValue) { - // For non-nil (or void) return types, push an explorer view controller to display the returned object - returnValue = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnValue type:self.method.returnType]; - FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnValue]; - [self.navigationController pushViewController:explorer animated:YES]; - } else { - [self exploreObjectOrPopViewController:returnValue]; - } -} - -- (FLEXMethod *)method { - return _data; -} - -@end diff --git a/Tweaks/FLEX/Editing/FLEXVariableEditorViewController.h b/Tweaks/FLEX/Editing/FLEXVariableEditorViewController.h deleted file mode 100644 index 8225d6c..0000000 --- a/Tweaks/FLEX/Editing/FLEXVariableEditorViewController.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// FLEXVariableEditorViewController.h -// Flipboard -// -// Created by Ryan Olson on 5/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@class FLEXFieldEditorView; -@class FLEXArgumentInputView; - -NS_ASSUME_NONNULL_BEGIN - -/// An abstract screen for editing or configuring one or more variables. -/// "Target" is the target of the edit operation, and "data" is the data -/// you want to mutate or pass to the target when the action is performed. -/// The action may be something like calling a method, setting an ivar, etc. -@interface FLEXVariableEditorViewController : UIViewController { - @protected - id _target; - _Nullable id _data; - void (^_Nullable _commitHandler)(void); -} - -/// @param target The target of the operation -/// @param data The data associated with the operation -/// @param onCommit An action to perform when the data changes -+ (instancetype)target:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit; -/// @param target The target of the operation -/// @param data The data associated with the operation -/// @param onCommit An action to perform when the data changes -- (id)initWithTarget:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit; - -@property (nonatomic, readonly) id target; - -/// Convenience accessor since many subclasses only use one input view -@property (nonatomic, readonly, nullable) FLEXArgumentInputView *firstInputView; - -@property (nonatomic, readonly) FLEXFieldEditorView *fieldEditorView; -/// Subclasses can change the button title via the button's \c title property -@property (nonatomic, readonly) UIBarButtonItem *actionButton; - -/// Subclasses should override to provide "set" functionality. -/// The commit handler--if present--is called here. -- (void)actionButtonPressed:(nullable id)sender; - -/// Pushes an explorer view controller for the given object -/// or pops the current view controller. -- (void)exploreObjectOrPopViewController:(nullable id)objectOrNil; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Editing/FLEXVariableEditorViewController.m b/Tweaks/FLEX/Editing/FLEXVariableEditorViewController.m deleted file mode 100644 index 9085aab..0000000 --- a/Tweaks/FLEX/Editing/FLEXVariableEditorViewController.m +++ /dev/null @@ -1,141 +0,0 @@ -// -// FLEXVariableEditorViewController.m -// Flipboard -// -// Created by Ryan Olson on 5/16/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXVariableEditorViewController.h" -#import "FLEXFieldEditorView.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXUtility.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXArgumentInputView.h" -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXObjectExplorerViewController.h" -#import "UIBarButtonItem+FLEX.h" - -@interface FLEXVariableEditorViewController () -@property (nonatomic) UIScrollView *scrollView; -@end - -@implementation FLEXVariableEditorViewController - -#pragma mark - Initialization - -+ (instancetype)target:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit { - return [[self alloc] initWithTarget:target data:data commitHandler:onCommit]; -} - -- (id)initWithTarget:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit { - self = [super init]; - if (self) { - _target = target; - _data = data; - _commitHandler = onCommit; - [NSNotificationCenter.defaultCenter - addObserver:self selector:@selector(keyboardDidShow:) - name:UIKeyboardDidShowNotification object:nil - ]; - [NSNotificationCenter.defaultCenter - addObserver:self selector:@selector(keyboardWillHide:) - name:UIKeyboardWillHideNotification object:nil - ]; - } - - return self; -} - -- (void)dealloc { - [NSNotificationCenter.defaultCenter removeObserver:self]; -} - -#pragma mark - UIViewController methods - -- (void)keyboardDidShow:(NSNotification *)notification { - CGRect keyboardRectInWindow = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; - CGSize keyboardSize = [self.view convertRect:keyboardRectInWindow fromView:nil].size; - UIEdgeInsets scrollInsets = self.scrollView.contentInset; - scrollInsets.bottom = keyboardSize.height; - self.scrollView.contentInset = scrollInsets; - self.scrollView.scrollIndicatorInsets = scrollInsets; - - // Find the active input view and scroll to make sure it's visible. - for (FLEXArgumentInputView *argumentInputView in self.fieldEditorView.argumentInputViews) { - if (argumentInputView.inputViewIsFirstResponder) { - CGRect scrollToVisibleRect = [self.scrollView convertRect:argumentInputView.bounds fromView:argumentInputView]; - [self.scrollView scrollRectToVisible:scrollToVisibleRect animated:YES]; - break; - } - } -} - -- (void)keyboardWillHide:(NSNotification *)notification { - UIEdgeInsets scrollInsets = self.scrollView.contentInset; - scrollInsets.bottom = 0.0; - self.scrollView.contentInset = scrollInsets; - self.scrollView.scrollIndicatorInsets = scrollInsets; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.view.backgroundColor = FLEXColor.scrollViewBackgroundColor; - - self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; - self.scrollView.backgroundColor = self.view.backgroundColor; - self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.scrollView.delegate = self; - [self.view addSubview:self.scrollView]; - - _fieldEditorView = [FLEXFieldEditorView new]; - self.fieldEditorView.targetDescription = [NSString stringWithFormat:@"%@ %p", [self.target class], self.target]; - [self.scrollView addSubview:self.fieldEditorView]; - - _actionButton = [[UIBarButtonItem alloc] - initWithTitle:@"Set" - style:UIBarButtonItemStyleDone - target:self - action:@selector(actionButtonPressed:) - ]; - - self.navigationController.toolbarHidden = NO; - self.toolbarItems = @[UIBarButtonItem.flex_flexibleSpace, self.actionButton]; -} - -- (void)viewWillLayoutSubviews { - CGSize constrainSize = CGSizeMake(self.scrollView.bounds.size.width, CGFLOAT_MAX); - CGSize fieldEditorSize = [self.fieldEditorView sizeThatFits:constrainSize]; - self.fieldEditorView.frame = CGRectMake(0, 0, fieldEditorSize.width, fieldEditorSize.height); - self.scrollView.contentSize = fieldEditorSize; -} - -#pragma mark - Public - -- (FLEXArgumentInputView *)firstInputView { - return [self.fieldEditorView argumentInputViews].firstObject; -} - -- (void)actionButtonPressed:(id)sender { - // Subclasses can override - [self.fieldEditorView endEditing:YES]; - if (_commitHandler) { - _commitHandler(); - } -} - -- (void)exploreObjectOrPopViewController:(id)objectOrNil { - if (objectOrNil) { - // For non-nil (or void) return types, push an explorer view controller to display the object - FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:objectOrNil]; - [self.navigationController pushViewController:explorerViewController animated:YES]; - } else { - // If we didn't get a returned object but the method call succeeded, - // pop this view controller off the stack to indicate that the call went through. - [self.navigationController popViewControllerAnimated:YES]; - } -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarkManager.h b/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarkManager.h deleted file mode 100644 index 5e4c84a..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarkManager.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXBookmarkManager.h -// FLEX -// -// Created by Tanner on 2/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXBookmarkManager : NSObject - -@property (nonatomic, readonly, class) NSMutableArray *bookmarks; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarkManager.m b/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarkManager.m deleted file mode 100644 index fc9606d..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarkManager.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// FLEXBookmarkManager.m -// FLEX -// -// Created by Tanner on 2/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXBookmarkManager.h" - -static NSMutableArray *kFLEXBookmarkManagerBookmarks = nil; - -@implementation FLEXBookmarkManager - -+ (void)initialize { - if (self == [FLEXBookmarkManager class]) { - kFLEXBookmarkManagerBookmarks = [NSMutableArray new]; - } -} - -+ (NSMutableArray *)bookmarks { - return kFLEXBookmarkManagerBookmarks; -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.h b/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.h deleted file mode 100644 index 514184f..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXBookmarksViewController.h -// FLEX -// -// Created by Tanner on 2/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXBookmarksViewController : FLEXTableViewController - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.m b/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.m deleted file mode 100644 index f14140a..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.m +++ /dev/null @@ -1,235 +0,0 @@ -// -// FLEXBookmarksViewController.m -// FLEX -// -// Created by Tanner on 2/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXBookmarksViewController.h" -#import "FLEXExplorerViewController.h" -#import "FLEXNavigationController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXBookmarkManager.h" -#import "UIBarButtonItem+FLEX.h" -#import "FLEXColor.h" -#import "FLEXUtility.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXTableView.h" - -@interface FLEXBookmarksViewController () -@property (nonatomic, copy) NSArray *bookmarks; -@property (nonatomic, readonly) FLEXExplorerViewController *corePresenter; -@end - -@implementation FLEXBookmarksViewController - -#pragma mark - Initialization - -- (id)init { - return [self initWithStyle:UITableViewStylePlain]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.navigationController.hidesBarsOnSwipe = NO; - self.tableView.allowsMultipleSelectionDuringEditing = YES; - - [self reloadData]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [self setupDefaultBarItems]; -} - - -#pragma mark - Private - -- (void)reloadData { - // We assume the bookmarks aren't going to change out from under us, since - // presenting any other tool via keyboard shortcuts should dismiss us first - self.bookmarks = FLEXBookmarkManager.bookmarks; - self.title = [NSString stringWithFormat:@"Bookmarks (%@)", @(self.bookmarks.count)]; -} - -- (void)setupDefaultBarItems { - self.navigationItem.rightBarButtonItem = FLEXBarButtonItemSystem(Done, self, @selector(dismissAnimated)); - self.toolbarItems = @[ - UIBarButtonItem.flex_flexibleSpace, - FLEXBarButtonItemSystem(Edit, self, @selector(toggleEditing)), - ]; - - // Disable editing if no bookmarks available - self.toolbarItems.lastObject.enabled = self.bookmarks.count > 0; -} - -- (void)setupEditingBarItems { - self.navigationItem.rightBarButtonItem = nil; - self.toolbarItems = @[ - [UIBarButtonItem flex_itemWithTitle:@"Close All" target:self action:@selector(closeAllButtonPressed:)], - UIBarButtonItem.flex_flexibleSpace, - // We use a non-system done item because we change its title dynamically - [UIBarButtonItem flex_doneStyleitemWithTitle:@"Done" target:self action:@selector(toggleEditing)] - ]; - - self.toolbarItems.firstObject.tintColor = FLEXColor.destructiveColor; -} - -- (FLEXExplorerViewController *)corePresenter { - // We must be presented by a FLEXExplorerViewController, or presented - // by another view controller that was presented by FLEXExplorerViewController - FLEXExplorerViewController *presenter = (id)self.presentingViewController; - presenter = (id)presenter.presentingViewController ?: presenter; - presenter = (id)presenter.presentingViewController ?: presenter; - NSAssert( - [presenter isKindOfClass:[FLEXExplorerViewController class]], - @"The bookmarks view controller expects to be presented by the explorer controller" - ); - return presenter; -} - -#pragma mark Button Actions - -- (void)dismissAnimated { - [self dismissAnimated:nil]; -} - -- (void)dismissAnimated:(id)selectedObject { - if (selectedObject) { - UIViewController *explorer = [FLEXObjectExplorerFactory - explorerViewControllerForObject:selectedObject - ]; - if ([self.presentingViewController isKindOfClass:[FLEXNavigationController class]]) { - // I am presented on an existing navigation stack, so - // dismiss myself and push the bookmark there - UINavigationController *presenter = (id)self.presentingViewController; - [presenter dismissViewControllerAnimated:YES completion:^{ - [presenter pushViewController:explorer animated:YES]; - }]; - } else { - // Dismiss myself and present explorer - UIViewController *presenter = self.corePresenter; - [presenter dismissViewControllerAnimated:YES completion:^{ - [presenter presentViewController:[FLEXNavigationController - withRootViewController:explorer - ] animated:YES completion:nil]; - }]; - } - } else { - // Just dismiss myself - [self dismissViewControllerAnimated:YES completion:nil]; - } -} - -- (void)toggleEditing { - NSArray *selected = self.tableView.indexPathsForSelectedRows; - self.editing = !self.editing; - - if (self.isEditing) { - [self setupEditingBarItems]; - } else { - [self setupDefaultBarItems]; - - // Get index set of bookmarks to close - NSMutableIndexSet *indexes = [NSMutableIndexSet new]; - for (NSIndexPath *ip in selected) { - [indexes addIndex:ip.row]; - } - - if (selected.count) { - // Close bookmarks and update data source - [FLEXBookmarkManager.bookmarks removeObjectsAtIndexes:indexes]; - [self reloadData]; - - // Remove deleted rows - [self.tableView deleteRowsAtIndexPaths:selected withRowAnimation:UITableViewRowAnimationAutomatic]; - } - } -} - -- (void)closeAllButtonPressed:(UIBarButtonItem *)sender { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - NSInteger count = self.bookmarks.count; - NSString *title = FLEXPluralFormatString(count, @"Remove %@ bookmarks", @"Remove %@ bookmark"); - make.button(title).destructiveStyle().handler(^(NSArray *strings) { - [self closeAll]; - [self toggleEditing]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; -} - -- (void)closeAll { - NSInteger rowCount = self.bookmarks.count; - - // Close bookmarks and update data source - [FLEXBookmarkManager.bookmarks removeAllObjects]; - [self reloadData]; - - // Delete rows from table view - NSArray *allRows = [NSArray flex_forEachUpTo:rowCount map:^id(NSUInteger row) { - return [NSIndexPath indexPathForRow:row inSection:0]; - }]; - [self.tableView deleteRowsAtIndexPaths:allRows withRowAnimation:UITableViewRowAnimationAutomatic]; -} - - -#pragma mark - Table View Data Source - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.bookmarks.count; -} - -- (UITableViewCell *)tableView:(FLEXTableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXDetailCell forIndexPath:indexPath]; - - id object = self.bookmarks[indexPath.row]; - cell.textLabel.text = [FLEXRuntimeUtility safeDescriptionForObject:object]; - cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ — %p", [object class], object]; - - return cell; -} - - -#pragma mark - Table View Delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (self.editing) { - // Case: editing with multi-select - self.toolbarItems.lastObject.title = @"Remove Selected"; - self.toolbarItems.lastObject.tintColor = FLEXColor.destructiveColor; - } else { - // Case: selected a bookmark - [self dismissAnimated:self.bookmarks[indexPath.row]]; - } -} - -- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { - NSParameterAssert(self.editing); - - if (tableView.indexPathsForSelectedRows.count == 0) { - self.toolbarItems.lastObject.title = @"Done"; - self.toolbarItems.lastObject.tintColor = self.view.tintColor; - } -} - -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; -} - -- (void)tableView:(UITableView *)table -commitEditingStyle:(UITableViewCellEditingStyle)edit -forRowAtIndexPath:(NSIndexPath *)indexPath { - NSParameterAssert(edit == UITableViewCellEditingStyleDelete); - - // Remove bookmark and update data source - [FLEXBookmarkManager.bookmarks removeObjectAtIndex:indexPath.row]; - [self reloadData]; - - // Delete row from table view - [table deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXExplorerViewController.h b/Tweaks/FLEX/ExplorerInterface/FLEXExplorerViewController.h deleted file mode 100644 index 6f92b34..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXExplorerViewController.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// FLEXExplorerViewController.h -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXExplorerToolbar.h" - -@class FLEXWindow; -@protocol FLEXExplorerViewControllerDelegate; - -/// A view controller that manages the FLEX toolbar. -@interface FLEXExplorerViewController : UIViewController - -@property (nonatomic, weak) id delegate; -@property (nonatomic, readonly) BOOL wantsWindowToBecomeKey; - -@property (nonatomic, readonly) FLEXExplorerToolbar *explorerToolbar; - -- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates; - -/// @brief Used to present (or dismiss) a modal view controller ("tool"), -/// typically triggered by pressing a button in the toolbar. -/// -/// If a tool is already presented, this method simply dismisses it and calls the completion block. -/// If no tool is presented, @code future() @endcode is presented and the completion block is called. -- (void)toggleToolWithViewControllerProvider:(UINavigationController *(^)(void))future - completion:(void (^)(void))completion; - -/// @brief Used to present (or dismiss) a modal view controller ("tool"), -/// typically triggered by pressing a button in the toolbar. -/// -/// If a tool is already presented, this method dismisses it and presents the given tool. -/// The completion block is called once the tool has been presented. -- (void)presentTool:(UINavigationController *(^)(void))future - completion:(void (^)(void))completion; - -// Keyboard shortcut helpers - -- (void)toggleSelectTool; -- (void)toggleMoveTool; -- (void)toggleViewsTool; -- (void)toggleMenuTool; - -/// @return YES if the explorer used the key press to perform an action, NO otherwise -- (BOOL)handleDownArrowKeyPressed; -/// @return YES if the explorer used the key press to perform an action, NO otherwise -- (BOOL)handleUpArrowKeyPressed; -/// @return YES if the explorer used the key press to perform an action, NO otherwise -- (BOOL)handleRightArrowKeyPressed; -/// @return YES if the explorer used the key press to perform an action, NO otherwise -- (BOOL)handleLeftArrowKeyPressed; - -@end - -#pragma mark - -@protocol FLEXExplorerViewControllerDelegate -- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController; -@end diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXExplorerViewController.m b/Tweaks/FLEX/ExplorerInterface/FLEXExplorerViewController.m deleted file mode 100644 index 888295f..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXExplorerViewController.m +++ /dev/null @@ -1,1050 +0,0 @@ -// -// FLEXExplorerViewController.m -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXExplorerViewController.h" -#import "FLEXExplorerToolbarItem.h" -#import "FLEXUtility.h" -#import "FLEXWindow.h" -#import "FLEXTabList.h" -#import "FLEXNavigationController.h" -#import "FLEXHierarchyViewController.h" -#import "FLEXGlobalsViewController.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXNetworkMITMViewController.h" -#import "FLEXTabsViewController.h" -#import "FLEXWindowManagerController.h" -#import "FLEXViewControllersViewController.h" -#import "NSUserDefaults+FLEX.h" - -typedef NS_ENUM(NSUInteger, FLEXExplorerMode) { - FLEXExplorerModeDefault, - FLEXExplorerModeSelect, - FLEXExplorerModeMove -}; - -@interface FLEXExplorerViewController () - -/// Tracks the currently active tool/mode -@property (nonatomic) FLEXExplorerMode currentMode; - -/// Gesture recognizer for dragging a view in move mode -@property (nonatomic) UIPanGestureRecognizer *movePanGR; - -/// Gesture recognizer for showing additional details on the selected view -@property (nonatomic) UITapGestureRecognizer *detailsTapGR; - -/// Only valid while a move pan gesture is in progress. -@property (nonatomic) CGRect selectedViewFrameBeforeDragging; - -/// Only valid while a toolbar drag pan gesture is in progress. -@property (nonatomic) CGRect toolbarFrameBeforeDragging; - -/// Only valid while a selected view pan gesture is in progress. -@property (nonatomic) CGFloat selectedViewLastPanX; - -/// Borders of all the visible views in the hierarchy at the selection point. -/// The keys are NSValues with the corresponding view (nonretained). -@property (nonatomic) NSDictionary *outlineViewsForVisibleViews; - -/// The actual views at the selection point with the deepest view last. -@property (nonatomic) NSArray *viewsAtTapPoint; - -/// The view that we're currently highlighting with an overlay and displaying details for. -@property (nonatomic) UIView *selectedView; - -/// A colored transparent overlay to indicate that the view is selected. -@property (nonatomic) UIView *selectedViewOverlay; - -/// Used to actuate changes in view selection on iOS 10+ -@property (nonatomic, readonly) UISelectionFeedbackGenerator *selectionFBG API_AVAILABLE(ios(10.0)); - -/// self.view.window as a \c FLEXWindow -@property (nonatomic, readonly) FLEXWindow *window; - -/// All views that we're KVOing. Used to help us clean up properly. -@property (nonatomic) NSMutableSet *observedViews; - -/// Used to preserve the target app's UIMenuController items. -@property (nonatomic) NSArray *appMenuItems; - -@end - -@implementation FLEXExplorerViewController - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - if (self) { - self.observedViews = [NSMutableSet new]; - } - return self; -} - -- (void)dealloc { - for (UIView *view in _observedViews) { - [self stopObservingView:view]; - } -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Toolbar - _explorerToolbar = [FLEXExplorerToolbar new]; - - // Start the toolbar off below any bars that may be at the top of the view. - CGFloat toolbarOriginY = NSUserDefaults.standardUserDefaults.flex_toolbarTopMargin; - - CGRect safeArea = [self viewSafeArea]; - CGSize toolbarSize = [self.explorerToolbar sizeThatFits:CGSizeMake( - CGRectGetWidth(self.view.bounds), CGRectGetHeight(safeArea) - )]; - [self updateToolbarPositionWithUnconstrainedFrame:CGRectMake( - CGRectGetMinX(safeArea), toolbarOriginY, toolbarSize.width, toolbarSize.height - )]; - self.explorerToolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleBottomMargin | - UIViewAutoresizingFlexibleTopMargin; - [self.view addSubview:self.explorerToolbar]; - [self setupToolbarActions]; - [self setupToolbarGestures]; - - // View selection - UITapGestureRecognizer *selectionTapGR = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleSelectionTap:) - ]; - [self.view addGestureRecognizer:selectionTapGR]; - - // View moving - self.movePanGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMovePan:)]; - self.movePanGR.enabled = self.currentMode == FLEXExplorerModeMove; - [self.view addGestureRecognizer:self.movePanGR]; - - // Feedback - if (@available(iOS 10.0, *)) { - _selectionFBG = [UISelectionFeedbackGenerator new]; - } -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self updateButtonStates]; -} - - -#pragma mark - Rotation - -- (UIViewController *)viewControllerForRotationAndOrientation { - UIViewController *viewController = FLEXUtility.appKeyWindow.rootViewController; - // Obfuscating selector _viewControllerForSupportedInterfaceOrientations - NSString *viewControllerSelectorString = [@[ - @"_vie", @"wContro", @"llerFor", @"Supported", @"Interface", @"Orientations" - ] componentsJoinedByString:@""]; - SEL viewControllerSelector = NSSelectorFromString(viewControllerSelectorString); - if ([viewController respondsToSelector:viewControllerSelector]) { - viewController = [viewController valueForKey:viewControllerSelectorString]; - } - - return viewController; -} - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations { - // Commenting this out until I can figure out a better way to solve this -// if (self.window.isKeyWindow) { -// [self.window resignKeyWindow]; -// } - - UIViewController *viewControllerToAsk = [self viewControllerForRotationAndOrientation]; - UIInterfaceOrientationMask supportedOrientations = FLEXUtility.infoPlistSupportedInterfaceOrientationsMask; - if (viewControllerToAsk && ![viewControllerToAsk isKindOfClass:[self class]]) { - supportedOrientations = [viewControllerToAsk supportedInterfaceOrientations]; - } - - // The UIViewController docs state that this method must not return zero. - // If we weren't able to get a valid value for the supported interface - // orientations, default to all supported. - if (supportedOrientations == 0) { - supportedOrientations = UIInterfaceOrientationMaskAll; - } - - return supportedOrientations; -} - -- (BOOL)shouldAutorotate { - UIViewController *viewControllerToAsk = [self viewControllerForRotationAndOrientation]; - BOOL shouldAutorotate = YES; - if (viewControllerToAsk && viewControllerToAsk != self) { - shouldAutorotate = [viewControllerToAsk shouldAutorotate]; - } - return shouldAutorotate; -} - -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator:(id)coordinator { - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; - [coordinator animateAlongsideTransition:^(id context) { - for (UIView *outlineView in self.outlineViewsForVisibleViews.allValues) { - outlineView.hidden = YES; - } - self.selectedViewOverlay.hidden = YES; - } completion:^(id context) { - for (UIView *view in self.viewsAtTapPoint) { - NSValue *key = [NSValue valueWithNonretainedObject:view]; - UIView *outlineView = self.outlineViewsForVisibleViews[key]; - outlineView.frame = [self frameInLocalCoordinatesForView:view]; - if (self.currentMode == FLEXExplorerModeSelect) { - outlineView.hidden = NO; - } - } - - if (self.selectedView) { - self.selectedViewOverlay.frame = [self frameInLocalCoordinatesForView:self.selectedView]; - self.selectedViewOverlay.hidden = NO; - } - }]; -} - - -#pragma mark - Setter Overrides - -- (void)setSelectedView:(UIView *)selectedView { - if (![_selectedView isEqual:selectedView]) { - if (![self.viewsAtTapPoint containsObject:_selectedView]) { - [self stopObservingView:_selectedView]; - } - - _selectedView = selectedView; - - [self beginObservingView:selectedView]; - - // Update the toolbar and selected overlay - self.explorerToolbar.selectedViewDescription = [FLEXUtility - descriptionForView:selectedView includingFrame:YES - ]; - self.explorerToolbar.selectedViewOverlayColor = [FLEXUtility - consistentRandomColorForObject:selectedView - ]; - - if (selectedView) { - if (!self.selectedViewOverlay) { - self.selectedViewOverlay = [UIView new]; - [self.view addSubview:self.selectedViewOverlay]; - self.selectedViewOverlay.layer.borderWidth = 1.0; - } - UIColor *outlineColor = [FLEXUtility consistentRandomColorForObject:selectedView]; - self.selectedViewOverlay.backgroundColor = [outlineColor colorWithAlphaComponent:0.2]; - self.selectedViewOverlay.layer.borderColor = outlineColor.CGColor; - self.selectedViewOverlay.frame = [self.view convertRect:selectedView.bounds fromView:selectedView]; - - // Make sure the selected overlay is in front of all the other subviews - // except the toolbar, which should always stay on top. - [self.view bringSubviewToFront:self.selectedViewOverlay]; - [self.view bringSubviewToFront:self.explorerToolbar]; - } else { - [self.selectedViewOverlay removeFromSuperview]; - self.selectedViewOverlay = nil; - } - - // Some of the button states depend on whether we have a selected view. - [self updateButtonStates]; - } -} - -- (void)setViewsAtTapPoint:(NSArray *)viewsAtTapPoint { - if (![_viewsAtTapPoint isEqual:viewsAtTapPoint]) { - for (UIView *view in _viewsAtTapPoint) { - if (view != self.selectedView) { - [self stopObservingView:view]; - } - } - - _viewsAtTapPoint = viewsAtTapPoint; - - for (UIView *view in viewsAtTapPoint) { - [self beginObservingView:view]; - } - } -} - -- (void)setCurrentMode:(FLEXExplorerMode)currentMode { - if (_currentMode != currentMode) { - _currentMode = currentMode; - switch (currentMode) { - case FLEXExplorerModeDefault: - [self removeAndClearOutlineViews]; - self.viewsAtTapPoint = nil; - self.selectedView = nil; - break; - - case FLEXExplorerModeSelect: - // Make sure the outline views are unhidden in case we came from the move mode. - for (NSValue *key in self.outlineViewsForVisibleViews) { - UIView *outlineView = self.outlineViewsForVisibleViews[key]; - outlineView.hidden = NO; - } - break; - - case FLEXExplorerModeMove: - // Hide all the outline views to focus on the selected view, - // which is the only one that will move. - for (NSValue *key in self.outlineViewsForVisibleViews) { - UIView *outlineView = self.outlineViewsForVisibleViews[key]; - outlineView.hidden = YES; - } - break; - } - self.movePanGR.enabled = currentMode == FLEXExplorerModeMove; - [self updateButtonStates]; - } -} - - -#pragma mark - View Tracking - -- (void)beginObservingView:(UIView *)view { - // Bail if we're already observing this view or if there's nothing to observe. - if (!view || [self.observedViews containsObject:view]) { - return; - } - - for (NSString *keyPath in self.viewKeyPathsToTrack) { - [view addObserver:self forKeyPath:keyPath options:0 context:NULL]; - } - - [self.observedViews addObject:view]; -} - -- (void)stopObservingView:(UIView *)view { - if (!view) { - return; - } - - for (NSString *keyPath in self.viewKeyPathsToTrack) { - [view removeObserver:self forKeyPath:keyPath]; - } - - [self.observedViews removeObject:view]; -} - -- (NSArray *)viewKeyPathsToTrack { - static NSArray *trackedViewKeyPaths = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *frameKeyPath = NSStringFromSelector(@selector(frame)); - trackedViewKeyPaths = @[frameKeyPath]; - }); - return trackedViewKeyPaths; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - [self updateOverlayAndDescriptionForObjectIfNeeded:object]; -} - -- (void)updateOverlayAndDescriptionForObjectIfNeeded:(id)object { - NSUInteger indexOfView = [self.viewsAtTapPoint indexOfObject:object]; - if (indexOfView != NSNotFound) { - UIView *view = self.viewsAtTapPoint[indexOfView]; - NSValue *key = [NSValue valueWithNonretainedObject:view]; - UIView *outline = self.outlineViewsForVisibleViews[key]; - if (outline) { - outline.frame = [self frameInLocalCoordinatesForView:view]; - } - } - if (object == self.selectedView) { - // Update the selected view description since we show the frame value there. - self.explorerToolbar.selectedViewDescription = [FLEXUtility - descriptionForView:self.selectedView includingFrame:YES - ]; - CGRect selectedViewOutlineFrame = [self frameInLocalCoordinatesForView:self.selectedView]; - self.selectedViewOverlay.frame = selectedViewOutlineFrame; - } -} - -- (CGRect)frameInLocalCoordinatesForView:(UIView *)view { - // Convert to window coordinates since the view may be in a different window than our view - CGRect frameInWindow = [view convertRect:view.bounds toView:nil]; - // Convert from the window to our view's coordinate space - return [self.view convertRect:frameInWindow fromView:nil]; -} - - -#pragma mark - Toolbar Buttons - -- (void)setupToolbarActions { - FLEXExplorerToolbar *toolbar = self.explorerToolbar; - NSDictionary *actionsToItems = @{ - NSStringFromSelector(@selector(selectButtonTapped:)): toolbar.selectItem, - NSStringFromSelector(@selector(hierarchyButtonTapped:)): toolbar.hierarchyItem, - NSStringFromSelector(@selector(recentButtonTapped:)): toolbar.recentItem, - NSStringFromSelector(@selector(moveButtonTapped:)): toolbar.moveItem, - NSStringFromSelector(@selector(globalsButtonTapped:)): toolbar.globalsItem, - NSStringFromSelector(@selector(closeButtonTapped:)): toolbar.closeItem, - }; - - [actionsToItems enumerateKeysAndObjectsUsingBlock:^(NSString *sel, FLEXExplorerToolbarItem *item, BOOL *stop) { - [item addTarget:self action:NSSelectorFromString(sel) forControlEvents:UIControlEventTouchUpInside]; - }]; -} - -- (void)selectButtonTapped:(FLEXExplorerToolbarItem *)sender { - [self toggleSelectTool]; -} - -- (void)hierarchyButtonTapped:(FLEXExplorerToolbarItem *)sender { - [self toggleViewsTool]; -} - -- (UIWindow *)statusWindow { - if (!@available(iOS 16, *)) { - NSString *statusBarString = [NSString stringWithFormat:@"%@arWindow", @"_statusB"]; - return [UIApplication.sharedApplication valueForKey:statusBarString]; - } - - return nil; -} - -- (void)recentButtonTapped:(FLEXExplorerToolbarItem *)sender { - NSAssert(FLEXTabList.sharedList.activeTab, @"Must have active tab"); - [self presentViewController:FLEXTabList.sharedList.activeTab animated:YES completion:nil]; -} - -- (void)moveButtonTapped:(FLEXExplorerToolbarItem *)sender { - [self toggleMoveTool]; -} - -- (void)globalsButtonTapped:(FLEXExplorerToolbarItem *)sender { - [self toggleMenuTool]; -} - -- (void)closeButtonTapped:(FLEXExplorerToolbarItem *)sender { - self.currentMode = FLEXExplorerModeDefault; - [self.delegate explorerViewControllerDidFinish:self]; -} - -- (void)updateButtonStates { - FLEXExplorerToolbar *toolbar = self.explorerToolbar; - - toolbar.selectItem.selected = self.currentMode == FLEXExplorerModeSelect; - - // Move only enabled when an object is selected. - BOOL hasSelectedObject = self.selectedView != nil; - toolbar.moveItem.enabled = hasSelectedObject; - toolbar.moveItem.selected = self.currentMode == FLEXExplorerModeMove; - - // Recent only enabled when we have a last active tab - toolbar.recentItem.enabled = FLEXTabList.sharedList.activeTab != nil; -} - - -#pragma mark - Toolbar Dragging - -- (void)setupToolbarGestures { - FLEXExplorerToolbar *toolbar = self.explorerToolbar; - - // Pan gesture for dragging. - [toolbar.dragHandle addGestureRecognizer:[[UIPanGestureRecognizer alloc] - initWithTarget:self action:@selector(handleToolbarPanGesture:) - ]]; - - // Tap gesture for hinting. - [toolbar.dragHandle addGestureRecognizer:[[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleToolbarHintTapGesture:) - ]]; - - // Tap gesture for showing additional details - self.detailsTapGR = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleToolbarDetailsTapGesture:) - ]; - [toolbar.selectedViewDescriptionContainer addGestureRecognizer:self.detailsTapGR]; - - // Swipe gestures for selecting deeper / higher views at a point - UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] - initWithTarget:self action:@selector(handleChangeViewAtPointGesture:) - ]; - [toolbar.selectedViewDescriptionContainer addGestureRecognizer:panGesture]; - - // Long press gesture to present tabs manager - [toolbar.globalsItem addGestureRecognizer:[[UILongPressGestureRecognizer alloc] - initWithTarget:self action:@selector(handleToolbarShowTabsGesture:) - ]]; - - // Long press gesture to present window manager - [toolbar.selectItem addGestureRecognizer:[[UILongPressGestureRecognizer alloc] - initWithTarget:self action:@selector(handleToolbarWindowManagerGesture:) - ]]; - - // Long press gesture to present view controllers at tap - [toolbar.hierarchyItem addGestureRecognizer:[[UILongPressGestureRecognizer alloc] - initWithTarget:self action:@selector(handleToolbarShowViewControllersGesture:) - ]]; -} - -- (void)handleToolbarPanGesture:(UIPanGestureRecognizer *)panGR { - switch (panGR.state) { - case UIGestureRecognizerStateBegan: - self.toolbarFrameBeforeDragging = self.explorerToolbar.frame; - [self updateToolbarPositionWithDragGesture:panGR]; - break; - - case UIGestureRecognizerStateChanged: - case UIGestureRecognizerStateEnded: - [self updateToolbarPositionWithDragGesture:panGR]; - break; - - default: - break; - } -} - -- (void)updateToolbarPositionWithDragGesture:(UIPanGestureRecognizer *)panGR { - CGPoint translation = [panGR translationInView:self.view]; - CGRect newToolbarFrame = self.toolbarFrameBeforeDragging; - newToolbarFrame.origin.y += translation.y; - - [self updateToolbarPositionWithUnconstrainedFrame:newToolbarFrame]; -} - -- (void)updateToolbarPositionWithUnconstrainedFrame:(CGRect)unconstrainedFrame { - CGRect safeArea = [self viewSafeArea]; - // We only constrain the Y-axis because we want the toolbar - // to handle the X-axis safeArea layout by itself - CGFloat minY = CGRectGetMinY(safeArea); - CGFloat maxY = CGRectGetMaxY(safeArea) - unconstrainedFrame.size.height; - if (unconstrainedFrame.origin.y < minY) { - unconstrainedFrame.origin.y = minY; - } else if (unconstrainedFrame.origin.y > maxY) { - unconstrainedFrame.origin.y = maxY; - } - - self.explorerToolbar.frame = unconstrainedFrame; - NSUserDefaults.standardUserDefaults.flex_toolbarTopMargin = unconstrainedFrame.origin.y; -} - -- (void)handleToolbarHintTapGesture:(UITapGestureRecognizer *)tapGR { - // Bounce the toolbar to indicate that it is draggable. - // TODO: make it bouncier. - if (tapGR.state == UIGestureRecognizerStateRecognized) { - CGRect originalToolbarFrame = self.explorerToolbar.frame; - const NSTimeInterval kHalfwayDuration = 0.2; - const CGFloat kVerticalOffset = 30.0; - [UIView animateWithDuration:kHalfwayDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ - CGRect newToolbarFrame = self.explorerToolbar.frame; - newToolbarFrame.origin.y += kVerticalOffset; - self.explorerToolbar.frame = newToolbarFrame; - } completion:^(BOOL finished) { - [UIView animateWithDuration:kHalfwayDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ - self.explorerToolbar.frame = originalToolbarFrame; - } completion:nil]; - }]; - } -} - -- (void)handleToolbarDetailsTapGesture:(UITapGestureRecognizer *)tapGR { - if (tapGR.state == UIGestureRecognizerStateRecognized && self.selectedView) { - UIViewController *topStackVC = [FLEXObjectExplorerFactory explorerViewControllerForObject:self.selectedView]; - [self presentViewController: - [FLEXNavigationController withRootViewController:topStackVC] - animated:YES completion:nil]; - } -} - -- (void)handleToolbarShowTabsGesture:(UILongPressGestureRecognizer *)sender { - if (sender.state == UIGestureRecognizerStateBegan) { - // Back up the UIMenuController items since dismissViewController: will attempt to replace them - self.appMenuItems = UIMenuController.sharedMenuController.menuItems; - - // Don't use FLEXNavigationController because the tab viewer itself is not a tab - [super presentViewController:[[UINavigationController alloc] - initWithRootViewController:[FLEXTabsViewController new] - ] animated:YES completion:nil]; - } -} - -- (void)handleToolbarWindowManagerGesture:(UILongPressGestureRecognizer *)sender { - if (sender.state == UIGestureRecognizerStateBegan) { - // Back up the UIMenuController items since dismissViewController: will attempt to replace them - self.appMenuItems = UIMenuController.sharedMenuController.menuItems; - - [super presentViewController:[FLEXNavigationController - withRootViewController:[FLEXWindowManagerController new] - ] animated:YES completion:nil]; - } -} - -- (void)handleToolbarShowViewControllersGesture:(UILongPressGestureRecognizer *)sender { - if (sender.state == UIGestureRecognizerStateBegan && self.viewsAtTapPoint.count) { - // Back up the UIMenuController items since dismissViewController: will attempt to replace them - self.appMenuItems = UIMenuController.sharedMenuController.menuItems; - - UIViewController *list = [FLEXViewControllersViewController - controllersForViews:self.viewsAtTapPoint - ]; - [self presentViewController: - [FLEXNavigationController withRootViewController:list - ] animated:YES completion:nil]; - } -} - - -#pragma mark - View Selection - -- (void)handleSelectionTap:(UITapGestureRecognizer *)tapGR { - // Only if we're in selection mode - if (self.currentMode == FLEXExplorerModeSelect && tapGR.state == UIGestureRecognizerStateRecognized) { - // Note that [tapGR locationInView:nil] is broken in iOS 8, - // so we have to do a two step conversion to window coordinates. - // Thanks to @lascorbe for finding this: https://github.com/Flipboard/FLEX/pull/31 - CGPoint tapPointInView = [tapGR locationInView:self.view]; - CGPoint tapPointInWindow = [self.view convertPoint:tapPointInView toView:nil]; - [self updateOutlineViewsForSelectionPoint:tapPointInWindow]; - } -} - -- (void)handleChangeViewAtPointGesture:(UIPanGestureRecognizer *)sender { - NSInteger max = self.viewsAtTapPoint.count - 1; - NSInteger currentIdx = [self.viewsAtTapPoint indexOfObject:self.selectedView]; - CGFloat locationX = [sender locationInView:self.view].x; - - // Track the pan gesture: every N points we move along the X axis, - // actuate some haptic feedback and move up or down the hierarchy. - // We only store the "last" location when we've met the threshold. - // We only change the view and actuate feedback if the view selection - // changes; that is, as long as we don't go outside or under the array. - switch (sender.state) { - case UIGestureRecognizerStateBegan: { - self.selectedViewLastPanX = locationX; - break; - } - case UIGestureRecognizerStateChanged: { - static CGFloat kNextLevelThreshold = 20.f; - CGFloat lastX = self.selectedViewLastPanX; - NSInteger newSelection = currentIdx; - - // Left, go down the hierarchy - if (locationX < lastX && (lastX - locationX) >= kNextLevelThreshold) { - // Choose a new view index up to the max index - newSelection = MIN(max, currentIdx + 1); - self.selectedViewLastPanX = locationX; - } - // Right, go up the hierarchy - else if (lastX < locationX && (locationX - lastX) >= kNextLevelThreshold) { - // Choose a new view index down to the min index - newSelection = MAX(0, currentIdx - 1); - self.selectedViewLastPanX = locationX; - } - - if (currentIdx != newSelection) { - self.selectedView = self.viewsAtTapPoint[newSelection]; - [self actuateSelectionChangedFeedback]; - } - - break; - } - - default: break; - } -} - -- (void)actuateSelectionChangedFeedback { - if (@available(iOS 10.0, *)) { - [self.selectionFBG selectionChanged]; - } -} - -- (void)updateOutlineViewsForSelectionPoint:(CGPoint)selectionPointInWindow { - [self removeAndClearOutlineViews]; - - // Include hidden views in the "viewsAtTapPoint" array so we can show them in the hierarchy list. - self.viewsAtTapPoint = [self viewsAtPoint:selectionPointInWindow skipHiddenViews:NO]; - - // For outlined views and the selected view, only use visible views. - // Outlining hidden views adds clutter and makes the selection behavior confusing. - NSArray *visibleViewsAtTapPoint = [self viewsAtPoint:selectionPointInWindow skipHiddenViews:YES]; - NSMutableDictionary *newOutlineViewsForVisibleViews = [NSMutableDictionary new]; - for (UIView *view in visibleViewsAtTapPoint) { - UIView *outlineView = [self outlineViewForView:view]; - [self.view addSubview:outlineView]; - NSValue *key = [NSValue valueWithNonretainedObject:view]; - [newOutlineViewsForVisibleViews setObject:outlineView forKey:key]; - } - self.outlineViewsForVisibleViews = newOutlineViewsForVisibleViews; - self.selectedView = [self viewForSelectionAtPoint:selectionPointInWindow]; - - // Make sure the explorer toolbar doesn't end up behind the newly added outline views. - [self.view bringSubviewToFront:self.explorerToolbar]; - - [self updateButtonStates]; -} - -- (UIView *)outlineViewForView:(UIView *)view { - CGRect outlineFrame = [self frameInLocalCoordinatesForView:view]; - UIView *outlineView = [[UIView alloc] initWithFrame:outlineFrame]; - outlineView.backgroundColor = UIColor.clearColor; - outlineView.layer.borderColor = [FLEXUtility consistentRandomColorForObject:view].CGColor; - outlineView.layer.borderWidth = 1.0; - return outlineView; -} - -- (void)removeAndClearOutlineViews { - for (NSValue *key in self.outlineViewsForVisibleViews) { - UIView *outlineView = self.outlineViewsForVisibleViews[key]; - [outlineView removeFromSuperview]; - } - self.outlineViewsForVisibleViews = nil; -} - -- (NSArray *)viewsAtPoint:(CGPoint)tapPointInWindow skipHiddenViews:(BOOL)skipHidden { - NSMutableArray *views = [NSMutableArray new]; - for (UIWindow *window in FLEXUtility.allWindows) { - // Don't include the explorer's own window or subviews. - if (window != self.view.window && [window pointInside:tapPointInWindow withEvent:nil]) { - [views addObject:window]; - [views addObjectsFromArray:[self - recursiveSubviewsAtPoint:tapPointInWindow inView:window skipHiddenViews:skipHidden - ]]; - } - } - return views; -} - -- (UIView *)viewForSelectionAtPoint:(CGPoint)tapPointInWindow { - // Select in the window that would handle the touch, but don't just use the result of - // hitTest:withEvent: so we can still select views with interaction disabled. - // Default to the the application's key window if none of the windows want the touch. - UIWindow *windowForSelection = UIApplication.sharedApplication.keyWindow; - for (UIWindow *window in FLEXUtility.allWindows.reverseObjectEnumerator) { - // Ignore the explorer's own window. - if (window != self.view.window) { - if ([window hitTest:tapPointInWindow withEvent:nil]) { - windowForSelection = window; - break; - } - } - } - - // Select the deepest visible view at the tap point. This generally corresponds to what the user wants to select. - return [self recursiveSubviewsAtPoint:tapPointInWindow inView:windowForSelection skipHiddenViews:YES].lastObject; -} - -- (NSArray *)recursiveSubviewsAtPoint:(CGPoint)pointInView - inView:(UIView *)view - skipHiddenViews:(BOOL)skipHidden { - NSMutableArray *subviewsAtPoint = [NSMutableArray new]; - for (UIView *subview in view.subviews) { - BOOL isHidden = subview.hidden || subview.alpha < 0.01; - if (skipHidden && isHidden) { - continue; - } - - BOOL subviewContainsPoint = CGRectContainsPoint(subview.frame, pointInView); - if (subviewContainsPoint) { - [subviewsAtPoint addObject:subview]; - } - - // If this view doesn't clip to its bounds, we need to check its subviews even if it - // doesn't contain the selection point. They may be visible and contain the selection point. - if (subviewContainsPoint || !subview.clipsToBounds) { - CGPoint pointInSubview = [view convertPoint:pointInView toView:subview]; - [subviewsAtPoint addObjectsFromArray:[self - recursiveSubviewsAtPoint:pointInSubview inView:subview skipHiddenViews:skipHidden - ]]; - } - } - return subviewsAtPoint; -} - - -#pragma mark - Selected View Moving - -- (void)handleMovePan:(UIPanGestureRecognizer *)movePanGR { - switch (movePanGR.state) { - case UIGestureRecognizerStateBegan: - self.selectedViewFrameBeforeDragging = self.selectedView.frame; - [self updateSelectedViewPositionWithDragGesture:movePanGR]; - break; - - case UIGestureRecognizerStateChanged: - case UIGestureRecognizerStateEnded: - [self updateSelectedViewPositionWithDragGesture:movePanGR]; - break; - - default: - break; - } -} - -- (void)updateSelectedViewPositionWithDragGesture:(UIPanGestureRecognizer *)movePanGR { - CGPoint translation = [movePanGR translationInView:self.selectedView.superview]; - CGRect newSelectedViewFrame = self.selectedViewFrameBeforeDragging; - newSelectedViewFrame.origin.x = FLEXFloor(newSelectedViewFrame.origin.x + translation.x); - newSelectedViewFrame.origin.y = FLEXFloor(newSelectedViewFrame.origin.y + translation.y); - self.selectedView.frame = newSelectedViewFrame; -} - - -#pragma mark - Safe Area Handling - -- (CGRect)viewSafeArea { - CGRect safeArea = self.view.bounds; - if (@available(iOS 11.0, *)) { - safeArea = UIEdgeInsetsInsetRect(self.view.bounds, self.view.safeAreaInsets); - } - - return safeArea; -} - -- (void)viewSafeAreaInsetsDidChange { - if (@available(iOS 11.0, *)) { - [super viewSafeAreaInsetsDidChange]; - - CGRect safeArea = [self viewSafeArea]; - CGSize toolbarSize = [self.explorerToolbar sizeThatFits:CGSizeMake( - CGRectGetWidth(self.view.bounds), CGRectGetHeight(safeArea) - )]; - [self updateToolbarPositionWithUnconstrainedFrame:CGRectMake( - CGRectGetMinX(self.explorerToolbar.frame), - CGRectGetMinY(self.explorerToolbar.frame), - toolbarSize.width, - toolbarSize.height) - ]; - } -} - - -#pragma mark - Touch Handling - -- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates { - BOOL shouldReceiveTouch = NO; - - CGPoint pointInLocalCoordinates = [self.view convertPoint:pointInWindowCoordinates fromView:nil]; - - // Always if it's on the toolbar - if (CGRectContainsPoint(self.explorerToolbar.frame, pointInLocalCoordinates)) { - shouldReceiveTouch = YES; - } - - // Always if we're in selection mode - if (!shouldReceiveTouch && self.currentMode == FLEXExplorerModeSelect) { - shouldReceiveTouch = YES; - } - - // Always in move mode too - if (!shouldReceiveTouch && self.currentMode == FLEXExplorerModeMove) { - shouldReceiveTouch = YES; - } - - // Always if we have a modal presented - if (!shouldReceiveTouch && self.presentedViewController) { - shouldReceiveTouch = YES; - } - - return shouldReceiveTouch; -} - - -#pragma mark - FLEXHierarchyDelegate - -- (void)viewHierarchyDidDismiss:(UIView *)selectedView { - // Note that we need to wait until the view controller is dismissed to calculate the frame - // of the outline view, otherwise the coordinate conversion doesn't give the correct result. - [self toggleViewsToolWithCompletion:^{ - // If the selected view is outside of the tap point array (selected from "Full Hierarchy"), - // then clear out the tap point array and remove all the outline views. - if (![self.viewsAtTapPoint containsObject:selectedView]) { - self.viewsAtTapPoint = nil; - [self removeAndClearOutlineViews]; - } - - // If we now have a selected view and we didn't have one previously, go to "select" mode. - if (self.currentMode == FLEXExplorerModeDefault && selectedView) { - self.currentMode = FLEXExplorerModeSelect; - } - - // The selected view setter will also update the selected view overlay appropriately. - self.selectedView = selectedView; - }]; -} - - -#pragma mark - Modal Presentation and Window Management - -- (void)presentViewController:(UIViewController *)toPresent - animated:(BOOL)animated - completion:(void (^)(void))completion { - // Make our window key to correctly handle input. - [self.view.window makeKeyWindow]; - - // Move the status bar on top of FLEX so we can get scroll to top behavior for taps. - if (!@available(iOS 13, *)) { - [self statusWindow].windowLevel = self.view.window.windowLevel + 1.0; - } - - // Back up and replace the UIMenuController items - // Edit: no longer replacing the items, but still backing them - // up in case we start replacing them again in the future - self.appMenuItems = UIMenuController.sharedMenuController.menuItems; - - // Show the view controller - [super presentViewController:toPresent animated:animated completion:completion]; -} - -- (void)dismissViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion { - UIWindow *appWindow = self.window.previousKeyWindow; - [appWindow makeKeyWindow]; - [appWindow.rootViewController setNeedsStatusBarAppearanceUpdate]; - - // Restore previous UIMenuController items - // Back up and replace the UIMenuController items - UIMenuController.sharedMenuController.menuItems = self.appMenuItems; - [UIMenuController.sharedMenuController update]; - self.appMenuItems = nil; - - // Restore the status bar window's normal window level. - // We want it above FLEX while a modal is presented for - // scroll to top, but below FLEX otherwise for exploration. - [self statusWindow].windowLevel = UIWindowLevelStatusBar; - - [self updateButtonStates]; - - [super dismissViewControllerAnimated:animated completion:completion]; -} - -- (BOOL)wantsWindowToBecomeKey { - return self.window.previousKeyWindow != nil; -} - -- (void)toggleToolWithViewControllerProvider:(UINavigationController *(^)(void))future - completion:(void (^)(void))completion { - if (self.presentedViewController) { - // We do NOT want to present the future; this is - // a convenience method for toggling the SAME TOOL - [self dismissViewControllerAnimated:YES completion:completion]; - } else if (future) { - [self presentViewController:future() animated:YES completion:completion]; - } -} - -- (void)presentTool:(UINavigationController *(^)(void))future - completion:(void (^)(void))completion { - if (self.presentedViewController) { - // If a tool is already presented, dismiss it first - [self dismissViewControllerAnimated:YES completion:^{ - [self presentViewController:future() animated:YES completion:completion]; - }]; - } else if (future) { - [self presentViewController:future() animated:YES completion:completion]; - } -} - -- (FLEXWindow *)window { - return (id)self.view.window; -} - - -#pragma mark - Keyboard Shortcut Helpers - -- (void)toggleSelectTool { - if (self.currentMode == FLEXExplorerModeSelect) { - self.currentMode = FLEXExplorerModeDefault; - } else { - self.currentMode = FLEXExplorerModeSelect; - } -} - -- (void)toggleMoveTool { - if (self.currentMode == FLEXExplorerModeMove) { - self.currentMode = FLEXExplorerModeSelect; - } else if (self.currentMode == FLEXExplorerModeSelect && self.selectedView) { - self.currentMode = FLEXExplorerModeMove; - } -} - -- (void)toggleViewsTool { - [self toggleViewsToolWithCompletion:nil]; -} - -- (void)toggleViewsToolWithCompletion:(void(^)(void))completion { - [self toggleToolWithViewControllerProvider:^UINavigationController *{ - if (self.selectedView) { - return [FLEXHierarchyViewController - delegate:self - viewsAtTap:self.viewsAtTapPoint - selectedView:self.selectedView - ]; - } else { - return [FLEXHierarchyViewController delegate:self]; - } - } completion:completion]; -} - -- (void)toggleMenuTool { - [self toggleToolWithViewControllerProvider:^UINavigationController *{ - return [FLEXNavigationController withRootViewController:[FLEXGlobalsViewController new]]; - } completion:nil]; -} - -- (BOOL)handleDownArrowKeyPressed { - if (self.currentMode == FLEXExplorerModeMove) { - CGRect frame = self.selectedView.frame; - frame.origin.y += 1.0 / UIScreen.mainScreen.scale; - self.selectedView.frame = frame; - } else if (self.currentMode == FLEXExplorerModeSelect && self.viewsAtTapPoint.count > 0) { - NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView]; - if (selectedViewIndex > 0) { - self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex - 1]; - } - } else { - return NO; - } - - return YES; -} - -- (BOOL)handleUpArrowKeyPressed { - if (self.currentMode == FLEXExplorerModeMove) { - CGRect frame = self.selectedView.frame; - frame.origin.y -= 1.0 / UIScreen.mainScreen.scale; - self.selectedView.frame = frame; - } else if (self.currentMode == FLEXExplorerModeSelect && self.viewsAtTapPoint.count > 0) { - NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView]; - if (selectedViewIndex < self.viewsAtTapPoint.count - 1) { - self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex + 1]; - } - } else { - return NO; - } - - return YES; -} - -- (BOOL)handleRightArrowKeyPressed { - if (self.currentMode == FLEXExplorerModeMove) { - CGRect frame = self.selectedView.frame; - frame.origin.x += 1.0 / UIScreen.mainScreen.scale; - self.selectedView.frame = frame; - return YES; - } - - return NO; -} - -- (BOOL)handleLeftArrowKeyPressed { - if (self.currentMode == FLEXExplorerModeMove) { - CGRect frame = self.selectedView.frame; - frame.origin.x -= 1.0 / UIScreen.mainScreen.scale; - self.selectedView.frame = frame; - return YES; - } - - return NO; -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXViewControllersViewController.h b/Tweaks/FLEX/ExplorerInterface/FLEXViewControllersViewController.h deleted file mode 100644 index b2d9ec4..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXViewControllersViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXViewControllersViewController.h -// FLEX -// -// Created by Tanner Bennett on 2/13/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXViewControllersViewController : FLEXFilteringTableViewController - -+ (instancetype)controllersForViews:(NSArray *)views; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXViewControllersViewController.m b/Tweaks/FLEX/ExplorerInterface/FLEXViewControllersViewController.m deleted file mode 100644 index 956f1ea..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXViewControllersViewController.m +++ /dev/null @@ -1,79 +0,0 @@ -// -// FLEXViewControllersViewController.m -// FLEX -// -// Created by Tanner Bennett on 2/13/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXViewControllersViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXMutableListSection.h" -#import "FLEXUtility.h" - -@interface FLEXViewControllersViewController () -@property (nonatomic, readonly) FLEXMutableListSection *section; -@property (nonatomic, readonly) NSArray *controllers; -@end - -@implementation FLEXViewControllersViewController -@dynamic sections, allSections; - -#pragma mark - Initialization - -+ (instancetype)controllersForViews:(NSArray *)views { - return [[self alloc] initWithViews:views]; -} - -- (id)initWithViews:(NSArray *)views { - NSParameterAssert(views.count); - - self = [self initWithStyle:UITableViewStylePlain]; - if (self) { - _controllers = [views flex_mapped:^id(UIView *view, NSUInteger idx) { - return [FLEXUtility viewControllerForView:view]; - }]; - } - - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = @"View Controllers at Tap"; - self.showsSearchBar = YES; - [self disableToolbar]; -} - -- (NSArray *)makeSections { - _section = [FLEXMutableListSection list:self.controllers - cellConfiguration:^(UITableViewCell *cell, UIViewController *controller, NSInteger row) { - cell.textLabel.text = [NSString - stringWithFormat:@"%@ — %p", NSStringFromClass(controller.class), controller - ]; - cell.detailTextLabel.text = controller.view.description; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; - } filterMatcher:^BOOL(NSString *filterText, UIViewController *controller) { - return [NSStringFromClass(controller.class) localizedCaseInsensitiveContainsString:filterText]; - }]; - - self.section.selectionHandler = ^(UIViewController *host, UIViewController *controller) { - [host.navigationController pushViewController: - [FLEXObjectExplorerFactory explorerViewControllerForObject:controller] - animated:YES]; - }; - - self.section.customTitle = @"View Controllers"; - return @[self.section]; -} - - -#pragma mark - Private - -- (void)dismissAnimated { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXWindow.h b/Tweaks/FLEX/ExplorerInterface/FLEXWindow.h deleted file mode 100644 index 4de7ae4..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXWindow.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// FLEXWindow.h -// Flipboard -// -// Created by Ryan Olson on 4/13/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@protocol FLEXWindowEventDelegate - -- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow; -- (BOOL)canBecomeKeyWindow; - -@end - -#pragma mark - -@interface FLEXWindow : UIWindow - -@property (nonatomic, weak) id eventDelegate; - -/// Tracked so we can restore the key window after dismissing a modal. -/// We need to become key after modal presentation so we can correctly capture input. -/// If we're just showing the toolbar, we want the main app's window to remain key -/// so that we don't interfere with input, status bar, etc. -@property (nonatomic, readonly) UIWindow *previousKeyWindow; - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXWindow.m b/Tweaks/FLEX/ExplorerInterface/FLEXWindow.m deleted file mode 100644 index 48fc1cf..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXWindow.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// FLEXWindow.m -// Flipboard -// -// Created by Ryan Olson on 4/13/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXWindow.h" -#import "FLEXUtility.h" -#import - -@implementation FLEXWindow - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - // Some apps have windows at UIWindowLevelStatusBar + n. - // If we make the window level too high, we block out UIAlertViews. - // There's a balance between staying above the app's windows and staying below alerts. - // UIWindowLevelStatusBar + 100 seems to hit that balance. - self.windowLevel = UIWindowLevelStatusBar + 100.0; - } - return self; -} - -- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { - BOOL pointInside = NO; - if ([self.eventDelegate shouldHandleTouchAtPoint:point]) { - pointInside = [super pointInside:point withEvent:event]; - } - return pointInside; -} - -- (BOOL)shouldAffectStatusBarAppearance { - return [self isKeyWindow]; -} - -- (BOOL)canBecomeKeyWindow { - return [self.eventDelegate canBecomeKeyWindow]; -} - -- (void)makeKeyWindow { - _previousKeyWindow = FLEXUtility.appKeyWindow; - [super makeKeyWindow]; -} - -- (void)resignKeyWindow { - [super resignKeyWindow]; - _previousKeyWindow = nil; -} - -+ (void)initialize { - // This adds a method (superclass override) at runtime which gives us the status bar behavior we want. - // The FLEX window is intended to be an overlay that generally doesn't affect the app underneath. - // Most of the time, we want the app's main window(s) to be in control of status bar behavior. - // Done at runtime with an obfuscated selector because it is private API. But you shouldn't ship this to the App Store anyways... - NSString *canAffectSelectorString = [@[@"_can", @"Affect", @"Status", @"Bar", @"Appearance"] componentsJoinedByString:@""]; - SEL canAffectSelector = NSSelectorFromString(canAffectSelectorString); - Method shouldAffectMethod = class_getInstanceMethod(self, @selector(shouldAffectStatusBarAppearance)); - IMP canAffectImplementation = method_getImplementation(shouldAffectMethod); - class_addMethod(self, canAffectSelector, canAffectImplementation, method_getTypeEncoding(shouldAffectMethod)); - - // One more... - NSString *canBecomeKeySelectorString = [NSString stringWithFormat:@"_%@", NSStringFromSelector(@selector(canBecomeKeyWindow))]; - SEL canBecomeKeySelector = NSSelectorFromString(canBecomeKeySelectorString); - Method canBecomeKeyMethod = class_getInstanceMethod(self, @selector(canBecomeKeyWindow)); - IMP canBecomeKeyImplementation = method_getImplementation(canBecomeKeyMethod); - class_addMethod(self, canBecomeKeySelector, canBecomeKeyImplementation, method_getTypeEncoding(canBecomeKeyMethod)); -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXWindowManagerController.h b/Tweaks/FLEX/ExplorerInterface/FLEXWindowManagerController.h deleted file mode 100644 index d0dd05e..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXWindowManagerController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXWindowManagerController.h -// FLEX -// -// Created by Tanner on 2/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXWindowManagerController : FLEXTableViewController - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ExplorerInterface/FLEXWindowManagerController.m b/Tweaks/FLEX/ExplorerInterface/FLEXWindowManagerController.m deleted file mode 100644 index 1c9846d..0000000 --- a/Tweaks/FLEX/ExplorerInterface/FLEXWindowManagerController.m +++ /dev/null @@ -1,302 +0,0 @@ -// -// FLEXWindowManagerController.m -// FLEX -// -// Created by Tanner on 2/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXWindowManagerController.h" -#import "FLEXManager+Private.h" -#import "FLEXUtility.h" -#import "FLEXObjectExplorerFactory.h" - -@interface FLEXWindowManagerController () -@property (nonatomic) UIWindow *keyWindow; -@property (nonatomic, copy) NSString *keyWindowSubtitle; -@property (nonatomic, copy) NSArray *windows; -@property (nonatomic, copy) NSArray *windowSubtitles; -@property (nonatomic, copy) NSArray *scenes API_AVAILABLE(ios(13)); -@property (nonatomic, copy) NSArray *sceneSubtitles; -@property (nonatomic, copy) NSArray *sections; -@end - -@implementation FLEXWindowManagerController - -#pragma mark - Initialization - -- (id)init { - return [self initWithStyle:UITableViewStylePlain]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = @"Windows"; - if (@available(iOS 13, *)) { - self.title = @"Windows and Scenes"; - } - - [self disableToolbar]; - [self reloadData]; -} - - -#pragma mark - Private - -- (void)reloadData { - self.keyWindow = UIApplication.sharedApplication.keyWindow; - self.windows = UIApplication.sharedApplication.windows; - self.keyWindowSubtitle = self.windowSubtitles[[self.windows indexOfObject:self.keyWindow]]; - self.windowSubtitles = [self.windows flex_mapped:^id(UIWindow *window, NSUInteger idx) { - return [NSString stringWithFormat:@"Level: %@ — Root: %@", - @(window.windowLevel), window.rootViewController - ]; - }]; - - if (@available(iOS 13, *)) { - self.scenes = UIApplication.sharedApplication.connectedScenes.allObjects; - self.sceneSubtitles = [self.scenes flex_mapped:^id(UIScene *scene, NSUInteger idx) { - return [self sceneDescription:scene]; - }]; - - self.sections = @[@[self.keyWindow], self.windows, self.scenes]; - } else { - self.sections = @[@[self.keyWindow], self.windows]; - } - - [self.tableView reloadData]; -} - -- (void)dismissAnimated { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -- (void)showRevertOrDismissAlert:(void(^)(void))revertBlock { - [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES]; - [self reloadData]; - [self.tableView reloadData]; - - UIWindow *highestWindow = UIApplication.sharedApplication.keyWindow; - UIWindowLevel maxLevel = 0; - for (UIWindow *window in UIApplication.sharedApplication.windows) { - if (window.windowLevel > maxLevel) { - maxLevel = window.windowLevel; - highestWindow = window; - } - } - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Keep Changes?"); - make.message(@"If you do not wish to keep these settings, choose 'Revert Changes' below."); - - make.button(@"Keep Changes").destructiveStyle(); - make.button(@"Keep Changes and Dismiss").destructiveStyle().handler(^(NSArray *strings) { - [self dismissAnimated]; - }); - make.button(@"Revert Changes").cancelStyle().handler(^(NSArray *strings) { - revertBlock(); - [self reloadData]; - [self.tableView reloadData]; - }); - } showFrom:[FLEXUtility topViewControllerInWindow:highestWindow]]; -} - -- (NSString *)sceneDescription:(UIScene *)scene API_AVAILABLE(ios(13)) { - NSString *state = [self stringFromSceneState:scene.activationState]; - NSString *title = scene.title.length ? scene.title : nil; - NSString *suffix = nil; - - if ([scene isKindOfClass:[UIWindowScene class]]) { - UIWindowScene *windowScene = (id)scene; - suffix = FLEXPluralString(windowScene.windows.count, @"windows", @"window"); - } - - NSMutableString *description = state.mutableCopy; - if (title) { - [description appendFormat:@" — %@", title]; - } - if (suffix) { - [description appendFormat:@" — %@", suffix]; - } - - return description.copy; -} - -- (NSString *)stringFromSceneState:(UISceneActivationState)state API_AVAILABLE(ios(13)) { - switch (state) { - case UISceneActivationStateUnattached: - return @"Unattached"; - case UISceneActivationStateForegroundActive: - return @"Active"; - case UISceneActivationStateForegroundInactive: - return @"Inactive"; - case UISceneActivationStateBackground: - return @"Backgrounded"; - } - - return [NSString stringWithFormat:@"Unknown state: %@", @(state)]; -} - - -#pragma mark - Table View Data Source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.sections.count; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.sections[section].count; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - switch (section) { - case 0: return @"Key Window"; - case 1: return @"Windows"; - case 2: return @"Connected Scenes"; - } - - return nil; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXDetailCell forIndexPath:indexPath]; - cell.accessoryType = UITableViewCellAccessoryDetailButton; - cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; - - UIWindow *window = nil; - NSString *subtitle = nil; - - switch (indexPath.section) { - case 0: - window = self.keyWindow; - subtitle = self.keyWindowSubtitle; - break; - case 1: - window = self.windows[indexPath.row]; - subtitle = self.windowSubtitles[indexPath.row]; - break; - case 2: - if (@available(iOS 13, *)) { - UIScene *scene = self.scenes[indexPath.row]; - cell.textLabel.text = scene.description; - cell.detailTextLabel.text = self.sceneSubtitles[indexPath.row]; - return cell; - } - } - - cell.textLabel.text = window.description; - cell.detailTextLabel.text = [NSString - stringWithFormat:@"Level: %@ — Root: %@", - @((NSInteger)window.windowLevel), window.rootViewController.class - ]; - - return cell; -} - - -#pragma mark - Table View Delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - UIWindow *window = nil; - NSString *subtitle = nil; - FLEXWindow *flex = FLEXManager.sharedManager.explorerWindow; - - id cancelHandler = ^{ - [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES]; - }; - - switch (indexPath.section) { - case 0: - window = self.keyWindow; - subtitle = self.keyWindowSubtitle; - break; - case 1: - window = self.windows[indexPath.row]; - subtitle = self.windowSubtitles[indexPath.row]; - break; - case 2: - if (@available(iOS 13, *)) { - UIScene *scene = self.scenes[indexPath.row]; - UIWindowScene *oldScene = flex.windowScene; - BOOL isWindowScene = [scene isKindOfClass:[UIWindowScene class]]; - BOOL isFLEXScene = isWindowScene ? flex.windowScene == scene : NO; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(NSStringFromClass(scene.class)); - - if (isWindowScene) { - if (isFLEXScene) { - make.message(@"Already the FLEX window scene"); - } - - make.button(@"Set as FLEX Window Scene") - .handler(^(NSArray *strings) { - flex.windowScene = (id)scene; - [self showRevertOrDismissAlert:^{ - flex.windowScene = oldScene; - }]; - }).enabled(!isFLEXScene); - make.button(@"Cancel").cancelStyle(); - } else { - make.message(@"Not a UIWindowScene"); - make.button(@"Dismiss").cancelStyle().handler(cancelHandler); - } - } showFrom:self]; - } - } - - __block UIWindow *targetWindow = nil, *oldKeyWindow = nil; - __block UIWindowLevel oldLevel; - __block BOOL wasVisible; - - subtitle = [subtitle stringByAppendingString: - @"\n\n1) Adjust the FLEX window level relative to this window,\n" - "2) adjust this window's level relative to the FLEX window,\n" - "3) set this window's level to a specific value, or\n" - "4) make this window the key window if it isn't already." - ]; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(NSStringFromClass(window.class)).message(subtitle); - make.button(@"Adjust FLEX Window Level").handler(^(NSArray *strings) { - targetWindow = flex; oldLevel = flex.windowLevel; - flex.windowLevel = window.windowLevel + strings.firstObject.integerValue; - - [self showRevertOrDismissAlert:^{ targetWindow.windowLevel = oldLevel; }]; - }); - make.button(@"Adjust This Window's Level").handler(^(NSArray *strings) { - targetWindow = window; oldLevel = window.windowLevel; - window.windowLevel = flex.windowLevel + strings.firstObject.integerValue; - - [self showRevertOrDismissAlert:^{ targetWindow.windowLevel = oldLevel; }]; - }); - make.button(@"Set This Window's Level").handler(^(NSArray *strings) { - targetWindow = window; oldLevel = window.windowLevel; - window.windowLevel = strings.firstObject.integerValue; - - [self showRevertOrDismissAlert:^{ targetWindow.windowLevel = oldLevel; }]; - }); - make.button(@"Make Key And Visible").handler(^(NSArray *strings) { - oldKeyWindow = UIApplication.sharedApplication.keyWindow; - wasVisible = window.hidden; - [window makeKeyAndVisible]; - - [self showRevertOrDismissAlert:^{ - window.hidden = wasVisible; - [oldKeyWindow makeKeyWindow]; - }]; - }).enabled(!window.isKeyWindow && !window.hidden); - make.button(@"Cancel").cancelStyle().handler(cancelHandler); - - make.textField(@"+/- window level, i.e. 5 or -10"); - } showFrom:self]; -} - -- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)ip { - [self.navigationController pushViewController: - [FLEXObjectExplorerFactory explorerViewControllerForObject:self.sections[ip.section][ip.row]] - animated:YES]; -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabList.h b/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabList.h deleted file mode 100644 index 24f2154..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabList.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// FLEXTabList.h -// FLEX -// -// Created by Tanner on 2/1/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXTabList : NSObject - -@property (nonatomic, readonly, class) FLEXTabList *sharedList; - -@property (nonatomic, readonly, nullable) UINavigationController *activeTab; -@property (nonatomic, readonly) NSArray *openTabs; -/// Snapshots of each tab when they were last active. -@property (nonatomic, readonly) NSArray *openTabSnapshots; -/// \c NSNotFound if no tabs are present. -/// Setting this property changes the active tab to one of the already open tabs. -@property (nonatomic) NSInteger activeTabIndex; - -/// Adds a new tab and sets the new tab as the active tab. -- (void)addTab:(UINavigationController *)newTab; -/// Closes the given tab. If this tab was the active tab, -/// the most recent tab before that becomes the active tab. -- (void)closeTab:(UINavigationController *)tab; -/// Closes a tab at the given index. If this tab was the active tab, -/// the most recent tab before that becomes the active tab. -- (void)closeTabAtIndex:(NSInteger)idx; -/// Closes all of the tabs at the given indexes. If the active tab -/// is included, the most recent still-open tab becomes the active tab. -- (void)closeTabsAtIndexes:(NSIndexSet *)indexes; -/// A shortcut to close the active tab. -- (void)closeActiveTab; -/// A shortcut to close \e every tab. -- (void)closeAllTabs; - -- (void)updateSnapshotForActiveTab; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabList.m b/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabList.m deleted file mode 100644 index cb4f006..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabList.m +++ /dev/null @@ -1,133 +0,0 @@ -// -// FLEXTabList.m -// FLEX -// -// Created by Tanner on 2/1/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTabList.h" -#import "FLEXUtility.h" - -@interface FLEXTabList () { - NSMutableArray *_openTabs; - NSMutableArray *_openTabSnapshots; -} -@end -#pragma mark - -@implementation FLEXTabList - -#pragma mark Initialization - -+ (FLEXTabList *)sharedList { - static FLEXTabList *sharedList = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedList = [self new]; - }); - - return sharedList; -} - -- (id)init { - self = [super init]; - if (self) { - _openTabs = [NSMutableArray new]; - _openTabSnapshots = [NSMutableArray new]; - _activeTabIndex = NSNotFound; - } - - return self; -} - - -#pragma mark Private - -- (void)chooseNewActiveTab { - if (self.openTabs.count) { - self.activeTabIndex = self.openTabs.count - 1; - } else { - self.activeTabIndex = NSNotFound; - } -} - - -#pragma mark Public - -- (void)setActiveTabIndex:(NSInteger)idx { - NSParameterAssert(idx < self.openTabs.count || idx == NSNotFound); - if (_activeTabIndex == idx) return; - - _activeTabIndex = idx; - _activeTab = (idx == NSNotFound) ? nil : self.openTabs[idx]; -} - -- (void)addTab:(UINavigationController *)newTab { - NSParameterAssert(newTab); - - // Update snapshot of the last active tab - if (self.activeTab) { - [self updateSnapshotForActiveTab]; - } - - // Add new tab and snapshot, - // update active tab and index - [_openTabs addObject:newTab]; - [_openTabSnapshots addObject:[FLEXUtility previewImageForView:newTab.view]]; - _activeTab = newTab; - _activeTabIndex = self.openTabs.count - 1; -} - -- (void)closeTab:(UINavigationController *)tab { - NSParameterAssert(tab); - NSInteger idx = [self.openTabs indexOfObject:tab]; - if (idx != NSNotFound) { - [self closeTabAtIndex:idx]; - } -} - -- (void)closeTabAtIndex:(NSInteger)idx { - NSParameterAssert(idx < self.openTabs.count); - - // Remove old tab and snapshot - [_openTabs removeObjectAtIndex:idx]; - [_openTabSnapshots removeObjectAtIndex:idx]; - - // Update active tab and index if needed - if (self.activeTabIndex == idx) { - [self chooseNewActiveTab]; - } -} - -- (void)closeTabsAtIndexes:(NSIndexSet *)indexes { - // Remove old tabs and snapshot - [_openTabs removeObjectsAtIndexes:indexes]; - [_openTabSnapshots removeObjectsAtIndexes:indexes]; - - // Update active tab and index if needed - if ([indexes containsIndex:self.activeTabIndex]) { - [self chooseNewActiveTab]; - } -} - -- (void)closeActiveTab { - [self closeTab:self.activeTab]; -} - -- (void)closeAllTabs { - // Remove tabs and snapshots - [_openTabs removeAllObjects]; - [_openTabSnapshots removeAllObjects]; - - // Update active tab index - self.activeTabIndex = NSNotFound; -} - -- (void)updateSnapshotForActiveTab { - if (self.activeTabIndex != NSNotFound) { - UIImage *newSnapshot = [FLEXUtility previewImageForView:self.activeTab.view]; - [_openTabSnapshots replaceObjectAtIndex:self.activeTabIndex withObject:newSnapshot]; - } -} - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabsViewController.h b/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabsViewController.h deleted file mode 100644 index f288a0a..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabsViewController.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXTabsViewController.h -// FLEX -// -// Created by Tanner on 2/4/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" - -@interface FLEXTabsViewController : FLEXTableViewController - -@end diff --git a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabsViewController.m b/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabsViewController.m deleted file mode 100644 index 9f22046..0000000 --- a/Tweaks/FLEX/ExplorerInterface/Tabs/FLEXTabsViewController.m +++ /dev/null @@ -1,335 +0,0 @@ -// -// FLEXTabsViewController.m -// FLEX -// -// Created by Tanner on 2/4/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTabsViewController.h" -#import "FLEXNavigationController.h" -#import "FLEXTabList.h" -#import "FLEXBookmarkManager.h" -#import "FLEXTableView.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" -#import "UIBarButtonItem+FLEX.h" -#import "FLEXExplorerViewController.h" -#import "FLEXGlobalsViewController.h" -#import "FLEXBookmarksViewController.h" - -@interface FLEXTabsViewController () -@property (nonatomic, copy) NSArray *openTabs; -@property (nonatomic, copy) NSArray *tabSnapshots; -@property (nonatomic) NSInteger activeIndex; -@property (nonatomic) BOOL presentNewActiveTabOnDismiss; - -@property (nonatomic, readonly) FLEXExplorerViewController *corePresenter; -@end - -@implementation FLEXTabsViewController - -#pragma mark - Initialization - -- (id)init { - return [self initWithStyle:UITableViewStylePlain]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = @"Open Tabs"; - self.navigationController.hidesBarsOnSwipe = NO; - self.tableView.allowsMultipleSelectionDuringEditing = YES; - - [self reloadData:NO]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [self setupDefaultBarItems]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - // Instead of updating the active snapshot before we present, - // we update it after we present to avoid pre-presenation latency - dispatch_async(dispatch_get_main_queue(), ^{ - [FLEXTabList.sharedList updateSnapshotForActiveTab]; - [self reloadData:NO]; - [self.tableView reloadData]; - }); -} - - -#pragma mark - Private - -/// @param trackActiveTabDelta whether to check if the active -/// tab changed and needs to be presented upon "Done" dismissal. -/// @return whether the active tab changed or not (if there are any tabs left) -- (BOOL)reloadData:(BOOL)trackActiveTabDelta { - BOOL activeTabDidChange = NO; - FLEXTabList *list = FLEXTabList.sharedList; - - // Flag to enable check to determine whether - if (trackActiveTabDelta) { - NSInteger oldActiveIndex = self.activeIndex; - if (oldActiveIndex != list.activeTabIndex && list.activeTabIndex != NSNotFound) { - self.presentNewActiveTabOnDismiss = YES; - activeTabDidChange = YES; - } else if (self.presentNewActiveTabOnDismiss) { - // If we had something to present before, now we don't - // (i.e. activeTabIndex == NSNotFound) - self.presentNewActiveTabOnDismiss = NO; - } - } - - // We assume the tabs aren't going to change out from under us, since - // presenting any other tool via keyboard shortcuts should dismiss us first - self.openTabs = list.openTabs; - self.tabSnapshots = list.openTabSnapshots; - self.activeIndex = list.activeTabIndex; - - return activeTabDidChange; -} - -- (void)reloadActiveTabRowIfChanged:(BOOL)activeTabChanged { - // Refresh the newly active tab row if needed - if (activeTabChanged) { - NSIndexPath *active = [NSIndexPath - indexPathForRow:self.activeIndex inSection:0 - ]; - [self.tableView reloadRowsAtIndexPaths:@[active] withRowAnimation:UITableViewRowAnimationNone]; - } -} - -- (void)setupDefaultBarItems { - self.navigationItem.rightBarButtonItem = FLEXBarButtonItemSystem(Done, self, @selector(dismissAnimated)); - self.toolbarItems = @[ - UIBarButtonItem.flex_fixedSpace, - UIBarButtonItem.flex_flexibleSpace, - FLEXBarButtonItemSystem(Add, self, @selector(addTabButtonPressed:)), - UIBarButtonItem.flex_flexibleSpace, - FLEXBarButtonItemSystem(Edit, self, @selector(toggleEditing)), - ]; - - // Disable editing if no tabs available - self.toolbarItems.lastObject.enabled = self.openTabs.count > 0; -} - -- (void)setupEditingBarItems { - self.navigationItem.rightBarButtonItem = nil; - self.toolbarItems = @[ - [UIBarButtonItem flex_itemWithTitle:@"Close All" target:self action:@selector(closeAllButtonPressed:)], - UIBarButtonItem.flex_flexibleSpace, - [UIBarButtonItem flex_disabledSystemItem:UIBarButtonSystemItemAdd], - UIBarButtonItem.flex_flexibleSpace, - // We use a non-system done item because we change its title dynamically - [UIBarButtonItem flex_doneStyleitemWithTitle:@"Done" target:self action:@selector(toggleEditing)] - ]; - - self.toolbarItems.firstObject.tintColor = FLEXColor.destructiveColor; -} - -- (FLEXExplorerViewController *)corePresenter { - // We must be presented by a FLEXExplorerViewController, or presented - // by another view controller that was presented by FLEXExplorerViewController - FLEXExplorerViewController *presenter = (id)self.presentingViewController; - presenter = (id)presenter.presentingViewController ?: presenter; - NSAssert( - [presenter isKindOfClass:[FLEXExplorerViewController class]], - @"The tabs view controller expects to be presented by the explorer controller" - ); - return presenter; -} - - -#pragma mark Button Actions - -- (void)dismissAnimated { - if (self.presentNewActiveTabOnDismiss) { - // The active tab was closed so we need to present the new one - UIViewController *activeTab = FLEXTabList.sharedList.activeTab; - FLEXExplorerViewController *presenter = self.corePresenter; - [presenter dismissViewControllerAnimated:YES completion:^{ - [presenter presentViewController:activeTab animated:YES completion:nil]; - }]; - } else if (self.activeIndex == NSNotFound) { - // The only tab was closed, so dismiss everything - [self.corePresenter dismissViewControllerAnimated:YES completion:nil]; - } else { - // Simple dismiss with the same active tab, only dismiss myself - [self dismissViewControllerAnimated:YES completion:nil]; - } -} - -- (void)toggleEditing { - NSArray *selected = self.tableView.indexPathsForSelectedRows; - self.editing = !self.editing; - - if (self.isEditing) { - [self setupEditingBarItems]; - } else { - [self setupDefaultBarItems]; - - // Get index set of tabs to close - NSMutableIndexSet *indexes = [NSMutableIndexSet new]; - for (NSIndexPath *ip in selected) { - [indexes addIndex:ip.row]; - } - - if (selected.count) { - // Close tabs and update data source - [FLEXTabList.sharedList closeTabsAtIndexes:indexes]; - BOOL activeTabChanged = [self reloadData:YES]; - - // Remove deleted rows - [self.tableView deleteRowsAtIndexPaths:selected withRowAnimation:UITableViewRowAnimationAutomatic]; - - // Refresh the newly active tab row if needed - [self reloadActiveTabRowIfChanged:activeTabChanged]; - } - } -} - -- (void)addTabButtonPressed:(UIBarButtonItem *)sender { - if (FLEXBookmarkManager.bookmarks.count) { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - make.title(@"New Tab"); - make.button(@"Main Menu").handler(^(NSArray *strings) { - [self addTabAndDismiss:[FLEXNavigationController - withRootViewController:[FLEXGlobalsViewController new] - ]]; - }); - make.button(@"Choose from Bookmarks").handler(^(NSArray *strings) { - [self presentViewController:[FLEXNavigationController - withRootViewController:[FLEXBookmarksViewController new] - ] animated:YES completion:nil]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; - } else { - // No bookmarks, just open the main menu - [self addTabAndDismiss:[FLEXNavigationController - withRootViewController:[FLEXGlobalsViewController new] - ]]; - } -} - -- (void)addTabAndDismiss:(UINavigationController *)newTab { - FLEXExplorerViewController *presenter = self.corePresenter; - [presenter dismissViewControllerAnimated:YES completion:^{ - [presenter presentViewController:newTab animated:YES completion:nil]; - }]; -} - -- (void)closeAllButtonPressed:(UIBarButtonItem *)sender { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - NSInteger count = self.openTabs.count; - NSString *title = FLEXPluralFormatString(count, @"Close %@ tabs", @"Close %@ tab"); - make.button(title).destructiveStyle().handler(^(NSArray *strings) { - [self closeAll]; - [self toggleEditing]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; -} - -- (void)closeAll { - NSInteger rowCount = self.openTabs.count; - - // Close tabs and update data source - [FLEXTabList.sharedList closeAllTabs]; - [self reloadData:YES]; - - // Delete rows from table view - NSArray *allRows = [NSArray flex_forEachUpTo:rowCount map:^id(NSUInteger row) { - return [NSIndexPath indexPathForRow:row inSection:0]; - }]; - [self.tableView deleteRowsAtIndexPaths:allRows withRowAnimation:UITableViewRowAnimationAutomatic]; -} - - -#pragma mark - Table View Data Source - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.openTabs.count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXDetailCell forIndexPath:indexPath]; - - UINavigationController *tab = self.openTabs[indexPath.row]; - cell.imageView.image = self.tabSnapshots[indexPath.row]; - cell.textLabel.text = tab.topViewController.title; - cell.detailTextLabel.text = FLEXPluralString(tab.viewControllers.count, @"pages", @"page"); - - if (!cell.tag) { - cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; - cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - cell.detailTextLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; - cell.tag = 1; - } - - if (indexPath.row == self.activeIndex) { - cell.backgroundColor = FLEXColor.secondaryBackgroundColor; - } else { - cell.backgroundColor = FLEXColor.primaryBackgroundColor; - } - - return cell; -} - - -#pragma mark - Table View Delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (self.editing) { - // Case: editing with multi-select - self.toolbarItems.lastObject.title = @"Close Selected"; - self.toolbarItems.lastObject.tintColor = FLEXColor.destructiveColor; - } else { - if (self.activeIndex == indexPath.row && self.corePresenter != self.presentingViewController) { - // Case: selected the already active tab - [self dismissAnimated]; - } else { - // Case: selected a different tab, - // or selected a tab when presented from the FLEX toolbar - FLEXTabList.sharedList.activeTabIndex = indexPath.row; - self.presentNewActiveTabOnDismiss = YES; - [self dismissAnimated]; - } - } -} - -- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { - NSParameterAssert(self.editing); - - if (tableView.indexPathsForSelectedRows.count == 0) { - self.toolbarItems.lastObject.title = @"Done"; - self.toolbarItems.lastObject.tintColor = self.view.tintColor; - } -} - -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; -} - -- (void)tableView:(UITableView *)table -commitEditingStyle:(UITableViewCellEditingStyle)edit -forRowAtIndexPath:(NSIndexPath *)indexPath { - NSParameterAssert(edit == UITableViewCellEditingStyleDelete); - - // Close tab and update data source - [FLEXTabList.sharedList closeTab:self.openTabs[indexPath.row]]; - BOOL activeTabChanged = [self reloadData:YES]; - - // Delete row from table view - [table deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; - - // Refresh the newly active tab row if needed - [self reloadActiveTabRowIfChanged:activeTabChanged]; -} - -@end diff --git a/Tweaks/FLEX/FLEX-Categories.h b/Tweaks/FLEX/FLEX-Categories.h deleted file mode 100644 index aa7f784..0000000 --- a/Tweaks/FLEX/FLEX-Categories.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FLEX-Categories.h -// FLEX -// -// Created by Tanner on 3/12/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIBarButtonItem+FLEX.h" -#import "CALayer+FLEX.h" -#import "UIFont+FLEX.h" -#import "UIGestureRecognizer+Blocks.h" -#import "UIPasteboard+FLEX.h" -#import "UIMenu+FLEX.h" -#import "UITextField+Range.h" - -#import "NSObject+FLEX_Reflection.h" -#import "NSArray+FLEX.h" -#import "NSUserDefaults+FLEX.h" -#import "NSTimer+FLEX.h" diff --git a/Tweaks/FLEX/FLEX-Core.h b/Tweaks/FLEX/FLEX-Core.h deleted file mode 100644 index db98641..0000000 --- a/Tweaks/FLEX/FLEX-Core.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// FLEX-Core.h -// FLEX -// -// Created by Tanner on 3/11/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" -#import "FLEXNavigationController.h" -#import "FLEXTableViewController.h" -#import "FLEXTableView.h" - -#import "FLEXSingleRowSection.h" -#import "FLEXTableViewSection.h" - -#import "FLEXCodeFontCell.h" -#import "FLEXSubtitleTableViewCell.h" -#import "FLEXTableViewCell.h" -#import "FLEXMultilineTableViewCell.h" -#import "FLEXKeyValueTableViewCell.h" - diff --git a/Tweaks/FLEX/FLEX-ObjectExploring.h b/Tweaks/FLEX/FLEX-ObjectExploring.h deleted file mode 100644 index 82773e5..0000000 --- a/Tweaks/FLEX/FLEX-ObjectExploring.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// FLEX-ObjectExploring.h -// FLEX -// -// Created by Tanner on 3/11/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectExplorerFactory.h" -#import "FLEXObjectExplorerViewController.h" - -#import "FLEXObjectExplorer.h" - -#import "FLEXShortcut.h" -#import "FLEXShortcutsSection.h" - -#import "FLEXCollectionContentSection.h" -#import "FLEXColorPreviewSection.h" -#import "FLEXDefaultsContentSection.h" -#import "FLEXMetadataSection.h" -#import "FLEXMutableListSection.h" -#import "FLEXObjectInfoSection.h" diff --git a/Tweaks/FLEX/FLEX-Runtime.h b/Tweaks/FLEX/FLEX-Runtime.h deleted file mode 100644 index 9fc8a69..0000000 --- a/Tweaks/FLEX/FLEX-Runtime.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// FLEX-Runtime.h -// FLEX -// -// Created by Tanner on 3/11/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjcInternal.h" -#import "FLEXRuntimeSafety.h" -#import "FLEXBlockDescription.h" -#import "FLEXTypeEncodingParser.h" - -#import "FLEXMirror.h" -#import "FLEXProtocol.h" -#import "FLEXProperty.h" -#import "FLEXIvar.h" -#import "FLEXMethodBase.h" -#import "FLEXMethod.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXRuntime+Compare.h" -#import "FLEXRuntime+UIKitHelpers.h" - -#import "FLEXProtocolBuilder.h" -#import "FLEXClassBuilder.h" diff --git a/Tweaks/FLEX/FLEX.h b/Tweaks/FLEX/FLEX.h deleted file mode 100644 index 6172068..0000000 --- a/Tweaks/FLEX/FLEX.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// FLEX.h -// FLEX -// -// Created by Eric Horacek on 7/18/15. -// Modified by Tanner Bennett on 3/12/20. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager.h" -#import "FLEXManager+Extensibility.h" -#import "FLEXManager+Networking.h" - -#import "FLEXExplorerToolbar.h" -#import "FLEXExplorerToolbarItem.h" -#import "FLEXGlobalsEntry.h" - -#import "FLEX-Core.h" -#import "FLEX-Runtime.h" -#import "FLEX-Categories.h" -#import "FLEX-ObjectExploring.h" - -#import "FLEXMacros.h" -#import "FLEXAlert.h" -#import "FLEXResources.h" diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.h deleted file mode 100644 index 3d9dd02..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// FLEXDBQueryRowCell.h -// FLEX -// -// Created by Peng Tao on 15/11/24. -// Copyright © 2015年 f. All rights reserved. -// - -#import - -@class FLEXDBQueryRowCell; - -extern NSString * const kFLEXDBQueryRowCellReuse; - -@protocol FLEXDBQueryRowCellLayoutSource - -- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell minXForColumn:(NSUInteger)column; -- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell widthForColumn:(NSUInteger)column; - -@end - -@interface FLEXDBQueryRowCell : UITableViewCell - -/// An array of NSString, NSNumber, or NSData objects -@property (nonatomic) NSArray *data; -@property (nonatomic, weak) id layoutSource; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.m deleted file mode 100644 index 486cc98..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.m +++ /dev/null @@ -1,75 +0,0 @@ -// -// FLEXDBQueryRowCell.m -// FLEX -// -// Created by Peng Tao on 15/11/24. -// Copyright © 2015年 f. All rights reserved. -// - -#import "FLEXDBQueryRowCell.h" -#import "FLEXMultiColumnTableView.h" -#import "NSArray+FLEX.h" -#import "UIFont+FLEX.h" -#import "FLEXColor.h" - -NSString * const kFLEXDBQueryRowCellReuse = @"kFLEXDBQueryRowCellReuse"; - -@interface FLEXDBQueryRowCell () -@property (nonatomic) NSInteger columnCount; -@property (nonatomic) NSArray *labels; -@end - -@implementation FLEXDBQueryRowCell - -- (void)setData:(NSArray *)data { - _data = data; - self.columnCount = data.count; - - [self.labels flex_forEach:^(UILabel *label, NSUInteger idx) { - id content = self.data[idx]; - - if ([content isKindOfClass:[NSString class]]) { - label.text = content; - } else if (content == NSNull.null) { - label.text = @""; - label.textColor = FLEXColor.deemphasizedTextColor; - } else { - label.text = [content description]; - } - }]; -} - -- (void)setColumnCount:(NSInteger)columnCount { - if (columnCount != _columnCount) { - _columnCount = columnCount; - - // Remove existing labels - for (UILabel *l in self.labels) { - [l removeFromSuperview]; - } - - // Create new labels - self.labels = [NSArray flex_forEachUpTo:columnCount map:^id(NSUInteger i) { - UILabel *label = [UILabel new]; - label.font = UIFont.flex_defaultTableCellFont; - label.textAlignment = NSTextAlignmentLeft; - [self.contentView addSubview:label]; - - return label; - }]; - } -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGFloat height = self.contentView.frame.size.height; - - [self.labels flex_forEach:^(UILabel *label, NSUInteger i) { - CGFloat width = [self.layoutSource dbQueryRowCell:self widthForColumn:i]; - CGFloat minX = [self.layoutSource dbQueryRowCell:self minXForColumn:i]; - label.frame = CGRectMake(minX + 5, 0, (width - 10), height); - }]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h deleted file mode 100644 index c8e37b1..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// PTDatabaseManager.h -// Derived from: -// -// FMDatabase.h -// FMDB( https://github.com/ccgus/fmdb ) -// -// Created by Peng Tao on 15/11/23. -// -// Licensed to Flying Meat Inc. under one or more contributor license agreements. -// See the LICENSE file distributed with this work for the terms under -// which Flying Meat Inc. licenses this file to you. - -#import -#import "FLEXSQLResult.h" - -/// Conformers should automatically open and close the database -@protocol FLEXDatabaseManager - -@required - -/// @return \c nil if the database couldn't be opened -+ (instancetype)managerForDatabase:(NSString *)path; - -/// @return a list of all table names -- (NSArray *)queryAllTables; -- (NSArray *)queryAllColumnsOfTable:(NSString *)tableName; -- (NSArray *)queryAllDataInTable:(NSString *)tableName; - -@optional - -- (NSArray *)queryRowIDsInTable:(NSString *)tableName; -- (FLEXSQLResult *)executeStatement:(NSString *)SQLStatement; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.h deleted file mode 100644 index 15b9d0f..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// PTMultiColumnTableView.h -// PTMultiColumnTableViewDemo -// -// Created by Peng Tao on 15/11/16. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import -#import "FLEXTableColumnHeader.h" - -@class FLEXMultiColumnTableView; - -@protocol FLEXMultiColumnTableViewDelegate - -@required -- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didSelectRow:(NSInteger)row; -- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didSelectHeaderForColumn:(NSInteger)column sortType:(FLEXTableColumnHeaderSortType)sortType; - -@end - -@protocol FLEXMultiColumnTableViewDataSource - -@required - -- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView; -- (NSInteger)numberOfRowsInTableView:(FLEXMultiColumnTableView *)tableView; -- (NSString *)columnTitle:(NSInteger)column; -- (NSString *)rowTitle:(NSInteger)row; -- (NSArray *)contentForRow:(NSInteger)row; - -- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView minWidthForContentCellInColumn:(NSInteger)column; -- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView heightForContentCellInRow:(NSInteger)row; -- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView; -- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView; - -@end - - -@interface FLEXMultiColumnTableView : UIView - -@property (nonatomic, weak) id dataSource; -@property (nonatomic, weak) id delegate; - -- (void)reloadData; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m deleted file mode 100644 index 5f4116e..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.m +++ /dev/null @@ -1,339 +0,0 @@ -// -// PTMultiColumnTableView.m -// PTMultiColumnTableViewDemo -// -// Created by Peng Tao on 15/11/16. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import "FLEXMultiColumnTableView.h" -#import "FLEXDBQueryRowCell.h" -#import "FLEXTableLeftCell.h" -#import "NSArray+FLEX.h" -#import "FLEXColor.h" - -@interface FLEXMultiColumnTableView () < - UITableViewDataSource, UITableViewDelegate, - UIScrollViewDelegate, FLEXDBQueryRowCellLayoutSource -> - -@property (nonatomic) UIScrollView *contentScrollView; -@property (nonatomic) UIScrollView *headerScrollView; -@property (nonatomic) UITableView *leftTableView; -@property (nonatomic) UITableView *contentTableView; -@property (nonatomic) UIView *leftHeader; - -@property (nonatomic) NSArray *headerViews; - -/// \c NSNotFound if no column selected -@property (nonatomic) NSInteger sortColumn; -@property (nonatomic) FLEXTableColumnHeaderSortType sortType; - -@property (nonatomic, readonly) NSInteger numberOfColumns; -@property (nonatomic, readonly) NSInteger numberOfRows; -@property (nonatomic, readonly) CGFloat topHeaderHeight; -@property (nonatomic, readonly) CGFloat leftHeaderWidth; -@property (nonatomic, readonly) CGFloat columnMargin; - -@end - -static const CGFloat kColumnMargin = 1; - -@implementation FLEXMultiColumnTableView - -#pragma mark - Initialization - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.autoresizingMask |= UIViewAutoresizingFlexibleWidth; - self.autoresizingMask |= UIViewAutoresizingFlexibleHeight; - self.autoresizingMask |= UIViewAutoresizingFlexibleTopMargin; - self.backgroundColor = FLEXColor.groupedBackgroundColor; - - [self loadHeaderScrollView]; - [self loadContentScrollView]; - [self loadLeftView]; - } - - return self; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGFloat width = self.frame.size.width; - CGFloat height = self.frame.size.height; - CGFloat topheaderHeight = self.topHeaderHeight; - CGFloat leftHeaderWidth = self.leftHeaderWidth; - CGFloat topInsets = 0.f; - - if (@available (iOS 11.0, *)) { - topInsets = self.safeAreaInsets.top; - } - - CGFloat contentWidth = 0.0; - NSInteger columnsCount = self.numberOfColumns; - for (int i = 0; i < columnsCount; i++) { - contentWidth += CGRectGetWidth(self.headerViews[i].bounds); - } - - CGFloat contentHeight = height - topheaderHeight - topInsets; - - self.leftHeader.frame = CGRectMake(0, topInsets, self.leftHeaderWidth, self.topHeaderHeight); - self.leftTableView.frame = CGRectMake( - 0, topheaderHeight + topInsets, leftHeaderWidth, contentHeight - ); - self.headerScrollView.frame = CGRectMake( - leftHeaderWidth, topInsets, width - leftHeaderWidth, topheaderHeight - ); - self.headerScrollView.contentSize = CGSizeMake( - self.contentTableView.frame.size.width, self.headerScrollView.frame.size.height - ); - self.contentTableView.frame = CGRectMake( - 0, 0, contentWidth + self.numberOfColumns * self.columnMargin , contentHeight - ); - self.contentScrollView.frame = CGRectMake( - leftHeaderWidth, topheaderHeight + topInsets, width - leftHeaderWidth, contentHeight - ); - self.contentScrollView.contentSize = self.contentTableView.frame.size; -} - - -#pragma mark - UI - -- (void)loadHeaderScrollView { - UIScrollView *headerScrollView = [UIScrollView new]; - headerScrollView.delegate = self; - headerScrollView.backgroundColor = FLEXColor.secondaryGroupedBackgroundColor; - self.headerScrollView = headerScrollView; - - [self addSubview:headerScrollView]; -} - -- (void)loadContentScrollView { - UIScrollView *scrollView = [UIScrollView new]; - scrollView.bounces = NO; - scrollView.delegate = self; - - UITableView *tableView = [UITableView new]; - tableView.delegate = self; - tableView.dataSource = self; - tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - [tableView registerClass:[FLEXDBQueryRowCell class] - forCellReuseIdentifier:kFLEXDBQueryRowCellReuse - ]; - - [scrollView addSubview:tableView]; - [self addSubview:scrollView]; - - self.contentScrollView = scrollView; - self.contentTableView = tableView; -} - -- (void)loadLeftView { - UITableView *leftTableView = [UITableView new]; - leftTableView.delegate = self; - leftTableView.dataSource = self; - leftTableView.separatorStyle = UITableViewCellSeparatorStyleNone; - self.leftTableView = leftTableView; - [self addSubview:leftTableView]; - - UIView *leftHeader = [UIView new]; - leftHeader.backgroundColor = FLEXColor.secondaryBackgroundColor; - self.leftHeader = leftHeader; - [self addSubview:leftHeader]; -} - - -#pragma mark - Data - -- (void)reloadData { - [self loadHeaderData]; - [self loadLeftViewData]; - [self loadContentData]; -} - -- (void)loadHeaderData { - // Remove existing headers, if any - for (UIView *subview in self.headerViews) { - [subview removeFromSuperview]; - } - - __block CGFloat xOffset = 0; - - self.headerViews = [NSArray flex_forEachUpTo:self.numberOfColumns map:^id(NSUInteger column) { - FLEXTableColumnHeader *header = [FLEXTableColumnHeader new]; - header.titleLabel.text = [self columnTitle:column]; - - CGSize fittingSize = CGSizeMake(CGFLOAT_MAX, self.topHeaderHeight - 1); - CGFloat width = self.columnMargin + MAX( - [self minContentWidthForColumn:column], - [header sizeThatFits:fittingSize].width - ); - header.frame = CGRectMake(xOffset, 0, width, self.topHeaderHeight - 1); - - if (column == self.sortColumn) { - header.sortType = self.sortType; - } - - // Header tap gesture - UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(contentHeaderTap:) - ]; - [header addGestureRecognizer:gesture]; - header.userInteractionEnabled = YES; - - xOffset += width; - [self.headerScrollView addSubview:header]; - return header; - }]; -} - -- (void)contentHeaderTap:(UIGestureRecognizer *)gesture { - NSInteger newSortColumn = [self.headerViews indexOfObject:gesture.view]; - FLEXTableColumnHeaderSortType newType = FLEXNextTableColumnHeaderSortType(self.sortType); - - // Reset old header - FLEXTableColumnHeader *oldHeader = (id)self.headerViews[self.sortColumn]; - oldHeader.sortType = FLEXTableColumnHeaderSortTypeNone; - - // Update new header - FLEXTableColumnHeader *newHeader = (id)self.headerViews[newSortColumn]; - newHeader.sortType = newType; - - // Update self - self.sortColumn = newSortColumn; - self.sortType = newType; - - // Notify delegate - [self.delegate multiColumnTableView:self didSelectHeaderForColumn:newSortColumn sortType:newType]; -} - -- (void)loadContentData { - [self.contentTableView reloadData]; -} - -- (void)loadLeftViewData { - [self.leftTableView reloadData]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - // Alternating background color - UIColor *backgroundColor = FLEXColor.primaryBackgroundColor; - if (indexPath.row % 2 != 0) { - backgroundColor = FLEXColor.secondaryBackgroundColor; - } - - // Left side table view for row numbers - if (tableView == self.leftTableView) { - FLEXTableLeftCell *cell = [FLEXTableLeftCell cellWithTableView:tableView]; - cell.contentView.backgroundColor = backgroundColor; - cell.titlelabel.text = [self rowTitle:indexPath.row]; - return cell; - } - // Right side table view for data - else { - FLEXDBQueryRowCell *cell = [tableView - dequeueReusableCellWithIdentifier:kFLEXDBQueryRowCellReuse forIndexPath:indexPath - ]; - - cell.contentView.backgroundColor = backgroundColor; - cell.data = [self.dataSource contentForRow:indexPath.row]; - cell.layoutSource = self; - NSAssert(cell.data.count == self.numberOfColumns, @"Count of data provided was incorrect"); - return cell; - } -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.dataSource numberOfRowsInTableView:self]; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return [self.dataSource multiColumnTableView:self heightForContentCellInRow:indexPath.row]; -} - -// Scroll all scroll views in sync -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - if (scrollView == self.contentScrollView) { - self.headerScrollView.contentOffset = scrollView.contentOffset; - } - else if (scrollView == self.headerScrollView) { - self.contentScrollView.contentOffset = scrollView.contentOffset; - } - else if (scrollView == self.leftTableView) { - self.contentTableView.contentOffset = scrollView.contentOffset; - } - else if (scrollView == self.contentTableView) { - self.leftTableView.contentOffset = scrollView.contentOffset; - } -} - - -#pragma mark UITableView Delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (tableView == self.leftTableView) { - [self.contentTableView - selectRowAtIndexPath:indexPath - animated:NO - scrollPosition:UITableViewScrollPositionNone - ]; - } - else if (tableView == self.contentTableView) { - [self.delegate multiColumnTableView:self didSelectRow:indexPath.row]; - } -} - - -#pragma mark FLEXDBQueryRowCellLayoutSource - -- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell minXForColumn:(NSUInteger)column { - return CGRectGetMinX(self.headerViews[column].frame); -} - -- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell widthForColumn:(NSUInteger)column { - return CGRectGetWidth(self.headerViews[column].bounds); -} - - -#pragma mark DataSource Accessor - -- (NSInteger)numberOfRows { - return [self.dataSource numberOfRowsInTableView:self]; -} - -- (NSInteger)numberOfColumns { - return [self.dataSource numberOfColumnsInTableView:self]; -} - -- (NSString *)columnTitle:(NSInteger)column { - return [self.dataSource columnTitle:column]; -} - -- (NSString *)rowTitle:(NSInteger)row { - return [self.dataSource rowTitle:row]; -} - -- (CGFloat)minContentWidthForColumn:(NSInteger)column { - return [self.dataSource multiColumnTableView:self minWidthForContentCellInColumn:column]; -} - -- (CGFloat)contentHeightForRow:(NSInteger)row { - return [self.dataSource multiColumnTableView:self heightForContentCellInRow:row]; -} - -- (CGFloat)topHeaderHeight { - return [self.dataSource heightForTopHeaderInTableView:self]; -} - -- (CGFloat)leftHeaderWidth { - return [self.dataSource widthForLeftHeaderInTableView:self]; -} - -- (CGFloat)columnMargin { - return kColumnMargin; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.h deleted file mode 100644 index 44c78fb..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXRealmDatabaseManager.h -// FLEX -// -// Created by Tim Oliver on 28/01/2016. -// Copyright © 2016 Realm. All rights reserved. -// - -#import -#import "FLEXDatabaseManager.h" - -@interface FLEXRealmDatabaseManager : NSObject - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m deleted file mode 100644 index d7da829..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.m +++ /dev/null @@ -1,102 +0,0 @@ -// -// FLEXRealmDatabaseManager.m -// FLEX -// -// Created by Tim Oliver on 28/01/2016. -// Copyright © 2016 Realm. All rights reserved. -// - -#import "FLEXRealmDatabaseManager.h" -#import "NSArray+FLEX.h" -#import "FLEXSQLResult.h" - -#if __has_include() -#import -#import -#else -#import "FLEXRealmDefines.h" -#endif - -@interface FLEXRealmDatabaseManager () - -@property (nonatomic, copy) NSString *path; -@property (nonatomic) RLMRealm *realm; - -@end - -@implementation FLEXRealmDatabaseManager -static Class RLMRealmClass = nil; - -+ (void)load { - RLMRealmClass = NSClassFromString(@"RLMRealm"); -} - -+ (instancetype)managerForDatabase:(NSString *)path { - return [[self alloc] initWithPath:path]; -} - -- (instancetype)initWithPath:(NSString *)path { - if (!RLMRealmClass) { - return nil; - } - - self = [super init]; - if (self) { - _path = path; - - if (![self open]) { - return nil; - } - } - - return self; -} - -- (BOOL)open { - Class configurationClass = NSClassFromString(@"RLMRealmConfiguration"); - if (!RLMRealmClass || !configurationClass) { - return NO; - } - - NSError *error = nil; - id configuration = [configurationClass new]; - [(RLMRealmConfiguration *)configuration setFileURL:[NSURL fileURLWithPath:self.path]]; - self.realm = [RLMRealmClass realmWithConfiguration:configuration error:&error]; - - return (error == nil); -} - -- (NSArray *)queryAllTables { - // Map each schema to its name - NSArray *tableNames = [self.realm.schema.objectSchema flex_mapped:^id(RLMObjectSchema *schema, NSUInteger idx) { - return schema.className ?: nil; - }]; - - return [tableNames sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; -} - -- (NSArray *)queryAllColumnsOfTable:(NSString *)tableName { - RLMObjectSchema *objectSchema = [self.realm.schema schemaForClassName:tableName]; - // Map each column to its name - return [objectSchema.properties flex_mapped:^id(RLMProperty *property, NSUInteger idx) { - return property.name; - }]; -} - -- (NSArray *)queryAllDataInTable:(NSString *)tableName { - RLMObjectSchema *objectSchema = [self.realm.schema schemaForClassName:tableName]; - RLMResults *results = [self.realm allObjects:tableName]; - if (results.count == 0 || !objectSchema) { - return nil; - } - - // Map results to an array of rows - return [NSArray flex_mapped:results block:^id(RLMObject *result, NSUInteger idx) { - // Map each row to an array of the values of its properties - return [objectSchema.properties flex_mapped:^id(RLMProperty *property, NSUInteger idx) { - return [result valueForKey:property.name] ?: NSNull.null; - }]; - }]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDefines.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDefines.h deleted file mode 100644 index 992429a..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDefines.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Realm.h -// FLEX -// -// Created by Tim Oliver on 16/02/2016. -// Copyright © 2016 Realm. All rights reserved. -// - -#if __has_include() -#else - -@class RLMObject, RLMResults, RLMRealm, RLMRealmConfiguration, RLMSchema, RLMObjectSchema, RLMProperty; - -@interface RLMRealmConfiguration : NSObject -@property (nonatomic, copy) NSURL *fileURL; -@end - -@interface RLMRealm : NSObject -@property (nonatomic, readonly) RLMSchema *schema; -+ (RLMRealm *)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error; -- (RLMResults *)allObjects:(NSString *)className; -@end - -@interface RLMSchema : NSObject -@property (nonatomic, readonly) NSArray *objectSchema; -- (RLMObjectSchema *)schemaForClassName:(NSString *)className; -@end - -@interface RLMObjectSchema : NSObject -@property (nonatomic, readonly) NSString *className; -@property (nonatomic, readonly) NSArray *properties; -@end - -@interface RLMProperty : NSString -@property (nonatomic, readonly) NSString *name; -@end - -@interface RLMResults : NSObject -@property (nonatomic, readonly) NSInteger count; -@end - -@interface RLMObject : NSObject - -@end - -#endif diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h deleted file mode 100644 index 4fece3a..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// FLEXSQLResult.h -// FLEX -// -// Created by Tanner on 3/3/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXSQLResult : NSObject - -/// Describes the result of a non-select query, or an error of any kind of query -+ (instancetype)message:(NSString *)message; -/// Describes the result of a known failed execution -+ (instancetype)error:(NSString *)message; - -/// @param rowData A list of rows, where each element in the row -/// corresponds to the column given in /c columnNames -+ (instancetype)columns:(NSArray *)columnNames - rows:(NSArray *> *)rowData; - -@property (nonatomic, readonly, nullable) NSString *message; - -/// A value of YES means this is surely an error, -/// but it still might be an error even with a value of NO -@property (nonatomic, readonly) BOOL isError; - -/// A list of column names -@property (nonatomic, readonly, nullable) NSArray *columns; -/// A list of rows, where each element in the row corresponds -/// to the value of the column at the same index in \c columns. -/// -/// That is, given a row, looping over the contents of the row and -/// the contents of \c columns will give you key-value pairs of -/// column names to column values for that row. -@property (nonatomic, readonly, nullable) NSArray *> *rows; -/// A list of rows where the fields are paired to column names. -/// -/// This property is lazily constructed by looping over -/// the rows and columns present in the other two properties. -@property (nonatomic, readonly, nullable) NSArray *> *keyedRows; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.m deleted file mode 100644 index b4f6cb9..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.m +++ /dev/null @@ -1,53 +0,0 @@ -// -// FLEXSQLResult.m -// FLEX -// -// Created by Tanner on 3/3/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSQLResult.h" -#import "NSArray+FLEX.h" - -@implementation FLEXSQLResult -@synthesize keyedRows = _keyedRows; - -+ (instancetype)message:(NSString *)message { - return [[self alloc] initWithMessage:message columns:nil rows:nil]; -} - -+ (instancetype)error:(NSString *)message { - FLEXSQLResult *result = [self message:message]; - result->_isError = YES; - return result; -} - -+ (instancetype)columns:(NSArray *)columnNames rows:(NSArray *> *)rowData { - return [[self alloc] initWithMessage:nil columns:columnNames rows:rowData]; -} - -- (instancetype)initWithMessage:(NSString *)message columns:(NSArray *)columns rows:(NSArray *> *)rows { - NSParameterAssert(message || (columns && rows)); - NSParameterAssert(rows.count == 0 || columns.count == rows.firstObject.count); - - self = [super init]; - if (self) { - _message = message; - _columns = columns; - _rows = rows; - } - - return self; -} - -- (NSArray *> *)keyedRows { - if (!_keyedRows) { - _keyedRows = [self.rows flex_mapped:^id(NSArray *row, NSUInteger idx) { - return [NSDictionary dictionaryWithObjects:row forKeys:self.columns]; - }]; - } - - return _keyedRows; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.h deleted file mode 100644 index 50dc4cd..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// PTDatabaseManager.h -// Derived from: -// -// FMDatabase.h -// FMDB( https://github.com/ccgus/fmdb ) -// -// Created by Peng Tao on 15/11/23. -// -// Licensed to Flying Meat Inc. under one or more contributor license agreements. -// See the LICENSE file distributed with this work for the terms under -// which Flying Meat Inc. licenses this file to you. - -#import -#import "FLEXDatabaseManager.h" -#import "FLEXSQLResult.h" - -@interface FLEXSQLiteDatabaseManager : NSObject - -/// Contains the result of the last operation, which may be an error -@property (nonatomic, readonly) FLEXSQLResult *lastResult; -/// Calls into \c sqlite3_last_insert_rowid() -@property (nonatomic, readonly) NSInteger lastRowID; - -/// Given a statement like 'SELECT * from @table where @col = @val' and arguments -/// like { @"table": @"Album", @"col": @"year", @"val" @1 } this method will -/// invoke the statement and properly bind the given arguments to the statement. -/// -/// You may pass NSStrings, NSData, NSNumbers, or NSNulls as values. -- (FLEXSQLResult *)executeStatement:(NSString *)statement arguments:(NSDictionary *)args; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m deleted file mode 100644 index c67f613..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.m +++ /dev/null @@ -1,329 +0,0 @@ -// -// PTDatabaseManager.m -// PTDatabaseReader -// -// Created by Peng Tao on 15/11/23. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import "FLEXSQLiteDatabaseManager.h" -#import "FLEXManager.h" -#import "NSArray+FLEX.h" -#import "FLEXRuntimeConstants.h" -#import - -#define kQuery(name, str) static NSString * const QUERY_##name = str - -kQuery(TABLENAMES, @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"); -kQuery(ROWIDS, @"SELECT rowid FROM \"%@\" ORDER BY rowid ASC"); - -@interface FLEXSQLiteDatabaseManager () -@property (nonatomic) sqlite3 *db; -@property (nonatomic, copy) NSString *path; -@end - -@implementation FLEXSQLiteDatabaseManager - -#pragma mark - FLEXDatabaseManager - -+ (instancetype)managerForDatabase:(NSString *)path { - return [[self alloc] initWithPath:path]; -} - -- (instancetype)initWithPath:(NSString *)path { - self = [super init]; - if (self) { - self.path = path; - } - - return self; -} - -- (void)dealloc { - [self close]; -} - -- (BOOL)open { - if (self.db) { - return YES; - } - - int err = sqlite3_open(self.path.UTF8String, &_db); - -#if SQLITE_HAS_CODEC - NSString *defaultSqliteDatabasePassword = FLEXManager.sharedManager.defaultSqliteDatabasePassword; - if (defaultSqliteDatabasePassword) { - const char *key = defaultSqliteDatabasePassword.UTF8String; - sqlite3_key(_db, key, (int)strlen(key)); - } -#endif - - if (err != SQLITE_OK) { - return [self storeErrorForLastTask:@"Open"]; - } - - return YES; -} - -- (BOOL)close { - if (!self.db) { - return YES; - } - - int rc; - BOOL retry, triedFinalizingOpenStatements = NO; - - do { - retry = NO; - rc = sqlite3_close(_db); - if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) { - if (!triedFinalizingOpenStatements) { - triedFinalizingOpenStatements = YES; - sqlite3_stmt *pStmt; - while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) { - NSLog(@"Closing leaked statement"); - sqlite3_finalize(pStmt); - retry = YES; - } - } - } else if (SQLITE_OK != rc) { - [self storeErrorForLastTask:@"Close"]; - self.db = nil; - return NO; - } - } while (retry); - - self.db = nil; - return YES; -} - -- (NSInteger)lastRowID { - return (NSInteger)sqlite3_last_insert_rowid(self.db); -} - -- (NSArray *)queryAllTables { - return [[self executeStatement:QUERY_TABLENAMES].rows flex_mapped:^id(NSArray *table, NSUInteger idx) { - return table.firstObject; - }] ?: @[]; -} - -- (NSArray *)queryAllColumnsOfTable:(NSString *)tableName { - NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info('%@')",tableName]; - FLEXSQLResult *results = [self executeStatement:sql]; - - // https://github.com/FLEXTool/FLEX/issues/554 - if (!results.keyedRows.count) { - sql = [NSString stringWithFormat:@"SELECT * FROM pragma_table_info('%@')", tableName]; - results = [self executeStatement:sql]; - - // Fallback to empty query - if (!results.keyedRows.count) { - sql = [NSString stringWithFormat:@"SELECT * FROM \"%@\" where 0=1", tableName]; - return [self executeStatement:sql].columns ?: @[]; - } - } - - return [results.keyedRows flex_mapped:^id(NSDictionary *column, NSUInteger idx) { - return column[@"name"]; - }] ?: @[]; -} - -- (NSArray *)queryAllDataInTable:(NSString *)tableName { - NSString *command = [NSString stringWithFormat:@"SELECT * FROM \"%@\"", tableName]; - return [self executeStatement:command].rows ?: @[]; -} - -- (NSArray *)queryRowIDsInTable:(NSString *)tableName { - NSString *command = [NSString stringWithFormat:QUERY_ROWIDS, tableName]; - NSArray *> *data = [self executeStatement:command].rows ?: @[]; - - return [data flex_mapped:^id(NSArray *obj, NSUInteger idx) { - return obj.firstObject; - }]; -} - -- (FLEXSQLResult *)executeStatement:(NSString *)sql { - return [self executeStatement:sql arguments:nil]; -} - -- (FLEXSQLResult *)executeStatement:(NSString *)sql arguments:(NSDictionary *)args { - [self open]; - - FLEXSQLResult *result = nil; - - sqlite3_stmt *pstmt; - int status; - if ((status = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &pstmt, 0)) == SQLITE_OK) { - NSMutableArray *rows = [NSMutableArray new]; - - // Bind parameters, if any - if (![self bindParameters:args toStatement:pstmt]) { - return self.lastResult; - } - - // Grab columns (columnCount will be 0 for insert/update/delete) - int columnCount = sqlite3_column_count(pstmt); - NSArray *columns = [NSArray flex_forEachUpTo:columnCount map:^id(NSUInteger i) { - return @(sqlite3_column_name(pstmt, (int)i)); - }]; - - // Execute statement - while ((status = sqlite3_step(pstmt)) == SQLITE_ROW) { - // Grab rows if this is a selection query - int dataCount = sqlite3_data_count(pstmt); - if (dataCount > 0) { - [rows addObject:[NSArray flex_forEachUpTo:columnCount map:^id(NSUInteger i) { - return [self objectForColumnIndex:(int)i stmt:pstmt]; - }]]; - } - } - - if (status == SQLITE_DONE) { - // columnCount will be 0 for insert/update/delete - if (rows.count || columnCount > 0) { - // We executed a SELECT query - result = _lastResult = [FLEXSQLResult columns:columns rows:rows]; - } else { - // We executed a query like INSERT, UDPATE, or DELETE - int rowsAffected = sqlite3_changes(_db); - NSString *message = [NSString stringWithFormat:@"%d row(s) affected", rowsAffected]; - result = _lastResult = [FLEXSQLResult message:message]; - } - } else { - // An error occured executing the query - result = _lastResult = [self errorResult:@"Execution"]; - } - } else { - // An error occurred creating the prepared statement - result = _lastResult = [self errorResult:@"Prepared statement"]; - } - - sqlite3_finalize(pstmt); - return result; -} - - -#pragma mark - Private - -/// @return YES on success, NO if an error was encountered and stored in \c lastResult -- (BOOL)bindParameters:(NSDictionary *)args toStatement:(sqlite3_stmt *)pstmt { - for (NSString *param in args.allKeys) { - int status = SQLITE_OK, idx = sqlite3_bind_parameter_index(pstmt, param.UTF8String); - id value = args[param]; - - if (idx == 0) { - // No parameter matching that arg - @throw NSInternalInconsistencyException; - } - - // Null - if ([value isKindOfClass:[NSNull class]]) { - status = sqlite3_bind_null(pstmt, idx); - } - // String params - else if ([value isKindOfClass:[NSString class]]) { - const char *str = [value UTF8String]; - status = sqlite3_bind_text(pstmt, idx, str, (int)strlen(str), SQLITE_TRANSIENT); - } - // Data params - else if ([value isKindOfClass:[NSData class]]) { - const void *blob = [value bytes]; - status = sqlite3_bind_blob64(pstmt, idx, blob, [value length], SQLITE_TRANSIENT); - } - // Primitive params - else if ([value isKindOfClass:[NSNumber class]]) { - FLEXTypeEncoding type = [value objCType][0]; - switch (type) { - case FLEXTypeEncodingCBool: - case FLEXTypeEncodingChar: - case FLEXTypeEncodingUnsignedChar: - case FLEXTypeEncodingShort: - case FLEXTypeEncodingUnsignedShort: - case FLEXTypeEncodingInt: - case FLEXTypeEncodingUnsignedInt: - case FLEXTypeEncodingLong: - case FLEXTypeEncodingUnsignedLong: - case FLEXTypeEncodingLongLong: - case FLEXTypeEncodingUnsignedLongLong: - status = sqlite3_bind_int64(pstmt, idx, (sqlite3_int64)[value longValue]); - break; - - case FLEXTypeEncodingFloat: - case FLEXTypeEncodingDouble: - status = sqlite3_bind_double(pstmt, idx, [value doubleValue]); - break; - - default: - @throw NSInternalInconsistencyException; - break; - } - } - // Unsupported type - else { - @throw NSInternalInconsistencyException; - } - - if (status != SQLITE_OK) { - return [self storeErrorForLastTask: - [NSString stringWithFormat:@"Binding param named '%@'", param] - ]; - } - } - - return YES; -} - -- (BOOL)storeErrorForLastTask:(NSString *)action { - _lastResult = [self errorResult:action]; - return NO; -} - -- (FLEXSQLResult *)errorResult:(NSString *)description { - const char *error = sqlite3_errmsg(_db); - NSString *message = error ? @(error) : [NSString - stringWithFormat:@"(%@: empty error)", description - ]; - - return [FLEXSQLResult error:message]; -} - -- (id)objectForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt*)stmt { - int columnType = sqlite3_column_type(stmt, columnIdx); - - switch (columnType) { - case SQLITE_INTEGER: - return @(sqlite3_column_int64(stmt, columnIdx)).stringValue; - case SQLITE_FLOAT: - return @(sqlite3_column_double(stmt, columnIdx)).stringValue; - case SQLITE_BLOB: - return [NSString stringWithFormat:@"Data (%@ bytes)", - @([self dataForColumnIndex:columnIdx stmt:stmt].length) - ]; - - default: - // Default to a string for everything else - return [self stringForColumnIndex:columnIdx stmt:stmt] ?: NSNull.null; - } -} - -- (NSString *)stringForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt { - if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || columnIdx < 0) { - return nil; - } - - const char *text = (const char *)sqlite3_column_text(stmt, columnIdx); - return text ? @(text) : nil; -} - -- (NSData *)dataForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt { - if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { - return nil; - } - - const void *blob = sqlite3_column_blob(stmt, columnIdx); - NSInteger size = (NSInteger)sqlite3_column_bytes(stmt, columnIdx); - - return blob ? [NSData dataWithBytes:blob length:size] : nil; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h deleted file mode 100644 index 474a870..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// FLEXTableContentHeaderCell.h -// FLEX -// -// Created by Peng Tao on 15/11/26. -// Copyright © 2015年 f. All rights reserved. -// - -#import - -typedef NS_ENUM(NSUInteger, FLEXTableColumnHeaderSortType) { - FLEXTableColumnHeaderSortTypeNone = 0, - FLEXTableColumnHeaderSortTypeAsc, - FLEXTableColumnHeaderSortTypeDesc, -}; - -NS_INLINE FLEXTableColumnHeaderSortType FLEXNextTableColumnHeaderSortType( - FLEXTableColumnHeaderSortType current) { - switch (current) { - case FLEXTableColumnHeaderSortTypeAsc: - return FLEXTableColumnHeaderSortTypeDesc; - case FLEXTableColumnHeaderSortTypeNone: - case FLEXTableColumnHeaderSortTypeDesc: - return FLEXTableColumnHeaderSortTypeAsc; - } - - return FLEXTableColumnHeaderSortTypeNone; -} - -@interface FLEXTableColumnHeader : UIView - -@property (nonatomic) NSInteger index; -@property (nonatomic, readonly) UILabel *titleLabel; - -@property (nonatomic) FLEXTableColumnHeaderSortType sortType; - -@end - diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m deleted file mode 100644 index 9adaec4..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.m +++ /dev/null @@ -1,78 +0,0 @@ -// -// FLEXTableContentHeaderCell.m -// FLEX -// -// Created by Peng Tao on 15/11/26. -// Copyright © 2015年 f. All rights reserved. -// - -#import "FLEXTableColumnHeader.h" -#import "FLEXColor.h" -#import "UIFont+FLEX.h" -#import "FLEXUtility.h" - -static const CGFloat kMargin = 5; -static const CGFloat kArrowWidth = 20; - -@interface FLEXTableColumnHeader () -@property (nonatomic, readonly) UILabel *arrowLabel; -@property (nonatomic, readonly) UIView *lineView; -@end - -@implementation FLEXTableColumnHeader - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.backgroundColor = FLEXColor.secondaryBackgroundColor; - - _titleLabel = [UILabel new]; - _titleLabel.font = UIFont.flex_defaultTableCellFont; - [self addSubview:_titleLabel]; - - _arrowLabel = [UILabel new]; - _arrowLabel.font = UIFont.flex_defaultTableCellFont; - [self addSubview:_arrowLabel]; - - _lineView = [UIView new]; - _lineView.backgroundColor = FLEXColor.hairlineColor; - [self addSubview:_lineView]; - - } - return self; -} - -- (void)setSortType:(FLEXTableColumnHeaderSortType)type { - _sortType = type; - - switch (type) { - case FLEXTableColumnHeaderSortTypeNone: - _arrowLabel.text = @""; - break; - case FLEXTableColumnHeaderSortTypeAsc: - _arrowLabel.text = @"⬆️"; - break; - case FLEXTableColumnHeaderSortTypeDesc: - _arrowLabel.text = @"⬇️"; - break; - } -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGSize size = self.frame.size; - - self.titleLabel.frame = CGRectMake(kMargin, 0, size.width - kArrowWidth - kMargin, size.height); - self.arrowLabel.frame = CGRectMake(size.width - kArrowWidth, 0, kArrowWidth, size.height); - self.lineView.frame = CGRectMake(size.width - 1, 2, FLEXPointsToPixels(1), size.height - 4); -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat margins = kArrowWidth - 2 * kMargin; - size = CGSizeMake(size.width - margins, size.height); - CGFloat width = [_titleLabel sizeThatFits:size].width + margins; - return CGSizeMake(width, size.height); -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h deleted file mode 100644 index f0149f0..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// PTTableContentViewController.h -// PTDatabaseReader -// -// Created by Peng Tao on 15/11/23. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import -#import "FLEXDatabaseManager.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXTableContentViewController : UIViewController - -/// Display a mutable table with the given columns, rows, and name. -/// -/// @param columnNames self explanatory. -/// @param rowData an array of rows, where each row is an array of column data. -/// @param rowIDs an array of stringy row IDs. Required for deleting rows. -/// @param tableName an optional name of the table being viewed, if any. Enables adding rows. -/// @param databaseManager an optional manager to allow modifying the table. -/// Required for deleting rows. Required for adding rows if \c tableName is supplied. -+ (instancetype)columns:(NSArray *)columnNames - rows:(NSArray *> *)rowData - rowIDs:(NSArray *)rowIDs - tableName:(NSString *)tableName - database:(id)databaseManager; - -/// Display an immutable table with the given columns and rows. -+ (instancetype)columns:(NSArray *)columnNames - rows:(NSArray *> *)rowData; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m deleted file mode 100755 index b311166..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableContentViewController.m +++ /dev/null @@ -1,359 +0,0 @@ -// -// PTTableContentViewController.m -// PTDatabaseReader -// -// Created by Peng Tao on 15/11/23. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import "FLEXTableContentViewController.h" -#import "FLEXTableRowDataViewController.h" -#import "FLEXMultiColumnTableView.h" -#import "FLEXWebViewController.h" -#import "FLEXUtility.h" -#import "UIBarButtonItem+FLEX.h" - -@interface FLEXTableContentViewController () < - FLEXMultiColumnTableViewDataSource, FLEXMultiColumnTableViewDelegate -> -@property (nonatomic, readonly) NSArray *columns; -@property (nonatomic) NSMutableArray *rows; -@property (nonatomic, readonly) NSString *tableName; -@property (nonatomic, nullable) NSMutableArray *rowIDs; -@property (nonatomic, readonly, nullable) id databaseManager; - -@property (nonatomic, readonly) BOOL canRefresh; - -@property (nonatomic) FLEXMultiColumnTableView *multiColumnView; -@end - -@implementation FLEXTableContentViewController - -+ (instancetype)columns:(NSArray *)columnNames - rows:(NSArray *> *)rowData - rowIDs:(NSArray *)rowIDs - tableName:(NSString *)tableName - database:(id)databaseManager { - return [[self alloc] - initWithColumns:columnNames - rows:rowData - rowIDs:rowIDs - tableName:tableName - database:databaseManager - ]; -} - -+ (instancetype)columns:(NSArray *)cols - rows:(NSArray *> *)rowData { - return [[self alloc] initWithColumns:cols rows:rowData rowIDs:nil tableName:nil database:nil]; -} - -- (instancetype)initWithColumns:(NSArray *)columnNames - rows:(NSArray *> *)rowData - rowIDs:(nullable NSArray *)rowIDs - tableName:(nullable NSString *)tableName - database:(nullable id)databaseManager { - // Must supply all optional parameters as one, or none - BOOL all = rowIDs && tableName && databaseManager; - BOOL none = !rowIDs && !tableName && !databaseManager; - NSParameterAssert(all || none); - - self = [super init]; - if (self) { - self->_columns = columnNames.copy; - self->_rows = rowData.mutableCopy; - self->_rowIDs = rowIDs.mutableCopy; - self->_tableName = tableName.copy; - self->_databaseManager = databaseManager; - } - - return self; -} - -- (void)loadView { - [super loadView]; - - [self.view addSubview:self.multiColumnView]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - self.title = self.tableName; - [self.multiColumnView reloadData]; - [self setupToolbarItems]; -} - -- (FLEXMultiColumnTableView *)multiColumnView { - if (!_multiColumnView) { - _multiColumnView = [[FLEXMultiColumnTableView alloc] - initWithFrame:FLEXRectSetSize(CGRectZero, self.view.frame.size) - ]; - - _multiColumnView.dataSource = self; - _multiColumnView.delegate = self; - } - - return _multiColumnView; -} - -- (BOOL)canRefresh { - return self.databaseManager && self.tableName; -} - -#pragma mark MultiColumnTableView DataSource - -- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView { - return self.columns.count; -} - -- (NSInteger)numberOfRowsInTableView:(FLEXMultiColumnTableView *)tableView { - return self.rows.count; -} - -- (NSString *)columnTitle:(NSInteger)column { - return self.columns[column]; -} - -- (NSString *)rowTitle:(NSInteger)row { - return @(row).stringValue; -} - -- (NSArray *)contentForRow:(NSInteger)row { - return self.rows[row]; -} - -- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView - heightForContentCellInRow:(NSInteger)row { - return 40; -} - -- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView - minWidthForContentCellInColumn:(NSInteger)column { - return 100; -} - -- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView { - return 40; -} - -- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView { - NSString *str = [NSString stringWithFormat:@"%lu",(unsigned long)self.rows.count]; - NSDictionary *attrs = @{ NSFontAttributeName : [UIFont systemFontOfSize:17.0] }; - CGSize size = [str boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 14) - options:NSStringDrawingUsesLineFragmentOrigin - attributes:attrs context:nil - ].size; - - return size.width + 20; -} - - -#pragma mark MultiColumnTableView Delegate - -- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didSelectRow:(NSInteger)row { - NSArray *fields = [self.rows[row] flex_mapped:^id(NSString *field, NSUInteger idx) { - return [NSString stringWithFormat:@"%@:\n%@", self.columns[idx], field]; - }]; - - NSArray *values = [self.rows[row] flex_mapped:^id(NSString *value, NSUInteger idx) { - return [NSString stringWithFormat:@"'%@'", value]; - }]; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title([@"Row " stringByAppendingString:@(row).stringValue]); - NSString *message = [fields componentsJoinedByString:@"\n\n"]; - make.message(message); - make.button(@"Copy").handler(^(NSArray *strings) { - UIPasteboard.generalPasteboard.string = message; - }); - make.button(@"Copy as CSV").handler(^(NSArray *strings) { - UIPasteboard.generalPasteboard.string = [values componentsJoinedByString:@", "]; - }); - make.button(@"Focus on Row").handler(^(NSArray *strings) { - UIViewController *focusedRow = [FLEXTableRowDataViewController - rows:[NSDictionary dictionaryWithObjects:self.rows[row] forKeys:self.columns] - ]; - [self.navigationController pushViewController:focusedRow animated:YES]; - }); - - // Option to delete row - BOOL hasRowID = self.rows.count && row < self.rows.count; - if (hasRowID && self.canRefresh) { - make.button(@"Delete").destructiveStyle().handler(^(NSArray *strings) { - NSString *deleteRow = [NSString stringWithFormat: - @"DELETE FROM %@ WHERE rowid = %@", - self.tableName, self.rowIDs[row] - ]; - - [self executeStatementAndShowResult:deleteRow completion:^(BOOL success) { - // Remove deleted row and reload view - if (success) { - [self reloadTableDataFromDB]; - } - }]; - }); - } - - make.button(@"Dismiss").cancelStyle(); - } showFrom:self]; -} - -- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView - didSelectHeaderForColumn:(NSInteger)column - sortType:(FLEXTableColumnHeaderSortType)sortType { - - NSArray *sortContentData = [self.rows - sortedArrayWithOptions:NSSortStable - usingComparator:^NSComparisonResult(NSArray *obj1, NSArray *obj2) { - id a = obj1[column], b = obj2[column]; - if (a == NSNull.null) { - return NSOrderedAscending; - } - if (b == NSNull.null) { - return NSOrderedDescending; - } - - if ([a respondsToSelector:@selector(compare:options:)] && - [b respondsToSelector:@selector(compare:options:)]) { - return [a compare:b options:NSNumericSearch]; - } - - if ([a respondsToSelector:@selector(compare:)] && [b respondsToSelector:@selector(compare:)]) { - return [a compare:b]; - } - - return NSOrderedSame; - } - ]; - - if (sortType == FLEXTableColumnHeaderSortTypeDesc) { - sortContentData = sortContentData.reverseObjectEnumerator.allObjects.copy; - } - - self.rows = sortContentData.mutableCopy; - [self.multiColumnView reloadData]; -} - -#pragma mark - About Transition - -- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection - withTransitionCoordinator:(id )coordinator { - [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator]; - - [coordinator animateAlongsideTransition:^(id context) { - if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) { - self.multiColumnView.frame = CGRectMake(0, 32, self.view.frame.size.width, self.view.frame.size.height - 32); - } - else { - self.multiColumnView.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64); - } - - [self.view setNeedsLayout]; - } completion:nil]; -} - -#pragma mark - Toolbar - -- (void)setupToolbarItems { - // We do not support modifying realm databases - if (![self.databaseManager respondsToSelector:@selector(executeStatement:)]) { - return; - } - - UIBarButtonItem *trashButton = FLEXBarButtonItemSystem(Trash, self, @selector(trashPressed)); - UIBarButtonItem *addButton = FLEXBarButtonItemSystem(Add, self, @selector(addPressed)); - - // Only allow adding rows or deleting rows if we have a table name - trashButton.enabled = self.canRefresh; - addButton.enabled = self.canRefresh; - - self.toolbarItems = @[ - UIBarButtonItem.flex_flexibleSpace, - addButton, - UIBarButtonItem.flex_flexibleSpace, - [trashButton flex_withTintColor:UIColor.redColor], - ]; -} - -- (void)trashPressed { - NSParameterAssert(self.tableName); - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Delete All Rows"); - make.message(@"All rows in this table will be permanently deleted.\nDo you want to proceed?"); - - make.button(@"Yes, I'm sure").destructiveStyle().handler(^(NSArray *strings) { - NSString *deleteAll = [NSString stringWithFormat:@"DELETE FROM %@", self.tableName]; - [self executeStatementAndShowResult:deleteAll completion:^(BOOL success) { - // Only dismiss on success - if (success) { - [self.navigationController popViewControllerAnimated:YES]; - } - }]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; -} - -- (void)addPressed { - NSParameterAssert(self.tableName); - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Add a New Row"); - make.message(@"Comma separate values to use in an INSERT statement.\n\n"); - make.message(@"INSERT INTO [table] VALUES (your_input)"); - make.textField(@"5, 'John Smith', 14,..."); - make.button(@"Insert").handler(^(NSArray *strings) { - NSString *statement = [NSString stringWithFormat: - @"INSERT INTO %@ VALUES (%@)", self.tableName, strings[0] - ]; - - [self executeStatementAndShowResult:statement completion:^(BOOL success) { - if (success) { - [self reloadTableDataFromDB]; - } - }]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; -} - -#pragma mark - Helpers - -- (void)executeStatementAndShowResult:(NSString *)statement - completion:(void (^_Nullable)(BOOL success))completion { - NSParameterAssert(self.databaseManager); - - FLEXSQLResult *result = [self.databaseManager executeStatement:statement]; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - if (result.isError) { - make.title(@"Error"); - } - - make.message(result.message ?: @""); - make.button(@"Dismiss").cancelStyle().handler(^(NSArray *_) { - if (completion) { - completion(!result.isError); - } - }); - } showFrom:self]; -} - -- (void)reloadTableDataFromDB { - if (!self.canRefresh) { - return; - } - - NSArray *rows = [self.databaseManager queryAllDataInTable:self.tableName]; - NSArray *rowIDs = nil; - if ([self.databaseManager respondsToSelector:@selector(queryRowIDsInTable:)]) { - rowIDs = [self.databaseManager queryRowIDsInTable:self.tableName]; - } - - self.rows = rows.mutableCopy; - self.rowIDs = rowIDs.mutableCopy; - [self.multiColumnView reloadData]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h deleted file mode 100644 index e351072..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXTableLeftCell.h -// FLEX -// -// Created by Peng Tao on 15/11/24. -// Copyright © 2015年 f. All rights reserved. -// - -#import - -@interface FLEXTableLeftCell : UITableViewCell - -@property (nonatomic) UILabel *titlelabel; - -+ (instancetype)cellWithTableView:(UITableView *)tableView; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m deleted file mode 100644 index b99404e..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.m +++ /dev/null @@ -1,33 +0,0 @@ -// -// FLEXTableLeftCell.m -// FLEX -// -// Created by Peng Tao on 15/11/24. -// Copyright © 2015年 f. All rights reserved. -// - -#import "FLEXTableLeftCell.h" - -@implementation FLEXTableLeftCell - -+ (instancetype)cellWithTableView:(UITableView *)tableView { - static NSString *identifier = @"FLEXTableLeftCell"; - FLEXTableLeftCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; - - if (!cell) { - cell = [[FLEXTableLeftCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; - UILabel *textLabel = [UILabel new]; - textLabel.textAlignment = NSTextAlignmentCenter; - textLabel.font = [UIFont systemFontOfSize:13.0]; - [cell.contentView addSubview:textLabel]; - cell.titlelabel = textLabel; - } - - return cell; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - self.titlelabel.frame = self.contentView.frame; -} -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.h deleted file mode 100644 index b866202..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// PTTableListViewController.h -// PTDatabaseReader -// -// Created by Peng Tao on 15/11/23. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" - -@interface FLEXTableListViewController : FLEXFilteringTableViewController - -+ (BOOL)supportsExtension:(NSString *)extension; -- (instancetype)initWithPath:(NSString *)path; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m deleted file mode 100644 index 28dba39..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableListViewController.m +++ /dev/null @@ -1,165 +0,0 @@ -// -// PTTableListViewController.m -// PTDatabaseReader -// -// Created by Peng Tao on 15/11/23. -// Copyright © 2015年 Peng Tao. All rights reserved. -// - -#import "FLEXTableListViewController.h" -#import "FLEXDatabaseManager.h" -#import "FLEXSQLiteDatabaseManager.h" -#import "FLEXRealmDatabaseManager.h" -#import "FLEXTableContentViewController.h" -#import "FLEXMutableListSection.h" -#import "NSArray+FLEX.h" -#import "FLEXAlert.h" -#import "FLEXMacros.h" - -@interface FLEXTableListViewController () -@property (nonatomic, readonly) id dbm; -@property (nonatomic, readonly) NSString *path; - -@property (nonatomic, readonly) FLEXMutableListSection *tables; - -+ (NSArray *)supportedSQLiteExtensions; -+ (NSArray *)supportedRealmExtensions; - -@end - -@implementation FLEXTableListViewController - -- (instancetype)initWithPath:(NSString *)path { - self = [super initWithStyle:UITableViewStyleGrouped]; - if (self) { - _path = path.copy; - _dbm = [self databaseManagerForFileAtPath:path]; - } - - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsSearchBar = YES; - - // Compose query button // - - UIBarButtonItem *composeQuery = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemCompose - target:self - action:@selector(queryButtonPressed) - ]; - // Cannot run custom queries on realm databases - composeQuery.enabled = [self.dbm - respondsToSelector:@selector(executeStatement:) - ]; - - [self addToolbarItems:@[composeQuery]]; -} - -- (NSArray *)makeSections { - _tables = [FLEXMutableListSection list:[self.dbm queryAllTables] - cellConfiguration:^(__kindof UITableViewCell *cell, NSString *tableName, NSInteger row) { - cell.textLabel.text = tableName; - } filterMatcher:^BOOL(NSString *filterText, NSString *tableName) { - return [tableName localizedCaseInsensitiveContainsString:filterText]; - } - ]; - - self.tables.selectionHandler = ^(FLEXTableListViewController *host, NSString *tableName) { - NSArray *rows = [host.dbm queryAllDataInTable:tableName]; - NSArray *columns = [host.dbm queryAllColumnsOfTable:tableName]; - NSArray *rowIDs = nil; - if ([host.dbm respondsToSelector:@selector(queryRowIDsInTable:)]) { - rowIDs = [host.dbm queryRowIDsInTable:tableName]; - } - UIViewController *resultsScreen = [FLEXTableContentViewController - columns:columns rows:rows rowIDs:rowIDs tableName:tableName database:host.dbm - ]; - [host.navigationController pushViewController:resultsScreen animated:YES]; - }; - - return @[self.tables]; -} - -- (void)reloadData { - self.tables.customTitle = [NSString - stringWithFormat:@"Tables (%@)", @(self.tables.filteredList.count) - ]; - - [super reloadData]; -} - -- (void)queryButtonPressed { - FLEXSQLiteDatabaseManager *database = self.dbm; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Execute an SQL query"); - make.textField(nil); - make.button(@"Run").handler(^(NSArray *strings) { - FLEXSQLResult *result = [database executeStatement:strings[0]]; - - if (result.message) { - [FLEXAlert showAlert:@"Message" message:result.message from:self]; - } else { - UIViewController *resultsScreen = [FLEXTableContentViewController - columns:result.columns rows:result.rows - ]; - - [self.navigationController pushViewController:resultsScreen animated:YES]; - } - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; -} - -- (id)databaseManagerForFileAtPath:(NSString *)path { - NSString *pathExtension = path.pathExtension.lowercaseString; - - NSArray *sqliteExtensions = FLEXTableListViewController.supportedSQLiteExtensions; - if ([sqliteExtensions indexOfObject:pathExtension] != NSNotFound) { - return [FLEXSQLiteDatabaseManager managerForDatabase:path]; - } - - NSArray *realmExtensions = FLEXTableListViewController.supportedRealmExtensions; - if (realmExtensions != nil && [realmExtensions indexOfObject:pathExtension] != NSNotFound) { - return [FLEXRealmDatabaseManager managerForDatabase:path]; - } - - return nil; -} - - -#pragma mark - FLEXTableListViewController - -+ (BOOL)supportsExtension:(NSString *)extension { - extension = extension.lowercaseString; - - NSArray *sqliteExtensions = FLEXTableListViewController.supportedSQLiteExtensions; - if (sqliteExtensions.count > 0 && [sqliteExtensions indexOfObject:extension] != NSNotFound) { - return YES; - } - - NSArray *realmExtensions = FLEXTableListViewController.supportedRealmExtensions; - if (realmExtensions.count > 0 && [realmExtensions indexOfObject:extension] != NSNotFound) { - return YES; - } - - return NO; -} - -+ (NSArray *)supportedSQLiteExtensions { - return @[@"db", @"sqlite", @"sqlite3"]; -} - -+ (NSArray *)supportedRealmExtensions { - if (NSClassFromString(@"RLMRealm") == nil) { - return nil; - } - - return @[@"realm"]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableRowDataViewController.h b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableRowDataViewController.h deleted file mode 100644 index 56aad7e..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableRowDataViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXTableRowDataViewController.h -// FLEX -// -// Created by Chaoshuai Lu on 7/8/20. -// - -#import "FLEXFilteringTableViewController.h" - -@interface FLEXTableRowDataViewController : FLEXFilteringTableViewController - -+ (instancetype)rows:(NSDictionary *)rowData; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableRowDataViewController.m b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableRowDataViewController.m deleted file mode 100644 index f4f7939..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/FLEXTableRowDataViewController.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// FLEXTableRowDataViewController.m -// FLEX -// -// Created by Chaoshuai Lu on 7/8/20. -// - -#import "FLEXTableRowDataViewController.h" -#import "FLEXMutableListSection.h" -#import "FLEXAlert.h" - -@interface FLEXTableRowDataViewController () -@property (nonatomic) NSDictionary *rowsByColumn; -@end - -@implementation FLEXTableRowDataViewController - -#pragma mark - Initialization - -+ (instancetype)rows:(NSDictionary *)rowData { - FLEXTableRowDataViewController *controller = [self new]; - controller.rowsByColumn = rowData; - return controller; -} - -#pragma mark - Overrides - -- (NSArray *)makeSections { - NSDictionary *rowsByColumn = self.rowsByColumn; - - FLEXMutableListSection *section = [FLEXMutableListSection list:self.rowsByColumn.allKeys - cellConfiguration:^(UITableViewCell *cell, NSString *column, NSInteger row) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = column; - cell.detailTextLabel.text = rowsByColumn[column].description; - } filterMatcher:^BOOL(NSString *filterText, NSString *column) { - return [column localizedCaseInsensitiveContainsString:filterText] || - [rowsByColumn[column] localizedCaseInsensitiveContainsString:filterText]; - } - ]; - - section.selectionHandler = ^(UIViewController *host, NSString *column) { - UIPasteboard.generalPasteboard.string = rowsByColumn[column].description; - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Column Copied to Clipboard"); - make.message(rowsByColumn[column].description); - make.button(@"Dismiss").cancelStyle(); - } showFrom:host]; - }; - - return @[section]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/LICENSE b/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/LICENSE deleted file mode 100644 index fad3577..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/DatabaseBrowser/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - -FMDB -Copyright (c) 2008-2014 Flying Meat Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXAddressExplorerCoordinator.h b/Tweaks/FLEX/GlobalStateExplorers/FLEXAddressExplorerCoordinator.h deleted file mode 100644 index 16d9401..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXAddressExplorerCoordinator.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXAddressExplorerCoordinator.h -// FLEX -// -// Created by Tanner Bennett on 7/10/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsEntry.h" - -@interface FLEXAddressExplorerCoordinator : NSObject - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m b/Tweaks/FLEX/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m deleted file mode 100644 index 7835668..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXAddressExplorerCoordinator.m +++ /dev/null @@ -1,95 +0,0 @@ -// -// FLEXAddressExplorerCoordinator.m -// FLEX -// -// Created by Tanner Bennett on 7/10/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXAddressExplorerCoordinator.h" -#import "FLEXGlobalsViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXUtility.h" - -@interface UITableViewController (FLEXAddressExploration) -- (void)deselectSelectedRow; -- (void)tryExploreAddress:(NSString *)addressString safely:(BOOL)safely; -@end - -@implementation FLEXAddressExplorerCoordinator - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"🔎 Address Explorer"; -} - -+ (FLEXGlobalsEntryRowAction)globalsEntryRowAction:(FLEXGlobalsRow)row { - return ^(UITableViewController *host) { - - NSString *title = @"Explore Object at Address"; - NSString *message = @"Paste a hexadecimal address below, starting with '0x'. " - "Use the unsafe option if you need to bypass pointer validation, " - "but know that it may crash the app if the address is invalid."; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(title).message(message); - make.configuredTextField(^(UITextField *textField) { - NSString *copied = UIPasteboard.generalPasteboard.string; - textField.placeholder = @"0x00000070deadbeef"; - // Go ahead and paste our clipboard if we have an address copied - if ([copied hasPrefix:@"0x"]) { - textField.text = copied; - [textField selectAll:nil]; - } - }); - make.button(@"Explore").handler(^(NSArray *strings) { - [host tryExploreAddress:strings.firstObject safely:YES]; - }); - make.button(@"Unsafe Explore").destructiveStyle().handler(^(NSArray *strings) { - [host tryExploreAddress:strings.firstObject safely:NO]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:host]; - - }; -} - -@end - -@implementation UITableViewController (FLEXAddressExploration) - -- (void)deselectSelectedRow { - NSIndexPath *selected = self.tableView.indexPathForSelectedRow; - [self.tableView deselectRowAtIndexPath:selected animated:YES]; -} - -- (void)tryExploreAddress:(NSString *)addressString safely:(BOOL)safely { - NSScanner *scanner = [NSScanner scannerWithString:addressString]; - unsigned long long hexValue = 0; - BOOL didParseAddress = [scanner scanHexLongLong:&hexValue]; - const void *pointerValue = (void *)hexValue; - - NSString *error = nil; - - if (didParseAddress) { - if (safely && ![FLEXRuntimeUtility pointerIsValidObjcObject:pointerValue]) { - error = @"The given address is unlikely to be a valid object."; - } - } else { - error = @"Malformed address. Make sure it's not too long and starts with '0x'."; - } - - if (!error) { - id object = (__bridge id)pointerValue; - FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:object]; - [self.navigationController pushViewController:explorer animated:YES]; - } else { - [FLEXAlert showAlert:@"Uh-oh" message:error from:self]; - [self deselectSelectedRow]; - } -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXCookiesViewController.h b/Tweaks/FLEX/GlobalStateExplorers/FLEXCookiesViewController.h deleted file mode 100644 index 40bdaba..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXCookiesViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXCookiesViewController.h -// FLEX -// -// Created by Rich Robinson on 19/10/2015. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsEntry.h" -#import "FLEXFilteringTableViewController.h" - -@interface FLEXCookiesViewController : FLEXFilteringTableViewController - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXCookiesViewController.m b/Tweaks/FLEX/GlobalStateExplorers/FLEXCookiesViewController.m deleted file mode 100644 index 886d902..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXCookiesViewController.m +++ /dev/null @@ -1,76 +0,0 @@ -// -// FLEXCookiesViewController.m -// FLEX -// -// Created by Rich Robinson on 19/10/2015. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXCookiesViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXMutableListSection.h" -#import "FLEXUtility.h" - -@interface FLEXCookiesViewController () -@property (nonatomic, readonly) FLEXMutableListSection *cookies; -@property (nonatomic) NSString *headerTitle; -@end - -@implementation FLEXCookiesViewController - -#pragma mark - Overrides - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = @"Cookies"; -} - -- (NSArray *)makeSections { - NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] - initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:) - ]; - NSArray *cookies = [NSHTTPCookieStorage.sharedHTTPCookieStorage.cookies - sortedArrayUsingDescriptors:@[nameSortDescriptor] - ]; - - _cookies = [FLEXMutableListSection list:cookies - cellConfiguration:^(UITableViewCell *cell, NSHTTPCookie *cookie, NSInteger row) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = [cookie.name stringByAppendingFormat:@" (%@)", cookie.value]; - cell.detailTextLabel.text = [cookie.domain stringByAppendingFormat:@" — %@", cookie.path]; - } filterMatcher:^BOOL(NSString *filterText, NSHTTPCookie *cookie) { - return [cookie.name localizedCaseInsensitiveContainsString:filterText] || - [cookie.value localizedCaseInsensitiveContainsString:filterText] || - [cookie.domain localizedCaseInsensitiveContainsString:filterText] || - [cookie.path localizedCaseInsensitiveContainsString:filterText]; - } - ]; - - self.cookies.selectionHandler = ^(UIViewController *host, NSHTTPCookie *cookie) { - [host.navigationController pushViewController:[ - FLEXObjectExplorerFactory explorerViewControllerForObject:cookie - ] animated:YES]; - }; - - return @[self.cookies]; -} - -- (void)reloadData { - self.headerTitle = [NSString stringWithFormat: - @"%@ cookies", @(self.cookies.filteredList.count) - ]; - [super reloadData]; -} - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"🍪 Cookies"; -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - return [self new]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXLiveObjectsController.h b/Tweaks/FLEX/GlobalStateExplorers/FLEXLiveObjectsController.h deleted file mode 100644 index a406077..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXLiveObjectsController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXLiveObjectsController.h -// Flipboard -// -// Created by Ryan Olson on 5/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" -#import "FLEXGlobalsEntry.h" - -@interface FLEXLiveObjectsController : FLEXTableViewController - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXLiveObjectsController.m b/Tweaks/FLEX/GlobalStateExplorers/FLEXLiveObjectsController.m deleted file mode 100644 index fce0f8c..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXLiveObjectsController.m +++ /dev/null @@ -1,236 +0,0 @@ -// -// FLEXLiveObjectsController.m -// Flipboard -// -// Created by Ryan Olson on 5/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXLiveObjectsController.h" -#import "FLEXHeapEnumerator.h" -#import "FLEXObjectListViewController.h" -#import "FLEXUtility.h" -#import "FLEXScopeCarousel.h" -#import "FLEXTableView.h" -#import - -static const NSInteger kFLEXLiveObjectsSortAlphabeticallyIndex = 0; -static const NSInteger kFLEXLiveObjectsSortByCountIndex = 1; -static const NSInteger kFLEXLiveObjectsSortBySizeIndex = 2; - -@interface FLEXLiveObjectsController () - -@property (nonatomic) NSDictionary *instanceCountsForClassNames; -@property (nonatomic) NSDictionary *instanceSizesForClassNames; -@property (nonatomic, readonly) NSArray *allClassNames; -@property (nonatomic) NSArray *filteredClassNames; -@property (nonatomic) NSString *headerTitle; - -@end - -@implementation FLEXLiveObjectsController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsSearchBar = YES; - self.showSearchBarInitially = YES; - self.activatesSearchBarAutomatically = YES; - self.searchBarDebounceInterval = kFLEXDebounceInstant; - self.showsCarousel = YES; - self.carousel.items = @[@"A→Z", @"Count", @"Size"]; - - self.refreshControl = [UIRefreshControl new]; - [self.refreshControl addTarget:self action:@selector(refreshControlDidRefresh:) forControlEvents:UIControlEventValueChanged]; - - [self reloadTableData]; -} - -- (NSArray *)allClassNames { - return self.instanceCountsForClassNames.allKeys; -} - -- (void)reloadTableData { - // Set up a CFMutableDictionary with class pointer keys and NSUInteger values. - // We abuse CFMutableDictionary a little to have primitive keys through judicious casting, but it gets the job done. - // The dictionary is intialized with a 0 count for each class so that it doesn't have to expand during enumeration. - // While it might be a little cleaner to populate an NSMutableDictionary with class name string keys to NSNumber counts, - // we choose the CF/primitives approach because it lets us enumerate the objects in the heap without allocating any memory during enumeration. - // The alternative of creating one NSString/NSNumber per object on the heap ends up polluting the count of live objects quite a bit. - unsigned int classCount = 0; - Class *classes = objc_copyClassList(&classCount); - CFMutableDictionaryRef mutableCountsForClasses = CFDictionaryCreateMutable(NULL, classCount, NULL, NULL); - for (unsigned int i = 0; i < classCount; i++) { - CFDictionarySetValue(mutableCountsForClasses, (__bridge const void *)classes[i], (const void *)0); - } - - // Enumerate all objects on the heap to build the counts of instances for each class. - [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) { - NSUInteger instanceCount = (NSUInteger)CFDictionaryGetValue(mutableCountsForClasses, (__bridge const void *)actualClass); - instanceCount++; - CFDictionarySetValue(mutableCountsForClasses, (__bridge const void *)actualClass, (const void *)instanceCount); - }]; - - // Convert our CF primitive dictionary into a nicer mapping of class name strings to counts that we will use as the table's model. - NSMutableDictionary *mutableCountsForClassNames = [NSMutableDictionary new]; - NSMutableDictionary *mutableSizesForClassNames = [NSMutableDictionary new]; - for (unsigned int i = 0; i < classCount; i++) { - Class class = classes[i]; - NSUInteger instanceCount = (NSUInteger)CFDictionaryGetValue(mutableCountsForClasses, (__bridge const void *)(class)); - NSString *className = @(class_getName(class)); - if (instanceCount > 0) { - [mutableCountsForClassNames setObject:@(instanceCount) forKey:className]; - } - [mutableSizesForClassNames setObject:@(class_getInstanceSize(class)) forKey:className]; - } - free(classes); - - self.instanceCountsForClassNames = mutableCountsForClassNames; - self.instanceSizesForClassNames = mutableSizesForClassNames; - - [self updateSearchResults:nil]; -} - -- (void)refreshControlDidRefresh:(id)sender { - [self reloadTableData]; - [self.refreshControl endRefreshing]; -} - -- (void)updateHeaderTitle { - NSUInteger totalCount = 0; - NSUInteger totalSize = 0; - for (NSString *className in self.allClassNames) { - NSUInteger count = self.instanceCountsForClassNames[className].unsignedIntegerValue; - totalCount += count; - totalSize += count * self.instanceSizesForClassNames[className].unsignedIntegerValue; - } - - NSUInteger filteredCount = 0; - NSUInteger filteredSize = 0; - for (NSString *className in self.filteredClassNames) { - NSUInteger count = self.instanceCountsForClassNames[className].unsignedIntegerValue; - filteredCount += count; - filteredSize += count * self.instanceSizesForClassNames[className].unsignedIntegerValue; - } - - if (filteredCount == totalCount) { - // Unfiltered - self.headerTitle = [NSString - stringWithFormat:@"%@ objects, %@", - @(totalCount), [NSByteCountFormatter - stringFromByteCount:totalSize - countStyle:NSByteCountFormatterCountStyleFile - ] - ]; - } else { - self.headerTitle = [NSString - stringWithFormat:@"%@ of %@ objects, %@", - @(filteredCount), @(totalCount), [NSByteCountFormatter - stringFromByteCount:filteredSize - countStyle:NSByteCountFormatterCountStyleFile - ] - ]; - } -} - - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"💩 Heap Objects"; -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - FLEXLiveObjectsController *liveObjectsViewController = [self new]; - liveObjectsViewController.title = [self globalsEntryTitle:row]; - - return liveObjectsViewController; -} - - -#pragma mark - Search bar - -- (void)updateSearchResults:(NSString *)filter { - NSInteger selectedScope = self.selectedScope; - - if (filter.length) { - NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", filter]; - self.filteredClassNames = [self.allClassNames filteredArrayUsingPredicate:searchPredicate]; - } else { - self.filteredClassNames = self.allClassNames; - } - - if (selectedScope == kFLEXLiveObjectsSortAlphabeticallyIndex) { - self.filteredClassNames = [self.filteredClassNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; - } else if (selectedScope == kFLEXLiveObjectsSortByCountIndex) { - self.filteredClassNames = [self.filteredClassNames sortedArrayUsingComparator:^NSComparisonResult(NSString *className1, NSString *className2) { - NSNumber *count1 = self.instanceCountsForClassNames[className1]; - NSNumber *count2 = self.instanceCountsForClassNames[className2]; - // Reversed for descending counts. - return [count2 compare:count1]; - }]; - } else if (selectedScope == kFLEXLiveObjectsSortBySizeIndex) { - self.filteredClassNames = [self.filteredClassNames sortedArrayUsingComparator:^NSComparisonResult(NSString *className1, NSString *className2) { - NSNumber *count1 = self.instanceCountsForClassNames[className1]; - NSNumber *count2 = self.instanceCountsForClassNames[className2]; - NSNumber *size1 = self.instanceSizesForClassNames[className1]; - NSNumber *size2 = self.instanceSizesForClassNames[className2]; - // Reversed for descending sizes. - return [@(count2.integerValue * size2.integerValue) compare:@(count1.integerValue * size1.integerValue)]; - }]; - } - - [self updateHeaderTitle]; - [self.tableView reloadData]; -} - - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.filteredClassNames.count; -} - -- (UITableViewCell *)tableView:(__kindof UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView - dequeueReusableCellWithIdentifier:kFLEXDefaultCell - forIndexPath:indexPath - ]; - - NSString *className = self.filteredClassNames[indexPath.row]; - NSNumber *count = self.instanceCountsForClassNames[className]; - NSNumber *size = self.instanceSizesForClassNames[className]; - unsigned long totalSize = count.unsignedIntegerValue * size.unsignedIntegerValue; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = [NSString stringWithFormat:@"%@ (%ld, %@)", - className, (long)[count integerValue], - [NSByteCountFormatter - stringFromByteCount:totalSize - countStyle:NSByteCountFormatterCountStyleFile - ] - ]; - - return cell; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return self.headerTitle; -} - - -#pragma mark - Table view delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *className = self.filteredClassNames[indexPath.row]; - UIViewController *instances = [FLEXObjectListViewController - instancesOfClassWithName:className - retained:YES - ]; - [self.navigationController pushViewController:instances animated:YES]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectListViewController.h b/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectListViewController.h deleted file mode 100644 index 5dc1985..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectListViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXObjectListViewController.h -// Flipboard -// -// Created by Ryan Olson on 5/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" - -@interface FLEXObjectListViewController : FLEXFilteringTableViewController - -/// This will either return a list of the instances, or take you straight -/// to the explorer itself if there is only one instance. -+ (UIViewController *)instancesOfClassWithName:(NSString *)className retained:(BOOL)retain; -+ (instancetype)subclassesOfClassWithName:(NSString *)className; -+ (instancetype)objectsWithReferencesToObject:(id)object retained:(BOOL)retain; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectListViewController.m b/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectListViewController.m deleted file mode 100644 index faa8f4b..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectListViewController.m +++ /dev/null @@ -1,250 +0,0 @@ -// -// FLEXObjectListViewController.m -// Flipboard -// -// Created by Ryan Olson on 5/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectListViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXMutableListSection.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXUtility.h" -#import "FLEXHeapEnumerator.h" -#import "FLEXObjectRef.h" -#import "NSString+FLEX.h" -#import "NSObject+FLEX_Reflection.h" -#import "FLEXTableViewCell.h" -#import - - -typedef NS_ENUM(NSUInteger, FLEXObjectReferenceSection) { - FLEXObjectReferenceSectionMain, - FLEXObjectReferenceSectionAutoLayout, - FLEXObjectReferenceSectionKVO, - FLEXObjectReferenceSectionFLEX, - - FLEXObjectReferenceSectionCount -}; - -@interface FLEXObjectListViewController () - -@property (nonatomic, readonly, class) NSArray *defaultPredicates; -@property (nonatomic, readonly, class) NSArray *defaultSectionTitles; - - -@property (nonatomic, copy) NSArray *sections; -@property (nonatomic, copy) NSArray *allSections; - -@property (nonatomic, readonly, nullable) NSArray *references; -@property (nonatomic, readonly) NSArray *predicates; -@property (nonatomic, readonly) NSArray *sectionTitles; - -@end - -@implementation FLEXObjectListViewController -@dynamic sections, allSections; - -#pragma mark - Reference Grouping - -+ (NSPredicate *)defaultPredicateForSection:(NSInteger)section { - // These are the types of references that we typically don't care about. - // We want this list of "object-ivar pairs" split into two sections. - BOOL(^isKVORelated)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) { - NSString *row = ref.reference; - return [row isEqualToString:@"__NSObserver object"] || - [row isEqualToString:@"_CFXNotificationObjcObserverRegistration _object"]; - }; - - /// These are common AutoLayout related references we also rarely care about. - BOOL(^isConstraintRelated)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) { - static NSSet *ignored = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - ignored = [NSSet setWithArray:@[ - @"NSLayoutConstraint _container", - @"NSContentSizeLayoutConstraint _container", - @"NSAutoresizingMaskLayoutConstraint _container", - @"MASViewConstraint _installedView", - @"MASLayoutConstraint _container", - @"MASViewAttribute _view" - ]]; - }); - - NSString *row = ref.reference; - return ([row hasPrefix:@"NSLayout"] && [row hasSuffix:@" _referenceItem"]) || - ([row hasPrefix:@"NSIS"] && [row hasSuffix:@" _delegate"]) || - ([row hasPrefix:@"_NSAutoresizingMask"] && [row hasSuffix:@" _referenceItem"]) || - [ignored containsObject:row]; - }; - - /// These are FLEX classes and usually you aren't looking for FLEX references inside FLEX itself - BOOL(^isFLEXClass)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) { - return [ref.reference hasPrefix:@"FLEX"]; - }; - - BOOL(^isEssential)(FLEXObjectRef *, NSDictionary *) = ^BOOL(FLEXObjectRef *ref, NSDictionary *bindings) { - return !( - isKVORelated(ref, bindings) || - isConstraintRelated(ref, bindings) || - isFLEXClass(ref, bindings) - ); - }; - - switch (section) { - case FLEXObjectReferenceSectionMain: - return [NSPredicate predicateWithBlock:isEssential]; - case FLEXObjectReferenceSectionAutoLayout: - return [NSPredicate predicateWithBlock:isConstraintRelated]; - case FLEXObjectReferenceSectionKVO: - return [NSPredicate predicateWithBlock:isKVORelated]; - case FLEXObjectReferenceSectionFLEX: - return [NSPredicate predicateWithBlock:isFLEXClass]; - - default: return nil; - } -} - -+ (NSArray *)defaultPredicates { - return [NSArray flex_forEachUpTo:FLEXObjectReferenceSectionCount map:^id(NSUInteger i) { - return [self defaultPredicateForSection:i]; - }]; -} - -+ (NSArray *)defaultSectionTitles { - return @[ - @"", @"AutoLayout", @"Key-Value Observing", @"FLEX" - ]; -} - - -#pragma mark - Initialization - -- (id)initWithReferences:(nullable NSArray *)references { - return [self initWithReferences:references predicates:nil sectionTitles:nil]; -} - -- (id)initWithReferences:(NSArray *)references - predicates:(NSArray *)predicates - sectionTitles:(NSArray *)sectionTitles { - NSParameterAssert(predicates.count == sectionTitles.count); - - self = [super initWithStyle:UITableViewStylePlain]; - if (self) { - _references = references; - _predicates = predicates; - _sectionTitles = sectionTitles; - } - - return self; -} - -+ (UIViewController *)instancesOfClassWithName:(NSString *)className retained:(BOOL)retain { - NSArray *references = [FLEXHeapEnumerator - instancesOfClassWithName:className retained:retain - ]; - - if (references.count == 1) { - return [FLEXObjectExplorerFactory - explorerViewControllerForObject:references.firstObject.object - ]; - } - - FLEXObjectListViewController *controller = [[self alloc] initWithReferences:references]; - controller.title = [NSString stringWithFormat:@"%@ (%@)", className, @(references.count)]; - return controller; -} - -+ (instancetype)subclassesOfClassWithName:(NSString *)className { - NSArray *references = [FLEXHeapEnumerator subclassesOfClassWithName:className]; - FLEXObjectListViewController *controller = [[self alloc] initWithReferences:references]; - controller.title = [NSString stringWithFormat:@"Subclasses of %@ (%@)", - className, @(references.count) - ]; - - return controller; -} - -+ (instancetype)objectsWithReferencesToObject:(id)object retained:(BOOL)retain { - static Class SwiftObjectClass = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - SwiftObjectClass = NSClassFromString(@"SwiftObject"); - if (!SwiftObjectClass) { - SwiftObjectClass = NSClassFromString(@"Swift._SwiftObject"); - } - }); - - NSArray *instances = [FLEXHeapEnumerator - objectsWithReferencesToObject:object retained:retain - ]; - - FLEXObjectListViewController *viewController = [[self alloc] - initWithReferences:instances - predicates:self.defaultPredicates - sectionTitles:self.defaultSectionTitles - ]; - viewController.title = [NSString stringWithFormat:@"Referencing %@ %p", - [FLEXRuntimeUtility safeClassNameForObject:object], object - ]; - return viewController; -} - - -#pragma mark - Overrides - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsSearchBar = YES; -} - -- (NSArray *)makeSections { - if (self.predicates.count) { - return [self buildSections:self.sectionTitles predicates:self.predicates]; - } else { - return @[[self makeSection:self.references title:nil]]; - } -} - - -#pragma mark - Private - -- (NSArray *)buildSections:(NSArray *)titles predicates:(NSArray *)predicates { - NSParameterAssert(titles.count == predicates.count); - NSParameterAssert(titles); NSParameterAssert(predicates); - - return [NSArray flex_forEachUpTo:titles.count map:^id(NSUInteger i) { - NSArray *rows = [self.references filteredArrayUsingPredicate:predicates[i]]; - return [self makeSection:rows title:titles[i]]; - }]; -} - -- (FLEXMutableListSection *)makeSection:(NSArray *)rows title:(NSString *)title { - FLEXMutableListSection *section = [FLEXMutableListSection list:rows - cellConfiguration:^(FLEXTableViewCell *cell, FLEXObjectRef *ref, NSInteger row) { - cell.textLabel.text = ref.reference; - cell.detailTextLabel.text = ref.summary; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } filterMatcher:^BOOL(NSString *filterText, FLEXObjectRef *ref) { - if (ref.summary && [ref.summary localizedCaseInsensitiveContainsString:filterText]) { - return YES; - } - - return [ref.reference localizedCaseInsensitiveContainsString:filterText]; - } - ]; - - section.selectionHandler = ^(UIViewController *host, FLEXObjectRef *ref) { - [host.navigationController pushViewController:[ - FLEXObjectExplorerFactory explorerViewControllerForObject:ref.object - ] animated:YES]; - }; - - section.customTitle = title; - return section; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectRef.h b/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectRef.h deleted file mode 100644 index 2de3c5e..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectRef.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// FLEXObjectRef.h -// FLEX -// -// Created by Tanner Bennett on 7/24/18. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXObjectRef : NSObject - -/// Reference an object without affecting its lifespan or or emitting reference-counting operations. -+ (instancetype)unretained:(__unsafe_unretained id)object; -+ (instancetype)unretained:(__unsafe_unretained id)object ivar:(NSString *)ivarName; - -/// Reference an object and control its lifespan. -+ (instancetype)retained:(id)object; -+ (instancetype)retained:(id)object ivar:(NSString *)ivarName; - -/// Reference an object and conditionally choose to retain it or not. -+ (instancetype)referencing:(__unsafe_unretained id)object retained:(BOOL)retain; -+ (instancetype)referencing:(__unsafe_unretained id)object ivar:(NSString *)ivarName retained:(BOOL)retain; - -+ (NSArray *)referencingAll:(NSArray *)objects retained:(BOOL)retain; -/// Classes do not have a summary, and the reference is just the class name. -+ (NSArray *)referencingClasses:(NSArray *)classes; - -/// For example, "NSString 0x1d4085d0" or "NSLayoutConstraint _object" -@property (nonatomic, readonly) NSString *reference; -/// For instances, this is the result of -[FLEXRuntimeUtility summaryForObject:] -/// For classes, there is no summary. -@property (nonatomic, readonly) NSString *summary; -@property (nonatomic, readonly, unsafe_unretained) id object; - -/// Retains the referenced object if it is not already retained -- (void)retainObject; -/// Releases the referenced object if it is already retained -- (void)releaseObject; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectRef.m b/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectRef.m deleted file mode 100644 index 925c89f..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXObjectRef.m +++ /dev/null @@ -1,112 +0,0 @@ -// -// FLEXObjectRef.m -// FLEX -// -// Created by Tanner Bennett on 7/24/18. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectRef.h" -#import "FLEXRuntimeUtility.h" -#import "NSArray+FLEX.h" - -@interface FLEXObjectRef () { - /// Used to retain the object if desired - id _retainer; -} -@property (nonatomic, readonly) BOOL wantsSummary; -@end - -@implementation FLEXObjectRef -@synthesize summary = _summary; - -+ (instancetype)unretained:(__unsafe_unretained id)object { - return [self referencing:object showSummary:YES retained:NO]; -} - -+ (instancetype)unretained:(__unsafe_unretained id)object ivar:(NSString *)ivarName { - return [[self alloc] initWithObject:object ivarName:ivarName showSummary:YES retained:NO]; -} - -+ (instancetype)retained:(id)object { - return [self referencing:object showSummary:YES retained:YES]; -} - -+ (instancetype)retained:(id)object ivar:(NSString *)ivarName { - return [[self alloc] initWithObject:object ivarName:ivarName showSummary:YES retained:YES]; -} - -+ (instancetype)referencing:(__unsafe_unretained id)object retained:(BOOL)retain { - return retain ? [self retained:object] : [self unretained:object]; -} - -+ (instancetype)referencing:(__unsafe_unretained id)object ivar:(NSString *)ivarName retained:(BOOL)retain { - return retain ? [self retained:object ivar:ivarName] : [self unretained:object ivar:ivarName]; -} - -+ (instancetype)referencing:(__unsafe_unretained id)object showSummary:(BOOL)showSummary retained:(BOOL)retain { - return [[self alloc] initWithObject:object ivarName:nil showSummary:showSummary retained:retain]; -} - -+ (NSArray *)referencingAll:(NSArray *)objects retained:(BOOL)retain { - return [objects flex_mapped:^id(id obj, NSUInteger idx) { - return [self referencing:obj showSummary:YES retained:retain]; - }]; -} - -+ (NSArray *)referencingClasses:(NSArray *)classes { - return [classes flex_mapped:^id(id obj, NSUInteger idx) { - return [self referencing:obj showSummary:NO retained:NO]; - }]; -} - -- (id)initWithObject:(__unsafe_unretained id)object - ivarName:(NSString *)ivar - showSummary:(BOOL)showSummary - retained:(BOOL)retain { - self = [super init]; - if (self) { - _object = object; - _wantsSummary = showSummary; - - if (retain) { - _retainer = object; - } - - NSString *class = [FLEXRuntimeUtility safeClassNameForObject:object]; - if (ivar) { - _reference = [NSString stringWithFormat:@"%@ %@", class, ivar]; - } else if (showSummary) { - _reference = [NSString stringWithFormat:@"%@ %p", class, object]; - } else { - _reference = class; - } - } - - return self; -} - -- (NSString *)summary { - if (self.wantsSummary) { - if (!_summary) { - _summary = [FLEXRuntimeUtility summaryForObject:self.object]; - } - - return _summary; - } - else { - return nil; - } -} - -- (void)retainObject { - if (!_retainer) { - _retainer = _object; - } -} - -- (void)releaseObject { - _retainer = nil; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXWebViewController.h b/Tweaks/FLEX/GlobalStateExplorers/FLEXWebViewController.h deleted file mode 100644 index e65bd0f..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXWebViewController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXWebViewController.m -// Flipboard -// -// Created by Ryan Olson on 6/10/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXWebViewController : UIViewController - -- (id)initWithURL:(NSURL *)url; -- (id)initWithText:(NSString *)text; - -+ (BOOL)supportsPathExtension:(NSString *)extension; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FLEXWebViewController.m b/Tweaks/FLEX/GlobalStateExplorers/FLEXWebViewController.m deleted file mode 100644 index 7680c46..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FLEXWebViewController.m +++ /dev/null @@ -1,143 +0,0 @@ -// -// FLEXWebViewController.m -// Flipboard -// -// Created by Ryan Olson on 6/10/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXWebViewController.h" -#import "FLEXUtility.h" -#import - -@interface FLEXWebViewController () - -@property (nonatomic) WKWebView *webView; -@property (nonatomic) NSString *originalText; - -@end - -@implementation FLEXWebViewController - -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - if (self) { - WKWebViewConfiguration *configuration = [WKWebViewConfiguration new]; - - if (@available(iOS 10.0, *)) { - configuration.dataDetectorTypes = WKDataDetectorTypeLink; - } - - self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]; - self.webView.navigationDelegate = self; - } - return self; -} - -- (id)initWithText:(NSString *)text { - self = [self initWithNibName:nil bundle:nil]; - if (self) { - self.originalText = text; - - NSString *html = @"" - "
%@
"; - - // Loading message for when input text takes a long time to escape - NSString *loadingMessage = [NSString stringWithFormat:html, @"Loading..."]; - [self.webView loadHTMLString:loadingMessage baseURL:nil]; - - // Escape HTML on a background thread - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSString *escapedText = [FLEXUtility stringByEscapingHTMLEntitiesInString:text]; - NSString *htmlString = [NSString stringWithFormat:html, escapedText]; - - // Update webview on the main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [self.webView loadHTMLString:htmlString baseURL:nil]; - }); - }); - } - - return self; -} - -- (id)initWithURL:(NSURL *)url { - self = [self initWithNibName:nil bundle:nil]; - if (self) { - NSURLRequest *request = [NSURLRequest requestWithURL:url]; - [self.webView loadRequest:request]; - } - - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - [self.view addSubview:self.webView]; - self.webView.frame = self.view.bounds; - self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - if (self.originalText.length > 0) { - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] - initWithTitle:@"Copy" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonTapped:) - ]; - } -} - -- (void)copyButtonTapped:(id)sender { - [UIPasteboard.generalPasteboard setString:self.originalText]; -} - - -#pragma mark - WKWebView Delegate - -- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction - decisionHandler:(void (^)(WKNavigationActionPolicy))handler { - WKNavigationActionPolicy policy = WKNavigationActionPolicyCancel; - if (navigationAction.navigationType == WKNavigationTypeOther) { - // Allow the initial load - policy = WKNavigationActionPolicyAllow; - } else { - // For clicked links, push another web view controller onto the navigation stack - // so that hitting the back button works as expected. - // Don't allow the current web view to handle the navigation. - NSURLRequest *request = navigationAction.request; - FLEXWebViewController *webVC = [[[self class] alloc] initWithURL:request.URL]; - webVC.title = request.URL.absoluteString; - [self.navigationController pushViewController:webVC animated:YES]; - } - - handler(policy); -} - - -#pragma mark - Class Helpers - -+ (BOOL)supportsPathExtension:(NSString *)extension { - BOOL supported = NO; - NSSet *supportedExtensions = [self webViewSupportedPathExtensions]; - if ([supportedExtensions containsObject:extension.lowercaseString]) { - supported = YES; - } - return supported; -} - -+ (NSSet *)webViewSupportedPathExtensions { - static NSSet *pathExtensions = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // Note that this is not exhaustive, but all these extensions should work well in the web view. - // See https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW7 - pathExtensions = [NSSet setWithArray:@[ - @"jpg", @"jpeg", @"png", @"gif", @"pdf", @"svg", @"tiff", @"3gp", @"3gpp", @"3g2", - @"3gp2", @"aiff", @"aif", @"aifc", @"cdda", @"amr", @"mp3", @"swa", @"mp4", @"mpeg", - @"mpg", @"mp3", @"wav", @"bwf", @"m4a", @"m4b", @"m4p", @"mov", @"qt", @"mqv", @"m4v" - ]]; - - }); - - return pathExtensions; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.h b/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.h deleted file mode 100644 index 29dae96..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXFileBrowserController.h -// Flipboard -// -// Created by Ryan Olson on 6/9/14. -// Based on previous work by Evan Doll -// - -#import "FLEXTableViewController.h" -#import "FLEXGlobalsEntry.h" -#import "FLEXFileBrowserSearchOperation.h" - -@interface FLEXFileBrowserController : FLEXTableViewController - -+ (instancetype)path:(NSString *)path; -- (id)initWithPath:(NSString *)path; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.m b/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.m deleted file mode 100644 index c8e6f0f..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.m +++ /dev/null @@ -1,560 +0,0 @@ -// -// FLEXFileBrowserController.m -// Flipboard -// -// Created by Ryan Olson on 6/9/14. -// -// - -#import "FLEXFileBrowserController.h" -#import "FLEXUtility.h" -#import "FLEXWebViewController.h" -#import "FLEXImagePreviewViewController.h" -#import "FLEXTableListViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXObjectExplorerViewController.h" -#import - -@interface FLEXFileBrowserTableViewCell : UITableViewCell -@end - -typedef NS_ENUM(NSUInteger, FLEXFileBrowserSortAttribute) { - FLEXFileBrowserSortAttributeNone = 0, - FLEXFileBrowserSortAttributeName, - FLEXFileBrowserSortAttributeCreationDate, -}; - -@interface FLEXFileBrowserController () - -@property (nonatomic, copy) NSString *path; -@property (nonatomic, copy) NSArray *childPaths; -@property (nonatomic) NSArray *searchPaths; -@property (nonatomic) NSNumber *recursiveSize; -@property (nonatomic) NSNumber *searchPathsSize; -@property (nonatomic) NSOperationQueue *operationQueue; -@property (nonatomic) UIDocumentInteractionController *documentController; -@property (nonatomic) FLEXFileBrowserSortAttribute sortAttribute; - -@end - -@implementation FLEXFileBrowserController - -+ (instancetype)path:(NSString *)path { - return [[self alloc] initWithPath:path]; -} - -- (id)init { - return [self initWithPath:NSHomeDirectory()]; -} - -- (id)initWithPath:(NSString *)path { - self = [super init]; - if (self) { - self.path = path; - self.title = [path lastPathComponent]; - self.operationQueue = [NSOperationQueue new]; - - // Compute path size - weakify(self) - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSFileManager *fileManager = NSFileManager.defaultManager; - NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:NULL]; - uint64_t totalSize = [attributes fileSize]; - - for (NSString *fileName in [fileManager enumeratorAtPath:path]) { - attributes = [fileManager attributesOfItemAtPath:[path stringByAppendingPathComponent:fileName] error:NULL]; - totalSize += [attributes fileSize]; - - // Bail if the interested view controller has gone away - if (!self) { - return; - } - } - - dispatch_async(dispatch_get_main_queue(), ^{ strongify(self) - self.recursiveSize = @(totalSize); - [self.tableView reloadData]; - }); - }); - - [self reloadCurrentPath]; - } - return self; -} - -#pragma mark - UIViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsSearchBar = YES; - self.searchBarDebounceInterval = kFLEXDebounceForAsyncSearch; - [self addToolbarItems:@[ - [[UIBarButtonItem alloc] initWithTitle:@"Sort" - style:UIBarButtonItemStylePlain - target:self - action:@selector(sortDidTouchUpInside:)] - ]]; -} - -- (void)sortDidTouchUpInside:(UIBarButtonItem *)sortButton { - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Sort" - message:nil - preferredStyle:UIAlertControllerStyleActionSheet]; - [alertController addAction:[UIAlertAction actionWithTitle:@"None" - style:UIAlertActionStyleCancel - handler:^(UIAlertAction * _Nonnull action) { - [self sortWithAttribute:FLEXFileBrowserSortAttributeNone]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"Name" - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * _Nonnull action) { - [self sortWithAttribute:FLEXFileBrowserSortAttributeName]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"Creation Date" - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * _Nonnull action) { - [self sortWithAttribute:FLEXFileBrowserSortAttributeCreationDate]; - }]]; - [self presentViewController:alertController animated:YES completion:nil]; -} - -- (void)sortWithAttribute:(FLEXFileBrowserSortAttribute)attribute { - self.sortAttribute = attribute; - [self reloadDisplayedPaths]; -} - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - switch (row) { - case FLEXGlobalsRowBrowseBundle: return @"📁 Browse Bundle Directory"; - case FLEXGlobalsRowBrowseContainer: return @"📁 Browse Container Directory"; - default: return nil; - } -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - switch (row) { - case FLEXGlobalsRowBrowseBundle: return [[self alloc] initWithPath:NSBundle.mainBundle.bundlePath]; - case FLEXGlobalsRowBrowseContainer: return [[self alloc] initWithPath:NSHomeDirectory()]; - default: return [self new]; - } -} - -#pragma mark - FLEXFileBrowserSearchOperationDelegate - -- (void)fileBrowserSearchOperationResult:(NSArray *)searchResult size:(uint64_t)size { - self.searchPaths = searchResult; - self.searchPathsSize = @(size); - [self.tableView reloadData]; -} - -#pragma mark - Search bar - -- (void)updateSearchResults:(NSString *)newText { - [self reloadDisplayedPaths]; -} - -#pragma mark UISearchControllerDelegate - -- (void)willDismissSearchController:(UISearchController *)searchController { - [self.operationQueue cancelAllOperations]; - [self reloadCurrentPath]; - [self.tableView reloadData]; -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.searchController.isActive ? self.searchPaths.count : self.childPaths.count; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - BOOL isSearchActive = self.searchController.isActive; - NSNumber *currentSize = isSearchActive ? self.searchPathsSize : self.recursiveSize; - NSArray *currentPaths = isSearchActive ? self.searchPaths : self.childPaths; - - NSString *sizeString = nil; - if (!currentSize) { - sizeString = @"Computing size…"; - } else { - sizeString = [NSByteCountFormatter stringFromByteCount:[currentSize longLongValue] countStyle:NSByteCountFormatterCountStyleFile]; - } - - return [NSString stringWithFormat:@"%lu files (%@)", (unsigned long)currentPaths.count, sizeString]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *fullPath = [self filePathAtIndexPath:indexPath]; - NSDictionary *attributes = [NSFileManager.defaultManager attributesOfItemAtPath:fullPath error:NULL]; - BOOL isDirectory = [attributes.fileType isEqual:NSFileTypeDirectory]; - NSString *subtitle = nil; - if (isDirectory) { - NSUInteger count = [NSFileManager.defaultManager contentsOfDirectoryAtPath:fullPath error:NULL].count; - subtitle = [NSString stringWithFormat:@"%lu item%@", (unsigned long)count, (count == 1 ? @"" : @"s")]; - } else { - NSString *sizeString = [NSByteCountFormatter stringFromByteCount:attributes.fileSize countStyle:NSByteCountFormatterCountStyleFile]; - subtitle = [NSString stringWithFormat:@"%@ - %@", sizeString, attributes.fileModificationDate ?: @"Never modified"]; - } - - static NSString *textCellIdentifier = @"textCell"; - static NSString *imageCellIdentifier = @"imageCell"; - UITableViewCell *cell = nil; - - // Separate image and text only cells because otherwise the separator lines get out-of-whack on image cells reused with text only. - UIImage *image = [UIImage imageWithContentsOfFile:fullPath]; - NSString *cellIdentifier = image ? imageCellIdentifier : textCellIdentifier; - - if (!cell) { - cell = [[FLEXFileBrowserTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; - cell.textLabel.font = UIFont.flex_defaultTableCellFont; - cell.detailTextLabel.font = UIFont.flex_defaultTableCellFont; - cell.detailTextLabel.textColor = UIColor.grayColor; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - NSString *cellTitle = [fullPath lastPathComponent]; - cell.textLabel.text = cellTitle; - cell.detailTextLabel.text = subtitle; - - if (image) { - cell.imageView.contentMode = UIViewContentModeScaleAspectFit; - cell.imageView.image = image; - } - - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; - - NSString *fullPath = [self filePathAtIndexPath:indexPath]; - NSString *subpath = fullPath.lastPathComponent; - NSString *pathExtension = subpath.pathExtension; - - BOOL isDirectory = NO; - BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:fullPath isDirectory:&isDirectory]; - UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; - UIImage *image = cell.imageView.image; - - if (!stillExists) { - [FLEXAlert showAlert:@"File Not Found" message:@"The file at the specified path no longer exists." from:self]; - [self reloadDisplayedPaths]; - return; - } - - UIViewController *drillInViewController = nil; - if (isDirectory) { - drillInViewController = [[[self class] alloc] initWithPath:fullPath]; - } else if (image) { - drillInViewController = [FLEXImagePreviewViewController forImage:image]; - } else { - NSData *fileData = [NSData dataWithContentsOfFile:fullPath]; - if (!fileData.length) { - [FLEXAlert showAlert:@"Empty File" message:@"No data returned from the file." from:self]; - return; - } - - // Special case keyed archives, json, and plists to get more readable data. - NSString *prettyString = nil; - if ([pathExtension isEqualToString:@"json"]) { - prettyString = [FLEXUtility prettyJSONStringFromData:fileData]; - } else { - // Regardless of file extension... - - id object = nil; - @try { - // Try to decode an archived object regardless of file extension - object = [NSKeyedUnarchiver unarchiveObjectWithData:fileData]; - } @catch (NSException *e) { } - - // Try to decode other things instead - object = object ?: [NSPropertyListSerialization - propertyListWithData:fileData - options:0 - format:NULL - error:NULL - ] ?: [NSDictionary dictionaryWithContentsOfFile:fullPath] - ?: [NSArray arrayWithContentsOfFile:fullPath]; - - if (object) { - drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:object]; - } else { - // Is it possibly a mach-O file? - if (fileData.length > sizeof(struct mach_header_64)) { - struct mach_header_64 header; - [fileData getBytes:&header length:sizeof(struct mach_header_64)]; - - // Does it have the mach header magic number? - if (header.magic == MH_MAGIC_64) { - // See if we can get some classes out of it... - unsigned int count = 0; - const char **classList = objc_copyClassNamesForImage( - fullPath.UTF8String, &count - ); - - if (count > 0) { - NSArray *classNames = [NSArray flex_forEachUpTo:count map:^id(NSUInteger i) { - return objc_getClass(classList[i]); - }]; - drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:classNames]; - } - } - } - } - } - - if (prettyString.length) { - drillInViewController = [[FLEXWebViewController alloc] initWithText:prettyString]; - } else if ([FLEXWebViewController supportsPathExtension:pathExtension]) { - drillInViewController = [[FLEXWebViewController alloc] initWithURL:[NSURL fileURLWithPath:fullPath]]; - } else if ([FLEXTableListViewController supportsExtension:pathExtension]) { - drillInViewController = [[FLEXTableListViewController alloc] initWithPath:fullPath]; - } - else if (!drillInViewController) { - NSString *fileString = [NSString stringWithUTF8String:fileData.bytes]; - if (fileString.length) { - drillInViewController = [[FLEXWebViewController alloc] initWithText:fileString]; - } - } - } - - if (drillInViewController) { - drillInViewController.title = subpath.lastPathComponent; - [self.navigationController pushViewController:drillInViewController animated:YES]; - } else { - // Share the file otherwise - [self openFileController:fullPath]; - } -} - -- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - UIMenuItem *rename = [[UIMenuItem alloc] initWithTitle:@"Rename" action:@selector(fileBrowserRename:)]; - UIMenuItem *delete = [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(fileBrowserDelete:)]; - UIMenuItem *copyPath = [[UIMenuItem alloc] initWithTitle:@"Copy Path" action:@selector(fileBrowserCopyPath:)]; - UIMenuItem *share = [[UIMenuItem alloc] initWithTitle:@"Share" action:@selector(fileBrowserShare:)]; - - UIMenuController.sharedMenuController.menuItems = @[rename, delete, copyPath, share]; - - return YES; -} - -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - return action == @selector(fileBrowserDelete:) - || action == @selector(fileBrowserRename:) - || action == @selector(fileBrowserCopyPath:) - || action == @selector(fileBrowserShare:); -} - -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - // Empty, but has to exist for the menu to show - // The table view only calls this method for actions in the UIResponderStandardEditActions informal protocol. - // Since our actions are outside of that protocol, we need to manually handle the action forwarding from the cells. -} - -- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView -contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath - point:(CGPoint)point __IOS_AVAILABLE(13.0) { - weakify(self) - return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil - actionProvider:^UIMenu *(NSArray *suggestedActions) { - UITableViewCell * const cell = [tableView cellForRowAtIndexPath:indexPath]; - UIAction *rename = [UIAction actionWithTitle:@"Rename" image:nil identifier:@"Rename" - handler:^(UIAction *action) { strongify(self) - [self fileBrowserRename:cell]; - } - ]; - UIAction *delete = [UIAction actionWithTitle:@"Delete" image:nil identifier:@"Delete" - handler:^(UIAction *action) { strongify(self) - [self fileBrowserDelete:cell]; - } - ]; - UIAction *copyPath = [UIAction actionWithTitle:@"Copy Path" image:nil identifier:@"Copy Path" - handler:^(UIAction *action) { strongify(self) - [self fileBrowserCopyPath:cell]; - } - ]; - UIAction *share = [UIAction actionWithTitle:@"Share" image:nil identifier:@"Share" - handler:^(UIAction *action) { strongify(self) - [self fileBrowserShare:cell]; - } - ]; - - return [UIMenu menuWithTitle:@"Manage File" image:nil - identifier:@"Manage File" - options:UIMenuOptionsDisplayInline - children:@[rename, delete, copyPath, share] - ]; - } - ]; -} - -- (void)openFileController:(NSString *)fullPath { - UIDocumentInteractionController *controller = [UIDocumentInteractionController new]; - controller.URL = [NSURL fileURLWithPath:fullPath]; - - [controller presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES]; - self.documentController = controller; -} - -- (void)fileBrowserRename:(UITableViewCell *)sender { - NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; - NSString *fullPath = [self filePathAtIndexPath:indexPath]; - - BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:self.path isDirectory:NULL]; - if (stillExists) { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title([NSString stringWithFormat:@"Rename %@?", fullPath.lastPathComponent]); - make.configuredTextField(^(UITextField *textField) { - textField.placeholder = @"New file name"; - textField.text = fullPath.lastPathComponent; - }); - make.button(@"Rename").handler(^(NSArray *strings) { - NSString *newFileName = strings.firstObject; - NSString *newPath = [fullPath.stringByDeletingLastPathComponent stringByAppendingPathComponent:newFileName]; - [NSFileManager.defaultManager moveItemAtPath:fullPath toPath:newPath error:NULL]; - [self reloadDisplayedPaths]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; - } else { - [FLEXAlert showAlert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; - } -} - -- (void)fileBrowserDelete:(UITableViewCell *)sender { - NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; - NSString *fullPath = [self filePathAtIndexPath:indexPath]; - - BOOL isDirectory = NO; - BOOL stillExists = [NSFileManager.defaultManager fileExistsAtPath:fullPath isDirectory:&isDirectory]; - if (stillExists) { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Confirm Deletion"); - make.message([NSString stringWithFormat: - @"The %@ '%@' will be deleted. This operation cannot be undone", - (isDirectory ? @"directory" : @"file"), fullPath.lastPathComponent - ]); - make.button(@"Delete").destructiveStyle().handler(^(NSArray *strings) { - [NSFileManager.defaultManager removeItemAtPath:fullPath error:NULL]; - [self reloadDisplayedPaths]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; - } else { - [FLEXAlert showAlert:@"File Removed" message:@"The file at the specified path no longer exists." from:self]; - } -} - -- (void)fileBrowserCopyPath:(UITableViewCell *)sender { - NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; - NSString *fullPath = [self filePathAtIndexPath:indexPath]; - UIPasteboard.generalPasteboard.string = fullPath; -} - -- (void)fileBrowserShare:(UITableViewCell *)sender { - NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; - NSString *pathString = [self filePathAtIndexPath:indexPath]; - NSURL *filePath = [NSURL fileURLWithPath:pathString]; - - BOOL isDirectory = NO; - [NSFileManager.defaultManager fileExistsAtPath:pathString isDirectory:&isDirectory]; - - if (isDirectory) { - // UIDocumentInteractionController for folders - [self openFileController:pathString]; - } else { - // Share sheet for files - UIActivityViewController *shareSheet = [[UIActivityViewController alloc] initWithActivityItems:@[filePath] applicationActivities:nil]; - if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { - shareSheet.popoverPresentationController.sourceView = sender; - } - [self presentViewController:shareSheet animated:true completion:nil]; - } -} - -- (void)reloadDisplayedPaths { - if (self.searchController.isActive) { - [self updateSearchPaths]; - } else { - [self reloadCurrentPath]; - [self.tableView reloadData]; - } -} - -- (void)reloadCurrentPath { - NSMutableArray *childPaths = [NSMutableArray new]; - NSArray *subpaths = [NSFileManager.defaultManager contentsOfDirectoryAtPath:self.path error:NULL]; - for (NSString *subpath in subpaths) { - [childPaths addObject:[self.path stringByAppendingPathComponent:subpath]]; - } - if (self.sortAttribute != FLEXFileBrowserSortAttributeNone) { - [childPaths sortUsingComparator:^NSComparisonResult(NSString *path1, NSString *path2) { - switch (self.sortAttribute) { - case FLEXFileBrowserSortAttributeNone: - // invalid state - return NSOrderedSame; - case FLEXFileBrowserSortAttributeName: - return [path1 compare:path2]; - case FLEXFileBrowserSortAttributeCreationDate: { - NSDictionary *path1Attributes = [NSFileManager.defaultManager attributesOfItemAtPath:path1 - error:NULL]; - NSDictionary *path2Attributes = [NSFileManager.defaultManager attributesOfItemAtPath:path2 - error:NULL]; - NSDate *path1Date = path1Attributes[NSFileCreationDate]; - NSDate *path2Date = path2Attributes[NSFileCreationDate]; - - return [path1Date compare:path2Date]; - } - } - }]; - } - self.childPaths = childPaths; -} - -- (void)updateSearchPaths { - self.searchPaths = nil; - self.searchPathsSize = nil; - - //clear pre search request and start a new one - [self.operationQueue cancelAllOperations]; - FLEXFileBrowserSearchOperation *newOperation = [[FLEXFileBrowserSearchOperation alloc] initWithPath:self.path searchString:self.searchText]; - newOperation.delegate = self; - [self.operationQueue addOperation:newOperation]; -} - -- (NSString *)filePathAtIndexPath:(NSIndexPath *)indexPath { - return self.searchController.isActive ? self.searchPaths[indexPath.row] : self.childPaths[indexPath.row]; -} - -@end - - -@implementation FLEXFileBrowserTableViewCell - -- (void)forwardAction:(SEL)action withSender:(id)sender { - id target = [self.nextResponder targetForAction:action withSender:sender]; - [UIApplication.sharedApplication sendAction:action to:target from:self forEvent:nil]; -} - -- (void)fileBrowserRename:(UIMenuController *)sender { - [self forwardAction:_cmd withSender:sender]; -} - -- (void)fileBrowserDelete:(UIMenuController *)sender { - [self forwardAction:_cmd withSender:sender]; -} - -- (void)fileBrowserCopyPath:(UIMenuController *)sender { - [self forwardAction:_cmd withSender:sender]; -} - -- (void)fileBrowserShare:(UIMenuController *)sender { - [self forwardAction:_cmd withSender:sender]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.h b/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.h deleted file mode 100644 index a9fa486..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// FLEXFileBrowserSearchOperation.h -// FLEX -// -// Created by 啟倫 陳 on 2014/8/4. -// Copyright (c) 2014年 f. All rights reserved. -// - -#import - -@protocol FLEXFileBrowserSearchOperationDelegate; - -@interface FLEXFileBrowserSearchOperation : NSOperation - -@property (nonatomic, weak) id delegate; - -- (id)initWithPath:(NSString *)currentPath searchString:(NSString *)searchString; - -@end - -@protocol FLEXFileBrowserSearchOperationDelegate - -- (void)fileBrowserSearchOperationResult:(NSArray *)searchResult size:(uint64_t)size; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m b/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m deleted file mode 100644 index a61c540..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/FileBrowser/FLEXFileBrowserSearchOperation.m +++ /dev/null @@ -1,118 +0,0 @@ -// -// FLEXFileBrowserSearchOperation.m -// FLEX -// -// Created by 啟倫 陳 on 2014/8/4. -// Copyright (c) 2014年 f. All rights reserved. -// - -#import "FLEXFileBrowserSearchOperation.h" - -@implementation NSMutableArray (FLEXStack) - -- (void)flex_push:(id)anObject { - [self addObject:anObject]; -} - -- (id)flex_pop { - id anObject = self.lastObject; - [self removeLastObject]; - return anObject; -} - -@end - -@interface FLEXFileBrowserSearchOperation () - -@property (nonatomic) NSString *path; -@property (nonatomic) NSString *searchString; - -@end - -@implementation FLEXFileBrowserSearchOperation - -#pragma mark - private - -- (uint64_t)totalSizeAtPath:(NSString *)path { - NSFileManager *fileManager = NSFileManager.defaultManager; - NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:NULL]; - uint64_t totalSize = [attributes fileSize]; - - for (NSString *fileName in [fileManager enumeratorAtPath:path]) { - attributes = [fileManager attributesOfItemAtPath:[path stringByAppendingPathComponent:fileName] error:NULL]; - totalSize += [attributes fileSize]; - } - return totalSize; -} - -#pragma mark - instance method - -- (id)initWithPath:(NSString *)currentPath searchString:(NSString *)searchString { - self = [super init]; - if (self) { - self.path = currentPath; - self.searchString = searchString; - } - return self; -} - -#pragma mark - methods to override - -- (void)main { - NSFileManager *fileManager = NSFileManager.defaultManager; - NSMutableArray *searchPaths = [NSMutableArray new]; - NSMutableDictionary *sizeMapping = [NSMutableDictionary new]; - uint64_t totalSize = 0; - NSMutableArray *stack = [NSMutableArray new]; - [stack flex_push:self.path]; - - //recursive found all match searchString paths, and precomputing there size - while (stack.count) { - NSString *currentPath = [stack flex_pop]; - NSArray *directoryPath = [fileManager contentsOfDirectoryAtPath:currentPath error:nil]; - - for (NSString *subPath in directoryPath) { - NSString *fullPath = [currentPath stringByAppendingPathComponent:subPath]; - - if ([[subPath lowercaseString] rangeOfString:[self.searchString lowercaseString]].location != NSNotFound) { - [searchPaths addObject:fullPath]; - if (!sizeMapping[fullPath]) { - uint64_t fullPathSize = [self totalSizeAtPath:fullPath]; - totalSize += fullPathSize; - [sizeMapping setObject:@(fullPathSize) forKey:fullPath]; - } - } - BOOL isDirectory; - if ([fileManager fileExistsAtPath:fullPath isDirectory:&isDirectory] && isDirectory) { - [stack flex_push:fullPath]; - } - - if ([self isCancelled]) { - return; - } - } - } - - //sort - NSArray *sortedArray = [searchPaths sortedArrayUsingComparator:^NSComparisonResult(NSString *path1, NSString *path2) { - uint64_t pathSize1 = [sizeMapping[path1] unsignedLongLongValue]; - uint64_t pathSize2 = [sizeMapping[path2] unsignedLongLongValue]; - if (pathSize1 < pathSize2) { - return NSOrderedAscending; - } else if (pathSize1 > pathSize2) { - return NSOrderedDescending; - } else { - return NSOrderedSame; - } - }]; - - if ([self isCancelled]) { - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [self.delegate fileBrowserSearchOperationResult:sortedArray size:totalSize]; - }); -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h b/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h deleted file mode 100644 index 6b920b9..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// FLEXGlobalsEntry.h -// FLEX -// -// Created by Javier Soto on 7/26/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) { - FLEXGlobalsRowProcessInfo, - FLEXGlobalsRowNetworkHistory, - FLEXGlobalsRowSystemLog, - FLEXGlobalsRowLiveObjects, - FLEXGlobalsRowAddressInspector, - FLEXGlobalsRowCookies, - FLEXGlobalsRowBrowseRuntime, - FLEXGlobalsRowAppKeychainItems, - FLEXGlobalsRowAppDelegate, - FLEXGlobalsRowRootViewController, - FLEXGlobalsRowUserDefaults, - FLEXGlobalsRowMainBundle, - FLEXGlobalsRowBrowseBundle, - FLEXGlobalsRowBrowseContainer, - FLEXGlobalsRowApplication, - FLEXGlobalsRowKeyWindow, - FLEXGlobalsRowMainScreen, - FLEXGlobalsRowCurrentDevice, - FLEXGlobalsRowPasteboard, - FLEXGlobalsRowURLSession, - FLEXGlobalsRowURLCache, - FLEXGlobalsRowNotificationCenter, - FLEXGlobalsRowMenuController, - FLEXGlobalsRowFileManager, - FLEXGlobalsRowTimeZone, - FLEXGlobalsRowLocale, - FLEXGlobalsRowCalendar, - FLEXGlobalsRowMainRunLoop, - FLEXGlobalsRowMainThread, - FLEXGlobalsRowOperationQueue, - FLEXGlobalsRowCount -}; - -typedef NSString * _Nonnull (^FLEXGlobalsEntryNameFuture)(void); -/// Simply return a view controller to be pushed on the navigation stack -typedef UIViewController * _Nullable (^FLEXGlobalsEntryViewControllerFuture)(void); -/// Do something like present an alert, then use the host -/// view controller to present or push another view controller. -typedef void (^FLEXGlobalsEntryRowAction)(__kindof UITableViewController * _Nonnull host); - -/// For view controllers to conform to to indicate they support being used -/// in the globals table view controller. These methods help create concrete entries. -/// -/// Previously, the concrete entries relied on "futures" for the view controller and title. -/// With this protocol, the conforming class itself can act as a future, since the methods -/// will not be invoked until the title and view controller / row action are needed. -/// -/// Entries can implement \c globalsEntryViewController: to unconditionally provide a -/// view controller, or \c globalsEntryRowAction: to conditionally provide one and -/// perform some action (such as present an alert) if no view controller is available, -/// or both if there is a mix of rows where some are guaranteed to work and some are not. -/// Where both are implemented, \c globalsEntryRowAction: takes precedence; if it returns -/// an action for the requested row, that will be used instead of \c globalsEntryViewController: -@protocol FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row; - -// Must respond to at least one of the below. -// globalsEntryRowAction: takes precedence if both are implemented. -@optional - -+ (nullable UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row; -+ (nullable FLEXGlobalsEntryRowAction)globalsEntryRowAction:(FLEXGlobalsRow)row; - -@end - -@interface FLEXGlobalsEntry : NSObject - -@property (nonatomic, readonly, nonnull) FLEXGlobalsEntryNameFuture entryNameFuture; -@property (nonatomic, readonly, nullable) FLEXGlobalsEntryViewControllerFuture viewControllerFuture; -@property (nonatomic, readonly, nullable) FLEXGlobalsEntryRowAction rowAction; - -+ (instancetype)entryWithEntry:(Class)entry row:(FLEXGlobalsRow)row; - -+ (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture - viewControllerFuture:(FLEXGlobalsEntryViewControllerFuture)viewControllerFuture; - -+ (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture - action:(FLEXGlobalsEntryRowAction)rowSelectedAction; - -@end - - -@interface NSObject (FLEXGlobalsEntry) - -/// @return The result of passing self to +[FLEXGlobalsEntry entryWithEntry:] -/// if the class conforms to FLEXGlobalsEntry, else, nil. -+ (nullable FLEXGlobalsEntry *)flex_concreteGlobalsEntry:(FLEXGlobalsRow)row; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m b/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m deleted file mode 100644 index b93b214..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m +++ /dev/null @@ -1,86 +0,0 @@ -// -// FLEXGlobalsEntry.m -// FLEX -// -// Created by Javier Soto on 7/26/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsEntry.h" - -@implementation FLEXGlobalsEntry - -+ (instancetype)entryWithEntry:(Class)cls row:(FLEXGlobalsRow)row { - BOOL providesVCs = [cls respondsToSelector:@selector(globalsEntryViewController:)]; - BOOL providesActions = [cls respondsToSelector:@selector(globalsEntryRowAction:)]; - NSParameterAssert(cls); - NSParameterAssert(providesVCs || providesActions); - - FLEXGlobalsEntry *entry = [self new]; - entry->_entryNameFuture = ^{ return [cls globalsEntryTitle:row]; }; - - if (providesVCs) { - id action = providesActions ? [cls globalsEntryRowAction:row] : nil; - if (action) { - entry->_rowAction = action; - } else { - entry->_viewControllerFuture = ^{ return [cls globalsEntryViewController:row]; }; - } - } else { - entry->_rowAction = [cls globalsEntryRowAction:row]; - } - - return entry; -} - -+ (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture - viewControllerFuture:(FLEXGlobalsEntryViewControllerFuture)viewControllerFuture { - NSParameterAssert(nameFuture); - NSParameterAssert(viewControllerFuture); - - FLEXGlobalsEntry *entry = [self new]; - entry->_entryNameFuture = [nameFuture copy]; - entry->_viewControllerFuture = [viewControllerFuture copy]; - - return entry; -} - -+ (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture - action:(FLEXGlobalsEntryRowAction)rowSelectedAction { - NSParameterAssert(nameFuture); - NSParameterAssert(rowSelectedAction); - - FLEXGlobalsEntry *entry = [self new]; - entry->_entryNameFuture = [nameFuture copy]; - entry->_rowAction = [rowSelectedAction copy]; - - return entry; -} - -@end - -@interface FLEXGlobalsEntry (Debugging) -@property (nonatomic, readonly) NSString *name; -@end - -@implementation FLEXGlobalsEntry (Debugging) - -- (NSString *)name { - return self.entryNameFuture(); -} - -@end - -#pragma mark - flex_concreteGlobalsEntry - -@implementation NSObject (FLEXGlobalsEntry) - -+ (FLEXGlobalsEntry *)flex_concreteGlobalsEntry:(FLEXGlobalsRow)row { - if ([self conformsToProtocol:@protocol(FLEXGlobalsEntry)]) { - return [FLEXGlobalsEntry entryWithEntry:self row:row]; - } - - return nil; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsSection.h b/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsSection.h deleted file mode 100644 index ae94553..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsSection.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FLEXGlobalsSection.h -// FLEX -// -// Created by Tanner Bennett on 7/11/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewSection.h" -#import "FLEXGlobalsEntry.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXGlobalsSection : FLEXTableViewSection - -+ (instancetype)title:(NSString *)title rows:(NSArray *)rows; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsSection.m b/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsSection.m deleted file mode 100644 index abb97ea..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsSection.m +++ /dev/null @@ -1,86 +0,0 @@ -// -// FLEXGlobalsSection.m -// FLEX -// -// Created by Tanner Bennett on 7/11/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsSection.h" -#import "NSArray+FLEX.h" -#import "UIFont+FLEX.h" - -@interface FLEXGlobalsSection () -/// Filtered rows -@property (nonatomic) NSArray *rows; -/// Unfiltered rows -@property (nonatomic) NSArray *allRows; -@end -@implementation FLEXGlobalsSection - -#pragma mark - Initialization - -+ (instancetype)title:(NSString *)title rows:(NSArray *)rows { - FLEXGlobalsSection *s = [self new]; - s->_title = title; - s.allRows = rows; - - return s; -} - -- (void)setAllRows:(NSArray *)allRows { - _allRows = allRows.copy; - [self reloadData]; -} - -#pragma mark - Overrides - -- (NSInteger)numberOfRows { - return self.rows.count; -} - -- (void)setFilterText:(NSString *)filterText { - super.filterText = filterText; - [self reloadData]; -} - -- (void)reloadData { - NSString *filterText = self.filterText; - - if (filterText.length) { - self.rows = [self.allRows flex_filtered:^BOOL(FLEXGlobalsEntry *entry, NSUInteger idx) { - return [entry.entryNameFuture() localizedCaseInsensitiveContainsString:filterText]; - }]; - } else { - self.rows = self.allRows; - } -} - -- (BOOL)canSelectRow:(NSInteger)row { - return YES; -} - -- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row { - return (id)self.rows[row].rowAction; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - return self.rows[row].viewControllerFuture ? self.rows[row].viewControllerFuture() : nil; -} - -- (void)configureCell:(__kindof UITableViewCell *)cell forRow:(NSInteger)row { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.font = UIFont.flex_defaultTableCellFont; - cell.textLabel.text = self.rows[row].entryNameFuture(); -} - -@end - - -@implementation FLEXGlobalsSection (Subscripting) - -- (id)objectAtIndexedSubscript:(NSUInteger)idx { - return self.rows[idx]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h b/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h deleted file mode 100644 index b4b79b8..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// FLEXGlobalsViewController.h -// Flipboard -// -// Created by Ryan Olson on 2014-05-03. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" -@protocol FLEXGlobalsTableViewControllerDelegate; - -typedef NS_ENUM(NSUInteger, FLEXGlobalsSectionKind) { - FLEXGlobalsSectionCustom, - /// NSProcessInfo, Network history, system log, - /// heap, address explorer, libraries, app classes - FLEXGlobalsSectionProcessAndEvents, - /// Browse container, browse bundle, NSBundle.main, - /// NSUserDefaults.standard, UIApplication, - /// app delegate, key window, root VC, cookies - FLEXGlobalsSectionAppShortcuts, - /// UIPasteBoard.general, UIScreen, UIDevice - FLEXGlobalsSectionMisc, - FLEXGlobalsSectionCount -}; - -@interface FLEXGlobalsViewController : FLEXFilteringTableViewController - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m deleted file mode 100644 index f70406b..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ /dev/null @@ -1,200 +0,0 @@ -// -// FLEXGlobalsViewController.m -// Flipboard -// -// Created by Ryan Olson on 2014-05-03. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsViewController.h" -#import "FLEXUtility.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXObjcRuntimeViewController.h" -#import "FLEXKeychainViewController.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXLiveObjectsController.h" -#import "FLEXFileBrowserController.h" -#import "FLEXCookiesViewController.h" -#import "FLEXGlobalsEntry.h" -#import "FLEXManager+Private.h" -#import "FLEXSystemLogViewController.h" -#import "FLEXNetworkMITMViewController.h" -#import "FLEXAddressExplorerCoordinator.h" -#import "FLEXGlobalsSection.h" -#import "UIBarButtonItem+FLEX.h" - -@interface FLEXGlobalsViewController () -/// Only displayed sections of the table view; empty sections are purged from this array. -@property (nonatomic) NSArray *sections; -/// Every section in the table view, regardless of whether or not a section is empty. -@property (nonatomic, readonly) NSArray *allSections; -@property (nonatomic, readonly) BOOL manuallyDeselectOnAppear; -@end - -@implementation FLEXGlobalsViewController -@dynamic sections, allSections; - -#pragma mark - Initialization - -+ (NSString *)globalsTitleForSection:(FLEXGlobalsSectionKind)section { - switch (section) { - case FLEXGlobalsSectionCustom: - return @"Custom Additions"; - case FLEXGlobalsSectionProcessAndEvents: - return @"Process and Events"; - case FLEXGlobalsSectionAppShortcuts: - return @"App Shortcuts"; - case FLEXGlobalsSectionMisc: - return @"Miscellaneous"; - - default: - @throw NSInternalInconsistencyException; - } -} - -+ (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row { - switch (row) { - case FLEXGlobalsRowAppKeychainItems: - return [FLEXKeychainViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowAddressInspector: - return [FLEXAddressExplorerCoordinator flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowBrowseRuntime: - return [FLEXObjcRuntimeViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowLiveObjects: - return [FLEXLiveObjectsController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowCookies: - return [FLEXCookiesViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowBrowseBundle: - case FLEXGlobalsRowBrowseContainer: - return [FLEXFileBrowserController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowSystemLog: - return [FLEXSystemLogViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowNetworkHistory: - return [FLEXNetworkMITMViewController flex_concreteGlobalsEntry:row]; - case FLEXGlobalsRowKeyWindow: - case FLEXGlobalsRowRootViewController: - case FLEXGlobalsRowProcessInfo: - case FLEXGlobalsRowAppDelegate: - case FLEXGlobalsRowUserDefaults: - case FLEXGlobalsRowMainBundle: - case FLEXGlobalsRowApplication: - case FLEXGlobalsRowMainScreen: - case FLEXGlobalsRowCurrentDevice: - case FLEXGlobalsRowPasteboard: - case FLEXGlobalsRowURLSession: - case FLEXGlobalsRowURLCache: - case FLEXGlobalsRowNotificationCenter: - case FLEXGlobalsRowMenuController: - case FLEXGlobalsRowFileManager: - case FLEXGlobalsRowTimeZone: - case FLEXGlobalsRowLocale: - case FLEXGlobalsRowCalendar: - case FLEXGlobalsRowMainRunLoop: - case FLEXGlobalsRowMainThread: - case FLEXGlobalsRowOperationQueue: - return [FLEXObjectExplorerFactory flex_concreteGlobalsEntry:row]; - - default: - @throw [NSException - exceptionWithName:NSInternalInconsistencyException - reason:@"Missing globals case in switch" userInfo:nil - ]; - } -} - -+ (NSArray *)defaultGlobalSections { - static NSMutableArray *sections = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSDictionary *> *rowsBySection = @{ - @(FLEXGlobalsSectionProcessAndEvents) : @[ - [self globalsEntryForRow:FLEXGlobalsRowNetworkHistory], - [self globalsEntryForRow:FLEXGlobalsRowSystemLog], - [self globalsEntryForRow:FLEXGlobalsRowProcessInfo], - [self globalsEntryForRow:FLEXGlobalsRowLiveObjects], - [self globalsEntryForRow:FLEXGlobalsRowAddressInspector], - [self globalsEntryForRow:FLEXGlobalsRowBrowseRuntime], - ], - @(FLEXGlobalsSectionAppShortcuts) : @[ - [self globalsEntryForRow:FLEXGlobalsRowBrowseBundle], - [self globalsEntryForRow:FLEXGlobalsRowBrowseContainer], - [self globalsEntryForRow:FLEXGlobalsRowMainBundle], - [self globalsEntryForRow:FLEXGlobalsRowUserDefaults], - [self globalsEntryForRow:FLEXGlobalsRowAppKeychainItems], - [self globalsEntryForRow:FLEXGlobalsRowApplication], - [self globalsEntryForRow:FLEXGlobalsRowAppDelegate], - [self globalsEntryForRow:FLEXGlobalsRowKeyWindow], - [self globalsEntryForRow:FLEXGlobalsRowRootViewController], - [self globalsEntryForRow:FLEXGlobalsRowCookies], - ], - @(FLEXGlobalsSectionMisc) : @[ - [self globalsEntryForRow:FLEXGlobalsRowPasteboard], - [self globalsEntryForRow:FLEXGlobalsRowMainScreen], - [self globalsEntryForRow:FLEXGlobalsRowCurrentDevice], - [self globalsEntryForRow:FLEXGlobalsRowURLSession], - [self globalsEntryForRow:FLEXGlobalsRowURLCache], - [self globalsEntryForRow:FLEXGlobalsRowNotificationCenter], - [self globalsEntryForRow:FLEXGlobalsRowMenuController], - [self globalsEntryForRow:FLEXGlobalsRowFileManager], - [self globalsEntryForRow:FLEXGlobalsRowTimeZone], - [self globalsEntryForRow:FLEXGlobalsRowLocale], - [self globalsEntryForRow:FLEXGlobalsRowCalendar], - [self globalsEntryForRow:FLEXGlobalsRowMainRunLoop], - [self globalsEntryForRow:FLEXGlobalsRowMainThread], - [self globalsEntryForRow:FLEXGlobalsRowOperationQueue], - ] - }; - - sections = [NSMutableArray array]; - for (FLEXGlobalsSectionKind i = FLEXGlobalsSectionCustom + 1; i < FLEXGlobalsSectionCount; ++i) { - NSString *title = [self globalsTitleForSection:i]; - [sections addObject:[FLEXGlobalsSection title:title rows:rowsBySection[@(i)]]]; - } - }); - - return sections; -} - - -#pragma mark - Overrides - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = @"💪 FLEX"; - self.showsSearchBar = YES; - self.searchBarDebounceInterval = kFLEXDebounceInstant; - self.navigationItem.backBarButtonItem = [UIBarButtonItem flex_backItemWithTitle:@"Back"]; - - _manuallyDeselectOnAppear = NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 10; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self disableToolbar]; - - if (self.manuallyDeselectOnAppear) { - [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES]; - } -} - -- (NSArray *)makeSections { - NSMutableArray *sections = [NSMutableArray array]; - // Do we have custom sections to add? - if (FLEXManager.sharedManager.userGlobalEntries.count) { - NSString *title = [[self class] globalsTitleForSection:FLEXGlobalsSectionCustom]; - FLEXGlobalsSection *custom = [FLEXGlobalsSection - title:title - rows:FLEXManager.sharedManager.userGlobalEntries - ]; - [sections addObject:custom]; - } - - [sections addObjectsFromArray:[self.class defaultGlobalSections]]; - - return sections; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychain.h b/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychain.h deleted file mode 100644 index 539b2f1..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychain.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// FLEXKeychain.h -// -// Derived from: -// SSKeychain.h in SSKeychain -// Created by Sam Soffes on 5/19/10. -// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. -// - -#import - -/// Error code specific to FLEXKeychain that can be returned in NSError objects. -/// For codes returned by the operating system, refer to SecBase.h for your -/// platform. -typedef NS_ENUM(OSStatus, FLEXKeychainErrorCode) { - /// Some of the arguments were invalid. - FLEXKeychainErrorBadArguments = -1001, -}; - -/// FLEXKeychain error domain -extern NSString *const kFLEXKeychainErrorDomain; - -/// Account name. -extern NSString *const kFLEXKeychainAccountKey; - -/// Time the item was created. -/// -/// The value will be a string. -extern NSString *const kFLEXKeychainCreatedAtKey; - -/// Item class. -extern NSString *const kFLEXKeychainClassKey; - -/// Item description. -extern NSString *const kFLEXKeychainDescriptionKey; - -/// Item group. -extern NSString *const kFLEXKeychainGroupKey; - -/// Item label. -extern NSString *const kFLEXKeychainLabelKey; - -/// Time the item was last modified. -/// -/// The value will be a string. -extern NSString *const kFLEXKeychainLastModifiedKey; - -/// Where the item was created. -extern NSString *const kFLEXKeychainWhereKey; - -/// A simple wrapper for accessing accounts, getting passwords, -/// setting passwords, and deleting passwords using the system Keychain. -@interface FLEXKeychain : NSObject - -#pragma mark - Classic methods - -/// @param serviceName The service for which to return the corresponding password. -/// @param account The account for which to return the corresponding password. -/// @return Returns a string containing the password for a given account and service, -/// or `nil` if the Keychain doesn't have a password for the given parameters. -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; - -/// Returns a nsdata containing the password for a given account and service, -/// or `nil` if the Keychain doesn't have a password for the given parameters. -/// -/// @param serviceName The service for which to return the corresponding password. -/// @param account The account for which to return the corresponding password. -/// @return Returns a nsdata containing the password for a given account and service, -/// or `nil` if the Keychain doesn't have a password for the given parameters. -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; - - -/// Deletes a password from the Keychain. -/// -/// @param serviceName The service for which to delete the corresponding password. -/// @param account The account for which to delete the corresponding password. -/// @return Returns `YES` on success, or `NO` on failure. -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; - - -/// Sets a password in the Keychain. -/// -/// @param password The password to store in the Keychain. -/// @param serviceName The service for which to set the corresponding password. -/// @param account The account for which to set the corresponding password. -/// @return Returns `YES` on success, or `NO` on failure. -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; - -/// Sets a password in the Keychain. -/// -/// @param password The password to store in the Keychain. -/// @param serviceName The service for which to set the corresponding password. -/// @param account The account for which to set the corresponding password. -/// @return Returns `YES` on success, or `NO` on failure. -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; - -/// @return An array of dictionaries containing the Keychain's accounts, or `nil` if -/// the Keychain doesn't have any accounts. The order of the objects in the array isn't defined. -/// -/// @note See the `NSString` constants declared in FLEXKeychain.h for a list of keys that -/// can be used when accessing the dictionaries returned by this method. -+ (NSArray *> *)allAccounts; -+ (NSArray *> *)allAccounts:(NSError *__autoreleasing *)error; - -/// @param serviceName The service for which to return the corresponding accounts. -/// @return An array of dictionaries containing the Keychain's accounts for a given `serviceName`, -/// or `nil` if the Keychain doesn't have any accounts for the given `serviceName`. -/// The order of the objects in the array isn't defined. -/// -/// @note See the `NSString` constants declared in FLEXKeychain.h for a list of keys that -/// can be used when accessing the dictionaries returned by this method. -+ (NSArray *> *)accountsForService:(NSString *)serviceName; -+ (NSArray *> *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error; - - -#pragma mark - Configuration - -#if __IPHONE_4_0 && TARGET_OS_IPHONE -/// Returns the accessibility type for all future passwords saved to the Keychain. -/// -/// @return `NULL` or one of the "Keychain Item Accessibility -/// Constants" used for determining when a keychain item should be readable. -+ (CFTypeRef)accessibilityType; - -/// Sets the accessibility type for all future passwords saved to the Keychain. -/// -/// @param accessibilityType One of the "Keychain Item Accessibility Constants" -/// used for determining when a keychain item should be readable. -/// If the value is `NULL` (the default), the Keychain default will be used which -/// is highly insecure. You really should use at least `kSecAttrAccessibleAfterFirstUnlock` -/// for background applications or `kSecAttrAccessibleWhenUnlocked` for all -/// other applications. -/// -/// @note See Security/SecItem.h -+ (void)setAccessibilityType:(CFTypeRef)accessibilityType; -#endif - -@end - diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychain.m b/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychain.m deleted file mode 100644 index cc89ca1..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychain.m +++ /dev/null @@ -1,121 +0,0 @@ -// -// FLEXKeychain.m -// -// Forked from: -// SSKeychain.m in SSKeychain -// Created by Sam Soffes on 5/19/10. -// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. -// - -#import "FLEXKeychain.h" -#import "FLEXKeychainQuery.h" - -NSString * const kFLEXKeychainErrorDomain = @"com.flipboard.flex"; -NSString * const kFLEXKeychainAccountKey = @"acct"; -NSString * const kFLEXKeychainCreatedAtKey = @"cdat"; -NSString * const kFLEXKeychainClassKey = @"labl"; -NSString * const kFLEXKeychainDescriptionKey = @"desc"; -NSString * const kFLEXKeychainGroupKey = @"agrp"; -NSString * const kFLEXKeychainLabelKey = @"labl"; -NSString * const kFLEXKeychainLastModifiedKey = @"mdat"; -NSString * const kFLEXKeychainWhereKey = @"svce"; - -#if __IPHONE_4_0 && TARGET_OS_IPHONE -static CFTypeRef FLEXKeychainAccessibilityType = NULL; -#endif - -@implementation FLEXKeychain - -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account { - return [self passwordForService:serviceName account:account error:nil]; -} - -+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = serviceName; - query.account = account; - [query fetch:error]; - return query.password; -} - -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account { - return [self passwordDataForService:serviceName account:account error:nil]; -} - -+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = serviceName; - query.account = account; - [query fetch:error]; - - return query.passwordData; -} - -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account { - return [self deletePasswordForService:serviceName account:account error:nil]; -} - -+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = serviceName; - query.account = account; - return [query deleteItem:error]; -} - -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account { - return [self setPassword:password forService:serviceName account:account error:nil]; -} - -+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = serviceName; - query.account = account; - query.password = password; - return [query save:error]; -} - -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account { - return [self setPasswordData:password forService:serviceName account:account error:nil]; -} - -+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = serviceName; - query.account = account; - query.passwordData = password; - return [query save:error]; -} - -+ (NSArray *)allAccounts { - return [self allAccounts:nil] ?: @[]; -} - -+ (NSArray *)allAccounts:(NSError *__autoreleasing *)error { - return [self accountsForService:nil error:error]; -} - -+ (NSArray *)accountsForService:(NSString *)serviceName { - return [self accountsForService:serviceName error:nil]; -} - -+ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError *__autoreleasing *)error { - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = serviceName; - return [query fetchAll:error]; -} - -#if __IPHONE_4_0 && TARGET_OS_IPHONE -+ (CFTypeRef)accessibilityType { - return FLEXKeychainAccessibilityType; -} - -+ (void)setAccessibilityType:(CFTypeRef)accessibilityType { - CFRetain(accessibilityType); - if (FLEXKeychainAccessibilityType) { - CFRelease(FLEXKeychainAccessibilityType); - } - FLEXKeychainAccessibilityType = accessibilityType; -} -#endif - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h b/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h deleted file mode 100644 index e5500bf..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainQuery.h +++ /dev/null @@ -1,112 +0,0 @@ -// -// FLEXKeychainQuery.h -// -// Derived from: -// SSKeychainQuery.h in SSKeychain -// Created by Caleb Davenport on 3/19/13. -// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. -// - -#import -#import - -#if __IPHONE_7_0 || __MAC_10_9 -// Keychain synchronization available at compile time -#define FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 -#endif - -#if __IPHONE_3_0 || __MAC_10_9 -// Keychain access group available at compile time -#define FLEXKEYCHAIN_ACCESS_GROUP_AVAILABLE 1 -#endif - -#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE -typedef NS_ENUM(NSUInteger, FLEXKeychainQuerySynchronizationMode) { - FLEXKeychainQuerySynchronizationModeAny, - FLEXKeychainQuerySynchronizationModeNo, - FLEXKeychainQuerySynchronizationModeYes -}; -#endif - -/// Simple interface for querying or modifying keychain items. -@interface FLEXKeychainQuery : NSObject - -/// kSecAttrAccount -@property (nonatomic, copy) NSString *account; - -/// kSecAttrService -@property (nonatomic, copy) NSString *service; - -/// kSecAttrLabel -@property (nonatomic, copy) NSString *label; - -#ifdef FLEXKEYCHAIN_ACCESS_GROUP_AVAILABLE -/// kSecAttrAccessGroup (only used on iOS) -@property (nonatomic, copy) NSString *accessGroup; -#endif - -#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE -/// kSecAttrSynchronizable -@property (nonatomic) FLEXKeychainQuerySynchronizationMode synchronizationMode; -#endif - -/// Root storage for password information -@property (nonatomic, copy) NSData *passwordData; - -/// This property automatically transitions between an object and the value of -/// `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver. -@property (nonatomic, copy) id passwordObject; - -/// Convenience accessor for setting and getting a password string. Passes through -/// to `passwordData` using UTF-8 string encoding. -@property (nonatomic, copy) NSString *password; - - -#pragma mark Saving & Deleting - -/// Save the receiver's attributes as a keychain item. Existing items with the -/// given account, service, and access group will first be deleted. -/// -/// @param error Populated should an error occur. -/// @return `YES` if saving was successful, `NO` otherwise. -- (BOOL)save:(NSError **)error; - -/// Delete keychain items that match the given account, service, and access group. -/// -/// @param error Populated should an error occur. -/// @return `YES` if saving was successful, `NO` otherwise. -- (BOOL)deleteItem:(NSError **)error; - - -#pragma mark Fetching - -/// Fetch all keychain items that match the given account, service, and access -/// group. The values of `password` and `passwordData` are ignored when fetching. -/// -/// @param error Populated should an error occur. -/// @return An array of dictionaries that represent all matching keychain items, -/// or `nil` should an error occur. The order of the items is not determined. -- (NSArray *> *)fetchAll:(NSError **)error; - -/// Fetch the keychain item that matches the given account, service, and access -/// group. The `password` and `passwordData` properties will be populated unless -/// an error occurs. The values of `password` and `passwordData` are ignored when -/// fetching. -/// -/// @param error Populated should an error occur. -/// @return `YES` if fetching was successful, `NO` otherwise. -- (BOOL)fetch:(NSError **)error; - - -#pragma mark Synchronization Status - -#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE -/// Returns a boolean indicating if keychain synchronization is available on the device at runtime. -/// The #define FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. -/// If you are checking for the presence of synchronization, you should use this method. -/// -/// @return A value indicating if keychain synchronization is available -+ (BOOL)isSynchronizationAvailable; -#endif - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m b/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m deleted file mode 100644 index 3879701..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainQuery.m +++ /dev/null @@ -1,304 +0,0 @@ -// -// FLEXKeychainQuery.m -// FLEXKeychain -// -// Created by Caleb Davenport on 3/19/13. -// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. -// - -#import "FLEXKeychainQuery.h" -#import "FLEXKeychain.h" - -@implementation FLEXKeychainQuery - -#pragma mark - Public - -- (BOOL)save:(NSError *__autoreleasing *)error { - OSStatus status = FLEXKeychainErrorBadArguments; - if (!self.service || !self.account || !self.passwordData) { - if (error) { - *error = [self errorWithCode:status]; - } - return NO; - } - - NSMutableDictionary *query = nil; - NSMutableDictionary * searchQuery = [self query]; - status = SecItemCopyMatching((__bridge CFDictionaryRef)searchQuery, nil); - if (status == errSecSuccess) {//item already exists, update it! - query = [[NSMutableDictionary alloc]init]; - query[(__bridge id)kSecValueData] = self.passwordData; -#if __IPHONE_4_0 && TARGET_OS_IPHONE - CFTypeRef accessibilityType = FLEXKeychain.accessibilityType; - if (accessibilityType) { - query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessibilityType; - } -#endif - status = SecItemUpdate((__bridge CFDictionaryRef)(searchQuery), (__bridge CFDictionaryRef)(query)); - }else if (status == errSecItemNotFound){//item not found, create it! - query = [self query]; - if (self.label) { - query[(__bridge id)kSecAttrLabel] = self.label; - } - query[(__bridge id)kSecValueData] = self.passwordData; -#if __IPHONE_4_0 && TARGET_OS_IPHONE - CFTypeRef accessibilityType = FLEXKeychain.accessibilityType; - if (accessibilityType) { - query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessibilityType; - } -#endif - status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); - } - - if (status != errSecSuccess && error != NULL) { - *error = [self errorWithCode:status]; - } - - return (status == errSecSuccess); -} - - -- (BOOL)deleteItem:(NSError *__autoreleasing *)error { - OSStatus status = FLEXKeychainErrorBadArguments; - if (!self.service || !self.account) { - if (error) { - *error = [self errorWithCode:status]; - } - - return NO; - } - - NSMutableDictionary *query = [self query]; -#if TARGET_OS_IPHONE - status = SecItemDelete((__bridge CFDictionaryRef)query); -#else - // On Mac OS, SecItemDelete will not delete a key created in a different - // app, nor in a different version of the same app. - // - // To replicate the issue, save a password, change to the code and - // rebuild the app, and then attempt to delete that password. - // - // This was true in OS X 10.6 and probably later versions as well. - // - // Work around it by using SecItemCopyMatching and SecKeychainItemDelete. - CFTypeRef result = NULL; - query[(__bridge id)kSecReturnRef] = @YES; - status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - if (status == errSecSuccess) { - status = SecKeychainItemDelete((SecKeychainItemRef)result); - CFRelease(result); - } -#endif - - if (status != errSecSuccess && error != NULL) { - *error = [self errorWithCode:status]; - } - - return (status == errSecSuccess); -} - - -- (NSArray *)fetchAll:(NSError *__autoreleasing *)error { - NSMutableDictionary *query = [self query]; - query[(__bridge id)kSecReturnAttributes] = @YES; - query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; -#if __IPHONE_4_0 && TARGET_OS_IPHONE - CFTypeRef accessibilityType = FLEXKeychain.accessibilityType; - if (accessibilityType) { - query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessibilityType; - } -#endif - - CFTypeRef result = NULL; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - if (status != errSecSuccess && error != NULL) { - *error = [self errorWithCode:status]; - return nil; - } - - return (__bridge_transfer NSArray *)result ?: @[]; -} - - -- (BOOL)fetch:(NSError *__autoreleasing *)error { - OSStatus status = FLEXKeychainErrorBadArguments; - if (!self.service || !self.account) { - if (error) { - *error = [self errorWithCode:status]; - } - return NO; - } - - CFTypeRef result = NULL; - NSMutableDictionary *query = [self query]; - query[(__bridge id)kSecReturnData] = @YES; - query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; - status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - - if (status != errSecSuccess) { - if (error) { - *error = [self errorWithCode:status]; - } - return NO; - } - - self.passwordData = (__bridge_transfer NSData *)result; - return YES; -} - - -#pragma mark - Accessors - -- (void)setPasswordObject:(id)object { - self.passwordData = [NSKeyedArchiver archivedDataWithRootObject:object]; -} - - -- (id)passwordObject { - if (self.passwordData.length) { - return [NSKeyedUnarchiver unarchiveObjectWithData:self.passwordData]; - } - - return nil; -} - - -- (void)setPassword:(NSString *)password { - self.passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; -} - - -- (NSString *)password { - if (self.passwordData.length) { - return [[NSString alloc] initWithData:self.passwordData encoding:NSUTF8StringEncoding]; - } - - return nil; -} - - -#pragma mark - Synchronization Status - -#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE -+ (BOOL)isSynchronizationAvailable { -#if TARGET_OS_IPHONE - return YES; -#else - return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; -#endif -} -#endif - - -#pragma mark - Private - -- (NSMutableDictionary *)query { - NSMutableDictionary *dictionary = [NSMutableDictionary new]; - dictionary[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; - - if (self.service) { - dictionary[(__bridge id)kSecAttrService] = self.service; - } - - if (self.account) { - dictionary[(__bridge id)kSecAttrAccount] = self.account; - } - -#ifdef FLEXKEYCHAIN_ACCESS_GROUP_AVAILABLE -#if !TARGET_IPHONE_SIMULATOR - if (self.accessGroup) { - dictionary[(__bridge id)kSecAttrAccessGroup] = self.accessGroup; - } -#endif -#endif - -#ifdef FLEXKEYCHAIN_SYNCHRONIZATION_AVAILABLE - if ([[self class] isSynchronizationAvailable]) { - id value; - - switch (self.synchronizationMode) { - case FLEXKeychainQuerySynchronizationModeNo: { - value = @NO; - break; - } - case FLEXKeychainQuerySynchronizationModeYes: { - value = @YES; - break; - } - case FLEXKeychainQuerySynchronizationModeAny: { - value = (__bridge id)(kSecAttrSynchronizableAny); - break; - } - } - - dictionary[(__bridge id)(kSecAttrSynchronizable)] = value; - } -#endif - - return dictionary; -} - -- (NSError *)errorWithCode:(OSStatus)code { - static dispatch_once_t onceToken; - static NSBundle *resourcesBundle = nil; - dispatch_once(&onceToken, ^{ - NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:@"FLEXKeychain" withExtension:@"bundle"]; - resourcesBundle = [NSBundle bundleWithURL:url]; - }); - - NSString *message = nil; - switch (code) { - case errSecSuccess: return nil; - case FLEXKeychainErrorBadArguments: message = NSLocalizedStringFromTableInBundle(@"FLEXKeychainErrorBadArguments", @"FLEXKeychain", resourcesBundle, nil); break; - -#if TARGET_OS_IPHONE - case errSecUnimplemented: { - message = NSLocalizedStringFromTableInBundle(@"errSecUnimplemented", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecParam: { - message = NSLocalizedStringFromTableInBundle(@"errSecParam", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecAllocate: { - message = NSLocalizedStringFromTableInBundle(@"errSecAllocate", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecNotAvailable: { - message = NSLocalizedStringFromTableInBundle(@"errSecNotAvailable", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecDuplicateItem: { - message = NSLocalizedStringFromTableInBundle(@"errSecDuplicateItem", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecItemNotFound: { - message = NSLocalizedStringFromTableInBundle(@"errSecItemNotFound", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecInteractionNotAllowed: { - message = NSLocalizedStringFromTableInBundle(@"errSecInteractionNotAllowed", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecDecode: { - message = NSLocalizedStringFromTableInBundle(@"errSecDecode", @"FLEXKeychain", resourcesBundle, nil); - break; - } - case errSecAuthFailed: { - message = NSLocalizedStringFromTableInBundle(@"errSecAuthFailed", @"FLEXKeychain", resourcesBundle, nil); - break; - } - default: { - message = NSLocalizedStringFromTableInBundle(@"errSecDefault", @"FLEXKeychain", resourcesBundle, nil); - } -#else - default: - message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL); -#endif - } - - NSDictionary *userInfo = message ? @{ NSLocalizedDescriptionKey : message } : nil; - return [NSError errorWithDomain:kFLEXKeychainErrorDomain code:code userInfo:userInfo]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainViewController.h b/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainViewController.h deleted file mode 100644 index 3545d21..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXKeychainViewController.h -// FLEX -// -// Created by ray on 2019/8/17. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsEntry.h" -#import "FLEXFilteringTableViewController.h" - -@interface FLEXKeychainViewController : FLEXFilteringTableViewController - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainViewController.m b/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainViewController.m deleted file mode 100644 index 745c33b..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/FLEXKeychainViewController.m +++ /dev/null @@ -1,254 +0,0 @@ -// -// FLEXKeychainViewController.m -// FLEX -// -// Created by ray on 2019/8/17. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXKeychain.h" -#import "FLEXKeychainQuery.h" -#import "FLEXKeychainViewController.h" -#import "FLEXTableViewCell.h" -#import "FLEXMutableListSection.h" -#import "FLEXUtility.h" -#import "UIPasteboard+FLEX.h" -#import "UIBarButtonItem+FLEX.h" - -@interface FLEXKeychainViewController () -@property (nonatomic, readonly) FLEXMutableListSection *section; -@end - -@implementation FLEXKeychainViewController - -- (id)init { - return [self initWithStyle:UITableViewStyleGrouped]; -} - -#pragma mark - Overrides - -- (void)viewDidLoad { - [super viewDidLoad]; - - [self addToolbarItems:@[ - FLEXBarButtonItemSystem(Add, self, @selector(addPressed)), - [FLEXBarButtonItemSystem(Trash, self, @selector(trashPressed:)) flex_withTintColor:UIColor.redColor], - ]]; - - [self reloadData]; -} - -- (NSArray *)makeSections { - _section = [FLEXMutableListSection list:FLEXKeychain.allAccounts.mutableCopy - cellConfiguration:^(__kindof FLEXTableViewCell *cell, NSDictionary *item, NSInteger row) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - id service = item[kFLEXKeychainWhereKey]; - if ([service isKindOfClass:[NSString class]]) { - cell.textLabel.text = service; - cell.detailTextLabel.text = [item[kFLEXKeychainAccountKey] description]; - } else { - cell.textLabel.text = [NSString stringWithFormat: - @"[%@]\n\n%@", - NSStringFromClass([service class]), - [service description] - ]; - } - } filterMatcher:^BOOL(NSString *filterText, NSDictionary *item) { - // Loop over contents of the keychain item looking for a match - for (NSString *field in item.allValues) { - if ([field isKindOfClass:[NSString class]]) { - if ([field localizedCaseInsensitiveContainsString:filterText]) { - return YES; - } - } - } - - return NO; - } - ]; - - return @[self.section]; -} - -/// We always want to show this section -- (NSArray *)nonemptySections { - return @[self.section]; -} - -- (void)reloadSections { - self.section.list = FLEXKeychain.allAccounts.mutableCopy; -} - -- (void)refreshSectionTitle { - self.section.customTitle = FLEXPluralString( - self.section.filteredList.count, @"items", @"item" - ); -} - -- (void)reloadData { - [self reloadSections]; - [self refreshSectionTitle]; - [super reloadData]; -} - - -#pragma mark - Private - -- (FLEXKeychainQuery *)queryForItemAtIndex:(NSInteger)idx { - NSDictionary *item = self.section.filteredList[idx]; - - FLEXKeychainQuery *query = [FLEXKeychainQuery new]; - query.service = [item[kFLEXKeychainWhereKey] description]; - query.account = [item[kFLEXKeychainAccountKey] description]; - query.accessGroup = [item[kFLEXKeychainGroupKey] description]; - [query fetch:nil]; - - return query; -} - -- (void)deleteItem:(NSDictionary *)item { - NSError *error = nil; - BOOL success = [FLEXKeychain - deletePasswordForService:item[kFLEXKeychainWhereKey] - account:item[kFLEXKeychainAccountKey] - error:&error - ]; - - if (!success) { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Error Deleting Item"); - make.message(error.localizedDescription); - } showFrom:self]; - } -} - - -#pragma mark Buttons - -- (void)trashPressed:(UIBarButtonItem *)sender { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - make.title(@"Clear Keychain"); - make.message(@"This will remove all keychain items for this app.\n"); - make.message(@"This action cannot be undone. Are you sure?"); - make.button(@"Yes, clear the keychain").destructiveStyle().handler(^(NSArray *strings) { - [self confirmClearKeychain]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; -} - -- (void)confirmClearKeychain { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"ARE YOU SURE?"); - make.message(@"This action CANNOT BE UNDONE.\nAre you sure you want to continue?\n"); - make.message(@"If you're sure, scroll to confirm."); - make.button(@"Yes, clear the keychain").destructiveStyle().handler(^(NSArray *strings) { - for (id account in self.section.list) { - [self deleteItem:account]; - } - - [self reloadData]; - }); - make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); - make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); - make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); - make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); make.button(@"Cancel"); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; -} - -- (void)addPressed { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Add Keychain Item"); - make.textField(@"Service name, i.e. Instagram"); - make.textField(@"Account"); - make.textField(@"Password"); - make.button(@"Cancel").cancelStyle(); - make.button(@"Save").handler(^(NSArray *strings) { - // Display errors - NSError *error = nil; - if (![FLEXKeychain setPassword:strings[2] forService:strings[0] account:strings[1] error:&error]) { - [FLEXAlert showAlert:@"Error" message:error.localizedDescription from:self]; - } - - [self reloadData]; - }); - } showFrom:self]; -} - - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"🔑 Keychain"; -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - FLEXKeychainViewController *viewController = [self new]; - viewController.title = [self globalsEntryTitle:row]; - - return viewController; -} - - -#pragma mark - Table View Data Source - -- (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)style forRowAtIndexPath:(NSIndexPath *)ip { - if (style == UITableViewCellEditingStyleDelete) { - // Update the model - NSDictionary *toRemove = self.section.filteredList[ip.row]; - [self deleteItem:toRemove]; - [self.section mutate:^(NSMutableArray *list) { - [list removeObject:toRemove]; - }]; - - // Delete the row - [tv deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationAutomatic]; - - // Update the title by refreshing the section without disturbing the delete animation - // - // This is an ugly hack, but literally nothing else works, save for manually getting - // the header and setting its title, which I personally think is worse since it - // would need to make assumptions about the default style of the header (CAPS) - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [self refreshSectionTitle]; - [tv reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone]; - }); - } -} - - -#pragma mark - Table View Delegate - -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXKeychainQuery *query = [self queryForItemAtIndex:indexPath.row]; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(query.service); - make.message(@"Service: ").message(query.service); - make.message(@"\nAccount: ").message(query.account); - make.message(@"\nPassword: ").message(query.password); - make.message(@"\nGroup: ").message(query.accessGroup); - - make.button(@"Copy Service").handler(^(NSArray *strings) { - [UIPasteboard.generalPasteboard flex_copy:query.service]; - }); - make.button(@"Copy Account").handler(^(NSArray *strings) { - [UIPasteboard.generalPasteboard flex_copy:query.account]; - }); - make.button(@"Copy Password").handler(^(NSArray *strings) { - [UIPasteboard.generalPasteboard flex_copy:query.password]; - }); - make.button(@"Dismiss").cancelStyle(); - - } showFrom:self]; - - [tableView deselectRowAtIndexPath:indexPath animated:YES]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/Keychain/SSKeychain_LICENSE b/Tweaks/FLEX/GlobalStateExplorers/Keychain/SSKeychain_LICENSE deleted file mode 100644 index b63e077..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/Keychain/SSKeychain_LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2010-2012 Sam Soffes. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeClient.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeClient.h deleted file mode 100644 index 03f263d..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeClient.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// FLEXRuntimeClient.h -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXSearchToken.h" -@class FLEXMethod; - -/// Accepts runtime queries given a token. -@interface FLEXRuntimeClient : NSObject - -@property (nonatomic, readonly, class) FLEXRuntimeClient *runtime; - -/// Called automatically when \c FLEXRuntime is first used. -/// You may call it again when you think a library has -/// been loaded since this method was first called. -- (void)reloadLibrariesList; - -/// You must call this method on the main thread -/// before you attempt to call \c copySafeClassList. -+ (void)initializeWebKitLegacy; - -/// Do not call unless you absolutely need all classes. This will cause -/// every class in the runtime to initialize itself, which is not common. -/// Before you call this method, call \c initializeWebKitLegacy on the main thread. -- (NSArray *)copySafeClassList; - -- (NSArray *)copyProtocolList; - -/// An array of strings representing the currently loaded libraries. -@property (nonatomic, readonly) NSArray *imageDisplayNames; - -/// "Image name" is the path of the bundle -- (NSString *)shortNameForImageName:(NSString *)imageName; -/// "Image name" is the path of the bundle -- (NSString *)imageNameForShortName:(NSString *)imageName; - -/// @return Bundle names for the UI -- (NSMutableArray *)bundleNamesForToken:(FLEXSearchToken *)token; -/// @return Bundle paths for more queries -- (NSMutableArray *)bundlePathsForToken:(FLEXSearchToken *)token; -/// @return Class names -- (NSMutableArray *)classesForToken:(FLEXSearchToken *)token - inBundles:(NSMutableArray *)bundlePaths; -/// @return A list of lists of \c FLEXMethods where -/// each list corresponds to one of the given classes -- (NSArray *> *)methodsForToken:(FLEXSearchToken *)token - instance:(NSNumber *)onlyInstanceMethods - inClasses:(NSArray *)classes; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeClient.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeClient.m deleted file mode 100644 index 34fac5e..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeClient.m +++ /dev/null @@ -1,416 +0,0 @@ -// -// FLEXRuntimeClient.m -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeClient.h" -#import "NSObject+FLEX_Reflection.h" -#import "FLEXMethod.h" -#import "NSArray+FLEX.h" -#import "FLEXRuntimeSafety.h" -#include - -#define Equals(a, b) ([a compare:b options:NSCaseInsensitiveSearch] == NSOrderedSame) -#define Contains(a, b) ([a rangeOfString:b options:NSCaseInsensitiveSearch].location != NSNotFound) -#define HasPrefix(a, b) ([a rangeOfString:b options:NSCaseInsensitiveSearch].location == 0) -#define HasSuffix(a, b) ([a rangeOfString:b options:NSCaseInsensitiveSearch].location == (a.length - b.length)) - - -@interface FLEXRuntimeClient () { - NSMutableArray *_imageDisplayNames; -} - -@property (nonatomic) NSMutableDictionary *bundles_pathToShort; -@property (nonatomic) NSMutableDictionary *bundles_shortToPath; -@property (nonatomic) NSCache *bundles_pathToClassNames; -@property (nonatomic) NSMutableArray *imagePaths; - -@end - -/// @return success if the map passes. -static inline NSString * TBWildcardMap_(NSString *token, NSString *candidate, NSString *success, TBWildcardOptions options) { - switch (options) { - case TBWildcardOptionsNone: - // Only "if equals" - if (Equals(candidate, token)) { - return success; - } - default: { - // Only "if contains" - if (options & TBWildcardOptionsPrefix && - options & TBWildcardOptionsSuffix) { - if (Contains(candidate, token)) { - return success; - } - } - // Only "if candidate ends with with token" - else if (options & TBWildcardOptionsPrefix) { - if (HasSuffix(candidate, token)) { - return success; - } - } - // Only "if candidate starts with with token" - else if (options & TBWildcardOptionsSuffix) { - // Case like "Bundle." where we want "" to match anything - if (!token.length) { - return success; - } - if (HasPrefix(candidate, token)) { - return success; - } - } - } - } - - return nil; -} - -/// @return candidate if the map passes. -static inline NSString * TBWildcardMap(NSString *token, NSString *candidate, TBWildcardOptions options) { - return TBWildcardMap_(token, candidate, candidate, options); -} - -@implementation FLEXRuntimeClient - -#pragma mark - Initialization - -+ (instancetype)runtime { - static FLEXRuntimeClient *runtime; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - runtime = [self new]; - [runtime reloadLibrariesList]; - }); - - return runtime; -} - -- (id)init { - self = [super init]; - if (self) { - _imagePaths = [NSMutableArray new]; - _bundles_pathToShort = [NSMutableDictionary new]; - _bundles_shortToPath = [NSMutableDictionary new]; - _bundles_pathToClassNames = [NSCache new]; - } - - return self; -} - -#pragma mark - Private - -- (void)reloadLibrariesList { - unsigned int imageCount = 0; - const char **imageNames = objc_copyImageNames(&imageCount); - - if (imageNames) { - NSMutableArray *imageNameStrings = [NSMutableArray flex_forEachUpTo:imageCount map:^NSString *(NSUInteger i) { - return @(imageNames[i]); - }]; - - self.imagePaths = imageNameStrings; - free(imageNames); - - // Sort alphabetically - [imageNameStrings sortUsingComparator:^NSComparisonResult(NSString *name1, NSString *name2) { - NSString *shortName1 = [self shortNameForImageName:name1]; - NSString *shortName2 = [self shortNameForImageName:name2]; - return [shortName1 caseInsensitiveCompare:shortName2]; - }]; - - // Cache image display names - _imageDisplayNames = [imageNameStrings flex_mapped:^id(NSString *path, NSUInteger idx) { - return [self shortNameForImageName:path]; - }]; - } -} - -- (NSString *)shortNameForImageName:(NSString *)imageName { - // Cache - NSString *shortName = _bundles_pathToShort[imageName]; - if (shortName) { - return shortName; - } - - NSArray *components = [imageName componentsSeparatedByString:@"/"]; - if (components.count >= 2) { - NSString *parentDir = components[components.count - 2]; - if ([parentDir hasSuffix:@".framework"] || [parentDir hasSuffix:@".axbundle"]) { - if ([imageName hasSuffix:@".dylib"]) { - shortName = imageName.lastPathComponent; - } else { - shortName = parentDir; - } - } - } - - if (!shortName) { - shortName = imageName.lastPathComponent; - } - - _bundles_pathToShort[imageName] = shortName; - _bundles_shortToPath[shortName] = imageName; - return shortName; -} - -- (NSString *)imageNameForShortName:(NSString *)imageName { - return _bundles_shortToPath[imageName]; -} - -- (NSMutableArray *)classNamesInImageAtPath:(NSString *)path { - // Check cache - NSMutableArray *classNameStrings = [_bundles_pathToClassNames objectForKey:path]; - if (classNameStrings) { - return classNameStrings.mutableCopy; - } - - unsigned int classCount = 0; - const char **classNames = objc_copyClassNamesForImage(path.UTF8String, &classCount); - - if (classNames) { - classNameStrings = [NSMutableArray flex_forEachUpTo:classCount map:^id(NSUInteger i) { - return @(classNames[i]); - }]; - - free(classNames); - - [classNameStrings sortUsingSelector:@selector(caseInsensitiveCompare:)]; - [_bundles_pathToClassNames setObject:classNameStrings forKey:path]; - - return classNameStrings.mutableCopy; - } - - return [NSMutableArray new]; -} - -#pragma mark - Public - -+ (void)initializeWebKitLegacy { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - void *handle = dlopen( - "/System/Library/PrivateFrameworks/WebKitLegacy.framework/WebKitLegacy", - RTLD_LAZY - ); - void (*WebKitInitialize)(void) = dlsym(handle, "WebKitInitialize"); - if (WebKitInitialize) { - NSAssert(NSThread.isMainThread, - @"WebKitInitialize can only be called on the main thread" - ); - WebKitInitialize(); - } - }); -} - -- (NSArray *)copySafeClassList { - unsigned int count = 0; - Class *classes = objc_copyClassList(&count); - return [NSArray flex_forEachUpTo:count map:^id(NSUInteger i) { - Class cls = classes[i]; - return FLEXClassIsSafe(cls) ? cls : nil; - }]; -} - -- (NSArray *)copyProtocolList { - unsigned int count = 0; - Protocol *__unsafe_unretained *protocols = objc_copyProtocolList(&count); - return [NSArray arrayWithObjects:protocols count:count]; -} - -- (NSMutableArray *)bundleNamesForToken:(FLEXSearchToken *)token { - if (self.imagePaths.count) { - TBWildcardOptions options = token.options; - NSString *query = token.string; - - // Optimization, avoid a loop - if (options == TBWildcardOptionsAny) { - return _imageDisplayNames; - } - - // No dot syntax because imageDisplayNames is only mutable internally - return [_imageDisplayNames flex_mapped:^id(NSString *binary, NSUInteger idx) { -// NSString *UIName = [self shortNameForImageName:binary]; - return TBWildcardMap(query, binary, options); - }]; - } - - return [NSMutableArray new]; -} - -- (NSMutableArray *)bundlePathsForToken:(FLEXSearchToken *)token { - if (self.imagePaths.count) { - TBWildcardOptions options = token.options; - NSString *query = token.string; - - // Optimization, avoid a loop - if (options == TBWildcardOptionsAny) { - return self.imagePaths; - } - - return [self.imagePaths flex_mapped:^id(NSString *binary, NSUInteger idx) { - NSString *UIName = [self shortNameForImageName:binary]; - // If query == UIName, -> binary - return TBWildcardMap_(query, UIName, binary, options); - }]; - } - - return [NSMutableArray new]; -} - -- (NSMutableArray *)classesForToken:(FLEXSearchToken *)token inBundles:(NSMutableArray *)bundles { - // Edge case where token is the class we want already; return superclasses - if (token.isAbsolute) { - if (FLEXClassIsSafe(NSClassFromString(token.string))) { - return [NSMutableArray arrayWithObject:token.string]; - } - - return [NSMutableArray new]; - } - - if (bundles.count) { - // Get class names, remove unsafe classes - NSMutableArray *names = [self _classesForToken:token inBundles:bundles]; - return [names flex_mapped:^NSString *(NSString *name, NSUInteger idx) { - Class cls = NSClassFromString(name); - BOOL safe = FLEXClassIsSafe(cls); - return safe ? name : nil; - }]; - } - - return [NSMutableArray new]; -} - -- (NSMutableArray *)_classesForToken:(FLEXSearchToken *)token inBundles:(NSMutableArray *)bundles { - TBWildcardOptions options = token.options; - NSString *query = token.string; - - // Optimization, avoid unnecessary sorting - if (bundles.count == 1) { - // Optimization, avoid a loop - if (options == TBWildcardOptionsAny) { - return [self classNamesInImageAtPath:bundles.firstObject]; - } - - return [[self classNamesInImageAtPath:bundles.firstObject] flex_mapped:^id(NSString *className, NSUInteger idx) { - return TBWildcardMap(query, className, options); - }]; - } - else { - // Optimization, avoid a loop - if (options == TBWildcardOptionsAny) { - return [[bundles flex_flatmapped:^NSArray *(NSString *bundlePath, NSUInteger idx) { - return [self classNamesInImageAtPath:bundlePath]; - }] flex_sortedUsingSelector:@selector(caseInsensitiveCompare:)]; - } - - return [[bundles flex_flatmapped:^NSArray *(NSString *bundlePath, NSUInteger idx) { - return [[self classNamesInImageAtPath:bundlePath] flex_mapped:^id(NSString *className, NSUInteger idx) { - return TBWildcardMap(query, className, options); - }]; - }] flex_sortedUsingSelector:@selector(caseInsensitiveCompare:)]; - } -} - -- (NSArray *> *)methodsForToken:(FLEXSearchToken *)token - instance:(NSNumber *)checkInstance - inClasses:(NSArray *)classes { - if (classes.count) { - TBWildcardOptions options = token.options; - BOOL instance = checkInstance.boolValue; - NSString *selector = token.string; - - switch (options) { - // In practice I don't think this case is ever used with methods, - // since they will always have a suffix wildcard at the end - case TBWildcardOptionsNone: { - SEL sel = (SEL)selector.UTF8String; - return @[[classes flex_mapped:^id(NSString *name, NSUInteger idx) { - Class cls = NSClassFromString(name); - // Use metaclass if not instance - if (!instance) { - cls = object_getClass(cls); - } - - // Method is absolute - return [FLEXMethod selector:sel class:cls]; - }]]; - } - case TBWildcardOptionsAny: { - return [classes flex_mapped:^NSArray *(NSString *name, NSUInteger idx) { - // Any means `instance` was not specified - Class cls = NSClassFromString(name); - return [cls flex_allMethods]; - }]; - } - default: { - // Only "if contains" - if (options & TBWildcardOptionsPrefix && - options & TBWildcardOptionsSuffix) { - return [classes flex_mapped:^NSArray *(NSString *name, NSUInteger idx) { - Class cls = NSClassFromString(name); - return [[cls flex_allMethods] flex_mapped:^id(FLEXMethod *method, NSUInteger idx) { - - // Method is a prefix-suffix wildcard - if (Contains(method.selectorString, selector)) { - return method; - } - return nil; - }]; - }]; - } - // Only "if method ends with with selector" - else if (options & TBWildcardOptionsPrefix) { - return [classes flex_mapped:^NSArray *(NSString *name, NSUInteger idx) { - Class cls = NSClassFromString(name); - - return [[cls flex_allMethods] flex_mapped:^id(FLEXMethod *method, NSUInteger idx) { - // Method is a prefix wildcard - if (HasSuffix(method.selectorString, selector)) { - return method; - } - return nil; - }]; - }]; - } - // Only "if method starts with with selector" - else if (options & TBWildcardOptionsSuffix) { - assert(checkInstance); - - return [classes flex_mapped:^NSArray *(NSString *name, NSUInteger idx) { - Class cls = NSClassFromString(name); - - // Case like "Bundle.class.-" where we want "-" to match anything - if (!selector.length) { - if (instance) { - return [cls flex_allInstanceMethods]; - } else { - return [cls flex_allClassMethods]; - } - } - - id mapping = ^id(FLEXMethod *method) { - // Method is a suffix wildcard - if (HasPrefix(method.selectorString, selector)) { - return method; - } - return nil; - }; - - if (instance) { - return [[cls flex_allInstanceMethods] flex_mapped:mapping]; - } else { - return [[cls flex_allClassMethods] flex_mapped:mapping]; - } - }]; - } - } - } - } - - return [NSMutableArray new]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeController.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeController.h deleted file mode 100644 index 968c975..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeController.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// FLEXRuntimeController.h -// FLEX -// -// Created by Tanner on 3/23/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeKeyPath.h" - -/// Wraps FLEXRuntimeClient and provides extra caching mechanisms -@interface FLEXRuntimeController : NSObject - -/// @return An array of strings if the key path only evaluates -/// to a class or bundle; otherwise, a list of lists of FLEXMethods. -+ (NSArray *)dataForKeyPath:(FLEXRuntimeKeyPath *)keyPath; - -/// Useful when you need to specify which classes to search in. -/// \c dataForKeyPath: will only search classes matching the class key. -/// We use this elsewhere when we need to search a class hierarchy. -+ (NSArray *> *)methodsForToken:(FLEXSearchToken *)token - instance:(NSNumber *)onlyInstanceMethods - inClasses:(NSArray *)classes; - -/// Useful when you need the classes that are associated with the -/// double list of methods returned from \c dataForKeyPath -+ (NSMutableArray *)classesForKeyPath:(FLEXRuntimeKeyPath *)keyPath; - -+ (NSString *)shortBundleNameForClass:(NSString *)name; - -+ (NSString *)imagePathWithShortName:(NSString *)suffix; - -/// Gives back short names. For example, "Foundation.framework" -+ (NSArray *)allBundleNames; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeController.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeController.m deleted file mode 100644 index 64dda72..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeController.m +++ /dev/null @@ -1,192 +0,0 @@ -// -// FLEXRuntimeController.m -// FLEX -// -// Created by Tanner on 3/23/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeController.h" -#import "FLEXRuntimeClient.h" -#import "FLEXMethod.h" - -@interface FLEXRuntimeController () -@property (nonatomic, readonly) NSCache *bundlePathsCache; -@property (nonatomic, readonly) NSCache *bundleNamesCache; -@property (nonatomic, readonly) NSCache *classNamesCache; -@property (nonatomic, readonly) NSCache *methodsCache; -@end - -@implementation FLEXRuntimeController - -#pragma mark Initialization - -static FLEXRuntimeController *controller = nil; -+ (instancetype)shared { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - controller = [self new]; - }); - - return controller; -} - -- (id)init { - self = [super init]; - if (self) { - _bundlePathsCache = [NSCache new]; - _bundleNamesCache = [NSCache new]; - _classNamesCache = [NSCache new]; - _methodsCache = [NSCache new]; - } - - return self; -} - -#pragma mark Public - -+ (NSArray *)dataForKeyPath:(FLEXRuntimeKeyPath *)keyPath { - if (keyPath.bundleKey) { - if (keyPath.classKey) { - if (keyPath.methodKey) { - return [[self shared] methodsForKeyPath:keyPath]; - } else { - return [[self shared] classesForKeyPath:keyPath]; - } - } else { - return [[self shared] bundleNamesForToken:keyPath.bundleKey]; - } - } else { - return @[]; - } -} - -+ (NSArray *> *)methodsForToken:(FLEXSearchToken *)token - instance:(NSNumber *)inst - inClasses:(NSArray *)classes { - return [FLEXRuntimeClient.runtime - methodsForToken:token - instance:inst - inClasses:classes - ]; -} - -+ (NSMutableArray *)classesForKeyPath:(FLEXRuntimeKeyPath *)keyPath { - return [[self shared] classesForKeyPath:keyPath]; -} - -+ (NSString *)shortBundleNameForClass:(NSString *)name { - const char *imageName = class_getImageName(NSClassFromString(name)); - if (!imageName) { - return @"(unspecified)"; - } - - return [FLEXRuntimeClient.runtime shortNameForImageName:@(imageName)]; -} - -+ (NSString *)imagePathWithShortName:(NSString *)suffix { - return [FLEXRuntimeClient.runtime imageNameForShortName:suffix]; -} - -+ (NSArray *)allBundleNames { - return FLEXRuntimeClient.runtime.imageDisplayNames; -} - -#pragma mark Private - -- (NSMutableArray *)bundlePathsForToken:(FLEXSearchToken *)token { - // Only cache if no wildcard - BOOL shouldCache = token == TBWildcardOptionsNone; - - if (shouldCache) { - NSMutableArray *cached = [self.bundlePathsCache objectForKey:token]; - if (cached) { - return cached; - } - - NSMutableArray *bundles = [FLEXRuntimeClient.runtime bundlePathsForToken:token]; - [self.bundlePathsCache setObject:bundles forKey:token]; - return bundles; - } - else { - return [FLEXRuntimeClient.runtime bundlePathsForToken:token]; - } -} - -- (NSMutableArray *)bundleNamesForToken:(FLEXSearchToken *)token { - // Only cache if no wildcard - BOOL shouldCache = token == TBWildcardOptionsNone; - - if (shouldCache) { - NSMutableArray *cached = [self.bundleNamesCache objectForKey:token]; - if (cached) { - return cached; - } - - NSMutableArray *bundles = [FLEXRuntimeClient.runtime bundleNamesForToken:token]; - [self.bundleNamesCache setObject:bundles forKey:token]; - return bundles; - } - else { - return [FLEXRuntimeClient.runtime bundleNamesForToken:token]; - } -} - -- (NSMutableArray *)classesForKeyPath:(FLEXRuntimeKeyPath *)keyPath { - FLEXSearchToken *classToken = keyPath.classKey; - FLEXSearchToken *bundleToken = keyPath.bundleKey; - - // Only cache if no wildcard - BOOL shouldCache = bundleToken.options == 0 && classToken.options == 0; - NSString *key = nil; - - if (shouldCache) { - key = [@[bundleToken.description, classToken.description] componentsJoinedByString:@"+"]; - NSMutableArray *cached = [self.classNamesCache objectForKey:key]; - if (cached) { - return cached; - } - } - - NSMutableArray *bundles = [self bundlePathsForToken:bundleToken]; - NSMutableArray *classes = [FLEXRuntimeClient.runtime - classesForToken:classToken inBundles:bundles - ]; - - if (shouldCache) { - [self.classNamesCache setObject:classes forKey:key]; - } - - return classes; -} - -- (NSArray *> *)methodsForKeyPath:(FLEXRuntimeKeyPath *)keyPath { - // Only cache if no wildcard, but check cache anyway bc I'm lazy - NSArray *cached = [self.methodsCache objectForKey:keyPath]; - if (cached) { - return cached; - } - - NSArray *classes = [self classesForKeyPath:keyPath]; - NSArray *> *methodLists = [FLEXRuntimeClient.runtime - methodsForToken:keyPath.methodKey - instance:keyPath.instanceMethods - inClasses:classes - ]; - - for (NSMutableArray *methods in methodLists) { - [methods sortUsingComparator:^NSComparisonResult(FLEXMethod *m1, FLEXMethod *m2) { - return [m1.description caseInsensitiveCompare:m2.description]; - }]; - } - - // Only cache if no wildcard, otherwise the cache could grow very large - if (keyPath.bundleKey.isAbsolute && - keyPath.classKey.isAbsolute) { - [self.methodsCache setObject:methodLists forKey:keyPath]; - } - - return methodLists; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeExporter.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeExporter.h deleted file mode 100644 index 69ce1cf..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeExporter.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// FLEXRuntimeExporter.h -// FLEX -// -// Created by Tanner Bennett on 3/26/20. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/// A class for exporting all runtime metadata to an SQLite database. -//API_AVAILABLE(ios(10.0)) -@interface FLEXRuntimeExporter : NSObject - -+ (void)createRuntimeDatabaseAtPath:(NSString *)path - progressHandler:(void(^)(NSString *status))progress - completion:(void(^)(NSString *_Nullable error))completion; - -+ (void)createRuntimeDatabaseAtPath:(NSString *)path - forImages:(nullable NSArray *)images - progressHandler:(void(^)(NSString *status))progress - completion:(void(^)(NSString *_Nullable error))completion; - - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeExporter.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeExporter.m deleted file mode 100644 index 0b89a6c..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/DataSources/FLEXRuntimeExporter.m +++ /dev/null @@ -1,875 +0,0 @@ -// -// FLEXRuntimeExporter.m -// FLEX -// -// Created by Tanner Bennett on 3/26/20. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeExporter.h" -#import "FLEXSQLiteDatabaseManager.h" -#import "NSObject+FLEX_Reflection.h" -#import "FLEXRuntimeController.h" -#import "FLEXRuntimeClient.h" -#import "NSArray+FLEX.h" -#import "FLEXTypeEncodingParser.h" -#import - -#import "FLEXProtocol.h" -#import "FLEXProperty.h" -#import "FLEXIvar.h" -#import "FLEXMethodBase.h" -#import "FLEXMethod.h" -#import "FLEXPropertyAttributes.h" - -NSString * const kFREEnableForeignKeys = @"PRAGMA foreign_keys = ON;"; - -/// Loaded images -NSString * const kFRECreateTableMachOCommand = @"CREATE TABLE MachO( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "shortName TEXT, " - "imagePath TEXT, " - "bundleID TEXT " -");"; - -NSString * const kFREInsertImage = @"INSERT INTO MachO ( " - "shortName, imagePath, bundleID " -") VALUES ( " - "$shortName, $imagePath, $bundleID " -");"; - -/// Objc classes -NSString * const kFRECreateTableClassCommand = @"CREATE TABLE Class( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "className TEXT, " - "superclass INTEGER, " - "instanceSize INTEGER, " - "version INTEGER, " - "image INTEGER, " - - "FOREIGN KEY(superclass) REFERENCES Class(id), " - "FOREIGN KEY(image) REFERENCES MachO(id) " -");"; - -NSString * const kFREInsertClass = @"INSERT INTO Class ( " - "className, instanceSize, version, image " -") VALUES ( " - "$className, $instanceSize, $version, $image " -");"; - -NSString * const kFREUpdateClassSetSuper = @"UPDATE Class SET superclass = $super WHERE id = $id;"; - -/// Unique objc selectors -NSString * const kFRECreateTableSelectorCommand = @"CREATE TABLE Selector( " - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " - "name text NOT NULL UNIQUE " -");"; - -NSString * const kFREInsertSelector = @"INSERT OR IGNORE INTO Selector (name) VALUES ($name);"; - -/// Unique objc type encodings -NSString * const kFRECreateTableTypeEncodingCommand = @"CREATE TABLE TypeEncoding( " - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " - "string text NOT NULL UNIQUE, " - "size integer " -");"; - -NSString * const kFREInsertTypeEncoding = @"INSERT OR IGNORE INTO TypeEncoding " - "(string, size) VALUES ($type, $size);"; - -/// Unique objc type signatures -NSString * const kFRECreateTableTypeSignatureCommand = @"CREATE TABLE TypeSignature( " - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " - "string text NOT NULL UNIQUE " -");"; - -NSString * const kFREInsertTypeSignature = @"INSERT OR IGNORE INTO TypeSignature " - "(string) VALUES ($type);"; - -NSString * const kFRECreateTableMethodSignatureCommand = @"CREATE TABLE MethodSignature( " - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " - "typeEncoding TEXT, " - "argc INTEGER, " - "returnType INTEGER, " - "frameLength INTEGER, " - - "FOREIGN KEY(returnType) REFERENCES TypeEncoding(id) " -");"; - -NSString * const kFREInsertMethodSignature = @"INSERT INTO MethodSignature ( " - "typeEncoding, argc, returnType, frameLength " -") VALUES ( " - "$typeEncoding, $argc, $returnType, $frameLength " -");"; - -NSString * const kFRECreateTableMethodCommand = @"CREATE TABLE Method( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "sel INTEGER, " - "class INTEGER, " - "instance INTEGER, " // 0 if class method, 1 if instance method - "signature INTEGER, " - "image INTEGER, " - - "FOREIGN KEY(sel) REFERENCES Selector(id), " - "FOREIGN KEY(class) REFERENCES Class(id), " - "FOREIGN KEY(signature) REFERENCES MethodSignature(id), " - "FOREIGN KEY(image) REFERENCES MachO(id) " -");"; - -NSString * const kFREInsertMethod = @"INSERT INTO Method ( " - "sel, class, instance, signature, image " -") VALUES ( " - "$sel, $class, $instance, $signature, $image " -");"; - -NSString * const kFRECreateTablePropertyCommand = @"CREATE TABLE Property( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "name TEXT, " - "class INTEGER, " - "instance INTEGER, " // 0 if class prop, 1 if instance prop - "image INTEGER, " - "attributes TEXT, " - - "customGetter INTEGER, " - "customSetter INTEGER, " - - "type INTEGER, " - "ivar TEXT, " - "readonly INTEGER, " - "copy INTEGER, " - "retained INTEGER, " - "nonatomic INTEGER, " - "dynamic INTEGER, " - "weak INTEGER, " - "canGC INTEGER, " - - "FOREIGN KEY(class) REFERENCES Class(id), " - "FOREIGN KEY(customGetter) REFERENCES Selector(id), " - "FOREIGN KEY(customSetter) REFERENCES Selector(id), " - "FOREIGN KEY(image) REFERENCES MachO(id) " -");"; - -NSString * const kFREInsertProperty = @"INSERT INTO Property ( " - "name, class, instance, attributes, image, " - "customGetter, customSetter, type, ivar, readonly, " - "copy, retained, nonatomic, dynamic, weak, canGC " -") VALUES ( " - "$name, $class, $instance, $attributes, $image, " - "$customGetter, $customSetter, $type, $ivar, $readonly, " - "$copy, $retained, $nonatomic, $dynamic, $weak, $canGC " -");"; - -NSString * const kFRECreateTableIvarCommand = @"CREATE TABLE Ivar( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "name TEXT, " - "offset INTEGER, " - "type INTEGER, " - "class INTEGER, " - "image INTEGER, " - - "FOREIGN KEY(type) REFERENCES TypeEncoding(id), " - "FOREIGN KEY(class) REFERENCES Class(id), " - "FOREIGN KEY(image) REFERENCES MachO(id) " -");"; - -NSString * const kFREInsertIvar = @"INSERT INTO Ivar ( " - "name, offset, type, class, image " -") VALUES ( " - "$name, $offset, $type, $class, $image " -");"; - -NSString * const kFRECreateTableProtocolCommand = @"CREATE TABLE Protocol( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "name TEXT, " - "image INTEGER, " - - "FOREIGN KEY(image) REFERENCES MachO(id) " -");"; - -NSString * const kFREInsertProtocol = @"INSERT INTO Protocol " - "(name, image) VALUES ($name, $image);"; - -NSString * const kFRECreateTableProtocolPropertyCommand = @"CREATE TABLE ProtocolMember( " - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "protocol INTEGER, " - "required INTEGER, " - "instance INTEGER, " // 0 if class member, 1 if instance member - - // Only of the two below is used - "property TEXT, " - "method TEXT, " - - "image INTEGER, " - - "FOREIGN KEY(protocol) REFERENCES Protocol(id), " - "FOREIGN KEY(image) REFERENCES MachO(id) " -");"; - -NSString * const kFREInsertProtocolMember = @"INSERT INTO ProtocolMember ( " - "protocol, required, instance, property, method, image " -") VALUES ( " - "$protocol, $required, $instance, $property, $method, $image " -");"; - -/// For protocols conforming to other protocols -NSString * const kFRECreateTableProtocolConformanceCommand = @"CREATE TABLE ProtocolConformance( " - "protocol INTEGER, " - "conformance INTEGER, " - - "FOREIGN KEY(protocol) REFERENCES Protocol(id), " - "FOREIGN KEY(conformance) REFERENCES Protocol(id) " -");"; - -NSString * const kFREInsertProtocolConformance = @"INSERT INTO ProtocolConformance " -"(protocol, conformance) VALUES ($protocol, $conformance);"; - -/// For classes conforming to protocols -NSString * const kFRECreateTableClassConformanceCommand = @"CREATE TABLE ClassConformance( " - "class INTEGER, " - "conformance INTEGER, " - - "FOREIGN KEY(class) REFERENCES Class(id), " - "FOREIGN KEY(conformance) REFERENCES Protocol(id) " -");"; - -NSString * const kFREInsertClassConformance = @"INSERT INTO ClassConformance " -"(class, conformance) VALUES ($class, $conformance);"; - -@interface FLEXRuntimeExporter () -@property (nonatomic, readonly) FLEXSQLiteDatabaseManager *db; -@property (nonatomic, copy) NSArray *loadedShortBundleNames; -@property (nonatomic, copy) NSArray *loadedBundlePaths; -@property (nonatomic, copy) NSArray *protocols; -@property (nonatomic, copy) NSArray *classes; - -@property (nonatomic) NSMutableDictionary *bundlePathsToIDs; -@property (nonatomic) NSMutableDictionary *protocolsToIDs; -@property (nonatomic) NSMutableDictionary *classesToIDs; -@property (nonatomic) NSMutableDictionary *typeEncodingsToIDs; -@property (nonatomic) NSMutableDictionary *methodSignaturesToIDs; -@property (nonatomic) NSMutableDictionary *selectorsToIDs; -@end - -@implementation FLEXRuntimeExporter - -+ (NSString *)tempFilename { - NSString *temp = NSTemporaryDirectory(); - NSString *uuid = [NSUUID.UUID.UUIDString substringToIndex:8]; - NSString *filename = [NSString stringWithFormat:@"FLEXRuntimeDatabase-%@.db", uuid]; - return [temp stringByAppendingPathComponent:filename]; -} - -+ (void)createRuntimeDatabaseAtPath:(NSString *)path - progressHandler:(void(^)(NSString *status))progress - completion:(void (^)(NSString *))completion { - [self createRuntimeDatabaseAtPath:path forImages:nil progressHandler:progress completion:completion]; -} - -+ (void)createRuntimeDatabaseAtPath:(NSString *)path - forImages:(NSArray *)images - progressHandler:(void(^)(NSString *status))progress - completion:(void(^)(NSString *_Nullable error))completion { - __typeof(completion) callback = ^(NSString *error) { - dispatch_async(dispatch_get_main_queue(), ^{ - completion(error); - }); - }; - - // This must be called on the main thread first - if (NSThread.isMainThread) { - [FLEXRuntimeClient initializeWebKitLegacy]; - } else { - dispatch_sync(dispatch_get_main_queue(), ^{ - [FLEXRuntimeClient initializeWebKitLegacy]; - }); - } - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - NSError *error = nil; - NSString *errorMessage = nil; - - // Get unused temp filename, remove existing database if any - NSString *tempPath = [self tempFilename]; - if ([NSFileManager.defaultManager fileExistsAtPath:tempPath]) { - [NSFileManager.defaultManager removeItemAtPath:tempPath error:&error]; - if (error) { - callback(error.localizedDescription); - return; - } - } - - // Attempt to create and populate the database, abort if we fail - FLEXRuntimeExporter *exporter = [self new]; - exporter.loadedBundlePaths = images; - if (![exporter createAndPopulateDatabaseAtPath:tempPath - progressHandler:progress - error:&errorMessage]) { - // Remove temp database if it was not moved - if ([NSFileManager.defaultManager fileExistsAtPath:tempPath]) { - [NSFileManager.defaultManager removeItemAtPath:tempPath error:nil]; - } - - callback(errorMessage); - return; - } - - // Remove old database at given path - if ([NSFileManager.defaultManager fileExistsAtPath:path]) { - [NSFileManager.defaultManager removeItemAtPath:path error:&error]; - if (error) { - callback(error.localizedDescription); - return; - } - } - - // Move new database to desired path - [NSFileManager.defaultManager moveItemAtPath:tempPath toPath:path error:&error]; - if (error) { - callback(error.localizedDescription); - } - - // Remove temp database if it was not moved - if ([NSFileManager.defaultManager fileExistsAtPath:tempPath]) { - [NSFileManager.defaultManager removeItemAtPath:tempPath error:nil]; - } - - callback(nil); - }); -} - -- (id)init { - self = [super init]; - if (self) { - _bundlePathsToIDs = [NSMutableDictionary new]; - _protocolsToIDs = [NSMutableDictionary new]; - _classesToIDs = [NSMutableDictionary new]; - _typeEncodingsToIDs = [NSMutableDictionary new]; - _methodSignaturesToIDs = [NSMutableDictionary new]; - _selectorsToIDs = [NSMutableDictionary new]; - - _bundlePathsToIDs[NSNull.null] = (id)NSNull.null; - } - - return self; -} - -- (BOOL)createAndPopulateDatabaseAtPath:(NSString *)path - progressHandler:(void(^)(NSString *status))step - error:(NSString **)error { - _db = [FLEXSQLiteDatabaseManager managerForDatabase:path]; - - [self loadMetadata:step]; - - if ([self createTables] && [self addImages:step] && [self addProtocols:step] && - [self addClasses:step] && [self setSuperclasses:step] && - [self addProtocolConformances:step] && [self addClassConformances:step] && - [self addIvars:step] && [self addMethods:step] && [self addProperties:step]) { - _db = nil; // Close the database - return YES; - } - - *error = self.db.lastResult.message; - return NO; -} - -- (void)loadMetadata:(void(^)(NSString *status))progress { - progress(@"Loading metadata…"); - - FLEXRuntimeClient *runtime = FLEXRuntimeClient.runtime; - - // Only load metadata for the existing paths if any - if (self.loadedBundlePaths) { - // Images - self.loadedShortBundleNames = [self.loadedBundlePaths flex_mapped:^id(NSString *path, NSUInteger idx) { - return [runtime shortNameForImageName:path]; - }]; - - // Classes - self.classes = [[runtime classesForToken:FLEXSearchToken.any - inBundles:self.loadedBundlePaths.mutableCopy - ] flex_mapped:^id(NSString *cls, NSUInteger idx) { - return NSClassFromString(cls); - }]; - } else { - // Images - self.loadedShortBundleNames = runtime.imageDisplayNames; - self.loadedBundlePaths = [self.loadedShortBundleNames flex_mapped:^id(NSString *name, NSUInteger idx) { - return [runtime imageNameForShortName:name]; - }]; - - // Classes - self.classes = [runtime copySafeClassList]; - } - - // ...except protocols, because there's not a lot of them - // and there's no way load the protocols for a given image - self.protocols = [[runtime copyProtocolList] flex_mapped:^id(Protocol *proto, NSUInteger idx) { - return [FLEXProtocol protocol:proto]; - }]; -} - -- (BOOL)createTables { - NSArray *commands = @[ - kFREEnableForeignKeys, - kFRECreateTableMachOCommand, - kFRECreateTableClassCommand, - kFRECreateTableSelectorCommand, - kFRECreateTableTypeEncodingCommand, - kFRECreateTableTypeSignatureCommand, - kFRECreateTableMethodSignatureCommand, - kFRECreateTableMethodCommand, - kFRECreateTablePropertyCommand, - kFRECreateTableIvarCommand, - kFRECreateTableProtocolCommand, - kFRECreateTableProtocolPropertyCommand, - kFRECreateTableProtocolConformanceCommand, - kFRECreateTableClassConformanceCommand - ]; - - for (NSString *command in commands) { - if (![self.db executeStatement:command]) { - return NO; - } - } - - return YES; -} - -- (BOOL)addImages:(void(^)(NSString *status))progress { - progress(@"Adding loaded images…"); - - FLEXSQLiteDatabaseManager *database = self.db; - NSArray *shortNames = self.loadedShortBundleNames; - NSArray *fullPaths = self.loadedBundlePaths; - NSParameterAssert(shortNames.count == fullPaths.count); - - NSInteger count = shortNames.count; - for (NSInteger i = 0; i < count; i++) { - // Grab bundle ID - NSString *bundleID = [NSBundle - bundleWithPath:fullPaths[i] - ].bundleIdentifier; - - [database executeStatement:kFREInsertImage arguments:@{ - @"$shortName": shortNames[i], - @"$imagePath": fullPaths[i], - @"$bundleID": bundleID ?: NSNull.null - }]; - - if (database.lastResult.isError) { - return NO; - } else { - self.bundlePathsToIDs[fullPaths[i]] = @(database.lastRowID); - } - } - - return YES; -} - -NS_INLINE BOOL FREInsertProtocolMember(FLEXSQLiteDatabaseManager *db, - id proto, id required, id instance, - id prop, id methSel, id image) { - return ![db executeStatement:kFREInsertProtocolMember arguments:@{ - @"$protocol": proto, - @"$required": required, - @"$instance": instance ?: NSNull.null, - @"$property": prop ?: NSNull.null, - @"$method": methSel ?: NSNull.null, - @"$image": image - }].isError; -} - -- (BOOL)addProtocols:(void(^)(NSString *status))progress { - progress([NSString stringWithFormat:@"Adding %@ protocols…", @(self.protocols.count)]); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *imageIDs = self.bundlePathsToIDs; - - for (FLEXProtocol *proto in self.protocols) { - id imagePath = proto.imagePath ?: NSNull.null; - NSNumber *image = imageIDs[imagePath] ?: NSNull.null; - NSNumber *pid = nil; - - // Insert protocol - BOOL failed = [database executeStatement:kFREInsertProtocol arguments:@{ - @"$name": proto.name, @"$image": image - }].isError; - - // Cache rowid - if (failed) { - return NO; - } else { - self.protocolsToIDs[proto.name] = pid = @(database.lastRowID); - } - - // Insert its members // - - // Required methods - for (FLEXMethodDescription *method in proto.requiredMethods) { - NSString *selector = NSStringFromSelector(method.selector); - if (!FREInsertProtocolMember(database, pid, @YES, method.instance, nil, selector, image)) { - return NO; - } - } - // Optional methods - for (FLEXMethodDescription *method in proto.optionalMethods) { - NSString *selector = NSStringFromSelector(method.selector); - if (!FREInsertProtocolMember(database, pid, @NO, method.instance, nil, selector, image)) { - return NO; - } - } - - if (@available(iOS 10, *)) { - // Required properties - for (FLEXProperty *property in proto.requiredProperties) { - BOOL success = FREInsertProtocolMember( - database, pid, @YES, @(property.isClassProperty), property.name, NSNull.null, image - ); - - if (!success) return NO; - } - // Optional properties - for (FLEXProperty *property in proto.optionalProperties) { - BOOL success = FREInsertProtocolMember( - database, pid, @NO, @(property.isClassProperty), property.name, NSNull.null, image - ); - - if (!success) return NO; - } - } else { - // Just... properties. - for (FLEXProperty *property in proto.properties) { - BOOL success = FREInsertProtocolMember( - database, pid, nil, @(property.isClassProperty), property.name, NSNull.null, image - ); - - if (!success) return NO; - } - } - } - - return YES; -} - -- (BOOL)addProtocolConformances:(void(^)(NSString *status))progress { - progress(@"Adding protocol-to-protocol conformances…"); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *protocolIDs = self.protocolsToIDs; - - for (FLEXProtocol *proto in self.protocols) { - id protoID = protocolIDs[proto.name]; - - for (FLEXProtocol *conform in proto.protocols) { - BOOL failed = [database executeStatement:kFREInsertProtocolConformance arguments:@{ - @"$protocol": protoID, - @"$conformance": protocolIDs[conform.name] - }].isError; - - if (failed) { - return NO; - } - } - } - - return YES; -} - -- (BOOL)addClasses:(void(^)(NSString *status))progress { - progress([NSString stringWithFormat:@"Adding %@ classes…", @(self.classes.count)]); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *imageIDs = self.bundlePathsToIDs; - - for (Class cls in self.classes) { - const char *imageName = class_getImageName(cls); - id image = imageName ? imageIDs[@(imageName)] : NSNull.null; - image = image ?: NSNull.null; - - BOOL failed = [database executeStatement:kFREInsertClass arguments:@{ - @"$className": NSStringFromClass(cls), - @"$instanceSize": @(class_getInstanceSize(cls)), - @"$version": @(class_getVersion(cls)), - @"$image": image - }].isError; - - if (failed) { - return NO; - } else { - self.classesToIDs[(id)cls] = @(database.lastRowID); - } - } - - return YES; -} - -- (BOOL)setSuperclasses:(void(^)(NSString *status))progress { - progress(@"Setting superclasses…"); - - FLEXSQLiteDatabaseManager *database = self.db; - - for (Class cls in self.classes) { - // Grab superclass ID - Class superclass = class_getSuperclass(cls); - NSNumber *superclassID = _classesToIDs[class_getSuperclass(cls)]; - - // ... or add the superclass and cache its ID if the - // superclass does not reside in the target image(s) - if (!superclassID) { - NSDictionary *args = @{ @"$className": NSStringFromClass(superclass) }; - BOOL failed = [database executeStatement:kFREInsertClass arguments:args].isError; - if (failed) { return NO; } - - _classesToIDs[(id)superclass] = superclassID = @(database.lastRowID); - } - - if (superclass) { - BOOL failed = [database executeStatement:kFREUpdateClassSetSuper arguments:@{ - @"$super": superclassID, @"$id": _classesToIDs[cls] - }].isError; - - if (failed) { - return NO; - } - } - } - - return YES; -} - -- (BOOL)addClassConformances:(void(^)(NSString *status))progress { - progress(@"Adding class-to-protocol conformances…"); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *protocolIDs = self.protocolsToIDs; - NSDictionary *classIDs = self.classesToIDs; - - for (Class cls in self.classes) { - id classID = classIDs[(id)cls]; - - for (FLEXProtocol *conform in FLEXGetConformedProtocols(cls)) { - BOOL failed = [database executeStatement:kFREInsertClassConformance arguments:@{ - @"$class": classID, - @"$conformance": protocolIDs[conform.name] - }].isError; - - if (failed) { - return NO; - } - } - } - - return YES; -} - -- (BOOL)addIvars:(void(^)(NSString *status))progress { - progress(@"Adding ivars…"); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *imageIDs = self.bundlePathsToIDs; - - for (Class cls in self.classes) { - for (FLEXIvar *ivar in FLEXGetAllIvars(cls)) { - // Insert type first - if (![self addTypeEncoding:ivar.typeEncoding size:ivar.size]) { - return NO; - } - - id imagePath = ivar.imagePath ?: NSNull.null; - NSNumber *image = imageIDs[imagePath] ?: NSNull.null; - - BOOL failed = [database executeStatement:kFREInsertIvar arguments:@{ - @"$name": ivar.name, - @"$offset": @(ivar.offset), - @"$type": _typeEncodingsToIDs[ivar.typeEncoding], - @"$class": _classesToIDs[cls], - @"$image": image - }].isError; - - if (failed) { - return NO; - } - } - } - - return YES; -} - -- (BOOL)addMethods:(void(^)(NSString *status))progress { - progress(@"Adding methods…"); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *imageIDs = self.bundlePathsToIDs; - - // Loop over all classes - for (Class cls in self.classes) { - NSNumber *classID = _classesToIDs[(id)cls]; - const char *imageName = class_getImageName(cls); - id image = imageName ? imageIDs[@(imageName)] : NSNull.null; - image = image ?: NSNull.null; - - // Block used to process each message - BOOL (^insert)(FLEXMethod *, NSNumber *) = ^BOOL(FLEXMethod *method, NSNumber *instance) { - // Insert selector and signature first - if (![self addSelector:method.selectorString]) { - return NO; - } - if (![self addMethodSignature:method]) { - return NO; - } - - return ![database executeStatement:kFREInsertMethod arguments:@{ - @"$sel": self->_selectorsToIDs[method.selectorString], - @"$class": classID, - @"$instance": instance, - @"$signature": self->_methodSignaturesToIDs[method.signatureString], - @"$image": image - }].isError; - }; - - // Loop over all instance and class methods of that class // - - for (FLEXMethod *method in FLEXGetAllMethods(cls, YES)) { - if (!insert(method, @YES)) { - return NO; - } - } - for (FLEXMethod *method in FLEXGetAllMethods(object_getClass(cls), NO)) { - if (!insert(method, @NO)) { - return NO; - } - } - } - - return YES; -} - -- (BOOL)addProperties:(void(^)(NSString *status))progress { - progress(@"Adding properties…"); - - FLEXSQLiteDatabaseManager *database = self.db; - NSDictionary *imageIDs = self.bundlePathsToIDs; - - // Loop over all classes - for (Class cls in self.classes) { - NSNumber *classID = _classesToIDs[(id)cls]; - - // Block used to process each message - BOOL (^insert)(FLEXProperty *, NSNumber *) = ^BOOL(FLEXProperty *property, NSNumber *instance) { - FLEXPropertyAttributes *attrs = property.attributes; - NSString *customGetter = attrs.customGetterString; - NSString *customSetter = attrs.customSetterString; - - // Insert selectors first - if (customGetter) { - if (![self addSelector:customGetter]) { - return NO; - } - } - if (customSetter) { - if (![self addSelector:customSetter]) { - return NO; - } - } - - // Insert type encoding first - NSInteger size = [FLEXTypeEncodingParser - sizeForTypeEncoding:attrs.typeEncoding alignment:nil - ]; - if (![self addTypeEncoding:attrs.typeEncoding size:size]) { - return NO; - } - - id imagePath = property.imagePath ?: NSNull.null; - id image = imageIDs[imagePath] ?: NSNull.null; - return ![database executeStatement:kFREInsertProperty arguments:@{ - @"$name": property.name, - @"$class": classID, - @"$instance": instance, - @"$image": image, - @"$attributes": attrs.string, - - @"$customGetter": self->_selectorsToIDs[customGetter] ?: NSNull.null, - @"$customSetter": self->_selectorsToIDs[customSetter] ?: NSNull.null, - - @"$type": self->_typeEncodingsToIDs[attrs.typeEncoding] ?: NSNull.null, - @"$ivar": attrs.backingIvar ?: NSNull.null, - @"$readonly": @(attrs.isReadOnly), - @"$copy": @(attrs.isCopy), - @"$retained": @(attrs.isRetained), - @"$nonatomic": @(attrs.isNonatomic), - @"$dynamic": @(attrs.isDynamic), - @"$weak": @(attrs.isWeak), - @"$canGC": @(attrs.isGarbageCollectable), - }].isError; - }; - - // Loop over all instance and class methods of that class // - - for (FLEXProperty *property in FLEXGetAllProperties(cls)) { - if (!insert(property, @YES)) { - return NO; - } - } - for (FLEXProperty *property in FLEXGetAllProperties(object_getClass(cls))) { - if (!insert(property, @NO)) { - return NO; - } - } - } - - return YES; -} - -- (BOOL)addSelector:(NSString *)sel { - return [self executeInsert:kFREInsertSelector args:@{ - @"$name": sel - } key:sel cacheResult:_selectorsToIDs]; -} - -- (BOOL)addTypeEncoding:(NSString *)type size:(NSInteger)size { - return [self executeInsert:kFREInsertTypeEncoding args:@{ - @"$type": type, @"$size": @(size) - } key:type cacheResult:_typeEncodingsToIDs]; -} - -- (BOOL)addMethodSignature:(FLEXMethod *)method { - NSString *signature = method.signatureString; - NSString *returnType = @((char *)method.returnType); - - // Insert return type first - if (![self addTypeEncoding:returnType size:method.returnSize]) { - return NO; - } - - return [self executeInsert:kFREInsertMethodSignature args:@{ - @"$typeEncoding": signature, - @"$returnType": _typeEncodingsToIDs[returnType], - @"$argc": @(method.numberOfArguments), - @"$frameLength": @(method.signature.frameLength) - } key:signature cacheResult:_methodSignaturesToIDs]; -} - -- (BOOL)executeInsert:(NSString *)statement - args:(NSDictionary *)args - key:(NSString *)cacheKey - cacheResult:(NSMutableDictionary *)rowids { - // Check if already inserted - if (rowids[cacheKey]) { - return YES; - } - - // Insert - FLEXSQLiteDatabaseManager *database = _db; - [database executeStatement:statement arguments:args]; - - if (database.lastResult.isError) { - return NO; - } - - // Cache rowid - rowids[cacheKey] = @(database.lastRowID); - return YES; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKBToolbarButton.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKBToolbarButton.h deleted file mode 100644 index f2ab468..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKBToolbarButton.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// FLEXKBToolbarButton.h -// FLEX -// -// Created by Tanner on 6/11/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import - -typedef void (^FLEXKBToolbarAction)(NSString *buttonTitle, BOOL isSuggestion); - - -@interface FLEXKBToolbarButton : UIButton - -/// Set to `default` to use the system appearance on iOS 13+ -@property (nonatomic) UIKeyboardAppearance appearance; - -+ (instancetype)buttonWithTitle:(NSString *)title; -+ (instancetype)buttonWithTitle:(NSString *)title action:(FLEXKBToolbarAction)eventHandler; -+ (instancetype)buttonWithTitle:(NSString *)title action:(FLEXKBToolbarAction)action forControlEvents:(UIControlEvents)controlEvents; - -/// Adds the event handler for the button. -/// -/// @param eventHandler The event handler block. -/// @param controlEvents The type of event. -- (void)addEventHandler:(FLEXKBToolbarAction)eventHandler forControlEvents:(UIControlEvents)controlEvents; - -@end - -@interface FLEXKBToolbarSuggestedButton : FLEXKBToolbarButton @end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKBToolbarButton.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKBToolbarButton.m deleted file mode 100644 index 15db7fc..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKBToolbarButton.m +++ /dev/null @@ -1,160 +0,0 @@ -// -// FLEXKBToolbarButton.m -// FLEX -// -// Created by Tanner on 6/11/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXKBToolbarButton.h" -#import "UIFont+FLEX.h" -#import "FLEXUtility.h" -#import "CALayer+FLEX.h" - -@interface FLEXKBToolbarButton () -@property (nonatomic ) NSString *title; -@property (nonatomic, copy) FLEXKBToolbarAction buttonPressBlock; -/// YES if appearance is set to `default` -@property (nonatomic, readonly) BOOL useSystemAppearance; -/// YES if the current trait collection is set to dark mode and \c useSystemAppearance is YES -@property (nonatomic, readonly) BOOL usingDarkMode; -@end - -@implementation FLEXKBToolbarButton - -+ (instancetype)buttonWithTitle:(NSString *)title { - return [[self alloc] initWithTitle:title]; -} - -+ (instancetype)buttonWithTitle:(NSString *)title action:(FLEXKBToolbarAction)eventHandler forControlEvents:(UIControlEvents)controlEvent { - FLEXKBToolbarButton *newButton = [self buttonWithTitle:title]; - [newButton addEventHandler:eventHandler forControlEvents:controlEvent]; - return newButton; -} - -+ (instancetype)buttonWithTitle:(NSString *)title action:(FLEXKBToolbarAction)eventHandler { - return [self buttonWithTitle:title action:eventHandler forControlEvents:UIControlEventTouchUpInside]; -} - -- (id)initWithTitle:(NSString *)title { - self = [super init]; - if (self) { - _title = title; - self.layer.shadowOffset = CGSizeMake(0, 1); - self.layer.shadowOpacity = 0.35; - self.layer.shadowRadius = 0; - self.layer.cornerRadius = 5; - self.clipsToBounds = NO; - self.titleLabel.font = [UIFont systemFontOfSize:18.0]; - self.layer.flex_continuousCorners = YES; - [self setTitle:self.title forState:UIControlStateNormal]; - [self sizeToFit]; - - if (@available(iOS 13, *)) { - self.appearance = UIKeyboardAppearanceDefault; - } else { - self.appearance = UIKeyboardAppearanceLight; - } - - CGRect frame = self.frame; - frame.size.width += title.length < 3 ? 30 : 15; - frame.size.height += 10; - self.frame = frame; - } - - return self; -} - -- (void)addEventHandler:(FLEXKBToolbarAction)eventHandler forControlEvents:(UIControlEvents)controlEvent { - self.buttonPressBlock = eventHandler; - [self addTarget:self action:@selector(buttonPressed) forControlEvents:controlEvent]; -} - -- (void)buttonPressed { - self.buttonPressBlock(self.title, NO); -} - -- (void)setAppearance:(UIKeyboardAppearance)appearance { - _appearance = appearance; - - UIColor *titleColor = nil, *backgroundColor = nil; - UIColor *lightColor = [UIColor colorWithRed:253.0/255.0 green:253.0/255.0 blue:254.0/255.0 alpha:1]; - UIColor *darkColor = [UIColor colorWithRed:101.0/255.0 green:102.0/255.0 blue:104.0/255.0 alpha:1]; - - switch (_appearance) { - default: - case UIKeyboardAppearanceDefault: - if (@available(iOS 13, *)) { - titleColor = UIColor.labelColor; - - if (self.usingDarkMode) { - // style = UIBlurEffectStyleSystemUltraThinMaterialLight; - backgroundColor = darkColor; - } else { - // style = UIBlurEffectStyleSystemMaterialLight; - backgroundColor = lightColor; - } - break; - } - case UIKeyboardAppearanceLight: - titleColor = UIColor.blackColor; - backgroundColor = lightColor; - // style = UIBlurEffectStyleExtraLight; - break; - case UIKeyboardAppearanceDark: - titleColor = UIColor.whiteColor; - backgroundColor = darkColor; - // style = UIBlurEffectStyleDark; - break; - } - - self.backgroundColor = backgroundColor; - [self setTitleColor:titleColor forState:UIControlStateNormal]; -} - -- (BOOL)isEqual:(id)object { - if ([object isKindOfClass:[FLEXKBToolbarButton class]]) { - return [self.title isEqualToString:[object title]]; - } - - return NO; -} - -- (NSUInteger)hash { - return self.title.hash; -} - -- (BOOL)useSystemAppearance { - return self.appearance == UIKeyboardAppearanceDefault; -} - -- (BOOL)usingDarkMode { - if (@available(iOS 12, *)) { - return self.useSystemAppearance && self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark; - } - - return self.appearance == UIKeyboardAppearanceDark; -} - -- (void)traitCollectionDidChange:(UITraitCollection *)previous { - if (@available(iOS 12, *)) { - // Was darkmode toggled? - if (previous.userInterfaceStyle != self.traitCollection.userInterfaceStyle) { - if (self.useSystemAppearance) { - // Recreate the background view with the proper colors - self.appearance = self.appearance; - } - } - } -} - -@end - - -@implementation FLEXKBToolbarSuggestedButton - -- (void)buttonPressed { - self.buttonPressBlock(self.title, YES); -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyPathSearchController.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyPathSearchController.h deleted file mode 100644 index 98c2960..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyPathSearchController.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// FLEXKeyPathSearchController.h -// FLEX -// -// Created by Tanner on 3/23/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import -#import "FLEXRuntimeBrowserToolbar.h" -#import "FLEXMethod.h" - -@protocol FLEXKeyPathSearchControllerDelegate - -@property (nonatomic, readonly) UITableView *tableView; -@property (nonatomic, readonly) UISearchController *searchController; - -/// For loaded images which don't have an NSBundle -- (void)didSelectImagePath:(NSString *)message shortName:(NSString *)shortName; -- (void)didSelectBundle:(NSBundle *)bundle; -- (void)didSelectClass:(Class)cls; - -@end - - -@interface FLEXKeyPathSearchController : NSObject - -+ (instancetype)delegate:(id)delegate; - -@property (nonatomic) FLEXRuntimeBrowserToolbar *toolbar; - -/// Suggestions for the toolbar -@property (nonatomic, readonly) NSArray *suggestions; - -- (void)didSelectKeyPathOption:(NSString *)text; -- (void)didPressButton:(NSString *)text insertInto:(UISearchBar *)searchBar; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyPathSearchController.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyPathSearchController.m deleted file mode 100644 index e33cf7c..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyPathSearchController.m +++ /dev/null @@ -1,417 +0,0 @@ -// -// FLEXKeyPathSearchController.m -// FLEX -// -// Created by Tanner on 3/23/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXKeyPathSearchController.h" -#import "FLEXRuntimeKeyPathTokenizer.h" -#import "FLEXRuntimeController.h" -#import "NSString+FLEX.h" -#import "NSArray+FLEX.h" -#import "UITextField+Range.h" -#import "NSTimer+FLEX.h" -#import "FLEXTableView.h" -#import "FLEXUtility.h" -#import "FLEXObjectExplorerFactory.h" - -@interface FLEXKeyPathSearchController () -@property (nonatomic, readonly, weak) id delegate; -@property (nonatomic) NSTimer *timer; -/// If \c keyPath is \c nil or if it only has a \c bundleKey, this is -/// a list of bundle key path components like \c UICatalog or \c UIKit\.framework -/// If \c keyPath has more than a \c bundleKey then it is a list of class names. -@property (nonatomic) NSArray *bundlesOrClasses; -/// nil when search bar is empty -@property (nonatomic) FLEXRuntimeKeyPath *keyPath; - -@property (nonatomic, readonly) NSString *emptySuggestion; - -/// Used to track which methods go with which classes. This is used in -/// two scenarios: (1) when the target class is absolute and has classes, -/// (this list will include the "leaf" class as well as parent classes in this case) -/// or (2) when the class key is a wildcard and we're searching methods in many -/// classes at once. Each list in \c classesToMethods correspnds to a class here. -@property (nonatomic) NSArray *classes; -/// A filtered version of \c classes used when searching for a specific attribute. -/// Classes with no matching ivars/properties/methods are not shown. -@property (nonatomic) NSArray *filteredClasses; -// We use this regardless of whether the target class is absolute, just as above -@property (nonatomic) NSArray *> *classesToMethods; -@end - -@implementation FLEXKeyPathSearchController - -+ (instancetype)delegate:(id)delegate { - FLEXKeyPathSearchController *controller = [self new]; - controller->_bundlesOrClasses = [FLEXRuntimeController allBundleNames]; - controller->_delegate = delegate; - controller->_emptySuggestion = NSBundle.mainBundle.executablePath.lastPathComponent; - - NSParameterAssert(delegate.tableView); - NSParameterAssert(delegate.searchController); - - delegate.tableView.delegate = controller; - delegate.tableView.dataSource = controller; - - UISearchBar *searchBar = delegate.searchController.searchBar; - searchBar.delegate = controller; - searchBar.keyboardType = UIKeyboardTypeWebSearch; - searchBar.autocorrectionType = UITextAutocorrectionTypeNo; - if (@available(iOS 11, *)) { - searchBar.smartQuotesType = UITextSmartQuotesTypeNo; - searchBar.smartInsertDeleteType = UITextSmartInsertDeleteTypeNo; - } - - return controller; -} - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - if (scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) { - [self.delegate.searchController.searchBar resignFirstResponder]; - } -} - -- (void)setToolbar:(FLEXRuntimeBrowserToolbar *)toolbar { - _toolbar = toolbar; - self.delegate.searchController.searchBar.inputAccessoryView = toolbar; -} - -- (NSArray *)classesOf:(NSString *)className { - Class baseClass = NSClassFromString(className); - if (!baseClass) { - return @[]; - } - - // Find classes - NSMutableArray *classes = [NSMutableArray arrayWithObject:className]; - while ([baseClass superclass]) { - [classes addObject:NSStringFromClass([baseClass superclass])]; - baseClass = [baseClass superclass]; - } - - return classes; -} - -#pragma mark Key path stuff - -- (void)didSelectKeyPathOption:(NSString *)text { - [_timer invalidate]; // Still might be waiting to refresh when method is selected - - // Change "Bundle.fooba" to "Bundle.foobar." - NSString *orig = self.delegate.searchController.searchBar.text; - NSString *keyPath = [orig flex_stringByReplacingLastKeyPathComponent:text]; - self.delegate.searchController.searchBar.text = keyPath; - - self.keyPath = [FLEXRuntimeKeyPathTokenizer tokenizeString:keyPath]; - - // Get classes if class was selected - if (self.keyPath.classKey.isAbsolute && self.keyPath.methodKey.isAny) { - [self didSelectAbsoluteClass:text]; - } else { - self.classes = nil; - self.filteredClasses = nil; - } - - [self updateTable]; -} - -- (void)didSelectAbsoluteClass:(NSString *)name { - self.classes = [self classesOf:name]; - self.filteredClasses = self.classes; - self.bundlesOrClasses = nil; - self.classesToMethods = nil; -} - -- (void)didPressButton:(NSString *)text insertInto:(UISearchBar *)searchBar { - [self.toolbar setKeyPath:self.keyPath suggestions:nil]; - - // Available since at least iOS 9, still present in iOS 13 - UITextField *field = [searchBar valueForKey:@"_searchBarTextField"]; - - if ([self searchBar:searchBar shouldChangeTextInRange:field.flex_selectedRange replacementText:text]) { - [field replaceRange:field.selectedTextRange withText:text]; - } -} - -- (NSArray *)suggestions { - if (self.bundlesOrClasses) { - if (self.classes) { - if (self.classesToMethods) { - // We have selected a class and are searching metadata - return nil; - } - - // We are currently searching classes - return [self.filteredClasses flex_subArrayUpto:10]; - } - - if (!self.keyPath) { - // Search bar is empty - return @[self.emptySuggestion]; - } - - // We are currently searching bundles - return [self.bundlesOrClasses flex_subArrayUpto:10]; - } - - // We have nothing at all to even search - return nil; -} - -#pragma mark - Filtering + UISearchBarDelegate - -- (void)updateTable { - // Compute the method, class, or bundle lists on a background thread - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - if (self.classes) { - // Here, our class key is 'absolute'; .classes is a list of superclasses - // and we want to show the methods for those classes specifically - // TODO: add caching to this somehow - NSMutableArray *methods = [FLEXRuntimeController - methodsForToken:self.keyPath.methodKey - instance:self.keyPath.instanceMethods - inClasses:self.classes - ].mutableCopy; - - // Remove classes without results if we're searching for a method - // - // Note: this will remove classes without any methods or overrides - // even if the query doesn't specify a method, like `*.*.` - if (self.keyPath.methodKey) { - [self setNonEmptyMethodLists:methods withClasses:self.classes.mutableCopy]; - } else { - self.filteredClasses = self.classes; - } - } - else { - FLEXRuntimeKeyPath *keyPath = self.keyPath; - NSArray *models = [FLEXRuntimeController dataForKeyPath:keyPath]; - if (keyPath.methodKey) { // We're looking at methods - self.bundlesOrClasses = nil; - - NSMutableArray *methods = models.mutableCopy; - NSMutableArray *classes = [ - FLEXRuntimeController classesForKeyPath:keyPath - ]; - self.classes = classes; - [self setNonEmptyMethodLists:methods withClasses:classes]; - } else { // We're looking at bundles or classes - self.bundlesOrClasses = models; - self.classesToMethods = nil; - } - } - - // Finally, reload the table on the main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [self updateToolbarButtons]; - [self.delegate.tableView reloadData]; - }); - }); -} - -- (void)updateToolbarButtons { - // Update toolbar buttons - [self.toolbar setKeyPath:self.keyPath suggestions:self.suggestions]; -} - -/// Assign assign .filteredClasses and .classesToMethods after removing empty sections -- (void)setNonEmptyMethodLists:(NSMutableArray *> *)methods - withClasses:(NSMutableArray *)classes { - // Remove sections with no methods - NSIndexSet *allEmpty = [methods indexesOfObjectsPassingTest:^BOOL(NSArray *list, NSUInteger idx, BOOL *stop) { - return list.count == 0; - }]; - [methods removeObjectsAtIndexes:allEmpty]; - [classes removeObjectsAtIndexes:allEmpty]; - - self.filteredClasses = classes; - self.classesToMethods = methods; -} - -- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { - // Check if character is even legal - if (![FLEXRuntimeKeyPathTokenizer allowedInKeyPath:text]) { - return NO; - } - - BOOL terminatedToken = NO; - BOOL isAppending = range.length == 0 && range.location == searchBar.text.length; - if (isAppending && [text isEqualToString:@"."]) { - terminatedToken = YES; - } - - // Actually parse input - @try { - text = [searchBar.text stringByReplacingCharactersInRange:range withString:text] ?: text; - self.keyPath = [FLEXRuntimeKeyPathTokenizer tokenizeString:text]; - if (self.keyPath.classKey.isAbsolute && terminatedToken) { - [self didSelectAbsoluteClass:self.keyPath.classKey.string]; - } - } @catch (id e) { - return NO; - } - - return YES; -} - -- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { - [_timer invalidate]; - - // Schedule update timer - if (searchText.length) { - if (!self.keyPath.methodKey) { - self.classes = nil; - self.filteredClasses = nil; - } - - self.timer = [NSTimer flex_fireSecondsFromNow:0.15 block:^{ - [self updateTable]; - }]; - } - // ... or remove all rows - else { - _bundlesOrClasses = [FLEXRuntimeController allBundleNames]; - _classesToMethods = nil; - _classes = nil; - _keyPath = nil; - [self updateToolbarButtons]; - [self.delegate.tableView reloadData]; - } -} - -- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { - self.keyPath = FLEXRuntimeKeyPath.empty; - [self updateTable]; -} - -/// Restore key path when going "back" and activating search bar again -- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { - searchBar.text = self.keyPath.description; -} - -- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { - [_timer invalidate]; - [searchBar resignFirstResponder]; - [self updateTable]; -} - -#pragma mark UITableViewDataSource - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.filteredClasses.count ?: self.bundlesOrClasses.count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView - dequeueReusableCellWithIdentifier:kFLEXMultilineDetailCell - forIndexPath:indexPath - ]; - - if (self.bundlesOrClasses.count) { - cell.accessoryType = UITableViewCellAccessoryDetailButton; - cell.textLabel.text = self.bundlesOrClasses[indexPath.row]; - cell.detailTextLabel.text = nil; - if (self.keyPath.classKey) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - } - // One row per section - else if (self.filteredClasses.count) { - NSArray *methods = self.classesToMethods[indexPath.row]; - NSMutableString *summary = [NSMutableString new]; - [methods enumerateObjectsUsingBlock:^(FLEXMethod *method, NSUInteger idx, BOOL *stop) { - NSString *format = nil; - if (idx == methods.count-1) { - format = @"%@%@"; - *stop = YES; - } else if (idx < 3) { - format = @"%@%@\n"; - } else { - format = @"%@%@\n…"; - *stop = YES; - } - - [summary appendFormat:format, method.isInstanceMethod ? @"-" : @"+", method.selectorString]; - }]; - - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = self.filteredClasses[indexPath.row]; - if (@available(iOS 10, *)) { - cell.detailTextLabel.text = summary.length ? summary : nil; - } - - } - else { - @throw NSInternalInconsistencyException; - } - - return cell; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (self.filteredClasses || self.keyPath.methodKey) { - return @" "; - } else if (self.bundlesOrClasses) { - NSInteger count = self.bundlesOrClasses.count; - if (self.keyPath.classKey) { - return FLEXPluralString(count, @"classes", @"class"); - } else { - return FLEXPluralString(count, @"bundles", @"bundle"); - } - } - - return [self.delegate tableView:tableView titleForHeaderInSection:section]; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - if (self.filteredClasses || self.keyPath.methodKey) { - if (section == 0) { - return 55; - } - - return 0; - } - - return 55; -} - -#pragma mark UITableViewDelegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (self.bundlesOrClasses) { - NSString *bundleSuffixOrClass = self.bundlesOrClasses[indexPath.row]; - if (self.keyPath.classKey) { - NSParameterAssert(NSClassFromString(bundleSuffixOrClass)); - [self.delegate didSelectClass:NSClassFromString(bundleSuffixOrClass)]; - } else { - // Selected a bundle - [self didSelectKeyPathOption:bundleSuffixOrClass]; - } - } else { - if (self.filteredClasses.count) { - Class cls = NSClassFromString(self.filteredClasses[indexPath.row]); - NSParameterAssert(cls); - [self.delegate didSelectClass:cls]; - } else { - @throw NSInternalInconsistencyException; - } - } -} - -- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - NSString *bundleSuffixOrClass = self.bundlesOrClasses[indexPath.row]; - NSString *imagePath = [FLEXRuntimeController imagePathWithShortName:bundleSuffixOrClass]; - NSBundle *bundle = [NSBundle bundleWithPath:imagePath.stringByDeletingLastPathComponent]; - - if (bundle) { - [self.delegate didSelectBundle:bundle]; - } else { - [self.delegate didSelectImagePath:imagePath shortName:bundleSuffixOrClass]; - } -} - -@end - diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyboardToolbar.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyboardToolbar.h deleted file mode 100644 index e44fdb6..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyboardToolbar.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXKeyboardToolbar.h -// FLEX -// -// Created by Tanner on 6/11/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXKBToolbarButton.h" - -@interface FLEXKeyboardToolbar : UIView - -+ (instancetype)toolbarWithButtons:(NSArray *)buttons; - -@property (nonatomic) NSArray *buttons; -@property (nonatomic) UIKeyboardAppearance appearance; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyboardToolbar.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyboardToolbar.m deleted file mode 100644 index 2640a4c..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXKeyboardToolbar.m +++ /dev/null @@ -1,225 +0,0 @@ -// -// FLEXKeyboardToolbar.m -// FLEX -// -// Created by Tanner on 6/11/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXKeyboardToolbar.h" -#import "FLEXUtility.h" - -#define kToolbarHeight 44 -#define kButtonSpacing 6 -#define kScrollViewHorizontalMargins 3 - -@interface FLEXKeyboardToolbar () - -/// The fake top border to replicate the toolbar. -@property (nonatomic) CALayer *topBorder; -@property (nonatomic) UIView *toolbarView; -@property (nonatomic) UIScrollView *scrollView; -@property (nonatomic) UIVisualEffectView *blurView; -/// YES if appearance is set to `default` -@property (nonatomic, readonly) BOOL useSystemAppearance; -/// YES if the current trait collection is set to dark mode and \c useSystemAppearance is YES -@property (nonatomic, readonly) BOOL usingDarkMode; -@end - -@implementation FLEXKeyboardToolbar - -+ (instancetype)toolbarWithButtons:(NSArray *)buttons { - return [[self alloc] initWithButtons:buttons]; -} - -- (id)initWithButtons:(NSArray *)buttons { - self = [super initWithFrame:CGRectMake(0, 0, self.window.rootViewController.view.bounds.size.width, kToolbarHeight)]; - if (self) { - _buttons = [buttons copy]; - - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - if (@available(iOS 13, *)) { - self.appearance = UIKeyboardAppearanceDefault; - } else { - self.appearance = UIKeyboardAppearanceLight; - } - } - - return self; -} - -- (void)setAppearance:(UIKeyboardAppearance)appearance { - _appearance = appearance; - - // Remove toolbar if it exits because it will be recreated below - if (self.toolbarView) { - [self.toolbarView removeFromSuperview]; - } - - [self addSubview:self.inputAccessoryView]; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - // Layout top border - CGRect frame = _toolbarView.bounds; - frame.size.height = 0.5; - _topBorder.frame = frame; - - // Scroll view // - - frame = CGRectMake(0, 0, self.bounds.size.width, kToolbarHeight); - CGSize contentSize = self.scrollView.contentSize; - CGFloat scrollViewWidth = frame.size.width; - - // If our content size is smaller than the scroll view, - // we want to right-align all the content - if (contentSize.width < scrollViewWidth) { - // Compute the content size to scroll view size difference - UIEdgeInsets insets = self.scrollView.contentInset; - CGFloat margin = insets.left + insets.right; - CGFloat difference = scrollViewWidth - contentSize.width - margin; - // Update the content size to be the full width of the scroll view - contentSize.width += difference; - self.scrollView.contentSize = contentSize; - - // Offset every button by the difference above - // so that every button appears right-aligned - for (UIView *button in self.scrollView.subviews) { - CGRect f = button.frame; - f.origin.x += difference; - button.frame = f; - } - } -} - -- (UIView *)inputAccessoryView { - _topBorder = [CALayer new]; - _topBorder.frame = CGRectMake(0.0, 0.0, self.bounds.size.width, 0.5); - [self makeScrollView]; - - UIColor *borderColor = nil, *backgroundColor = nil; - UIColor *lightColor = [UIColor colorWithHue:216.0/360.0 saturation:0.05 brightness:0.85 alpha:1]; - UIColor *darkColor = [UIColor colorWithHue:220.0/360.0 saturation:0.07 brightness:0.16 alpha:1]; - - switch (_appearance) { - case UIKeyboardAppearanceDefault: - if (@available(iOS 13, *)) { - borderColor = UIColor.systemBackgroundColor; - - if (self.usingDarkMode) { - // style = UIBlurEffectStyleSystemThickMaterial; - backgroundColor = darkColor; - } else { - // style = UIBlurEffectStyleSystemUltraThinMaterialLight; - backgroundColor = lightColor; - } - break; - } - case UIKeyboardAppearanceLight: { - borderColor = UIColor.clearColor; - backgroundColor = lightColor; - break; - } - case UIKeyboardAppearanceDark: { - borderColor = [UIColor colorWithWhite:0.100 alpha:1.000]; - backgroundColor = darkColor; - break; - } - } - - self.toolbarView = [UIView new]; - [self.toolbarView addSubview:self.scrollView]; - [self.toolbarView.layer addSublayer:self.topBorder]; - self.toolbarView.frame = CGRectMake(0, 0, self.bounds.size.width, kToolbarHeight); - self.toolbarView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - self.backgroundColor = backgroundColor; - self.topBorder.backgroundColor = borderColor.CGColor; - - return self.toolbarView; -} - -- (UIScrollView *)makeScrollView { - UIScrollView *scrollView = [UIScrollView new]; - scrollView.backgroundColor = UIColor.clearColor; - scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - scrollView.contentInset = UIEdgeInsetsMake( - 8.f, kScrollViewHorizontalMargins, 4.f, kScrollViewHorizontalMargins - ); - scrollView.showsHorizontalScrollIndicator = NO; - - self.scrollView = scrollView; - [self addButtons]; - - return scrollView; -} - -- (void)addButtons { - NSUInteger originX = 0.f; - - CGRect originFrame; - CGFloat top = self.scrollView.contentInset.top; - CGFloat bottom = self.scrollView.contentInset.bottom; - - for (FLEXKBToolbarButton *button in self.buttons) { - button.appearance = self.appearance; - - originFrame = button.frame; - originFrame.origin.x = originX; - originFrame.origin.y = 0.f; - originFrame.size.height = kToolbarHeight - (top + bottom); - button.frame = originFrame; - - [self.scrollView addSubview:button]; - - // originX tracks the origin of the next button to be added, - // so at the end of each iteration of this loop we increment - // it by the size of the last button with some padding - originX += button.bounds.size.width + kButtonSpacing; - } - - // Update contentSize, - // set to the max x value of the last button added - CGSize contentSize = self.scrollView.contentSize; - contentSize.width = originX - kButtonSpacing; - self.scrollView.contentSize = contentSize; - - // Needed to potentially right-align buttons - [self setNeedsLayout]; -} - -- (void)setButtons:(NSArray *)buttons { - [_buttons makeObjectsPerformSelector:@selector(removeFromSuperview)]; - _buttons = buttons.copy; - - [self addButtons]; -} - -- (BOOL)useSystemAppearance { - return self.appearance == UIKeyboardAppearanceDefault; -} - -- (BOOL)usingDarkMode { - if (@available(iOS 12, *)) { - return self.useSystemAppearance && self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark; - } - - return self.appearance == UIKeyboardAppearanceDark; -} - -- (void)traitCollectionDidChange:(UITraitCollection *)previous { - if (@available(iOS 12, *)) { - // Was darkmode toggled? - if (previous.userInterfaceStyle != self.traitCollection.userInterfaceStyle) { - if (self.useSystemAppearance) { - // Recreate the background view with the proper colors - self.appearance = self.appearance; - } - } - } -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXObjcRuntimeViewController.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXObjcRuntimeViewController.h deleted file mode 100644 index 93ac54a..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXObjcRuntimeViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXObjcRuntimeViewController.h -// FLEX -// -// Created by Tanner on 3/23/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXTableViewController.h" -#import "FLEXGlobalsEntry.h" - -@interface FLEXObjcRuntimeViewController : FLEXTableViewController - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXObjcRuntimeViewController.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXObjcRuntimeViewController.m deleted file mode 100644 index f729535..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXObjcRuntimeViewController.m +++ /dev/null @@ -1,178 +0,0 @@ -// -// FLEXObjcRuntimeViewController.m -// FLEX -// -// Created by Tanner on 3/23/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXObjcRuntimeViewController.h" -#import "FLEXKeyPathSearchController.h" -#import "FLEXRuntimeBrowserToolbar.h" -#import "UIGestureRecognizer+Blocks.h" -#import "UIBarButtonItem+FLEX.h" -#import "FLEXTableView.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXAlert.h" -#import "FLEXRuntimeClient.h" -#import - -@interface FLEXObjcRuntimeViewController () - -@property (nonatomic, readonly ) FLEXKeyPathSearchController *keyPathController; -@property (nonatomic, readonly ) UIView *promptView; - -@end - -@implementation FLEXObjcRuntimeViewController - -#pragma mark - Setup, view events - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Long press on navigation bar to initialize webkit legacy - // - // We call initializeWebKitLegacy automatically before you search - // all bundles just to be safe (since touching some classes before - // WebKit is initialized will initialize it on a thread other than - // the main thread), but sometimes you can encounter this crash - // without searching through all bundles, of course. - [self.navigationController.navigationBar addGestureRecognizer:[ - [UILongPressGestureRecognizer alloc] - initWithTarget:[FLEXRuntimeClient class] - action:@selector(initializeWebKitLegacy) - ] - ]; - - [self addToolbarItems:@[FLEXBarButtonItem(@"dlopen()", self, @selector(dlopenPressed:))]]; - - // Search bar stuff, must be first because this creates self.searchController - self.showsSearchBar = YES; - self.showSearchBarInitially = YES; - self.activatesSearchBarAutomatically = YES; - // Using pinSearchBar on this screen causes a weird visual - // thing on the next view controller that gets pushed. - // - // self.pinSearchBar = YES; - self.searchController.searchBar.placeholder = @"UIKit*.UIView.-setFrame:"; - - // Search controller stuff - // key path controller automatically assigns itself as the delegate of the search bar - // To avoid a retain cycle below, use local variables - UISearchBar *searchBar = self.searchController.searchBar; - FLEXKeyPathSearchController *keyPathController = [FLEXKeyPathSearchController delegate:self]; - _keyPathController = keyPathController; - _keyPathController.toolbar = [FLEXRuntimeBrowserToolbar toolbarWithHandler:^(NSString *text, BOOL suggestion) { - if (suggestion) { - [keyPathController didSelectKeyPathOption:text]; - } else { - [keyPathController didPressButton:text insertInto:searchBar]; - } - } suggestions:keyPathController.suggestions]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES]; -} - - -#pragma mark dlopen - -/// Prompt user for dlopen shortcuts to choose from -- (void)dlopenPressed:(id)sender { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Dynamically Open Library"); - make.message(@"Invoke dlopen() with the given path. Choose an option below."); - - make.button(@"System Framework").handler(^(NSArray *_) { - [self dlopenWithFormat:@"/System/Library/Frameworks/%@.framework/%@"]; - }); - make.button(@"System Private Framework").handler(^(NSArray *_) { - [self dlopenWithFormat:@"/System/Library/PrivateFrameworks/%@.framework/%@"]; - }); - make.button(@"Arbitrary Binary").handler(^(NSArray *_) { - [self dlopenWithFormat:nil]; - }); - - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; -} - -/// Prompt user for input and dlopen -- (void)dlopenWithFormat:(NSString *)format { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Dynamically Open Library"); - if (format) { - make.message(@"Pass in a framework name, such as CarKit or FrontBoard."); - } else { - make.message(@"Pass in an absolute path to a binary."); - } - - make.textField(format ? @"ARKit" : @"/System/Library/Frameworks/ARKit.framework/ARKit"); - - make.button(@"Cancel").cancelStyle(); - make.button(@"Open").destructiveStyle().handler(^(NSArray *strings) { - NSString *path = strings[0]; - - if (path.length < 2) { - [self dlopenInvalidPath]; - } else if (format) { - path = [NSString stringWithFormat:format, path, path]; - } - - dlopen(path.UTF8String, RTLD_NOW); - }); - } showFrom:self]; -} - -- (void)dlopenInvalidPath { - [FLEXAlert makeAlert:^(FLEXAlert * _Nonnull make) { - make.title(@"Path or Name Too Short"); - make.button(@"Dismiss").cancelStyle(); - } showFrom:self]; -} - - -#pragma mark Delegate stuff - -- (void)didSelectImagePath:(NSString *)path shortName:(NSString *)shortName { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(shortName); - make.message(@"No NSBundle associated with this path:\n\n"); - make.message(path); - - make.button(@"Copy Path").handler(^(NSArray *strings) { - UIPasteboard.generalPasteboard.string = path; - }); - make.button(@"Dismiss").cancelStyle(); - } showFrom:self]; -} - -- (void)didSelectBundle:(NSBundle *)bundle { - NSParameterAssert(bundle); - FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:bundle]; - [self.navigationController pushViewController:explorer animated:YES]; -} - -- (void)didSelectClass:(Class)cls { - NSParameterAssert(cls); - FLEXObjectExplorerViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:cls]; - [self.navigationController pushViewController:explorer animated:YES]; -} - - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"📚 Runtime Browser"; -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - UIViewController *controller = [self new]; - controller.title = [self globalsEntryTitle:row]; - return controller; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeBrowserToolbar.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeBrowserToolbar.h deleted file mode 100644 index ca917e8..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeBrowserToolbar.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXRuntimeBrowserToolbar.h -// FLEX -// -// Created by Tanner on 6/11/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXKeyboardToolbar.h" -#import "FLEXRuntimeKeyPath.h" - -@interface FLEXRuntimeBrowserToolbar : FLEXKeyboardToolbar - -+ (instancetype)toolbarWithHandler:(FLEXKBToolbarAction)tapHandler suggestions:(NSArray *)suggestions; - -- (void)setKeyPath:(FLEXRuntimeKeyPath *)keyPath suggestions:(NSArray *)suggestions; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeBrowserToolbar.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeBrowserToolbar.m deleted file mode 100644 index c34cc02..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeBrowserToolbar.m +++ /dev/null @@ -1,92 +0,0 @@ -// -// FLEXRuntimeBrowserToolbar.m -// FLEX -// -// Created by Tanner on 6/11/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeBrowserToolbar.h" -#import "FLEXRuntimeKeyPathTokenizer.h" - -@interface FLEXRuntimeBrowserToolbar () -@property (nonatomic, copy) FLEXKBToolbarAction tapHandler; -@end - -@implementation FLEXRuntimeBrowserToolbar - -+ (instancetype)toolbarWithHandler:(FLEXKBToolbarAction)tapHandler suggestions:(NSArray *)suggestions { - NSArray *buttons = [self - buttonsForKeyPath:FLEXRuntimeKeyPath.empty suggestions:suggestions handler:tapHandler - ]; - - FLEXRuntimeBrowserToolbar *me = [self toolbarWithButtons:buttons]; - me.tapHandler = tapHandler; - return me; -} - -+ (NSArray *)buttonsForKeyPath:(FLEXRuntimeKeyPath *)keyPath - suggestions:(NSArray *)suggestions - handler:(FLEXKBToolbarAction)handler { - NSMutableArray *buttons = [NSMutableArray new]; - FLEXSearchToken *lastKey = nil; - BOOL lastKeyIsMethod = NO; - - if (keyPath.methodKey) { - lastKey = keyPath.methodKey; - lastKeyIsMethod = YES; - } else { - lastKey = keyPath.classKey ?: keyPath.bundleKey; - } - - switch (lastKey.options) { - case TBWildcardOptionsNone: - case TBWildcardOptionsAny: - if (lastKeyIsMethod) { - if (!keyPath.instanceMethods) { - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"-" action:handler]]; - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"+" action:handler]]; - } - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*" action:handler]]; - } else { - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*" action:handler]]; - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*." action:handler]]; - } - break; - - default: { - if (lastKey.options & TBWildcardOptionsPrefix) { - if (lastKeyIsMethod) { - if (lastKey.string.length) { - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*" action:handler]]; - } - } else { - if (lastKey.string.length) { - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*." action:handler]]; - } - } - } - - else if (lastKey.options & TBWildcardOptionsSuffix) { - if (!lastKeyIsMethod) { - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*" action:handler]]; - [buttons addObject:[FLEXKBToolbarButton buttonWithTitle:@"*." action:handler]]; - } - } - } - } - - for (NSString *suggestion in suggestions) { - [buttons addObject:[FLEXKBToolbarSuggestedButton buttonWithTitle:suggestion action:handler]]; - } - - return buttons; -} - -- (void)setKeyPath:(FLEXRuntimeKeyPath *)keyPath suggestions:(NSArray *)suggestions { - self.buttons = [self.class - buttonsForKeyPath:keyPath suggestions:suggestions handler:self.tapHandler - ]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPath.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPath.h deleted file mode 100644 index 7babe80..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPath.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// FLEXRuntimeKeyPath.h -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXSearchToken.h" -@class FLEXMethod; - -NS_ASSUME_NONNULL_BEGIN - -/// A key path represents a query into a set of bundles or classes -/// for a set of one or more methods. It is composed of three tokens: -/// bundle, class, and method. A key path may be incomplete if it -/// is missing any of the tokens. A key path is considered "absolute" -/// if all tokens have no options and if methodKey.string begins -/// with a + or a -. -/// -/// The @code TBKeyPathTokenizer @endcode class is used to create -/// a key path from a string. -@interface FLEXRuntimeKeyPath : NSObject - -+ (instancetype)empty; - -/// @param method must start with either a wildcard or a + or -. -+ (instancetype)bundle:(FLEXSearchToken *)bundle - class:(FLEXSearchToken *)cls - method:(FLEXSearchToken *)method - isInstance:(NSNumber *)instance - string:(NSString *)keyPathString; - -@property (nonatomic, nullable, readonly) FLEXSearchToken *bundleKey; -@property (nonatomic, nullable, readonly) FLEXSearchToken *classKey; -@property (nonatomic, nullable, readonly) FLEXSearchToken *methodKey; - -/// Indicates whether the method token specifies instance methods. -/// Nil if not specified. -@property (nonatomic, nullable, readonly) NSNumber *instanceMethods; - -@end -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPath.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPath.m deleted file mode 100644 index 09d2099..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPath.m +++ /dev/null @@ -1,75 +0,0 @@ -// -// FLEXRuntimeKeyPath.m -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeKeyPath.h" -#import "FLEXRuntimeClient.h" - -@interface FLEXRuntimeKeyPath () { - NSString *flex_description; -} -@end - -@implementation FLEXRuntimeKeyPath - -+ (instancetype)empty { - static FLEXRuntimeKeyPath *empty = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - FLEXSearchToken *any = FLEXSearchToken.any; - - empty = [self new]; - empty->_bundleKey = any; - empty->flex_description = @""; - }); - - return empty; -} - -+ (instancetype)bundle:(FLEXSearchToken *)bundle - class:(FLEXSearchToken *)cls - method:(FLEXSearchToken *)method - isInstance:(NSNumber *)instance - string:(NSString *)keyPathString { - FLEXRuntimeKeyPath *keyPath = [self new]; - keyPath->_bundleKey = bundle; - keyPath->_classKey = cls; - keyPath->_methodKey = method; - - keyPath->_instanceMethods = instance; - - // Remove irrelevant trailing '*' for equality purposes - if ([keyPathString hasSuffix:@"*"]) { - keyPathString = [keyPathString substringToIndex:keyPathString.length]; - } - keyPath->flex_description = keyPathString; - - if (bundle.isAny && cls.isAny && method.isAny) { - [FLEXRuntimeClient initializeWebKitLegacy]; - } - - return keyPath; -} - -- (NSString *)description { - return flex_description; -} - -- (NSUInteger)hash { - return flex_description.hash; -} - -- (BOOL)isEqual:(id)object { - if ([object isKindOfClass:[FLEXRuntimeKeyPath class]]) { - FLEXRuntimeKeyPath *kp = object; - return [flex_description isEqualToString:kp->flex_description]; - } - - return NO; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPathTokenizer.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPathTokenizer.h deleted file mode 100644 index 1e8f687..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPathTokenizer.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXRuntimeKeyPathTokenizer.h -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeKeyPath.h" - -@interface FLEXRuntimeKeyPathTokenizer : NSObject - -+ (NSUInteger)tokenCountOfString:(NSString *)userInput; -+ (FLEXRuntimeKeyPath *)tokenizeString:(NSString *)userInput; - -+ (BOOL)allowedInKeyPath:(NSString *)text; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPathTokenizer.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPathTokenizer.m deleted file mode 100644 index e2cd6ff..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXRuntimeKeyPathTokenizer.m +++ /dev/null @@ -1,218 +0,0 @@ -// -// FLEXRuntimeKeyPathTokenizer.m -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeKeyPathTokenizer.h" - -#define TBCountOfStringOccurence(target, str) ([target componentsSeparatedByString:str].count - 1) - -@implementation FLEXRuntimeKeyPathTokenizer - -#pragma mark Initialization - -static NSCharacterSet *firstAllowed = nil; -static NSCharacterSet *identifierAllowed = nil; -static NSCharacterSet *filenameAllowed = nil; -static NSCharacterSet *keyPathDisallowed = nil; -static NSCharacterSet *methodAllowed = nil; -+ (void)initialize { - if (self == [self class]) { - NSString *_methodFirstAllowed = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"; - NSString *_identifierAllowed = [_methodFirstAllowed stringByAppendingString:@"1234567890"]; - NSString *_methodAllowedSansType = [_identifierAllowed stringByAppendingString:@":"]; - NSString *_filenameNameAllowed = [_identifierAllowed stringByAppendingString:@"-+?!"]; - firstAllowed = [NSCharacterSet characterSetWithCharactersInString:_methodFirstAllowed]; - identifierAllowed = [NSCharacterSet characterSetWithCharactersInString:_identifierAllowed]; - filenameAllowed = [NSCharacterSet characterSetWithCharactersInString:_filenameNameAllowed]; - methodAllowed = [NSCharacterSet characterSetWithCharactersInString:_methodAllowedSansType]; - - NSString *_kpDisallowed = [_identifierAllowed stringByAppendingString:@"-+:\\.*"]; - keyPathDisallowed = [NSCharacterSet characterSetWithCharactersInString:_kpDisallowed].invertedSet; - } -} - -#pragma mark Public - -+ (FLEXRuntimeKeyPath *)tokenizeString:(NSString *)userInput { - if (!userInput.length) { - return nil; - } - - NSUInteger tokens = [self tokenCountOfString:userInput]; - if (tokens == 0) { - return nil; - } - - if ([userInput containsString:@"**"]) { - @throw NSInternalInconsistencyException; - } - - NSNumber *instance = nil; - NSScanner *scanner = [NSScanner scannerWithString:userInput]; - FLEXSearchToken *bundle = [self scanToken:scanner allowed:filenameAllowed first:filenameAllowed]; - FLEXSearchToken *cls = [self scanToken:scanner allowed:identifierAllowed first:firstAllowed]; - FLEXSearchToken *method = tokens > 2 ? [self scanMethodToken:scanner instance:&instance] : nil; - - return [FLEXRuntimeKeyPath bundle:bundle - class:cls - method:method - isInstance:instance - string:userInput]; -} - -+ (BOOL)allowedInKeyPath:(NSString *)text { - if (!text.length) { - return YES; - } - - return [text rangeOfCharacterFromSet:keyPathDisallowed].location == NSNotFound; -} - -#pragma mark Private - -+ (NSUInteger)tokenCountOfString:(NSString *)userInput { - NSUInteger escapedCount = TBCountOfStringOccurence(userInput, @"\\."); - NSUInteger tokenCount = TBCountOfStringOccurence(userInput, @".") - escapedCount + 1; - - return tokenCount; -} - -+ (FLEXSearchToken *)scanToken:(NSScanner *)scanner allowed:(NSCharacterSet *)allowedChars first:(NSCharacterSet *)first { - if (scanner.isAtEnd) { - if ([scanner.string hasSuffix:@"."] && ![scanner.string hasSuffix:@"\\."]) { - return [FLEXSearchToken string:nil options:TBWildcardOptionsAny]; - } - return nil; - } - - TBWildcardOptions options = TBWildcardOptionsNone; - NSMutableString *token = [NSMutableString new]; - - // Token cannot start with '.' - if ([scanner scanString:@"." intoString:nil]) { - @throw NSInternalInconsistencyException; - } - - if ([scanner scanString:@"*." intoString:nil]) { - return [FLEXSearchToken string:nil options:TBWildcardOptionsAny]; - } else if ([scanner scanString:@"*" intoString:nil]) { - if (scanner.isAtEnd) { - return FLEXSearchToken.any; - } - - options |= TBWildcardOptionsPrefix; - } - - NSString *tmp = nil; - BOOL stop = NO, didScanDelimiter = NO, didScanFirstAllowed = NO; - NSCharacterSet *disallowed = allowedChars.invertedSet; - while (!stop && ![scanner scanString:@"." intoString:&tmp] && !scanner.isAtEnd) { - // Scan word chars - // In this block, we have not scanned anything yet, except maybe leading '\' or '\.' - if (!didScanFirstAllowed) { - if ([scanner scanCharactersFromSet:first intoString:&tmp]) { - [token appendString:tmp]; - didScanFirstAllowed = YES; - } else if ([scanner scanString:@"\\" intoString:nil]) { - if (options == TBWildcardOptionsPrefix && [scanner scanString:@"." intoString:nil]) { - [token appendString:@"."]; - } else if (scanner.isAtEnd && options == TBWildcardOptionsPrefix) { - // Only allow standalone '\' if prefixed by '*' - return FLEXSearchToken.any; - } else { - // Token starts with a number, period, or something else not allowed, - // or token is a standalone '\' with no '*' prefix - @throw NSInternalInconsistencyException; - } - } else { - // Token starts with a number, period, or something else not allowed - @throw NSInternalInconsistencyException; - } - } else if ([scanner scanCharactersFromSet:allowedChars intoString:&tmp]) { - [token appendString:tmp]; - } - // Scan '\.' or trailing '\' - else if ([scanner scanString:@"\\" intoString:nil]) { - if ([scanner scanString:@"." intoString:nil]) { - [token appendString:@"."]; - } else if (scanner.isAtEnd) { - // Ignore forward slash not followed by period if at end - return [FLEXSearchToken string:token options:options | TBWildcardOptionsSuffix]; - } else { - // Only periods can follow a forward slash - @throw NSInternalInconsistencyException; - } - } - // Scan '*.' - else if ([scanner scanString:@"*." intoString:nil]) { - options |= TBWildcardOptionsSuffix; - stop = YES; - didScanDelimiter = YES; - } - // Scan '*' not followed by . - else if ([scanner scanString:@"*" intoString:nil]) { - if (!scanner.isAtEnd) { - // Invalid token, wildcard in middle of token - @throw NSInternalInconsistencyException; - } - } else if ([scanner scanCharactersFromSet:disallowed intoString:nil]) { - // Invalid token, invalid characters - @throw NSInternalInconsistencyException; - } - } - - // Did we scan a trailing, un-escsaped '.'? - if ([tmp isEqualToString:@"."]) { - didScanDelimiter = YES; - } - - if (!didScanDelimiter) { - options |= TBWildcardOptionsSuffix; - } - - return [FLEXSearchToken string:token options:options]; -} - -+ (FLEXSearchToken *)scanMethodToken:(NSScanner *)scanner instance:(NSNumber **)instance { - if (scanner.isAtEnd) { - if ([scanner.string hasSuffix:@"."]) { - return [FLEXSearchToken string:nil options:TBWildcardOptionsAny]; - } - return nil; - } - - if ([scanner.string hasSuffix:@"."] && ![scanner.string hasSuffix:@"\\."]) { - // Methods cannot end with '.' except for '\.' - @throw NSInternalInconsistencyException; - } - - if ([scanner scanString:@"-" intoString:nil]) { - *instance = @YES; - } else if ([scanner scanString:@"+" intoString:nil]) { - *instance = @NO; - } else { - if ([scanner scanString:@"*" intoString:nil]) { - // Just checking... It has to start with one of these three! - scanner.scanLocation--; - } else { - @throw NSInternalInconsistencyException; - } - } - - // -*foo not allowed - if (*instance && [scanner scanString:@"*" intoString:nil]) { - @throw NSInternalInconsistencyException; - } - - if (scanner.isAtEnd) { - return [FLEXSearchToken string:@"" options:TBWildcardOptionsSuffix]; - } - - return [self scanToken:scanner allowed:methodAllowed first:firstAllowed]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXSearchToken.h b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXSearchToken.h deleted file mode 100644 index 07c627d..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXSearchToken.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// FLEXSearchToken.h -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import - -typedef NS_OPTIONS(NSUInteger, TBWildcardOptions) { - TBWildcardOptionsNone = 0, - TBWildcardOptionsAny = 1, - TBWildcardOptionsPrefix = 1 << 1, - TBWildcardOptionsSuffix = 1 << 2, -}; - -/// A token may contain wildcards at one or either end, -/// but not in the middle of the token (as of now). -@interface FLEXSearchToken : NSObject - -+ (instancetype)any; -+ (instancetype)string:(NSString *)string options:(TBWildcardOptions)options; - -/// Will not contain the wildcard (*) symbol -@property (nonatomic, readonly) NSString *string; -@property (nonatomic, readonly) TBWildcardOptions options; - -/// Opposite of "is ambiguous" -@property (nonatomic, readonly) BOOL isAbsolute; -@property (nonatomic, readonly) BOOL isAny; -/// Still \c isAny, but checks that the string is empty -@property (nonatomic, readonly) BOOL isEmpty; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXSearchToken.m b/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXSearchToken.m deleted file mode 100644 index 975becf..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/RuntimeBrowser/FLEXSearchToken.m +++ /dev/null @@ -1,88 +0,0 @@ -// -// FLEXSearchToken.m -// FLEX -// -// Created by Tanner on 3/22/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXSearchToken.h" - -@interface FLEXSearchToken () { - NSString *flex_description; -} -@end - -@implementation FLEXSearchToken - -+ (instancetype)any { - static FLEXSearchToken *any = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - any = [self string:nil options:TBWildcardOptionsAny]; - }); - - return any; -} - -+ (instancetype)string:(NSString *)string options:(TBWildcardOptions)options { - FLEXSearchToken *token = [self new]; - token->_string = string; - token->_options = options; - return token; -} - -- (BOOL)isAbsolute { - return _options == TBWildcardOptionsNone; -} - -- (BOOL)isAny { - return _options == TBWildcardOptionsAny; -} - -- (BOOL)isEmpty { - return self.isAny && self.string.length == 0; -} - -- (NSString *)description { - if (flex_description) { - return flex_description; - } - - switch (_options) { - case TBWildcardOptionsNone: - flex_description = _string; - break; - case TBWildcardOptionsAny: - flex_description = @"*"; - break; - default: { - NSMutableString *desc = [NSMutableString new]; - if (_options & TBWildcardOptionsPrefix) { - [desc appendString:@"*"]; - } - [desc appendString:_string]; - if (_options & TBWildcardOptionsSuffix) { - [desc appendString:@"*"]; - } - flex_description = desc; - } - } - - return flex_description; -} - -- (NSUInteger)hash { - return self.description.hash; -} - -- (BOOL)isEqual:(id)object { - if ([object isKindOfClass:[FLEXSearchToken class]]) { - FLEXSearchToken *token = object; - return [_string isEqualToString:token->_string] && _options == token->_options; - } - - return NO; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h deleted file mode 100644 index 0702db5..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/ActivityStreamAPI.h +++ /dev/null @@ -1,209 +0,0 @@ -// -// Taken from https://github.com/llvm-mirror/lldb/blob/master/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h -// by Tanner Bennett on 03/03/2019 with minimal modifications. -// - -//===-- ActivityStreamAPI.h -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef ActivityStreamSPI_h -#define ActivityStreamSPI_h - -#include - -#include -// #include - -/* By default, XPC objects are declared as Objective-C types when building with - * an Objective-C compiler. This allows them to participate in ARC, in RR - * management by the Blocks runtime and in leaks checking by the static - * analyzer, and enables them to be added to Cocoa collections. - * - * See for details. - */ -#if !TARGET_OS_MACCATALYST -#if OS_OBJECT_USE_OBJC -OS_OBJECT_DECL(xpc_object); -#else -typedef void * xpc_object_t; -#endif -#endif - -#define OS_ACTIVITY_MAX_CALLSTACK 32 - -// Enums - -typedef NS_ENUM(uint32_t, os_activity_stream_flag_t) { - OS_ACTIVITY_STREAM_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_STREAM_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_STREAM_PAYLOAD = 0x00000004, - OS_ACTIVITY_STREAM_HISTORICAL = 0x00000008, - OS_ACTIVITY_STREAM_CALLSTACK = 0x00000010, - OS_ACTIVITY_STREAM_DEBUG = 0x00000020, - OS_ACTIVITY_STREAM_BUFFERED = 0x00000040, - OS_ACTIVITY_STREAM_NO_SENSITIVE = 0x00000080, - OS_ACTIVITY_STREAM_INFO = 0x00000100, - OS_ACTIVITY_STREAM_PROMISCUOUS = 0x00000200, - OS_ACTIVITY_STREAM_PRECISE_TIMESTAMPS = 0x00000200 -}; - -typedef NS_ENUM(uint32_t, os_activity_stream_type_t) { - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201, - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202, - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203, - - OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300, - - OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400, - OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480, - - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603, - - OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00, -}; - -typedef NS_ENUM(uint32_t, os_activity_stream_event_t) { - OS_ACTIVITY_STREAM_EVENT_STARTED = 1, - OS_ACTIVITY_STREAM_EVENT_STOPPED = 2, - OS_ACTIVITY_STREAM_EVENT_FAILED = 3, - OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED = 4, - OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED = 5, -}; - -// Types - -typedef uint64_t os_activity_id_t; -typedef struct os_activity_stream_s *os_activity_stream_t; -typedef struct os_activity_stream_entry_s *os_activity_stream_entry_t; - -#define OS_ACTIVITY_STREAM_COMMON() \ -uint64_t trace_id; \ -uint64_t timestamp; \ -uint64_t thread; \ -const uint8_t *image_uuid; \ -const char *image_path; \ -struct timeval tv_gmt; \ -struct timezone tz; \ -uint32_t offset - -typedef struct os_activity_stream_common_s { - OS_ACTIVITY_STREAM_COMMON(); -} * os_activity_stream_common_t; - -struct os_activity_create_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *name; - os_activity_id_t creator_aid; - uint64_t unique_pid; -}; - -struct os_activity_transition_s { - OS_ACTIVITY_STREAM_COMMON(); - os_activity_id_t transition_id; -}; - -typedef struct os_log_message_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const uint8_t *buffer; - size_t buffer_sz; - const uint8_t *privdata; - size_t privdata_sz; - const char *subsystem; - const char *category; - uint32_t oversize_id; - uint8_t ttl; - bool persisted; -} * os_log_message_t; - -typedef struct os_trace_message_v2_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const void *buffer; - size_t bufferLen; - xpc_object_t __unsafe_unretained payload; -} * os_trace_message_v2_t; - -typedef struct os_activity_useraction_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *action; - bool persisted; -} * os_activity_useraction_t; - -typedef struct os_signpost_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const uint8_t *buffer; - size_t buffer_sz; - const uint8_t *privdata; - size_t privdata_sz; - const char *subsystem; - const char *category; - uint64_t duration_nsec; - uint32_t callstack_depth; - uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK]; -} * os_signpost_t; - -typedef struct os_activity_statedump_s { - OS_ACTIVITY_STREAM_COMMON(); - char *message; - size_t message_size; - char image_path_buffer[PATH_MAX]; -} * os_activity_statedump_t; - -struct os_activity_stream_entry_s { - os_activity_stream_type_t type; - - // information about the process streaming the data - pid_t pid; - uint64_t proc_id; - const uint8_t *proc_imageuuid; - const char *proc_imagepath; - - // the activity associated with this streamed event - os_activity_id_t activity_id; - os_activity_id_t parent_id; - - union { - struct os_activity_stream_common_s common; - struct os_activity_create_s activity_create; - struct os_activity_transition_s activity_transition; - struct os_log_message_s log_message; - struct os_trace_message_v2_s trace_message; - struct os_activity_useraction_s useraction; - struct os_signpost_s signpost; - struct os_activity_statedump_s statedump; - }; -}; - -// Blocks - -typedef bool (^os_activity_stream_block_t)(os_activity_stream_entry_t entry, - int error); - -typedef void (^os_activity_stream_event_block_t)( - os_activity_stream_t stream, os_activity_stream_event_t event); - -// SPI entry point prototypes - -typedef os_activity_stream_t (*os_activity_stream_for_pid_t)( - pid_t pid, os_activity_stream_flag_t flags, - os_activity_stream_block_t stream_block); - -typedef void (*os_activity_stream_resume_t)(os_activity_stream_t stream); - -typedef void (*os_activity_stream_cancel_t)(os_activity_stream_t stream); - -typedef char *(*os_log_copy_formatted_message_t)(os_log_message_t log_message); - -typedef void (*os_activity_stream_set_event_handler_t)( - os_activity_stream_t stream, os_activity_stream_event_block_t block); - -#endif /* ActivityStreamSPI_h */ diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXASLLogController.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXASLLogController.h deleted file mode 100644 index eeae761..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXASLLogController.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXASLLogController.h -// FLEX -// -// Created by Tanner on 3/14/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXLogController.h" - -@interface FLEXASLLogController : NSObject - -/// Guaranteed to call back on the main thread. -+ (instancetype)withUpdateHandler:(void(^)(NSArray *newMessages))newMessagesHandler; - -- (BOOL)startMonitoring; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXASLLogController.m b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXASLLogController.m deleted file mode 100644 index 328a1d0..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXASLLogController.m +++ /dev/null @@ -1,147 +0,0 @@ -// -// FLEXASLLogController.m -// FLEX -// -// Created by Tanner on 3/14/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXASLLogController.h" -#import - -// Querying the ASL is much slower in the simulator. We need a longer polling interval to keep things responsive. -#if TARGET_IPHONE_SIMULATOR - #define updateInterval 5.0 -#else - #define updateInterval 0.5 -#endif - -@interface FLEXASLLogController () - -@property (nonatomic, readonly) void (^updateHandler)(NSArray *); - -@property (nonatomic) NSTimer *logUpdateTimer; -@property (nonatomic, readonly) NSMutableIndexSet *logMessageIdentifiers; - -// ASL stuff - -@property (nonatomic) NSUInteger heapSize; -@property (nonatomic) dispatch_queue_t logQueue; -@property (nonatomic) dispatch_io_t io; -@property (nonatomic) NSString *remaining; -@property (nonatomic) int stderror; -@property (nonatomic) NSString *lastTimestamp; - -@end - -@implementation FLEXASLLogController - -+ (instancetype)withUpdateHandler:(void(^)(NSArray *newMessages))newMessagesHandler { - return [[self alloc] initWithUpdateHandler:newMessagesHandler]; -} - -- (id)initWithUpdateHandler:(void(^)(NSArray *newMessages))newMessagesHandler { - NSParameterAssert(newMessagesHandler); - - self = [super init]; - if (self) { - _updateHandler = newMessagesHandler; - _logMessageIdentifiers = [NSMutableIndexSet new]; - self.logUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:updateInterval - target:self - selector:@selector(updateLogMessages) - userInfo:nil - repeats:YES]; - } - - return self; -} - -- (void)dealloc { - [self.logUpdateTimer invalidate]; -} - -- (BOOL)startMonitoring { - [self.logUpdateTimer fire]; - return YES; -} - -- (void)updateLogMessages { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSArray *newMessages; - @synchronized (self) { - newMessages = [self newLogMessagesForCurrentProcess]; - if (!newMessages.count) { - return; - } - - for (FLEXSystemLogMessage *message in newMessages) { - [self.logMessageIdentifiers addIndex:(NSUInteger)message.messageID]; - } - - self.lastTimestamp = @(asl_get(newMessages.lastObject.aslMessage, ASL_KEY_TIME) ?: "null"); - } - - dispatch_async(dispatch_get_main_queue(), ^{ - self.updateHandler(newMessages); - }); - }); -} - -#pragma mark - Log Message Fetching - -- (NSArray *)newLogMessagesForCurrentProcess { - if (!self.logMessageIdentifiers.count) { - return [self allLogMessagesForCurrentProcess]; - } - - aslresponse response = [self ASLMessageListForCurrentProcess]; - aslmsg aslMessage = NULL; - - NSMutableArray *newMessages = [NSMutableArray new]; - - while ((aslMessage = asl_next(response))) { - NSUInteger messageID = (NSUInteger)atoll(asl_get(aslMessage, ASL_KEY_MSG_ID)); - if (![self.logMessageIdentifiers containsIndex:messageID]) { - [newMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]]; - } - } - - asl_release(response); - return newMessages; -} - -- (aslresponse)ASLMessageListForCurrentProcess { - static NSString *pidString = nil; - if (!pidString) { - pidString = @([NSProcessInfo.processInfo processIdentifier]).stringValue; - } - - // Create system log query object. - asl_object_t query = asl_new(ASL_TYPE_QUERY); - - // Filter for messages from the current process. - // Note that this appears to happen by default on device, but is required in the simulator. - asl_set_query(query, ASL_KEY_PID, pidString.UTF8String, ASL_QUERY_OP_EQUAL); - // Filter for messages after the last retrieved message. - if (self.lastTimestamp) { - asl_set_query(query, ASL_KEY_TIME, self.lastTimestamp.UTF8String, ASL_QUERY_OP_GREATER); - } - - return asl_search(NULL, query); -} - -- (NSArray *)allLogMessagesForCurrentProcess { - aslresponse response = [self ASLMessageListForCurrentProcess]; - aslmsg aslMessage = NULL; - - NSMutableArray *logMessages = [NSMutableArray new]; - while ((aslMessage = asl_next(response))) { - [logMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]]; - } - asl_release(response); - - return logMessages; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXLogController.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXLogController.h deleted file mode 100644 index cb35088..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXLogController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXLogController.h -// FLEX -// -// Created by Tanner on 3/17/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import "FLEXSystemLogMessage.h" - -@protocol FLEXLogController - -/// Guaranteed to call back on the main thread. -+ (instancetype)withUpdateHandler:(void(^)(NSArray *newMessages))newMessagesHandler; - -- (BOOL)startMonitoring; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXOSLogController.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXOSLogController.h deleted file mode 100644 index 154813c..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXOSLogController.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// FLEXOSLogController.h -// FLEX -// -// Created by Tanner on 12/19/18. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXLogController.h" - -#define FLEXOSLogAvailable() (NSProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 10) - -/// The log controller used for iOS 10 and up. -@interface FLEXOSLogController : NSObject - -+ (instancetype)withUpdateHandler:(void(^)(NSArray *newMessages))newMessagesHandler; - -- (BOOL)startMonitoring; - -/// Whether log messages are to be recorded and kept in-memory in the background. -/// You do not need to initialize this value, only change it. -@property (nonatomic) BOOL persistent; -/// Used mostly internally, but also used by the log VC to persist messages -/// that were created prior to enabling persistence. -@property (nonatomic) NSMutableArray *messages; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXOSLogController.m b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXOSLogController.m deleted file mode 100644 index 08e4f49..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXOSLogController.m +++ /dev/null @@ -1,214 +0,0 @@ -// -// FLEXOSLogController.m -// FLEX -// -// Created by Tanner on 12/19/18. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXOSLogController.h" -#import "NSUserDefaults+FLEX.h" -#include -#include "ActivityStreamAPI.h" - -static os_activity_stream_for_pid_t OSActivityStreamForPID; -static os_activity_stream_resume_t OSActivityStreamResume; -static os_activity_stream_cancel_t OSActivityStreamCancel; -static os_log_copy_formatted_message_t OSLogCopyFormattedMessage; -static os_activity_stream_set_event_handler_t OSActivityStreamSetEventHandler; -static int (*proc_name)(int, char *, unsigned int); -static int (*proc_listpids)(uint32_t, uint32_t, void*, int); -static uint8_t (*OSLogGetType)(void *); - -@interface FLEXOSLogController () - -+ (FLEXOSLogController *)sharedLogController; - -@property (nonatomic) void (^updateHandler)(NSArray *); - -@property (nonatomic) BOOL canPrint; -@property (nonatomic) int filterPid; -@property (nonatomic) BOOL levelInfo; -@property (nonatomic) BOOL subsystemInfo; - -@property (nonatomic) os_activity_stream_t stream; - -@end - -@implementation FLEXOSLogController - -+ (void)load { - // Persist logs when the app launches on iOS 10 if we have persistent logs turned on - if (FLEXOSLogAvailable()) { - if (NSUserDefaults.standardUserDefaults.flex_cacheOSLogMessages) { - [self sharedLogController].persistent = YES; - [[self sharedLogController] startMonitoring]; - } - } -} - -+ (instancetype)sharedLogController { - static FLEXOSLogController *shared = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - shared = [self new]; - }); - - return shared; -} - -+ (instancetype)withUpdateHandler:(void(^)(NSArray *newMessages))newMessagesHandler { - FLEXOSLogController *shared = [self sharedLogController]; - shared.updateHandler = newMessagesHandler; - return shared; -} - -- (id)init { - NSAssert(FLEXOSLogAvailable(), @"os_log is only available on iOS 10 and up"); - - self = [super init]; - if (self) { - _filterPid = NSProcessInfo.processInfo.processIdentifier; - _levelInfo = NO; - _subsystemInfo = NO; - } - - return self; -} - -- (void)dealloc { - OSActivityStreamCancel(self.stream); - _stream = nil; -} - -- (void)setPersistent:(BOOL)persistent { - if (_persistent == persistent) return; - - _persistent = persistent; - self.messages = persistent ? [NSMutableArray new] : nil; -} - -- (BOOL)startMonitoring { - if (![self lookupSPICalls]) { - // >= iOS 10 is required - return NO; - } - - // Are we already monitoring? - if (self.stream) { - // Should we send out the "persisted" messages? - if (self.updateHandler && self.messages.count) { - dispatch_async(dispatch_get_main_queue(), ^{ - self.updateHandler(self.messages); - }); - } - - return YES; - } - - // Stream entry handler - os_activity_stream_block_t block = ^bool(os_activity_stream_entry_t entry, int error) { - return [self handleStreamEntry:entry error:error]; - }; - - // Controls which types of messages we see - // 'Historical' appears to just show NSLog stuff - uint32_t activity_stream_flags = OS_ACTIVITY_STREAM_HISTORICAL; - activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY; -// activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY; - - self.stream = OSActivityStreamForPID(self.filterPid, activity_stream_flags, block); - - // Specify the stream-related event handler - OSActivityStreamSetEventHandler(self.stream, [self streamEventHandlerBlock]); - // Start the stream - OSActivityStreamResume(self.stream); - - return YES; -} - -- (BOOL)lookupSPICalls { - static BOOL hasSPI = NO; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - void *handle = dlopen("/System/Library/PrivateFrameworks/LoggingSupport.framework/LoggingSupport", RTLD_NOW); - - OSActivityStreamForPID = (os_activity_stream_for_pid_t)dlsym(handle, "os_activity_stream_for_pid"); - OSActivityStreamResume = (os_activity_stream_resume_t)dlsym(handle, "os_activity_stream_resume"); - OSActivityStreamCancel = (os_activity_stream_cancel_t)dlsym(handle, "os_activity_stream_cancel"); - OSLogCopyFormattedMessage = (os_log_copy_formatted_message_t)dlsym(handle, "os_log_copy_formatted_message"); - OSActivityStreamSetEventHandler = (os_activity_stream_set_event_handler_t)dlsym(handle, "os_activity_stream_set_event_handler"); - proc_name = (int(*)(int, char *, unsigned int))dlsym(handle, "proc_name"); - proc_listpids = (int(*)(uint32_t, uint32_t, void*, int))dlsym(handle, "proc_listpids"); - OSLogGetType = (uint8_t(*)(void *))dlsym(handle, "os_log_get_type"); - - hasSPI = (OSActivityStreamForPID != NULL) && - (OSActivityStreamResume != NULL) && - (OSActivityStreamCancel != NULL) && - (OSLogCopyFormattedMessage != NULL) && - (OSActivityStreamSetEventHandler != NULL) && - (OSLogGetType != NULL) && - (proc_name != NULL); - }); - - return hasSPI; -} - -- (BOOL)handleStreamEntry:(os_activity_stream_entry_t)entry error:(int)error { - if (!self.canPrint || (self.filterPid != -1 && entry->pid != self.filterPid)) { - return YES; - } - - if (!error && entry) { - if (entry->type == OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE || - entry->type == OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE) { - os_log_message_t log_message = &entry->log_message; - - // Get date - NSDate *date = [NSDate dateWithTimeIntervalSince1970:log_message->tv_gmt.tv_sec]; - - // Get log message text - // https://github.com/limneos/oslog/issues/1 - // https://github.com/FLEXTool/FLEX/issues/564 - const char *messageText = OSLogCopyFormattedMessage(log_message) ?: ""; - - // move messageText from stack to heap - NSString *msg = [NSString stringWithUTF8String:messageText]; - - dispatch_async(dispatch_get_main_queue(), ^{ - FLEXSystemLogMessage *message = [FLEXSystemLogMessage logMessageFromDate:date text:msg]; - if (self.persistent) { - [self.messages addObject:message]; - } - if (self.updateHandler) { - self.updateHandler(@[message]); - } - }); - } - } - - return YES; -} - -- (os_activity_stream_event_block_t)streamEventHandlerBlock { - return [^void(os_activity_stream_t stream, os_activity_stream_event_t event) { - switch (event) { - case OS_ACTIVITY_STREAM_EVENT_STARTED: - self.canPrint = YES; - break; - case OS_ACTIVITY_STREAM_EVENT_STOPPED: - break; - case OS_ACTIVITY_STREAM_EVENT_FAILED: - break; - case OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED: - break; - case OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED: - break; - default: - printf("=== Unhandled case ===\n"); - break; - } - } copy]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogCell.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogCell.h deleted file mode 100644 index 4fdc629..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogCell.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// FLEXSystemLogCell.h -// FLEX -// -// Created by Ryan Olson on 1/25/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewCell.h" - -@class FLEXSystemLogMessage; - -extern NSString *const kFLEXSystemLogCellIdentifier; - -@interface FLEXSystemLogCell : FLEXTableViewCell - -@property (nonatomic) FLEXSystemLogMessage *logMessage; -@property (nonatomic, copy) NSString *highlightedText; - -+ (NSString *)displayedTextForLogMessage:(FLEXSystemLogMessage *)logMessage; -+ (CGFloat)preferredHeightForLogMessage:(FLEXSystemLogMessage *)logMessage inWidth:(CGFloat)width; - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogCell.m b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogCell.m deleted file mode 100644 index 95cfbcd..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogCell.m +++ /dev/null @@ -1,119 +0,0 @@ -// -// FLEXSystemLogCell.m -// FLEX -// -// Created by Ryan Olson on 1/25/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSystemLogCell.h" -#import "FLEXSystemLogMessage.h" -#import "UIFont+FLEX.h" - -NSString *const kFLEXSystemLogCellIdentifier = @"FLEXSystemLogCellIdentifier"; - -@interface FLEXSystemLogCell () - -@property (nonatomic) UILabel *logMessageLabel; -@property (nonatomic) NSAttributedString *logMessageAttributedText; - -@end - -@implementation FLEXSystemLogCell - -- (void)postInit { - [super postInit]; - - self.logMessageLabel = [UILabel new]; - self.logMessageLabel.numberOfLines = 0; - self.separatorInset = UIEdgeInsetsZero; - self.selectionStyle = UITableViewCellSelectionStyleNone; - [self.contentView addSubview:self.logMessageLabel]; -} - -- (void)setLogMessage:(FLEXSystemLogMessage *)logMessage { - if (![_logMessage isEqual:logMessage]) { - _logMessage = logMessage; - self.logMessageAttributedText = nil; - [self setNeedsLayout]; - } -} - -- (void)setHighlightedText:(NSString *)highlightedText { - if (![_highlightedText isEqual:highlightedText]) { - _highlightedText = highlightedText; - self.logMessageAttributedText = nil; - [self setNeedsLayout]; - } -} - -- (NSAttributedString *)logMessageAttributedText { - if (!_logMessageAttributedText) { - _logMessageAttributedText = [[self class] attributedTextForLogMessage:self.logMessage highlightedText:self.highlightedText]; - } - return _logMessageAttributedText; -} - -static const UIEdgeInsets kFLEXLogMessageCellInsets = {10.0, 10.0, 10.0, 10.0}; - -- (void)layoutSubviews { - [super layoutSubviews]; - - self.logMessageLabel.attributedText = self.logMessageAttributedText; - self.logMessageLabel.frame = UIEdgeInsetsInsetRect(self.contentView.bounds, kFLEXLogMessageCellInsets); -} - - -#pragma mark - Stateless helpers - -+ (NSAttributedString *)attributedTextForLogMessage:(FLEXSystemLogMessage *)logMessage highlightedText:(NSString *)highlightedText { - NSString *text = [self displayedTextForLogMessage:logMessage]; - NSDictionary *attributes = @{ NSFontAttributeName : UIFont.flex_codeFont }; - NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes]; - - if (highlightedText.length > 0) { - NSMutableAttributedString *mutableAttributedText = attributedText.mutableCopy; - NSMutableDictionary *highlightAttributes = attributes.mutableCopy; - highlightAttributes[NSBackgroundColorAttributeName] = UIColor.yellowColor; - - NSRange remainingSearchRange = NSMakeRange(0, text.length); - while (remainingSearchRange.location < text.length) { - remainingSearchRange.length = text.length - remainingSearchRange.location; - NSRange foundRange = [text rangeOfString:highlightedText options:NSCaseInsensitiveSearch range:remainingSearchRange]; - if (foundRange.location != NSNotFound) { - remainingSearchRange.location = foundRange.location + foundRange.length; - [mutableAttributedText setAttributes:highlightAttributes range:foundRange]; - } else { - break; - } - } - attributedText = mutableAttributedText; - } - - return attributedText; -} - -+ (NSString *)displayedTextForLogMessage:(FLEXSystemLogMessage *)logMessage { - return [NSString stringWithFormat:@"%@: %@", [self logTimeStringFromDate:logMessage.date], logMessage.messageText]; -} - -+ (CGFloat)preferredHeightForLogMessage:(FLEXSystemLogMessage *)logMessage inWidth:(CGFloat)width { - UIEdgeInsets insets = kFLEXLogMessageCellInsets; - CGFloat availableWidth = width - insets.left - insets.right; - NSAttributedString *attributedLogText = [self attributedTextForLogMessage:logMessage highlightedText:nil]; - CGSize labelSize = [attributedLogText boundingRectWithSize:CGSizeMake(availableWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading context:nil].size; - return labelSize.height + insets.top + insets.bottom; -} - -+ (NSString *)logTimeStringFromDate:(NSDate *)date { - static NSDateFormatter *formatter = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - formatter = [NSDateFormatter new]; - formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; - }); - - return [formatter stringFromDate:date]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.h deleted file mode 100644 index 4976eac..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// FLEXSystemLogMessage.h -// FLEX -// -// Created by Ryan Olson on 1/25/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import -#import "ActivityStreamAPI.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXSystemLogMessage : NSObject - -+ (instancetype)logMessageFromASLMessage:(aslmsg)aslMessage; -+ (instancetype)logMessageFromDate:(NSDate *)date text:(NSString *)text; - -// ASL specific properties -@property (nonatomic, readonly, nullable) NSString *sender; -@property (nonatomic, readonly, nullable) aslmsg aslMessage; - -@property (nonatomic, readonly) NSDate *date; -@property (nonatomic, readonly) NSString *messageText; -@property (nonatomic, readonly) long long messageID; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.m b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.m deleted file mode 100644 index 98f9e05..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogMessage.m +++ /dev/null @@ -1,88 +0,0 @@ -// -// FLEXSystemLogMessage.m -// FLEX -// -// Created by Ryan Olson on 1/25/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSystemLogMessage.h" - -@implementation FLEXSystemLogMessage - -+ (instancetype)logMessageFromASLMessage:(aslmsg)aslMessage { - NSDate *date = nil; - NSString *sender = nil, *text = nil; - long long identifier = 0; - - const char *timestamp = asl_get(aslMessage, ASL_KEY_TIME); - if (timestamp) { - NSTimeInterval timeInterval = [@(timestamp) integerValue]; - const char *nanoseconds = asl_get(aslMessage, ASL_KEY_TIME_NSEC); - if (nanoseconds) { - timeInterval += [@(nanoseconds) doubleValue] / NSEC_PER_SEC; - } - date = [NSDate dateWithTimeIntervalSince1970:timeInterval]; - } - - const char *s = asl_get(aslMessage, ASL_KEY_SENDER); - if (s) { - sender = @(s); - } - - const char *messageText = asl_get(aslMessage, ASL_KEY_MSG); - if (messageText) { - text = @(messageText); - } - - const char *messageID = asl_get(aslMessage, ASL_KEY_MSG_ID); - if (messageID) { - identifier = [@(messageID) longLongValue]; - } - - FLEXSystemLogMessage *message = [[self alloc] initWithDate:date sender:sender text:text messageID:identifier]; - message->_aslMessage = aslMessage; - return message; -} - -+ (instancetype)logMessageFromDate:(NSDate *)date text:(NSString *)text { - return [[self alloc] initWithDate:date sender:nil text:text messageID:0]; -} - -- (id)initWithDate:(NSDate *)date sender:(NSString *)sender text:(NSString *)text messageID:(long long)identifier { - self = [super init]; - if (self) { - _date = date; - _sender = sender; - _messageText = text; - _messageID = identifier; - } - - return self; -} - -- (BOOL)isEqual:(id)object { - if ([object isKindOfClass:[self class]]) { - if (self.messageID) { - // Only ASL uses messageID, otherwise it is 0 - return self.messageID == [object messageID]; - } else { - // Test message texts and dates for OS Log - return [self.messageText isEqual:[object messageText]] && - [self.date isEqualToDate:[object date]]; - } - } - - return NO; -} - -- (NSUInteger)hash { - return (NSUInteger)self.messageID; -} - -- (NSString *)description { - NSString *escaped = [self.messageText stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; - return [NSString stringWithFormat:@"(%@) %@", @(self.messageText.length), escaped]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogViewController.h b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogViewController.h deleted file mode 100644 index 59ce054..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXSystemLogViewController.h -// FLEX -// -// Created by Ryan Olson on 1/19/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXFilteringTableViewController.h" -#import "FLEXGlobalsEntry.h" - -@interface FLEXSystemLogViewController : FLEXFilteringTableViewController - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogViewController.m b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogViewController.m deleted file mode 100644 index 0b5cfed..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/FLEXSystemLogViewController.m +++ /dev/null @@ -1,293 +0,0 @@ -// -// FLEXSystemLogViewController.m -// FLEX -// -// Created by Ryan Olson on 1/19/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSystemLogViewController.h" -#import "FLEXASLLogController.h" -#import "FLEXOSLogController.h" -#import "FLEXSystemLogCell.h" -#import "FLEXMutableListSection.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" -#import "FLEXResources.h" -#import "UIBarButtonItem+FLEX.h" -#import "NSUserDefaults+FLEX.h" -#import "flex_fishhook.h" -#import - -@interface FLEXSystemLogViewController () - -@property (nonatomic, readonly) FLEXMutableListSection *logMessages; -@property (nonatomic, readonly) id logController; - -@end - -static void (*MSHookFunction)(void *symbol, void *replace, void **result); - -static BOOL FLEXDidHookNSLog = NO; -static BOOL FLEXNSLogHookWorks = NO; - -BOOL (*os_log_shim_enabled)(void *addr) = nil; -BOOL (*orig_os_log_shim_enabled)(void *addr) = nil; -static BOOL my_os_log_shim_enabled(void *addr) { - return NO; -} - -@implementation FLEXSystemLogViewController - -#pragma mark - Initialization - -+ (void)load { - // User must opt-into disabling os_log - if (!NSUserDefaults.standardUserDefaults.flex_disableOSLog) { - return; - } - - // Thanks to @Ram4096 on GitHub for telling me that - // os_log is conditionally enabled by the SDK version - void *addr = __builtin_return_address(0); - void *libsystem_trace = dlopen("/usr/lib/system/libsystem_trace.dylib", RTLD_LAZY); - os_log_shim_enabled = dlsym(libsystem_trace, "os_log_shim_enabled"); - if (!os_log_shim_enabled) { - return; - } - - FLEXDidHookNSLog = flex_rebind_symbols((struct rebinding[1]) {{ - "os_log_shim_enabled", - (void *)my_os_log_shim_enabled, - (void **)&orig_os_log_shim_enabled - }}, 1) == 0; - - if (FLEXDidHookNSLog && orig_os_log_shim_enabled != nil) { - // Check if our rebinding worked - FLEXNSLogHookWorks = my_os_log_shim_enabled(addr) == NO; - } - - // So, just because we rebind the lazily loaded symbol for - // this function doesn't mean it's even going to be used. - // While it seems to be sufficient for the simulator, for - // whatever reason it is not sufficient on-device. We need - // to actually hook the function with something like Substrate. - - // Check if we have substrate, and if so use that instead - void *handle = dlopen("/usr/lib/libsubstrate.dylib", RTLD_LAZY); - if (handle) { - MSHookFunction = dlsym(handle, "MSHookFunction"); - - if (MSHookFunction) { - // Set the hook and check if it worked - void *unused; - MSHookFunction(os_log_shim_enabled, my_os_log_shim_enabled, &unused); - FLEXNSLogHookWorks = os_log_shim_enabled(addr) == NO; - } - } -} - -- (id)init { - return [super initWithStyle:UITableViewStylePlain]; -} - - -#pragma mark - Overrides - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsSearchBar = YES; - self.pinSearchBar = YES; - - weakify(self) - id logHandler = ^(NSArray *newMessages) { strongify(self) - [self handleUpdateWithNewMessages:newMessages]; - }; - - if (FLEXOSLogAvailable() && !FLEXNSLogHookWorks) { - _logController = [FLEXOSLogController withUpdateHandler:logHandler]; - } else { - _logController = [FLEXASLLogController withUpdateHandler:logHandler]; - } - - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - self.title = @"Waiting for Logs..."; - - // Toolbar buttons // - - UIBarButtonItem *scrollDown = [UIBarButtonItem - flex_itemWithImage:FLEXResources.scrollToBottomIcon - target:self - action:@selector(scrollToLastRow) - ]; - UIBarButtonItem *settings = [UIBarButtonItem - flex_itemWithImage:FLEXResources.gearIcon - target:self - action:@selector(showLogSettings) - ]; - - [self addToolbarItems:@[scrollDown, settings]]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self.logController startMonitoring]; -} - -- (NSArray *)makeSections { weakify(self) - _logMessages = [FLEXMutableListSection list:@[] - cellConfiguration:^(FLEXSystemLogCell *cell, FLEXSystemLogMessage *message, NSInteger row) { - strongify(self) - - cell.logMessage = message; - cell.highlightedText = self.filterText; - - if (row % 2 == 0) { - cell.backgroundColor = FLEXColor.primaryBackgroundColor; - } else { - cell.backgroundColor = FLEXColor.secondaryBackgroundColor; - } - } filterMatcher:^BOOL(NSString *filterText, FLEXSystemLogMessage *message) { - NSString *displayedText = [FLEXSystemLogCell displayedTextForLogMessage:message]; - return [displayedText localizedCaseInsensitiveContainsString:filterText]; - } - ]; - - self.logMessages.cellRegistrationMapping = @{ - kFLEXSystemLogCellIdentifier : [FLEXSystemLogCell class] - }; - - return @[self.logMessages]; -} - -- (NSArray *)nonemptySections { - return @[self.logMessages]; -} - - -#pragma mark - Private - -- (void)handleUpdateWithNewMessages:(NSArray *)newMessages { - self.title = [self.class globalsEntryTitle:FLEXGlobalsRowSystemLog]; - - [self.logMessages mutate:^(NSMutableArray *list) { - [list addObjectsFromArray:newMessages]; - }]; - - // Re-filter messages to filter against new messages - if (self.filterText.length) { - [self updateSearchResults:self.filterText]; - } - - // "Follow" the log as new messages stream in if we were previously near the bottom. - UITableView *tv = self.tableView; - BOOL wasNearBottom = tv.contentOffset.y >= tv.contentSize.height - tv.frame.size.height - 100.0; - [self reloadData]; - if (wasNearBottom) { - [self scrollToLastRow]; - } -} - -- (void)scrollToLastRow { - NSInteger numberOfRows = [self.tableView numberOfRowsInSection:0]; - if (numberOfRows > 0) { - NSIndexPath *last = [NSIndexPath indexPathForRow:numberOfRows - 1 inSection:0]; - [self.tableView scrollToRowAtIndexPath:last atScrollPosition:UITableViewScrollPositionBottom animated:YES]; - } -} - -- (void)showLogSettings { - NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; - BOOL disableOSLog = defaults.flex_disableOSLog; - BOOL persistent = defaults.flex_cacheOSLogMessages; - - NSString *aslToggle = disableOSLog ? @"Enable os_log (default)" : @"Disable os_log"; - NSString *persistence = persistent ? @"Disable persistent logging" : @"Enable persistent logging"; - - NSString *title = @"System Log Settings"; - NSString *body = @"In iOS 10 and up, ASL has been replaced by os_log. " - "The os_log API is much more limited. Below, you can opt-into the old behavior " - "if you want cleaner, more reliable logs within FLEX, but this will break " - "anything that expects os_log to be working, such as Console.app. " - "This setting requires the app to restart to take effect. \n\n" - - "To get as close to the old behavior as possible with os_log enabled, logs must " - "be collected manually at launch and stored. This setting has no effect " - "on iOS 9 and below, or if os_log is disabled. " - "You should only enable persistent logging when you need it."; - - FLEXOSLogController *logController = (FLEXOSLogController *)self.logController; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(title).message(body); - make.button(aslToggle).destructiveStyle().handler(^(NSArray *strings) { - [defaults flex_toggleBoolForKey:kFLEXDefaultsDisableOSLogForceASLKey]; - }); - - make.button(persistence).handler(^(NSArray *strings) { - [defaults flex_toggleBoolForKey:kFLEXDefaultsiOSPersistentOSLogKey]; - logController.persistent = !persistent; - [logController.messages addObjectsFromArray:self.logMessages.list]; - }); - make.button(@"Dismiss").cancelStyle(); - } showFrom:self]; -} - - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"⚠️ System Log"; -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - return [self new]; -} - - -#pragma mark - Table view data source - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXSystemLogMessage *logMessage = self.logMessages.filteredList[indexPath.row]; - return [FLEXSystemLogCell preferredHeightForLogMessage:logMessage inWidth:self.tableView.bounds.size.width]; -} - - -#pragma mark - Copy on long press - -- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; -} - -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - return action == @selector(copy:); -} - -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - if (action == @selector(copy:)) { - // We usually only want to copy the log message itself, not any metadata associated with it. - UIPasteboard.generalPasteboard.string = self.logMessages.filteredList[indexPath.row].messageText ?: @""; - } -} - -- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView -contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath - point:(CGPoint)point __IOS_AVAILABLE(13.0) { - weakify(self) - return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil - actionProvider:^UIMenu *(NSArray *suggestedActions) { - UIAction *copy = [UIAction actionWithTitle:@"Copy" - image:nil - identifier:@"Copy" - handler:^(UIAction *action) { strongify(self) - // We usually only want to copy the log message itself, not any metadata associated with it. - UIPasteboard.generalPasteboard.string = self.logMessages.filteredList[indexPath.row].messageText ?: @""; - }]; - return [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[copy]]; - } - ]; -} - -@end diff --git a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/LLVM_LICENSE.TXT b/Tweaks/FLEX/GlobalStateExplorers/SystemLog/LLVM_LICENSE.TXT deleted file mode 100644 index 029b1d9..0000000 --- a/Tweaks/FLEX/GlobalStateExplorers/SystemLog/LLVM_LICENSE.TXT +++ /dev/null @@ -1,276 +0,0 @@ -============================================================================== -The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: -============================================================================== - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ----- LLVM Exceptions to the Apache 2.0 License ---- - -As an exception, if, as a result of your compiling your source code, portions -of this Software are embedded into an Object form of such source code, you -may redistribute such embedded portions in such Object form without complying -with the conditions of Sections 4(a), 4(b) and 4(d) of the License. - -In addition, if you combine or link compiled forms of this Software with -software that is licensed under the GPLv2 ("Combined Software") and if a -court of competent jurisdiction determines that the patent provision (Section -3), the indemnity provision (Section 9) or other Section of the License -conflicts with the conditions of the GPLv2, you may retroactively and -prospectively choose to deem waived or otherwise exclude such Section(s) of -the License, but only in their entirety and only with respect to the Combined -Software. - -============================================================================== -Software from third parties included in the LLVM Project: -============================================================================== -The LLVM Project contains third party software which is under different license -terms. All such code will be identified clearly using at least one of two -mechanisms: -1) It will be in a separate directory tree with its own `LICENSE.txt` or - `LICENSE` file at the top containing the specific license and restrictions - which apply to that software, or -2) It will contain specific license and restriction terms at the top of every - file. - -============================================================================== -Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): -============================================================================== -University of Illinois/NCSA -Open Source License - -Copyright (c) 2010 Apple Inc. -All rights reserved. - -Developed by: - - LLDB Team - - http://lldb.llvm.org/ - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal with -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimers. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimers in the - documentation and/or other materials provided with the distribution. - - * Neither the names of the LLDB Team, copyright holders, nor the names of - its contributors may be used to endorse or promote products derived from - this Software without specific prior written permission. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE -SOFTWARE. - diff --git a/Tweaks/FLEX/Headers/CALayer+FLEX.h b/Tweaks/FLEX/Headers/CALayer+FLEX.h deleted file mode 120000 index fbfd906..0000000 --- a/Tweaks/FLEX/Headers/CALayer+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/CALayer+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEX-Categories.h b/Tweaks/FLEX/Headers/FLEX-Categories.h deleted file mode 120000 index 11e18d1..0000000 --- a/Tweaks/FLEX/Headers/FLEX-Categories.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/FLEX-Categories.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEX-Core.h b/Tweaks/FLEX/Headers/FLEX-Core.h deleted file mode 120000 index 0cad935..0000000 --- a/Tweaks/FLEX/Headers/FLEX-Core.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/FLEX-Core.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEX-ObjectExploring.h b/Tweaks/FLEX/Headers/FLEX-ObjectExploring.h deleted file mode 120000 index 5736d39..0000000 --- a/Tweaks/FLEX/Headers/FLEX-ObjectExploring.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/FLEX-ObjectExploring.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEX-Runtime.h b/Tweaks/FLEX/Headers/FLEX-Runtime.h deleted file mode 120000 index 62855bb..0000000 --- a/Tweaks/FLEX/Headers/FLEX-Runtime.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/FLEX-Runtime.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEX.h b/Tweaks/FLEX/Headers/FLEX.h deleted file mode 120000 index 738206d..0000000 --- a/Tweaks/FLEX/Headers/FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXAlert.h b/Tweaks/FLEX/Headers/FLEXAlert.h deleted file mode 120000 index 547ff86..0000000 --- a/Tweaks/FLEX/Headers/FLEXAlert.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/FLEXAlert.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXBlockDescription.h b/Tweaks/FLEX/Headers/FLEXBlockDescription.h deleted file mode 120000 index fd4faae..0000000 --- a/Tweaks/FLEX/Headers/FLEXBlockDescription.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXClassBuilder.h b/Tweaks/FLEX/Headers/FLEXClassBuilder.h deleted file mode 120000 index ea432a0..0000000 --- a/Tweaks/FLEX/Headers/FLEXClassBuilder.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXCodeFontCell.h b/Tweaks/FLEX/Headers/FLEXCodeFontCell.h deleted file mode 120000 index 00e66cd..0000000 --- a/Tweaks/FLEX/Headers/FLEXCodeFontCell.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Views/Cells/FLEXCodeFontCell.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXCollectionContentSection.h b/Tweaks/FLEX/Headers/FLEXCollectionContentSection.h deleted file mode 120000 index aced8cd..0000000 --- a/Tweaks/FLEX/Headers/FLEXCollectionContentSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/FLEXCollectionContentSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXColorPreviewSection.h b/Tweaks/FLEX/Headers/FLEXColorPreviewSection.h deleted file mode 120000 index e55ab3a..0000000 --- a/Tweaks/FLEX/Headers/FLEXColorPreviewSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/FLEXColorPreviewSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXDefaultsContentSection.h b/Tweaks/FLEX/Headers/FLEXDefaultsContentSection.h deleted file mode 120000 index 4932c59..0000000 --- a/Tweaks/FLEX/Headers/FLEXDefaultsContentSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/FLEXDefaultsContentSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXExplorerToolbar.h b/Tweaks/FLEX/Headers/FLEXExplorerToolbar.h deleted file mode 120000 index 80c1867..0000000 --- a/Tweaks/FLEX/Headers/FLEXExplorerToolbar.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Toolbar/FLEXExplorerToolbar.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXExplorerToolbarItem.h b/Tweaks/FLEX/Headers/FLEXExplorerToolbarItem.h deleted file mode 120000 index bdc7155..0000000 --- a/Tweaks/FLEX/Headers/FLEXExplorerToolbarItem.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Toolbar/FLEXExplorerToolbarItem.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXFilteringTableViewController.h b/Tweaks/FLEX/Headers/FLEXFilteringTableViewController.h deleted file mode 120000 index fbb2e5d..0000000 --- a/Tweaks/FLEX/Headers/FLEXFilteringTableViewController.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Controllers/FLEXFilteringTableViewController.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXGlobalsEntry.h b/Tweaks/FLEX/Headers/FLEXGlobalsEntry.h deleted file mode 120000 index f3c80b0..0000000 --- a/Tweaks/FLEX/Headers/FLEXGlobalsEntry.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXIvar.h b/Tweaks/FLEX/Headers/FLEXIvar.h deleted file mode 120000 index 6c61cd3..0000000 --- a/Tweaks/FLEX/Headers/FLEXIvar.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXIvar.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXKeyValueTableViewCell.h b/Tweaks/FLEX/Headers/FLEXKeyValueTableViewCell.h deleted file mode 120000 index 4a887f7..0000000 --- a/Tweaks/FLEX/Headers/FLEXKeyValueTableViewCell.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Views/Cells/FLEXKeyValueTableViewCell.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMacros.h b/Tweaks/FLEX/Headers/FLEXMacros.h deleted file mode 120000 index fff2f7a..0000000 --- a/Tweaks/FLEX/Headers/FLEXMacros.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/FLEXMacros.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXManager+Extensibility.h b/Tweaks/FLEX/Headers/FLEXManager+Extensibility.h deleted file mode 120000 index d4ce0e7..0000000 --- a/Tweaks/FLEX/Headers/FLEXManager+Extensibility.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Manager/FLEXManager+Extensibility.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXManager+Networking.h b/Tweaks/FLEX/Headers/FLEXManager+Networking.h deleted file mode 120000 index eee45ae..0000000 --- a/Tweaks/FLEX/Headers/FLEXManager+Networking.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Manager/FLEXManager+Networking.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXManager.h b/Tweaks/FLEX/Headers/FLEXManager.h deleted file mode 120000 index f041bb6..0000000 --- a/Tweaks/FLEX/Headers/FLEXManager.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Manager/FLEXManager.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMetadataSection.h b/Tweaks/FLEX/Headers/FLEXMetadataSection.h deleted file mode 120000 index bc6f4ed..0000000 --- a/Tweaks/FLEX/Headers/FLEXMetadataSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/FLEXMetadataSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMethod.h b/Tweaks/FLEX/Headers/FLEXMethod.h deleted file mode 120000 index 9c817b8..0000000 --- a/Tweaks/FLEX/Headers/FLEXMethod.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXMethod.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMethodBase.h b/Tweaks/FLEX/Headers/FLEXMethodBase.h deleted file mode 120000 index 5031eed..0000000 --- a/Tweaks/FLEX/Headers/FLEXMethodBase.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXMethodBase.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMirror.h b/Tweaks/FLEX/Headers/FLEXMirror.h deleted file mode 120000 index c3a34f1..0000000 --- a/Tweaks/FLEX/Headers/FLEXMirror.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXMirror.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMultilineTableViewCell.h b/Tweaks/FLEX/Headers/FLEXMultilineTableViewCell.h deleted file mode 120000 index 46c14ce..0000000 --- a/Tweaks/FLEX/Headers/FLEXMultilineTableViewCell.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Views/Cells/FLEXMultilineTableViewCell.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXMutableListSection.h b/Tweaks/FLEX/Headers/FLEXMutableListSection.h deleted file mode 120000 index bab3c7d..0000000 --- a/Tweaks/FLEX/Headers/FLEXMutableListSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/FLEXMutableListSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXNavigationController.h b/Tweaks/FLEX/Headers/FLEXNavigationController.h deleted file mode 120000 index 650cdc4..0000000 --- a/Tweaks/FLEX/Headers/FLEXNavigationController.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Controllers/FLEXNavigationController.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXObjcInternal.h b/Tweaks/FLEX/Headers/FLEXObjcInternal.h deleted file mode 120000 index 448469d..0000000 --- a/Tweaks/FLEX/Headers/FLEXObjcInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/FLEXObjcInternal.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXObjectExplorer.h b/Tweaks/FLEX/Headers/FLEXObjectExplorer.h deleted file mode 120000 index b22a3e1..0000000 --- a/Tweaks/FLEX/Headers/FLEXObjectExplorer.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/FLEXObjectExplorer.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXObjectExplorerFactory.h b/Tweaks/FLEX/Headers/FLEXObjectExplorerFactory.h deleted file mode 120000 index d14e830..0000000 --- a/Tweaks/FLEX/Headers/FLEXObjectExplorerFactory.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/FLEXObjectExplorerFactory.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXObjectExplorerViewController.h b/Tweaks/FLEX/Headers/FLEXObjectExplorerViewController.h deleted file mode 120000 index 21539ef..0000000 --- a/Tweaks/FLEX/Headers/FLEXObjectExplorerViewController.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/FLEXObjectExplorerViewController.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXObjectInfoSection.h b/Tweaks/FLEX/Headers/FLEXObjectInfoSection.h deleted file mode 120000 index cdd9f59..0000000 --- a/Tweaks/FLEX/Headers/FLEXObjectInfoSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/FLEXObjectInfoSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXProperty.h b/Tweaks/FLEX/Headers/FLEXProperty.h deleted file mode 120000 index e3167ab..0000000 --- a/Tweaks/FLEX/Headers/FLEXProperty.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXProperty.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXPropertyAttributes.h b/Tweaks/FLEX/Headers/FLEXPropertyAttributes.h deleted file mode 120000 index 539e138..0000000 --- a/Tweaks/FLEX/Headers/FLEXPropertyAttributes.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXProtocol.h b/Tweaks/FLEX/Headers/FLEXProtocol.h deleted file mode 120000 index a6d227c..0000000 --- a/Tweaks/FLEX/Headers/FLEXProtocol.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXProtocol.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXProtocolBuilder.h b/Tweaks/FLEX/Headers/FLEXProtocolBuilder.h deleted file mode 120000 index 962f66a..0000000 --- a/Tweaks/FLEX/Headers/FLEXProtocolBuilder.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXResources.h b/Tweaks/FLEX/Headers/FLEXResources.h deleted file mode 120000 index 12a95c4..0000000 --- a/Tweaks/FLEX/Headers/FLEXResources.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/FLEXResources.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXRuntime+Compare.h b/Tweaks/FLEX/Headers/FLEXRuntime+Compare.h deleted file mode 120000 index 9ddeefd..0000000 --- a/Tweaks/FLEX/Headers/FLEXRuntime+Compare.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/FLEXRuntime+Compare.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXRuntime+UIKitHelpers.h b/Tweaks/FLEX/Headers/FLEXRuntime+UIKitHelpers.h deleted file mode 120000 index 82208fb..0000000 --- a/Tweaks/FLEX/Headers/FLEXRuntime+UIKitHelpers.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXRuntimeConstants.h b/Tweaks/FLEX/Headers/FLEXRuntimeConstants.h deleted file mode 120000 index aad5f99..0000000 --- a/Tweaks/FLEX/Headers/FLEXRuntimeConstants.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/FLEXRuntimeConstants.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXRuntimeSafety.h b/Tweaks/FLEX/Headers/FLEXRuntimeSafety.h deleted file mode 120000 index 704ed2c..0000000 --- a/Tweaks/FLEX/Headers/FLEXRuntimeSafety.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/FLEXRuntimeSafety.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXShortcut.h b/Tweaks/FLEX/Headers/FLEXShortcut.h deleted file mode 120000 index d975056..0000000 --- a/Tweaks/FLEX/Headers/FLEXShortcut.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXShortcutsSection.h b/Tweaks/FLEX/Headers/FLEXShortcutsSection.h deleted file mode 120000 index 790d7d5..0000000 --- a/Tweaks/FLEX/Headers/FLEXShortcutsSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXSingleRowSection.h b/Tweaks/FLEX/Headers/FLEXSingleRowSection.h deleted file mode 120000 index 9cb1dca..0000000 --- a/Tweaks/FLEX/Headers/FLEXSingleRowSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/FLEXSingleRowSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXSubtitleTableViewCell.h b/Tweaks/FLEX/Headers/FLEXSubtitleTableViewCell.h deleted file mode 120000 index c74e04d..0000000 --- a/Tweaks/FLEX/Headers/FLEXSubtitleTableViewCell.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Views/Cells/FLEXSubtitleTableViewCell.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXTableView.h b/Tweaks/FLEX/Headers/FLEXTableView.h deleted file mode 120000 index 8fa2fb4..0000000 --- a/Tweaks/FLEX/Headers/FLEXTableView.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Views/FLEXTableView.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXTableViewCell.h b/Tweaks/FLEX/Headers/FLEXTableViewCell.h deleted file mode 120000 index 3c5fdea..0000000 --- a/Tweaks/FLEX/Headers/FLEXTableViewCell.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Views/Cells/FLEXTableViewCell.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXTableViewController.h b/Tweaks/FLEX/Headers/FLEXTableViewController.h deleted file mode 120000 index 7072001..0000000 --- a/Tweaks/FLEX/Headers/FLEXTableViewController.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/Controllers/FLEXTableViewController.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXTableViewSection.h b/Tweaks/FLEX/Headers/FLEXTableViewSection.h deleted file mode 120000 index 66415a8..0000000 --- a/Tweaks/FLEX/Headers/FLEXTableViewSection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Core/FLEXTableViewSection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/FLEXTypeEncodingParser.h b/Tweaks/FLEX/Headers/FLEXTypeEncodingParser.h deleted file mode 120000 index e4b250a..0000000 --- a/Tweaks/FLEX/Headers/FLEXTypeEncodingParser.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Runtime/Objc/FLEXTypeEncodingParser.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/NSArray+FLEX.h b/Tweaks/FLEX/Headers/NSArray+FLEX.h deleted file mode 120000 index 4144ec5..0000000 --- a/Tweaks/FLEX/Headers/NSArray+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/NSArray+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/NSObject+FLEX_Reflection.h b/Tweaks/FLEX/Headers/NSObject+FLEX_Reflection.h deleted file mode 120000 index c42b730..0000000 --- a/Tweaks/FLEX/Headers/NSObject+FLEX_Reflection.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/NSObject+FLEX_Reflection.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/NSTimer+FLEX.h b/Tweaks/FLEX/Headers/NSTimer+FLEX.h deleted file mode 120000 index e67c534..0000000 --- a/Tweaks/FLEX/Headers/NSTimer+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/NSTimer+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/NSUserDefaults+FLEX.h b/Tweaks/FLEX/Headers/NSUserDefaults+FLEX.h deleted file mode 120000 index a6ceabf..0000000 --- a/Tweaks/FLEX/Headers/NSUserDefaults+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/NSUserDefaults+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/UIBarButtonItem+FLEX.h b/Tweaks/FLEX/Headers/UIBarButtonItem+FLEX.h deleted file mode 120000 index db0238e..0000000 --- a/Tweaks/FLEX/Headers/UIBarButtonItem+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/UIBarButtonItem+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/UIFont+FLEX.h b/Tweaks/FLEX/Headers/UIFont+FLEX.h deleted file mode 120000 index 5f16d84..0000000 --- a/Tweaks/FLEX/Headers/UIFont+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/UIFont+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/UIGestureRecognizer+Blocks.h b/Tweaks/FLEX/Headers/UIGestureRecognizer+Blocks.h deleted file mode 120000 index c8cc1a8..0000000 --- a/Tweaks/FLEX/Headers/UIGestureRecognizer+Blocks.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/UIGestureRecognizer+Blocks.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/UIMenu+FLEX.h b/Tweaks/FLEX/Headers/UIMenu+FLEX.h deleted file mode 120000 index a7b0c1f..0000000 --- a/Tweaks/FLEX/Headers/UIMenu+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/UIMenu+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/UIPasteboard+FLEX.h b/Tweaks/FLEX/Headers/UIPasteboard+FLEX.h deleted file mode 120000 index 0c840bb..0000000 --- a/Tweaks/FLEX/Headers/UIPasteboard+FLEX.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/UIPasteboard+FLEX.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/UITextField+Range.h b/Tweaks/FLEX/Headers/UITextField+Range.h deleted file mode 120000 index 52e8bea..0000000 --- a/Tweaks/FLEX/Headers/UITextField+Range.h +++ /dev/null @@ -1 +0,0 @@ -../../Classes/Utility/Categories/UITextField+Range.h \ No newline at end of file diff --git a/Tweaks/FLEX/Headers/module.modulemap b/Tweaks/FLEX/Headers/module.modulemap deleted file mode 100644 index 7a10ccd..0000000 --- a/Tweaks/FLEX/Headers/module.modulemap +++ /dev/null @@ -1,8 +0,0 @@ -module FLEX { - umbrella header "FLEX.h" - - link "flex" - - export * - module * { export * } -} diff --git a/Tweaks/FLEX/Info.plist b/Tweaks/FLEX/Info.plist deleted file mode 100644 index d3de8ee..0000000 --- a/Tweaks/FLEX/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/Tweaks/FLEX/Manager/FLEXManager+Extensibility.h b/Tweaks/FLEX/Manager/FLEXManager+Extensibility.h deleted file mode 100644 index 1a71a0e..0000000 --- a/Tweaks/FLEX/Manager/FLEXManager+Extensibility.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// FLEXManager+Extensibility.h -// FLEX -// -// Created by Tanner on 2/2/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager.h" -#import "FLEXGlobalsEntry.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXManager (Extensibility) - -#pragma mark - Globals Screen Entries - -/// Adds an entry at the top of the list of Global State items. -/// Call this method before this view controller is displayed. -/// @param entryName The string to be displayed in the cell. -/// @param objectFutureBlock When you tap on the row, information about the object returned -/// by this block will be displayed. Passing a block that returns an object allows you to display -/// information about an object whose actual pointer may change at runtime (e.g. +currentUser) -/// @note This method must be called from the main thread. -/// The objectFutureBlock will be invoked from the main thread and may return nil. -/// @note The passed block will be copied and retain for the duration of the application, -/// you may want to use __weak references. -- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock; - -/// Adds an entry at the top of the list of Global State items. -/// Call this method before this view controller is displayed. -/// @param entryName The string to be displayed in the cell. -/// @param viewControllerFutureBlock When you tap on the row, view controller returned -/// by this block will be pushed on the navigation controller stack. -/// @note This method must be called from the main thread. -/// The viewControllerFutureBlock will be invoked from the main thread and may not return nil. -/// @note The passed block will be copied and retain for the duration of the application, -/// you may want to use __weak references as needed. -- (void)registerGlobalEntryWithName:(NSString *)entryName - viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock; - -/// Adds an entry at the top of the list of Global State items. -/// @param entryName The string to be displayed in the cell. -/// @param rowSelectedAction When you tap on the row, this block will be invoked -/// with the host table view view controller. Use it to deselect the row or present an alert. -/// @note This method must be called from the main thread. -/// The rowSelectedAction will be invoked from the main thread. -/// @note The passed block will be copied and retain for the duration of the application, -/// you may want to use __weak references as needed. -- (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction; - -/// Removes all registered global entries. -- (void)clearGlobalEntries; - -#pragma mark - Simulator Shortcuts - -/// Simulator keyboard shortcuts are enabled by default. -/// The shortcuts will not fire when there is an active text field, text view, or other responder -/// accepting key input. You can disable keyboard shortcuts if you have existing keyboard shortcuts -/// that conflict with FLEX, or if you like doing things the hard way ;) -/// Keyboard shortcuts are always disabled (and support is #if'd out) in non-simulator builds -@property (nonatomic) BOOL simulatorShortcutsEnabled; - -/// Adds an action to run when the specified key & modifier combination is pressed -/// @param key A single character string matching a key on the keyboard -/// @param modifiers Modifier keys such as shift, command, or alt/option -/// @param action The block to run on the main thread when the key & modifier combination is recognized. -/// @param description Shown the the keyboard shortcut help menu, which is accessed via the '?' key. -/// @note The action block will be retained for the duration of the application. You may want to use weak references. -/// @note FLEX registers several default keyboard shortcuts. Use the '?' key to see a list of shortcuts. -- (void)registerSimulatorShortcutWithKey:(NSString *)key - modifiers:(UIKeyModifierFlags)modifiers - action:(dispatch_block_t)action - description:(NSString *)description; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Manager/FLEXManager+Extensibility.m b/Tweaks/FLEX/Manager/FLEXManager+Extensibility.m deleted file mode 100644 index ce79b6a..0000000 --- a/Tweaks/FLEX/Manager/FLEXManager+Extensibility.m +++ /dev/null @@ -1,272 +0,0 @@ -// -// FLEXManager+Extensibility.m -// FLEX -// -// Created by Tanner on 2/2/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager+Extensibility.h" -#import "FLEXManager+Private.h" -#import "FLEXNavigationController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXKeyboardShortcutManager.h" -#import "FLEXExplorerViewController.h" -#import "FLEXNetworkMITMViewController.h" -#import "FLEXKeyboardHelpViewController.h" -#import "FLEXFileBrowserController.h" -#import "FLEXUtility.h" - -@interface FLEXManager (ExtensibilityPrivate) -@property (nonatomic, readonly) UIViewController *topViewController; -@end - -@implementation FLEXManager (Extensibility) - -#pragma mark - Globals Screen Entries - -- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock { - NSParameterAssert(entryName); - NSParameterAssert(objectFutureBlock); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - entryName = entryName.copy; - FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ - return entryName; - } viewControllerFuture:^UIViewController *{ - return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()]; - }]; - - [self.userGlobalEntries addObject:entry]; -} - -- (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { - NSParameterAssert(entryName); - NSParameterAssert(viewControllerFutureBlock); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - entryName = entryName.copy; - FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ - return entryName; - } viewControllerFuture:^UIViewController *{ - UIViewController *viewController = viewControllerFutureBlock(); - NSCAssert(viewController, @"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.", entryName); - return viewController; - }]; - - [self.userGlobalEntries addObject:entry]; -} - -- (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction { - NSParameterAssert(entryName); - NSParameterAssert(rowSelectedAction); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - entryName = entryName.copy; - FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString * _Nonnull{ - return entryName; - } action:rowSelectedAction]; - - [self.userGlobalEntries addObject:entry]; -} - -- (void)clearGlobalEntries { - [self.userGlobalEntries removeAllObjects]; -} - - -#pragma mark - Simulator Shortcuts - -- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description { -#if TARGET_OS_SIMULATOR - [FLEXKeyboardShortcutManager.sharedManager registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description allowOverride:YES]; -#endif -} - -- (void)setSimulatorShortcutsEnabled:(BOOL)simulatorShortcutsEnabled { -#if TARGET_OS_SIMULATOR - [FLEXKeyboardShortcutManager.sharedManager setEnabled:simulatorShortcutsEnabled]; -#endif -} - -- (BOOL)simulatorShortcutsEnabled { -#if TARGET_OS_SIMULATOR - return FLEXKeyboardShortcutManager.sharedManager.isEnabled; -#else - return NO; -#endif -} - - -#pragma mark - Shortcuts Defaults - -- (void)registerDefaultSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description { -#if TARGET_OS_SIMULATOR - // Don't allow override to avoid changing keys registered by the app - [FLEXKeyboardShortcutManager.sharedManager registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description allowOverride:NO]; -#endif -} - -- (void)registerDefaultSimulatorShortcuts { - [self registerDefaultSimulatorShortcutWithKey:@"f" modifiers:0 action:^{ - [self toggleExplorer]; - } description:@"Toggle FLEX toolbar"]; - - [self registerDefaultSimulatorShortcutWithKey:@"g" modifiers:0 action:^{ - [self showExplorerIfNeeded]; - [self.explorerViewController toggleMenuTool]; - } description:@"Toggle FLEX globals menu"]; - - [self registerDefaultSimulatorShortcutWithKey:@"v" modifiers:0 action:^{ - [self showExplorerIfNeeded]; - [self.explorerViewController toggleViewsTool]; - } description:@"Toggle view hierarchy menu"]; - - [self registerDefaultSimulatorShortcutWithKey:@"s" modifiers:0 action:^{ - [self showExplorerIfNeeded]; - [self.explorerViewController toggleSelectTool]; - } description:@"Toggle select tool"]; - - [self registerDefaultSimulatorShortcutWithKey:@"m" modifiers:0 action:^{ - [self showExplorerIfNeeded]; - [self.explorerViewController toggleMoveTool]; - } description:@"Toggle move tool"]; - - [self registerDefaultSimulatorShortcutWithKey:@"n" modifiers:0 action:^{ - [self toggleTopViewControllerOfClass:[FLEXNetworkMITMViewController class]]; - } description:@"Toggle network history view"]; - - [self registerDefaultSimulatorShortcutWithKey:UIKeyInputDownArrow modifiers:0 action:^{ - if (self.isHidden || ![self.explorerViewController handleDownArrowKeyPressed]) { - [self tryScrollDown]; - } - } description:@"Cycle view selection\n\t\tMove view down\n\t\tScroll down"]; - - [self registerDefaultSimulatorShortcutWithKey:UIKeyInputUpArrow modifiers:0 action:^{ - if (self.isHidden || ![self.explorerViewController handleUpArrowKeyPressed]) { - [self tryScrollUp]; - } - } description:@"Cycle view selection\n\t\tMove view up\n\t\tScroll up"]; - - [self registerDefaultSimulatorShortcutWithKey:UIKeyInputRightArrow modifiers:0 action:^{ - if (!self.isHidden) { - [self.explorerViewController handleRightArrowKeyPressed]; - } - } description:@"Move selected view right"]; - - [self registerDefaultSimulatorShortcutWithKey:UIKeyInputLeftArrow modifiers:0 action:^{ - if (self.isHidden) { - [self tryGoBack]; - } else { - [self.explorerViewController handleLeftArrowKeyPressed]; - } - } description:@"Move selected view left"]; - - [self registerDefaultSimulatorShortcutWithKey:@"?" modifiers:0 action:^{ - [self toggleTopViewControllerOfClass:[FLEXKeyboardHelpViewController class]]; - } description:@"Toggle (this) help menu"]; - - [self registerDefaultSimulatorShortcutWithKey:UIKeyInputEscape modifiers:0 action:^{ - [[self.topViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - } description:@"End editing text\n\t\tDismiss top view controller"]; - - [self registerDefaultSimulatorShortcutWithKey:@"o" modifiers:UIKeyModifierCommand|UIKeyModifierShift action:^{ - [self toggleTopViewControllerOfClass:[FLEXFileBrowserController class]]; - } description:@"Toggle file browser menu"]; -} - -+ (void)load { - dispatch_async(dispatch_get_main_queue(), ^{ - [self.sharedManager registerDefaultSimulatorShortcuts]; - }); -} - - -#pragma mark - Private - -- (UIEdgeInsets)contentInsetsOfScrollView:(UIScrollView *)scrollView { - if (@available(iOS 11, *)) { - return scrollView.adjustedContentInset; - } - - return scrollView.contentInset; -} - -- (void)tryScrollDown { - UIScrollView *scrollview = [self firstScrollView]; - UIEdgeInsets insets = [self contentInsetsOfScrollView:scrollview]; - CGPoint contentOffset = scrollview.contentOffset; - CGFloat maxYOffset = scrollview.contentSize.height - scrollview.bounds.size.height + insets.bottom; - contentOffset.y = MIN(contentOffset.y + 200, maxYOffset); - [scrollview setContentOffset:contentOffset animated:YES]; -} - -- (void)tryScrollUp { - UIScrollView *scrollview = [self firstScrollView]; - UIEdgeInsets insets = [self contentInsetsOfScrollView:scrollview]; - CGPoint contentOffset = scrollview.contentOffset; - contentOffset.y = MAX(contentOffset.y - 200, -insets.top); - [scrollview setContentOffset:contentOffset animated:YES]; -} - -- (UIScrollView *)firstScrollView { - NSMutableArray *views = FLEXUtility.appKeyWindow.subviews.mutableCopy; - UIScrollView *scrollView = nil; - while (views.count > 0) { - UIView *view = views.firstObject; - [views removeObjectAtIndex:0]; - if ([view isKindOfClass:[UIScrollView class]]) { - scrollView = (UIScrollView *)view; - break; - } else { - [views addObjectsFromArray:view.subviews]; - } - } - return scrollView; -} - -- (void)tryGoBack { - UINavigationController *navigationController = nil; - UIViewController *topViewController = self.topViewController; - if ([topViewController isKindOfClass:[UINavigationController class]]) { - navigationController = (UINavigationController *)topViewController; - } else { - navigationController = topViewController.navigationController; - } - [navigationController popViewControllerAnimated:YES]; -} - -- (UIViewController *)topViewController { - return [FLEXUtility topViewControllerInWindow:UIApplication.sharedApplication.keyWindow]; -} - -- (void)toggleTopViewControllerOfClass:(Class)class { - UINavigationController *topViewController = (id)self.topViewController; - if ([topViewController isKindOfClass:[FLEXNavigationController class]]) { - if ([topViewController.topViewController isKindOfClass:[class class]]) { - if (topViewController.viewControllers.count == 1) { - // Dismiss since we are already presenting it - [topViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; - } else { - // Pop since we are viewing it but it's not the only thing on the stack - [topViewController popViewControllerAnimated:YES]; - } - } else { - // Push it on the existing navigation stack - [topViewController pushViewController:[class new] animated:YES]; - } - } else { - // Present it in an entirely new navigation controller - [self.explorerViewController presentViewController: - [FLEXNavigationController withRootViewController:[class new]] - animated:YES completion:nil]; - } -} - -- (void)showExplorerIfNeeded { - if (self.isHidden) { - [self showExplorer]; - } -} - -@end diff --git a/Tweaks/FLEX/Manager/FLEXManager+Networking.h b/Tweaks/FLEX/Manager/FLEXManager+Networking.h deleted file mode 100644 index 827d7f9..0000000 --- a/Tweaks/FLEX/Manager/FLEXManager+Networking.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// FLEXManager+Networking.h -// FLEX -// -// Created by Tanner on 2/1/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXManager (Networking) - -/// If this property is set to YES, FLEX will swizzle NSURLConnection*Delegate and NSURLSession*Delegate methods -/// on classes that conform to the protocols. This allows you to view network activity history from the main FLEX menu. -/// Full responses are kept temporarily in a size-limited cache and may be pruned under memory pressure. -@property (nonatomic, getter=isNetworkDebuggingEnabled) BOOL networkDebuggingEnabled; - -/// Defaults to 25 MB if never set. Values set here are persisted across launches of the app. -/// The response cache uses an NSCache, so it may purge prior to hitting the limit when the app is under memory pressure. -@property (nonatomic) NSUInteger networkResponseCacheByteLimit; - -/// Requests whose host ends with one of the excluded entries in this array will be not be recorded (eg. google.com). -/// Wildcard or subdomain entries are not required (eg. google.com will match any subdomain under google.com). -/// Useful to remove requests that are typically noisy, such as analytics requests that you aren't interested in tracking. -@property (nonatomic) NSMutableArray *networkRequestHostDenylist; - -/// Sets custom viewer for specific content type. -/// @param contentType Mime type like application/json -/// @param viewControllerFutureBlock Viewer (view controller) creation block -/// @note This method must be called from the main thread. -/// The viewControllerFutureBlock will be invoked from the main thread and may not return nil. -/// @note The passed block will be copied and retain for the duration of the application, you may want to use __weak references. -- (void)setCustomViewerForContentType:(NSString *)contentType - viewControllerFutureBlock:(FLEXCustomContentViewerFuture)viewControllerFutureBlock; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Manager/FLEXManager+Networking.m b/Tweaks/FLEX/Manager/FLEXManager+Networking.m deleted file mode 100644 index a8cd15f..0000000 --- a/Tweaks/FLEX/Manager/FLEXManager+Networking.m +++ /dev/null @@ -1,68 +0,0 @@ -// -// FLEXManager+Networking.m -// FLEX -// -// Created by Tanner on 2/1/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager+Networking.h" -#import "FLEXManager+Private.h" -#import "FLEXNetworkObserver.h" -#import "FLEXNetworkRecorder.h" -#import "FLEXObjectExplorerFactory.h" -#import "NSUserDefaults+FLEX.h" - -@implementation FLEXManager (Networking) - -+ (void)load { - if (NSUserDefaults.standardUserDefaults.flex_registerDictionaryJSONViewerOnLaunch) { - dispatch_async(dispatch_get_main_queue(), ^{ - // Register array/dictionary viewer for JSON responses - [self.sharedManager setCustomViewerForContentType:@"application/json" - viewControllerFutureBlock:^UIViewController *(NSData *data) { - id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - if (jsonObject) { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:jsonObject]; - } - return nil; - } - ]; - }); - } -} - -- (BOOL)isNetworkDebuggingEnabled { - return FLEXNetworkObserver.isEnabled; -} - -- (void)setNetworkDebuggingEnabled:(BOOL)networkDebuggingEnabled { - FLEXNetworkObserver.enabled = networkDebuggingEnabled; -} - -- (NSUInteger)networkResponseCacheByteLimit { - return FLEXNetworkRecorder.defaultRecorder.responseCacheByteLimit; -} - -- (void)setNetworkResponseCacheByteLimit:(NSUInteger)networkResponseCacheByteLimit { - FLEXNetworkRecorder.defaultRecorder.responseCacheByteLimit = networkResponseCacheByteLimit; -} - -- (NSMutableArray *)networkRequestHostDenylist { - return FLEXNetworkRecorder.defaultRecorder.hostDenylist; -} - -- (void)setNetworkRequestHostDenylist:(NSMutableArray *)networkRequestHostDenylist { - FLEXNetworkRecorder.defaultRecorder.hostDenylist = networkRequestHostDenylist; -} - -- (void)setCustomViewerForContentType:(NSString *)contentType - viewControllerFutureBlock:(FLEXCustomContentViewerFuture)viewControllerFutureBlock { - NSParameterAssert(contentType.length); - NSParameterAssert(viewControllerFutureBlock); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - self.customContentTypeViewers[contentType.lowercaseString] = viewControllerFutureBlock; -} - -@end diff --git a/Tweaks/FLEX/Manager/FLEXManager.h b/Tweaks/FLEX/Manager/FLEXManager.h deleted file mode 100644 index a413acc..0000000 --- a/Tweaks/FLEX/Manager/FLEXManager.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// FLEXManager.h -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXExplorerToolbar.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXManager : NSObject - -@property (nonatomic, readonly, class) FLEXManager *sharedManager; - -@property (nonatomic, readonly) BOOL isHidden; -@property (nonatomic, readonly) FLEXExplorerToolbar *toolbar; - -- (void)showExplorer; -- (void)hideExplorer; -- (void)toggleExplorer; - -/// Programmatically dismiss anything presented by FLEX, leaving only the toolbar visible. -- (void)dismissAnyPresentedTools:(void (^_Nullable)(void))completion; -/// Programmatically present something on top of the FLEX toolbar. -/// This method will automatically dismiss any currently presented tool, -/// so you do not need to call \c dismissAnyPresentedTools: yourself. -- (void)presentTool:(UINavigationController *(^)(void))viewControllerFuture - completion:(void (^_Nullable)(void))completion; - -/// Use this to present the explorer in a specific scene when the one -/// it chooses by default is not the one you wish to display it in. -- (void)showExplorerFromScene:(UIWindowScene *)scene API_AVAILABLE(ios(13.0)); - -#pragma mark - Misc - -/// Default database password is @c nil by default. -/// Set this to the password you want the databases to open with. -@property (copy, nonatomic) NSString *defaultSqliteDatabasePassword; - -@end - - -typedef UIViewController * _Nullable(^FLEXCustomContentViewerFuture)(NSData *data); - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Manager/FLEXManager.m b/Tweaks/FLEX/Manager/FLEXManager.m deleted file mode 100644 index f011356..0000000 --- a/Tweaks/FLEX/Manager/FLEXManager.m +++ /dev/null @@ -1,145 +0,0 @@ -// -// FLEXManager.m -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager.h" -#import "FLEXUtility.h" -#import "FLEXExplorerViewController.h" -#import "FLEXWindow.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXFileBrowserController.h" - -@interface FLEXManager () - -@property (nonatomic, readonly, getter=isHidden) BOOL hidden; - -@property (nonatomic) FLEXWindow *explorerWindow; -@property (nonatomic) FLEXExplorerViewController *explorerViewController; - -@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; -@property (nonatomic, readonly) NSMutableDictionary *customContentTypeViewers; - -@end - -@implementation FLEXManager - -+ (instancetype)sharedManager { - static FLEXManager *sharedManager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedManager = [self new]; - }); - return sharedManager; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _userGlobalEntries = [NSMutableArray new]; - _customContentTypeViewers = [NSMutableDictionary new]; - } - return self; -} - -- (FLEXWindow *)explorerWindow { - NSAssert(NSThread.isMainThread, @"You must use %@ from the main thread only.", NSStringFromClass([self class])); - - if (!_explorerWindow) { - _explorerWindow = [[FLEXWindow alloc] initWithFrame:FLEXUtility.appKeyWindow.bounds]; - _explorerWindow.eventDelegate = self; - _explorerWindow.rootViewController = self.explorerViewController; - } - - return _explorerWindow; -} - -- (FLEXExplorerViewController *)explorerViewController { - if (!_explorerViewController) { - _explorerViewController = [FLEXExplorerViewController new]; - _explorerViewController.delegate = self; - } - - return _explorerViewController; -} - -- (void)showExplorer { - UIWindow *flex = self.explorerWindow; - flex.hidden = NO; - if (@available(iOS 13.0, *)) { - // Only look for a new scene if we don't have one - if (!flex.windowScene) { - flex.windowScene = FLEXUtility.appKeyWindow.windowScene; - } - } -} - -- (void)hideExplorer { - self.explorerWindow.hidden = YES; -} - -- (void)toggleExplorer { - if (self.explorerWindow.isHidden) { - if (@available(iOS 13.0, *)) { - [self showExplorerFromScene:FLEXUtility.appKeyWindow.windowScene]; - } else { - [self showExplorer]; - } - } else { - [self hideExplorer]; - } -} - -- (void)dismissAnyPresentedTools:(void (^)(void))completion { - if (self.explorerViewController.presentedViewController) { - [self.explorerViewController dismissViewControllerAnimated:YES completion:completion]; - } else if (completion) { - completion(); - } -} - -- (void)presentTool:(UINavigationController * _Nonnull (^)(void))future completion:(void (^)(void))completion { - [self showExplorer]; - [self.explorerViewController presentTool:future completion:completion]; -} - -- (void)showExplorerFromScene:(UIWindowScene *)scene { - if (@available(iOS 13.0, *)) { - self.explorerWindow.windowScene = scene; - } - self.explorerWindow.hidden = NO; -} - -- (BOOL)isHidden { - return self.explorerWindow.isHidden; -} - -- (FLEXExplorerToolbar *)toolbar { - return self.explorerViewController.explorerToolbar; -} - - -#pragma mark - FLEXWindowEventDelegate - -- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow { - // Ask the explorer view controller - return [self.explorerViewController shouldReceiveTouchAtWindowPoint:pointInWindow]; -} - -- (BOOL)canBecomeKeyWindow { - // Only when the explorer view controller wants it because - // it needs to accept key input & affect the status bar. - return self.explorerViewController.wantsWindowToBecomeKey; -} - - -#pragma mark - FLEXExplorerViewControllerDelegate - -- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController { - [self hideExplorer]; -} - -@end diff --git a/Tweaks/FLEX/Manager/Private/FLEXManager+Private.h b/Tweaks/FLEX/Manager/Private/FLEXManager+Private.h deleted file mode 100644 index a4f5a91..0000000 --- a/Tweaks/FLEX/Manager/Private/FLEXManager+Private.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// FLEXManager+Private.h -// PebbleApp -// -// Created by Javier Soto on 7/26/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXManager.h" -#import "FLEXWindow.h" - -@class FLEXGlobalsEntry, FLEXExplorerViewController; - -@interface FLEXManager (Private) - -@property (nonatomic, readonly) FLEXWindow *explorerWindow; -@property (nonatomic, readonly) FLEXExplorerViewController *explorerViewController; - -/// An array of FLEXGlobalsEntry objects that have been registered by the user. -@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; -@property (nonatomic, readonly) NSMutableDictionary *customContentTypeViewers; - -@end diff --git a/Tweaks/FLEX/Network/FLEXFirebaseTransaction.mm b/Tweaks/FLEX/Network/FLEXFirebaseTransaction.mm deleted file mode 100644 index 81f1f24..0000000 --- a/Tweaks/FLEX/Network/FLEXFirebaseTransaction.mm +++ /dev/null @@ -1,303 +0,0 @@ -// -// FLEXFirebaseTransaction.m -// FLEX -// -// Created by Tanner Bennett on 12/24/21. -// - -#import "FLEXNetworkTransaction.h" -#import "FLEXUtility.h" -#import -#include - -typedef std::string (*ReturnsString)(void *); - -@implementation FLEXFirebaseSetDataInfo - -+ (instancetype)data:(NSDictionary *)data merge:(NSNumber *)merge mergeFields:(NSArray *)mergeFields { - NSParameterAssert(data); - NSParameterAssert(merge || mergeFields); - - FLEXFirebaseSetDataInfo *info = [self new]; - info->_documentData = data; - info->_merge = merge; - info->_mergeFields = mergeFields; - - return info; -} - -@end - -static NSString *FLEXStringFromFIRRequestType(FLEXFIRRequestType type) { - switch (type) { - case FLEXFIRRequestTypeNotFirebase: - return @"not firebase"; - case FLEXFIRRequestTypeFetchQuery: - return @"query fetch"; - case FLEXFIRRequestTypeFetchDocument: - return @"document fetch"; - case FLEXFIRRequestTypeSetData: - return @"set data"; - case FLEXFIRRequestTypeUpdateData: - return @"update data"; - case FLEXFIRRequestTypeAddDocument: - return @"create"; - case FLEXFIRRequestTypeDeleteDocument: - return @"delete"; - } - - return nil; -} - -static FLEXFIRTransactionDirection FIRDirectionFromRequestType(FLEXFIRRequestType type) { - switch (type) { - case FLEXFIRRequestTypeNotFirebase: - return FLEXFIRTransactionDirectionNone; - case FLEXFIRRequestTypeFetchQuery: - case FLEXFIRRequestTypeFetchDocument: - return FLEXFIRTransactionDirectionPull; - case FLEXFIRRequestTypeSetData: - case FLEXFIRRequestTypeUpdateData: - case FLEXFIRRequestTypeAddDocument: - case FLEXFIRRequestTypeDeleteDocument: - return FLEXFIRTransactionDirectionPush; - } - - return FLEXFIRTransactionDirectionNone; -} - -@interface FLEXFirebaseTransaction () -@property (nonatomic) id extraData; -@property (nonatomic, readonly) NSString *queryDescription; -@end - -@implementation FLEXFirebaseTransaction -@synthesize queryDescription = _queryDescription; - -+ (instancetype)initiator:(id)initiator requestType:(FLEXFIRRequestType)type extraData:(id)data { - FLEXFirebaseTransaction *fire = [FLEXFirebaseTransaction withStartTime:NSDate.date]; - fire->_direction = FIRDirectionFromRequestType(type); - fire->_initiator = initiator; - fire->_requestType = type; - fire->_extraData = data; - return fire; -} - -+ (instancetype)queryFetch:(FIRQuery *)initiator { - return [self initiator:initiator requestType:FLEXFIRRequestTypeFetchQuery extraData:nil]; -} - -+ (instancetype)documentFetch:(FIRDocumentReference *)initiator { - return [self initiator:initiator requestType:FLEXFIRRequestTypeFetchDocument extraData:nil]; -} - -+ (instancetype)setData:(FIRDocumentReference *)initiator data:(NSDictionary *)data - merge:(NSNumber *)merge mergeFields:(NSArray *)mergeFields { - - FLEXFirebaseSetDataInfo *info = [FLEXFirebaseSetDataInfo data:data merge:merge mergeFields:mergeFields]; - return [self initiator:initiator requestType:FLEXFIRRequestTypeSetData extraData:info]; -} - -+ (instancetype)updateData:(FIRDocumentReference *)initiator data:(NSDictionary *)data { - return [self initiator:initiator requestType:FLEXFIRRequestTypeUpdateData extraData:data]; -} - -+ (instancetype)addDocument:(FIRCollectionReference *)initiator document:(FIRDocumentReference *)doc { - return [self initiator:initiator requestType:FLEXFIRRequestTypeAddDocument extraData:doc]; -} - -+ (instancetype)deleteDocument:(FIRDocumentReference *)initiator { - return [self initiator:initiator requestType:FLEXFIRRequestTypeDeleteDocument extraData:nil]; -} - -- (NSString *)queryDescription { - if (_queryDescription) { - return _queryDescription; - } - - // Grab C++ symbol to describe FIRQuery.query - static ReturnsString firebase_firestore_core_query_tostring = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // Is Firebase available? - if (NSClassFromString(@"FIRDocumentReference")) { - firebase_firestore_core_query_tostring = (ReturnsString)dlsym( - RTLD_DEFAULT, "_ZNK8firebase9firestore4core5Query8ToStringEv" - ); - } - }); - - if (!firebase_firestore_core_query_tostring) { - return @"nil"; - } - - FIRQuery *query = self.initiator_query; - if (!query) return nil; - - void *core_query = query.query; - std::string description = firebase_firestore_core_query_tostring(core_query); - - // Query strings are like 'Query(canonical_id=...)' so I remove the leading part, and the () - NSString *prefix = @"Query(canonical_id="; - NSString *desc = @(description.c_str()); - desc = [desc stringByReplacingOccurrencesOfString:prefix withString:@""]; - desc = [desc stringByReplacingCharactersInRange:NSMakeRange(desc.length-1, 1) withString:@""]; - - _queryDescription = desc; - return _queryDescription; -} - -- (FIRDocumentReference *)initiator_doc { - if ([_initiator isKindOfClass:cFIRDocumentReference]) { - return _initiator; - } - - return nil; -} -- (FIRQuery *)initiator_query { - if ([_initiator isKindOfClass:cFIRQuery]) { - return _initiator; - } - - return nil; -} - -- (FIRCollectionReference *)initiator_collection { - if ([_initiator isKindOfClass:cFIRCollectionReference]) { - return _initiator; - } - - return nil; -} - -- (FLEXFirebaseSetDataInfo *)setDataInfo { - if (self.requestType == FLEXFIRRequestTypeSetData) { - return self.extraData; - } - - return nil; -} - -- (NSDictionary *)updateData { - if (self.requestType == FLEXFIRRequestTypeUpdateData) { - return self.extraData; - } - - return nil; -} - -- (NSString *)path { - switch (self.direction) { - case FLEXFIRTransactionDirectionNone: - return nil; - case FLEXFIRTransactionDirectionPush: - case FLEXFIRTransactionDirectionPull: { - switch (self.requestType) { - case FLEXFIRRequestTypeNotFirebase: - @throw NSInternalInconsistencyException; - - case FLEXFIRRequestTypeFetchQuery: - case FLEXFIRRequestTypeAddDocument: - return self.initiator_collection.path ?: self.queryDescription; - case FLEXFIRRequestTypeFetchDocument: - case FLEXFIRRequestTypeSetData: - case FLEXFIRRequestTypeUpdateData: - case FLEXFIRRequestTypeDeleteDocument: - return self.initiator_doc.path; - } - } - } - - return nil; -} - -- (NSString *)primaryDescription { - if (!_primaryDescription) { - _primaryDescription = self.path.lastPathComponent; - } - - return _primaryDescription; -} - -- (NSString *)secondaryDescription { - if (!_secondaryDescription) { - _secondaryDescription = self.path.stringByDeletingLastPathComponent; - } - - return _secondaryDescription; -} - -- (NSString *)tertiaryDescription { - if (!_tertiaryDescription) { - NSMutableArray *detailComponents = [NSMutableArray new]; - - NSString *timestamp = [self timestampStringFromRequestDate:self.startTime]; - if (timestamp.length > 0) { - [detailComponents addObject:timestamp]; - } - - [detailComponents addObject:self.direction == FLEXFIRTransactionDirectionPush ? - @"Push ↑" : @"Pull ↓" - ]; - - if (self.direction == FLEXFIRTransactionDirectionPush) { - [detailComponents addObjectsFromArray:@[FLEXStringFromFIRRequestType(self.requestType)]]; - } - - if (self.state == FLEXNetworkTransactionStateFinished || self.state == FLEXNetworkTransactionStateFailed) { - if (self.direction == FLEXFIRTransactionDirectionPull) { - NSString *docCount = [NSString stringWithFormat:@"%@ document(s)", @(self.documents.count)]; - [detailComponents addObjectsFromArray:@[docCount]]; - } - } else { - // Unstarted, Awaiting Response, Receiving Data, etc. - NSString *state = [self.class readableStringFromTransactionState:self.state]; - [detailComponents addObject:state]; - } - - _tertiaryDescription = [detailComponents componentsJoinedByString:@" ・ "]; - } - - return _tertiaryDescription; -} - -- (NSString *)copyString { - return self.path; -} - -- (BOOL)matchesQuery:(NSString *)filterString { - if ([self.path localizedCaseInsensitiveContainsString:filterString]) { - return YES; - } - - BOOL isPull = self.direction == FLEXFIRTransactionDirectionPull; - BOOL isPush = self.direction == FLEXFIRTransactionDirectionPush; - - // Allow filtering for push or pull directly - if (isPull && [filterString localizedCaseInsensitiveCompare:@"pull"] == NSOrderedSame) { - return YES; - } - if (isPush && [filterString localizedCaseInsensitiveCompare:@"push"] == NSOrderedSame) { - return YES; - } - - return NO; -} - -//- (NSString *)responseString { -// if (!_responseString) { -// _responseString = [NSString stringWithUTF8String:(char *)self.response.bytes]; -// } -// -// return _responseString; -//} -// -//- (NSDictionary *)responseObject { -// if (!_responseObject) { -// _responseObject = [NSJSONSerialization JSONObjectWithData:self.response options:0 error:nil]; -// } -// -// return _responseObject; -//} - -@end diff --git a/Tweaks/FLEX/Network/FLEXHTTPTransactionDetailController.h b/Tweaks/FLEX/Network/FLEXHTTPTransactionDetailController.h deleted file mode 100644 index 3639052..0000000 --- a/Tweaks/FLEX/Network/FLEXHTTPTransactionDetailController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXHTTPTransactionDetailController.h -// Flipboard -// -// Created by Ryan Olson on 2/10/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@class FLEXHTTPTransaction; - -@interface FLEXHTTPTransactionDetailController : UITableViewController - -+ (instancetype)withTransaction:(FLEXHTTPTransaction *)transaction; - -@end diff --git a/Tweaks/FLEX/Network/FLEXHTTPTransactionDetailController.m b/Tweaks/FLEX/Network/FLEXHTTPTransactionDetailController.m deleted file mode 100644 index 3e5684f..0000000 --- a/Tweaks/FLEX/Network/FLEXHTTPTransactionDetailController.m +++ /dev/null @@ -1,535 +0,0 @@ -// -// FLEXNetworkTransactionDetailController.m -// Flipboard -// -// Created by Ryan Olson on 2/10/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXHTTPTransactionDetailController.h" -#import "FLEXNetworkCurlLogger.h" -#import "FLEXNetworkRecorder.h" -#import "FLEXNetworkTransaction.h" -#import "FLEXWebViewController.h" -#import "FLEXImagePreviewViewController.h" -#import "FLEXMultilineTableViewCell.h" -#import "FLEXUtility.h" -#import "FLEXManager+Private.h" -#import "FLEXTableView.h" -#import "UIBarButtonItem+FLEX.h" - -typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void); - -@interface FLEXNetworkDetailRow : NSObject -@property (nonatomic, copy) NSString *title; -@property (nonatomic, copy) NSString *detailText; -@property (nonatomic, copy) FLEXNetworkDetailRowSelectionFuture selectionFuture; -@end - -@implementation FLEXNetworkDetailRow -@end - -@interface FLEXNetworkDetailSection : NSObject -@property (nonatomic, copy) NSString *title; -@property (nonatomic, copy) NSArray *rows; -@end - -@implementation FLEXNetworkDetailSection -@end - -@interface FLEXHTTPTransactionDetailController () - -@property (nonatomic, readonly) FLEXHTTPTransaction *transaction; -@property (nonatomic, copy) NSArray *sections; - -@end - -@implementation FLEXHTTPTransactionDetailController - -+ (instancetype)withTransaction:(FLEXHTTPTransaction *)transaction { - FLEXHTTPTransactionDetailController *controller = [self new]; - controller.transaction = transaction; - return controller; -} - -- (instancetype)initWithStyle:(UITableViewStyle)style { - // Force grouped style - return [super initWithStyle:UITableViewStyleGrouped]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - [NSNotificationCenter.defaultCenter addObserver:self - selector:@selector(handleTransactionUpdatedNotification:) - name:kFLEXNetworkRecorderTransactionUpdatedNotification - object:nil - ]; - self.toolbarItems = @[ - UIBarButtonItem.flex_flexibleSpace, - [UIBarButtonItem - flex_itemWithTitle:@"Copy curl" - target:self - action:@selector(copyButtonPressed:) - ] - ]; - - [self.tableView registerClass:[FLEXMultilineTableViewCell class] forCellReuseIdentifier:kFLEXMultilineCell]; -} - -- (void)setTransaction:(FLEXHTTPTransaction *)transaction { - if (![_transaction isEqual:transaction]) { - _transaction = transaction; - self.title = [transaction.request.URL lastPathComponent]; - [self rebuildTableSections]; - } -} - -- (void)setSections:(NSArray *)sections { - if (![_sections isEqual:sections]) { - _sections = [sections copy]; - [self.tableView reloadData]; - } -} - -- (void)rebuildTableSections { - NSMutableArray *sections = [NSMutableArray new]; - - FLEXNetworkDetailSection *generalSection = [[self class] generalSectionForTransaction:self.transaction]; - if (generalSection.rows.count > 0) { - [sections addObject:generalSection]; - } - FLEXNetworkDetailSection *requestHeadersSection = [[self class] requestHeadersSectionForTransaction:self.transaction]; - if (requestHeadersSection.rows.count > 0) { - [sections addObject:requestHeadersSection]; - } - FLEXNetworkDetailSection *queryParametersSection = [[self class] queryParametersSectionForTransaction:self.transaction]; - if (queryParametersSection.rows.count > 0) { - [sections addObject:queryParametersSection]; - } - FLEXNetworkDetailSection *postBodySection = [[self class] postBodySectionForTransaction:self.transaction]; - if (postBodySection.rows.count > 0) { - [sections addObject:postBodySection]; - } - FLEXNetworkDetailSection *responseHeadersSection = [[self class] responseHeadersSectionForTransaction:self.transaction]; - if (responseHeadersSection.rows.count > 0) { - [sections addObject:responseHeadersSection]; - } - - self.sections = sections; -} - -- (void)handleTransactionUpdatedNotification:(NSNotification *)notification { - FLEXNetworkTransaction *transaction = [[notification userInfo] objectForKey:kFLEXNetworkRecorderUserInfoTransactionKey]; - if (transaction == self.transaction) { - [self rebuildTableSections]; - } -} - -- (void)copyButtonPressed:(id)sender { - [UIPasteboard.generalPasteboard setString:[FLEXNetworkCurlLogger curlCommandString:_transaction.request]]; -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.sections.count; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - FLEXNetworkDetailSection *sectionModel = self.sections[section]; - return sectionModel.rows.count; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - FLEXNetworkDetailSection *sectionModel = self.sections[section]; - return sectionModel.title; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXMultilineTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXMultilineCell forIndexPath:indexPath]; - - FLEXNetworkDetailRow *rowModel = [self rowModelAtIndexPath:indexPath]; - - cell.textLabel.attributedText = [[self class] attributedTextForRow:rowModel]; - cell.accessoryType = rowModel.selectionFuture ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; - cell.selectionStyle = rowModel.selectionFuture ? UITableViewCellSelectionStyleDefault : UITableViewCellSelectionStyleNone; - - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXNetworkDetailRow *rowModel = [self rowModelAtIndexPath:indexPath]; - - UIViewController *viewController = nil; - if (rowModel.selectionFuture) { - viewController = rowModel.selectionFuture(); - } - - if ([viewController isKindOfClass:UIAlertController.class]) { - [self presentViewController:viewController animated:YES completion:nil]; - } else if (viewController) { - [self.navigationController pushViewController:viewController animated:YES]; - } - - [tableView deselectRowAtIndexPath:indexPath animated:YES]; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXNetworkDetailRow *row = [self rowModelAtIndexPath:indexPath]; - NSAttributedString *attributedText = [[self class] attributedTextForRow:row]; - BOOL showsAccessory = row.selectionFuture != nil; - return [FLEXMultilineTableViewCell - preferredHeightWithAttributedText:attributedText - maxWidth:tableView.bounds.size.width - style:tableView.style - showsAccessory:showsAccessory - ]; -} - -- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { - return [NSArray flex_forEachUpTo:self.sections.count map:^id(NSUInteger i) { - return @"⦁"; - }]; -} - -- (FLEXNetworkDetailRow *)rowModelAtIndexPath:(NSIndexPath *)indexPath { - FLEXNetworkDetailSection *sectionModel = self.sections[indexPath.section]; - return sectionModel.rows[indexPath.row]; -} - -#pragma mark - Cell Copying - -- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; -} - -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - return action == @selector(copy:); -} - -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - if (action == @selector(copy:)) { - FLEXNetworkDetailRow *row = [self rowModelAtIndexPath:indexPath]; - UIPasteboard.generalPasteboard.string = row.detailText; - } -} - -- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __IOS_AVAILABLE(13.0) { - return [UIContextMenuConfiguration - configurationWithIdentifier:nil - previewProvider:nil - actionProvider:^UIMenu *(NSArray *suggestedActions) { - UIAction *copy = [UIAction - actionWithTitle:@"Copy" - image:nil - identifier:nil - handler:^(__kindof UIAction *action) { - FLEXNetworkDetailRow *row = [self rowModelAtIndexPath:indexPath]; - UIPasteboard.generalPasteboard.string = row.detailText; - } - ]; - return [UIMenu - menuWithTitle:@"" image:nil identifier:nil - options:UIMenuOptionsDisplayInline - children:@[copy] - ]; - } - ]; -} - -#pragma mark - View Configuration - -+ (NSAttributedString *)attributedTextForRow:(FLEXNetworkDetailRow *)row { - NSDictionary *titleAttributes = @{ NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:12.0], - NSForegroundColorAttributeName : [UIColor colorWithWhite:0.5 alpha:1.0] }; - NSDictionary *detailAttributes = @{ NSFontAttributeName : UIFont.flex_defaultTableCellFont, - NSForegroundColorAttributeName : FLEXColor.primaryTextColor }; - - NSString *title = [NSString stringWithFormat:@"%@: ", row.title]; - NSString *detailText = row.detailText ?: @""; - NSMutableAttributedString *attributedText = [NSMutableAttributedString new]; - [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:title attributes:titleAttributes]]; - [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:detailText attributes:detailAttributes]]; - - return attributedText; -} - -#pragma mark - Table Data Generation - -+ (FLEXNetworkDetailSection *)generalSectionForTransaction:(FLEXHTTPTransaction *)transaction { - NSMutableArray *rows = [NSMutableArray new]; - - FLEXNetworkDetailRow *requestURLRow = [FLEXNetworkDetailRow new]; - requestURLRow.title = @"Request URL"; - NSURL *url = transaction.request.URL; - requestURLRow.detailText = url.absoluteString; - requestURLRow.selectionFuture = ^{ - UIViewController *urlWebViewController = [[FLEXWebViewController alloc] initWithURL:url]; - urlWebViewController.title = url.absoluteString; - return urlWebViewController; - }; - [rows addObject:requestURLRow]; - - FLEXNetworkDetailRow *requestMethodRow = [FLEXNetworkDetailRow new]; - requestMethodRow.title = @"Request Method"; - requestMethodRow.detailText = transaction.request.HTTPMethod; - [rows addObject:requestMethodRow]; - - if (transaction.cachedRequestBody.length > 0) { - FLEXNetworkDetailRow *postBodySizeRow = [FLEXNetworkDetailRow new]; - postBodySizeRow.title = @"Request Body Size"; - postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:transaction.cachedRequestBody.length countStyle:NSByteCountFormatterCountStyleBinary]; - [rows addObject:postBodySizeRow]; - - FLEXNetworkDetailRow *postBodyRow = [FLEXNetworkDetailRow new]; - postBodyRow.title = @"Request Body"; - postBodyRow.detailText = @"tap to view"; - postBodyRow.selectionFuture = ^UIViewController * () { - // Show the body if we can - NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; - UIViewController *detailViewController = [self detailViewControllerForMIMEType:contentType data:[self postBodyDataForTransaction:transaction]]; - if (detailViewController) { - detailViewController.title = @"Request Body"; - return detailViewController; - } - - // We can't show the body, alert user - return [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Can't View HTTP Body Data"); - make.message(@"FLEX does not have a viewer for request body data with MIME type: "); - make.message(contentType); - make.button(@"Dismiss").cancelStyle(); - }]; - }; - - [rows addObject:postBodyRow]; - } - - NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:transaction.response]; - if (statusCodeString.length > 0) { - FLEXNetworkDetailRow *statusCodeRow = [FLEXNetworkDetailRow new]; - statusCodeRow.title = @"Status Code"; - statusCodeRow.detailText = statusCodeString; - [rows addObject:statusCodeRow]; - } - - if (transaction.error) { - FLEXNetworkDetailRow *errorRow = [FLEXNetworkDetailRow new]; - errorRow.title = @"Error"; - errorRow.detailText = transaction.error.localizedDescription; - [rows addObject:errorRow]; - } - - FLEXNetworkDetailRow *responseBodyRow = [FLEXNetworkDetailRow new]; - responseBodyRow.title = @"Response Body"; - NSData *responseData = [FLEXNetworkRecorder.defaultRecorder cachedResponseBodyForTransaction:transaction]; - if (responseData.length > 0) { - responseBodyRow.detailText = @"tap to view"; - - // Avoid a long lived strong reference to the response data in case we need to purge it from the cache. - weakify(responseData) - responseBodyRow.selectionFuture = ^UIViewController *() { strongify(responseData) - - // Show the response if we can - NSString *contentType = transaction.response.MIMEType; - if (responseData) { - UIViewController *bodyDetails = [self detailViewControllerForMIMEType:contentType data:responseData]; - if (bodyDetails) { - bodyDetails.title = @"Response"; - return bodyDetails; - } - } - - // We can't show the response, alert user - return [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Unable to View Response"); - if (responseData) { - make.message(@"No viewer content type: ").message(contentType); - } else { - make.message(@"The response has been purged from the cache"); - } - make.button(@"OK").cancelStyle(); - }]; - }; - } else { - BOOL emptyResponse = transaction.receivedDataLength == 0; - responseBodyRow.detailText = emptyResponse ? @"empty" : @"not in cache"; - } - - [rows addObject:responseBodyRow]; - - FLEXNetworkDetailRow *responseSizeRow = [FLEXNetworkDetailRow new]; - responseSizeRow.title = @"Response Size"; - responseSizeRow.detailText = [NSByteCountFormatter stringFromByteCount:transaction.receivedDataLength countStyle:NSByteCountFormatterCountStyleBinary]; - [rows addObject:responseSizeRow]; - - FLEXNetworkDetailRow *mimeTypeRow = [FLEXNetworkDetailRow new]; - mimeTypeRow.title = @"MIME Type"; - mimeTypeRow.detailText = transaction.response.MIMEType; - [rows addObject:mimeTypeRow]; - - FLEXNetworkDetailRow *mechanismRow = [FLEXNetworkDetailRow new]; - mechanismRow.title = @"Mechanism"; - mechanismRow.detailText = transaction.requestMechanism; - [rows addObject:mechanismRow]; - - NSDateFormatter *startTimeFormatter = [NSDateFormatter new]; - startTimeFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; - - FLEXNetworkDetailRow *localStartTimeRow = [FLEXNetworkDetailRow new]; - localStartTimeRow.title = [NSString stringWithFormat:@"Start Time (%@)", [NSTimeZone.localTimeZone abbreviationForDate:transaction.startTime]]; - localStartTimeRow.detailText = [startTimeFormatter stringFromDate:transaction.startTime]; - [rows addObject:localStartTimeRow]; - - startTimeFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; - - FLEXNetworkDetailRow *utcStartTimeRow = [FLEXNetworkDetailRow new]; - utcStartTimeRow.title = @"Start Time (UTC)"; - utcStartTimeRow.detailText = [startTimeFormatter stringFromDate:transaction.startTime]; - [rows addObject:utcStartTimeRow]; - - FLEXNetworkDetailRow *unixStartTime = [FLEXNetworkDetailRow new]; - unixStartTime.title = @"Unix Start Time"; - unixStartTime.detailText = [NSString stringWithFormat:@"%f", [transaction.startTime timeIntervalSince1970]]; - [rows addObject:unixStartTime]; - - FLEXNetworkDetailRow *durationRow = [FLEXNetworkDetailRow new]; - durationRow.title = @"Total Duration"; - durationRow.detailText = [FLEXUtility stringFromRequestDuration:transaction.duration]; - [rows addObject:durationRow]; - - FLEXNetworkDetailRow *latencyRow = [FLEXNetworkDetailRow new]; - latencyRow.title = @"Latency"; - latencyRow.detailText = [FLEXUtility stringFromRequestDuration:transaction.latency]; - [rows addObject:latencyRow]; - - FLEXNetworkDetailSection *generalSection = [FLEXNetworkDetailSection new]; - generalSection.title = @"General"; - generalSection.rows = rows; - - return generalSection; -} - -+ (FLEXNetworkDetailSection *)requestHeadersSectionForTransaction:(FLEXHTTPTransaction *)transaction { - FLEXNetworkDetailSection *requestHeadersSection = [FLEXNetworkDetailSection new]; - requestHeadersSection.title = @"Request Headers"; - requestHeadersSection.rows = [self networkDetailRowsFromDictionary:transaction.request.allHTTPHeaderFields]; - - return requestHeadersSection; -} - -+ (FLEXNetworkDetailSection *)postBodySectionForTransaction:(FLEXHTTPTransaction *)transaction { - FLEXNetworkDetailSection *postBodySection = [FLEXNetworkDetailSection new]; - postBodySection.title = @"Request Body Parameters"; - if (transaction.cachedRequestBody.length > 0) { - NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"]; - if ([contentType hasPrefix:@"application/x-www-form-urlencoded"]) { - NSData *body = [self postBodyDataForTransaction:transaction]; - NSString *bodyString = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]; - postBodySection.rows = [self networkDetailRowsFromQueryItems:[FLEXUtility itemsFromQueryString:bodyString]]; - } - } - return postBodySection; -} - -+ (FLEXNetworkDetailSection *)queryParametersSectionForTransaction:(FLEXHTTPTransaction *)transaction { - NSArray *queries = [FLEXUtility itemsFromQueryString:transaction.request.URL.query]; - FLEXNetworkDetailSection *querySection = [FLEXNetworkDetailSection new]; - querySection.title = @"Query Parameters"; - querySection.rows = [self networkDetailRowsFromQueryItems:queries]; - - return querySection; -} - -+ (FLEXNetworkDetailSection *)responseHeadersSectionForTransaction:(FLEXHTTPTransaction *)transaction { - FLEXNetworkDetailSection *responseHeadersSection = [FLEXNetworkDetailSection new]; - responseHeadersSection.title = @"Response Headers"; - if ([transaction.response isKindOfClass:[NSHTTPURLResponse class]]) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)transaction.response; - responseHeadersSection.rows = [self networkDetailRowsFromDictionary:httpResponse.allHeaderFields]; - } - return responseHeadersSection; -} - -+ (NSArray *)networkDetailRowsFromDictionary:(NSDictionary *)dictionary { - NSMutableArray *rows = [NSMutableArray new]; - NSArray *sortedKeys = [dictionary.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; - - for (NSString *key in sortedKeys) { - id value = dictionary[key]; - FLEXNetworkDetailRow *row = [FLEXNetworkDetailRow new]; - row.title = key; - row.detailText = [value description]; - [rows addObject:row]; - } - - return rows.copy; -} - -+ (NSArray *)networkDetailRowsFromQueryItems:(NSArray *)items { - // Sort the items by name - items = [items sortedArrayUsingComparator:^NSComparisonResult(NSURLQueryItem *item1, NSURLQueryItem *item2) { - return [item1.name caseInsensitiveCompare:item2.name]; - }]; - - NSMutableArray *rows = [NSMutableArray new]; - for (NSURLQueryItem *item in items) { - FLEXNetworkDetailRow *row = [FLEXNetworkDetailRow new]; - row.title = item.name; - row.detailText = item.value; - [rows addObject:row]; - } - - return [rows copy]; -} - -+ (UIViewController *)detailViewControllerForMIMEType:(NSString *)mimeType data:(NSData *)data { - FLEXCustomContentViewerFuture makeCustomViewer = FLEXManager.sharedManager.customContentTypeViewers[mimeType.lowercaseString]; - - if (makeCustomViewer) { - UIViewController *viewer = makeCustomViewer(data); - - if (viewer) { - return viewer; - } - } - - // FIXME (RKO): Don't rely on UTF8 string encoding - UIViewController *detailViewController = nil; - if ([FLEXUtility isValidJSONData:data]) { - NSString *prettyJSON = [FLEXUtility prettyJSONStringFromData:data]; - if (prettyJSON.length > 0) { - detailViewController = [[FLEXWebViewController alloc] initWithText:prettyJSON]; - } - } else if ([mimeType hasPrefix:@"image/"]) { - UIImage *image = [UIImage imageWithData:data]; - detailViewController = [FLEXImagePreviewViewController forImage:image]; - } else if ([mimeType isEqual:@"application/x-plist"]) { - id propertyList = [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:NULL]; - detailViewController = [[FLEXWebViewController alloc] initWithText:[propertyList description]]; - } - - // Fall back to trying to show the response as text - if (!detailViewController) { - NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - if (text.length > 0) { - detailViewController = [[FLEXWebViewController alloc] initWithText:text]; - } - } - return detailViewController; -} - -+ (NSData *)postBodyDataForTransaction:(FLEXHTTPTransaction *)transaction { - NSData *bodyData = transaction.cachedRequestBody; - if (bodyData.length > 0) { - NSString *contentEncoding = [transaction.request valueForHTTPHeaderField:@"Content-Encoding"]; - if ([contentEncoding rangeOfString:@"deflate" options:NSCaseInsensitiveSearch].length > 0 || [contentEncoding rangeOfString:@"gzip" options:NSCaseInsensitiveSearch].length > 0) { - bodyData = [FLEXUtility inflatedDataFromCompressedData:bodyData]; - } - } - return bodyData; -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXMITMDataSource.h b/Tweaks/FLEX/Network/FLEXMITMDataSource.h deleted file mode 100644 index c6da29f..0000000 --- a/Tweaks/FLEX/Network/FLEXMITMDataSource.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// FLEXMITMDataSource.h -// FLEX -// -// Created by Tanner Bennett on 8/22/21. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXMITMDataSource<__covariant TransactionType> : NSObject - -+ (instancetype)dataSourceWithProvider:(NSArray *(^)(void))future; - -/// Whether or not the data in \c transactions and \c bytesReceived are actually filtered yet or not -@property (nonatomic, readonly) BOOL isFiltered; - -/// The content of this array is filtered to match the input of \c filter:completion: -@property (nonatomic, readonly) NSArray *transactions; -@property (nonatomic, readonly) NSArray *allTransactions; - -/// The content of this array is filtered to match the input of \c filter:completion: -@property (nonatomic) NSInteger bytesReceived; -@property (nonatomic) NSInteger totalBytesReceived; - -- (void)reloadByteCounts; -- (void)reloadData:(void (^_Nullable)(FLEXMITMDataSource *dataSource))completion; -- (void)filter:(NSString *)searchString completion:(void(^_Nullable)(FLEXMITMDataSource *dataSource))completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Network/FLEXMITMDataSource.m b/Tweaks/FLEX/Network/FLEXMITMDataSource.m deleted file mode 100644 index 0b68f38..0000000 --- a/Tweaks/FLEX/Network/FLEXMITMDataSource.m +++ /dev/null @@ -1,104 +0,0 @@ -// -// FLEXMITMDataSource.m -// FLEX -// -// Created by Tanner Bennett on 8/22/21. -// - -#import "FLEXMITMDataSource.h" -#import "FLEXNetworkTransaction.h" -#import "FLEXUtility.h" - -@interface FLEXMITMDataSource () -@property (nonatomic, readonly) NSArray *(^dataProvider)(void); -@property (nonatomic) NSString *filterString; -@end - -@implementation FLEXMITMDataSource - -+ (instancetype)dataSourceWithProvider:(NSArray *(^)(void))future { - FLEXMITMDataSource *ds = [self new]; - ds->_dataProvider = future; - [ds reloadData:nil]; - - return ds; -} - -- (BOOL)isFiltered { - return self.filterString.length > 0; -} - -- (void)reloadByteCounts { - [self updateBytesReceived]; - [self updateFilteredBytesReceived]; -} - -- (void)reloadData:(void (^)(FLEXMITMDataSource *dataSource))completion { - self.allTransactions = self.dataProvider(); - [self filter:self.filterString completion:completion]; -} - -- (void)filter:(NSString *)searchString completion:(void (^)(FLEXMITMDataSource *dataSource))completion { - self.filterString = searchString; - - if (!searchString.length) { - self.filteredTransactions = self.allTransactions; - if (completion) completion(self); - } else { - NSArray *allTransactions = self.allTransactions.copy; - [self onBackgroundQueue:^NSArray *{ - return [allTransactions flex_filtered:^BOOL(FLEXNetworkTransaction *entry, NSUInteger idx) { - return [entry matchesQuery:searchString]; - }]; - } thenOnMainQueue:^(NSArray *filteredNetworkTransactions) { - if ([self.filterString isEqual:searchString]) { - self.filteredTransactions = filteredNetworkTransactions; - if (completion) completion(self); - } - }]; - } -} - -- (void)setAllTransactions:(NSArray *)transactions { - _allTransactions = transactions.copy; - [self updateBytesReceived]; -} - -/// This is really just a semantic setter for \c _transactions -- (void)setFilteredTransactions:(NSArray *)filteredTransactions { - _transactions = filteredTransactions.copy; - [self updateFilteredBytesReceived]; -} - -- (void)setTransactions:(NSArray *)transactions { - self.filteredTransactions = transactions; -} - -- (void)updateBytesReceived { - NSInteger bytesReceived = 0; - for (FLEXNetworkTransaction *transaction in self.transactions) { - bytesReceived += transaction.receivedDataLength; - } - - self.bytesReceived = bytesReceived; -} - -- (void)updateFilteredBytesReceived { - NSInteger filteredBytesReceived = 0; - for (FLEXNetworkTransaction *transaction in self.transactions) { - filteredBytesReceived += transaction.receivedDataLength; - } - - self.bytesReceived = filteredBytesReceived; -} - -- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSArray *items = backgroundBlock(); - dispatch_async(dispatch_get_main_queue(), ^{ - mainBlock(items); - }); - }); -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkCurlLogger.h b/Tweaks/FLEX/Network/FLEXNetworkCurlLogger.h deleted file mode 100644 index 6fb7eb6..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkCurlLogger.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXCurlLogger.h -// -// -// Created by Ji Pei on 07/27/16 -// - -#import - -@interface FLEXNetworkCurlLogger : NSObject - -/** - * Generates a cURL command equivalent to the given request. - * - * @param request The request to be translated - */ -+ (NSString *)curlCommandString:(NSURLRequest *)request; - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkCurlLogger.m b/Tweaks/FLEX/Network/FLEXNetworkCurlLogger.m deleted file mode 100644 index dff385d..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkCurlLogger.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// FLEXCurlLogger.m -// -// -// Created by Ji Pei on 07/27/16 -// - -#import "FLEXNetworkCurlLogger.h" - -@implementation FLEXNetworkCurlLogger - -+ (NSString *)curlCommandString:(NSURLRequest *)request { - __block NSMutableString *curlCommandString = [NSMutableString stringWithFormat:@"curl -v -X %@ ", request.HTTPMethod]; - - [curlCommandString appendFormat:@"\'%@\' ", request.URL.absoluteString]; - - [request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *val, BOOL *stop) { - [curlCommandString appendFormat:@"-H \'%@: %@\' ", key, val]; - }]; - - NSArray *cookies = [NSHTTPCookieStorage.sharedHTTPCookieStorage cookiesForURL:request.URL]; - if (cookies) { - [curlCommandString appendFormat:@"-H \'Cookie:"]; - for (NSHTTPCookie *cookie in cookies) { - [curlCommandString appendFormat:@" %@=%@;", cookie.name, cookie.value]; - } - [curlCommandString appendFormat:@"\' "]; - } - - if (request.HTTPBody) { - NSString *body = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]; - [curlCommandString appendFormat:@"-d \'%@\'", body]; - } - - return curlCommandString; -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkMITMViewController.h b/Tweaks/FLEX/Network/FLEXNetworkMITMViewController.h deleted file mode 100644 index 3db0089..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkMITMViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// FLEXNetworkMITMViewController.h -// Flipboard -// -// Created by Ryan Olson on 2/8/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" -#import "FLEXGlobalsEntry.h" - -/// The main screen for the network observer, which displays a list of network transactions. -@interface FLEXNetworkMITMViewController : FLEXTableViewController - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkMITMViewController.m b/Tweaks/FLEX/Network/FLEXNetworkMITMViewController.m deleted file mode 100644 index d048cf5..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkMITMViewController.m +++ /dev/null @@ -1,633 +0,0 @@ -// -// FLEXNetworkMITMViewController.m -// Flipboard -// -// Created by Ryan Olson on 2/8/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXUtility.h" -#import "FLEXMITMDataSource.h" -#import "FLEXNetworkMITMViewController.h" -#import "FLEXNetworkTransaction.h" -#import "FLEXNetworkRecorder.h" -#import "FLEXNetworkObserver.h" -#import "FLEXNetworkTransactionCell.h" -#import "FLEXHTTPTransactionDetailController.h" -#import "FLEXNetworkSettingsController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXGlobalsViewController.h" -#import "FLEXWebViewController.h" -#import "UIBarButtonItem+FLEX.h" -#import "FLEXResources.h" -#import "NSUserDefaults+FLEX.h" - -#define kFirebaseAvailable NSClassFromString(@"FIRDocumentReference") -#define kWebsocketsAvailable @available(iOS 13.0, *) - -typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) { - FLEXNetworkObserverModeFirebase = 0, - FLEXNetworkObserverModeREST, - FLEXNetworkObserverModeWebsockets, -}; - -@interface FLEXNetworkMITMViewController () - -@property (nonatomic) BOOL updateInProgress; -@property (nonatomic) BOOL pendingReload; - -@property (nonatomic) FLEXNetworkObserverMode mode; - -@property (nonatomic, readonly) FLEXMITMDataSource *dataSource; -@property (nonatomic, readonly) FLEXMITMDataSource *HTTPDataSource; -@property (nonatomic, readonly) FLEXMITMDataSource *websocketDataSource; -@property (nonatomic, readonly) FLEXMITMDataSource *firebaseDataSource; - -@end - -@implementation FLEXNetworkMITMViewController - -#pragma mark - Lifecycle - -- (id)init { - return [self initWithStyle:UITableViewStylePlain]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsSearchBar = YES; - self.pinSearchBar = YES; - self.showSearchBarInitially = NO; - NSMutableArray *scopeTitles = [NSMutableArray arrayWithObject:@"REST"]; - - _HTTPDataSource = [FLEXMITMDataSource dataSourceWithProvider:^NSArray * { - return FLEXNetworkRecorder.defaultRecorder.HTTPTransactions; - }]; - - if (kFirebaseAvailable) { - _firebaseDataSource = [FLEXMITMDataSource dataSourceWithProvider:^NSArray * { - return FLEXNetworkRecorder.defaultRecorder.firebaseTransactions; - }]; - [scopeTitles insertObject:@"Firebase" atIndex:0]; // First space - } - - if (kWebsocketsAvailable) { - [scopeTitles addObject:@"Websockets"]; // Last space - _websocketDataSource = [FLEXMITMDataSource dataSourceWithProvider:^NSArray * { - return FLEXNetworkRecorder.defaultRecorder.websocketTransactions; - }]; - } - - // Scopes will only be shown if we have either firebase or websockets available - self.searchController.searchBar.showsScopeBar = scopeTitles.count > 1; - self.searchController.searchBar.scopeButtonTitles = scopeTitles; - self.mode = NSUserDefaults.standardUserDefaults.flex_lastNetworkObserverMode; - - [self addToolbarItems:@[ - [UIBarButtonItem - flex_itemWithImage:FLEXResources.gearIcon - target:self - action:@selector(settingsButtonTapped:) - ], - [[UIBarButtonItem - flex_systemItem:UIBarButtonSystemItemTrash - target:self - action:@selector(trashButtonTapped:) - ] flex_withTintColor:UIColor.redColor] - ]]; - - [self.tableView - registerClass:FLEXNetworkTransactionCell.class - forCellReuseIdentifier:FLEXNetworkTransactionCell.reuseID - ]; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - self.tableView.rowHeight = FLEXNetworkTransactionCell.preferredCellHeight; - - [self registerForNotifications]; - [self updateTransactions:nil]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - // Reload the table if we received updates while not on-screen - if (self.pendingReload) { - [self.tableView reloadData]; - self.pendingReload = NO; - } -} - -- (void)dealloc { - [NSNotificationCenter.defaultCenter removeObserver:self]; -} - -- (void)registerForNotifications { - NSDictionary *notifications = @{ - kFLEXNetworkRecorderNewTransactionNotification: - NSStringFromSelector(@selector(handleNewTransactionRecordedNotification:)), - kFLEXNetworkRecorderTransactionUpdatedNotification: - NSStringFromSelector(@selector(handleTransactionUpdatedNotification:)), - kFLEXNetworkRecorderTransactionsClearedNotification: - NSStringFromSelector(@selector(handleTransactionsClearedNotification:)), - kFLEXNetworkObserverEnabledStateChangedNotification: - NSStringFromSelector(@selector(handleNetworkObserverEnabledStateChangedNotification:)), - }; - - for (NSString *name in notifications.allKeys) { - [NSNotificationCenter.defaultCenter addObserver:self - selector:NSSelectorFromString(notifications[name]) name:name object:nil - ]; - } -} - - -#pragma mark - Private - -#pragma mark Button Actions - -- (void)settingsButtonTapped:(UIBarButtonItem *)sender { - UIViewController *settings = [FLEXNetworkSettingsController new]; - settings.navigationItem.rightBarButtonItem = FLEXBarButtonItemSystem( - Done, self, @selector(settingsViewControllerDoneTapped:) - ); - settings.title = @"Network Debugging Settings"; - - // This is not a FLEXNavigationController because it is not intended as a new tab - UIViewController *nav = [[UINavigationController alloc] initWithRootViewController:settings]; - [self presentViewController:nav animated:YES completion:nil]; -} - -- (void)trashButtonTapped:(UIBarButtonItem *)sender { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - BOOL clearAll = !self.dataSource.isFiltered; - if (!clearAll) { - make.title(@"Clear Filtered Requests?"); - make.message(@"This will only remove the requests matching your search string on this screen."); - } else { - make.title(@"Clear All Recorded Requests?"); - make.message(@"This cannot be undone."); - } - - make.button(@"Cancel").cancelStyle(); - make.button(@"Clear").destructiveStyle().handler(^(NSArray *strings) { - if (clearAll) { - [FLEXNetworkRecorder.defaultRecorder clearRecordedActivity]; - } else { - FLEXNetworkTransactionKind kind = (FLEXNetworkTransactionKind)self.mode; - [FLEXNetworkRecorder.defaultRecorder clearRecordedActivity:kind matching:self.searchText]; - } - }); - } showFrom:self source:sender]; -} - -- (void)settingsViewControllerDoneTapped:(id)sender { - [self dismissViewControllerAnimated:YES completion:nil]; -} - - -#pragma mark Transactions - -- (FLEXNetworkObserverMode)mode { - FLEXNetworkObserverMode mode = self.searchController.searchBar.selectedScopeButtonIndex; - switch (mode) { - case FLEXNetworkObserverModeFirebase: - if (kFirebaseAvailable) { - return FLEXNetworkObserverModeFirebase; - } - - return FLEXNetworkObserverModeREST; - case FLEXNetworkObserverModeREST: - if (kFirebaseAvailable) { - return FLEXNetworkObserverModeREST; - } - - return FLEXNetworkObserverModeWebsockets; - case FLEXNetworkObserverModeWebsockets: - return FLEXNetworkObserverModeWebsockets; - } -} - -- (void)setMode:(FLEXNetworkObserverMode)mode { -// The segmentd control will have different appearances based on which APIs -// are available. For example, when only Websockets is available: -// -// 0 1 -// ┌───────────────────────────┬────────────────────────────┐ -// │ REST │ Websockets │ -// └───────────────────────────┴────────────────────────────┘ -// -// And when both Firebase and Websockets are available: -// -// 0 1 2 -// ┌──────────────────┬──────────────────┬──────────────────┐ -// │ Firebase │ REST │ Websockets │ -// └──────────────────┴──────────────────┴──────────────────┘ -// -// As a result, we need to adjust the input mode variable accordingly -// before we actually set it. When we try to set it to Firebase but -// Firebase is not available, we don't do anything, because when Firebase -// is unavailable, FLEXNetworkObserverModeFirebase represents the same index -// as REST would without Firebase. For each of the others, we subtract 1 -// from them for every relevant API that is unavailable. So for Websockets, -// if it is unavailable, we subtract 1 and it becomes FLEXNetworkObserverModeREST. -// And if Firebase is also unavailable, we subtract 1 again. - - switch (mode) { - case FLEXNetworkObserverModeFirebase: - // Will default to REST if Firebase is unavailable - break; - case FLEXNetworkObserverModeREST: - // Firebase will become REST when Firebase is unavailable - if (!kFirebaseAvailable) { - mode--; - } - break; - case FLEXNetworkObserverModeWebsockets: - // Default to REST if Websockets are unavailable - if (!kWebsocketsAvailable) { - mode--; - } - // Firebase will become REST when Firebase is unavailable - if (!kFirebaseAvailable) { - mode--; - } - } - - self.searchController.searchBar.selectedScopeButtonIndex = mode; -} - -- (FLEXMITMDataSource *)dataSource { - switch (self.mode) { - case FLEXNetworkObserverModeREST: - return self.HTTPDataSource; - case FLEXNetworkObserverModeWebsockets: - return self.websocketDataSource; - case FLEXNetworkObserverModeFirebase: - return self.firebaseDataSource; - } -} - -- (void)updateTransactions:(void(^)(void))callback { - id completion = ^(FLEXMITMDataSource *dataSource) { - // Update byte count - [self updateFirstSectionHeader]; - if (callback && dataSource == self.dataSource) callback(); - }; - - [self.HTTPDataSource reloadData:completion]; - [self.websocketDataSource reloadData:completion]; - [self.firebaseDataSource reloadData:completion]; -} - - -#pragma mark Header - -- (void)updateFirstSectionHeader { - UIView *view = [self.tableView headerViewForSection:0]; - if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) { - UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view; - headerView.textLabel.text = [self headerText]; - [headerView setNeedsLayout]; - } -} - -- (NSString *)headerText { - long long bytesReceived = self.dataSource.bytesReceived; - NSInteger totalRequests = self.dataSource.transactions.count; - - NSString *byteCountText = [NSByteCountFormatter - stringFromByteCount:bytesReceived countStyle:NSByteCountFormatterCountStyleBinary - ]; - NSString *requestsText = totalRequests == 1 ? @"Request" : @"Requests"; - - // Exclude byte count from Firebase - if (self.mode == FLEXNetworkObserverModeFirebase) { - return [NSString stringWithFormat:@"%@ %@", - @(totalRequests), requestsText - ]; - } - - return [NSString stringWithFormat:@"%@ %@ (%@ received)", - @(totalRequests), requestsText, byteCountText - ]; -} - - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - return @"📡 Network History"; -} - -+ (FLEXGlobalsEntryRowAction)globalsEntryRowAction:(FLEXGlobalsRow)row { - return ^(UITableViewController *host) { - if (FLEXNetworkObserver.isEnabled) { - [host.navigationController pushViewController:[ - self globalsEntryViewController:row - ] animated:YES]; - } else { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Network Monitor Disabled"); - make.message(@"You must enable network monitoring to proceed."); - - make.button(@"Turn On").handler(^(NSArray *strings) { - FLEXNetworkObserver.enabled = YES; - [host.navigationController pushViewController:[ - self globalsEntryViewController:row - ] animated:YES]; - }).cancelStyle(); - make.button(@"Dismiss"); - } showFrom:host]; - } - }; -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - UIViewController *controller = [self new]; - controller.title = [self globalsEntryTitle:row]; - return controller; -} - - -#pragma mark - Notification Handlers - -- (void)handleNewTransactionRecordedNotification:(NSNotification *)notification { - [self tryUpdateTransactions]; -} - -- (void)tryUpdateTransactions { - // Don't do any view updating if we aren't in the view hierarchy - if (!self.viewIfLoaded.window) { - [self updateTransactions:nil]; - self.pendingReload = YES; - return; - } - - // Let the previous row insert animation finish before starting a new one to avoid stomping. - // We'll try calling the method again when the insertion completes, - // and we properly no-op if there haven't been changes. - if (self.updateInProgress) { - return; - } - - self.updateInProgress = YES; - - // Get state before update - NSString *currentFilter = self.searchText; - FLEXNetworkObserverMode currentMode = self.mode; - NSInteger existingRowCount = self.dataSource.transactions.count; - - [self updateTransactions:^{ - // Compare to state after update - NSString *newFilter = self.searchText; - FLEXNetworkObserverMode newMode = self.mode; - NSInteger newRowCount = self.dataSource.transactions.count; - NSInteger rowCountDiff = newRowCount - existingRowCount; - - // Abort if the observation mode changed, or if the search field text changed - if (newMode != currentMode || ![currentFilter isEqualToString:newFilter]) { - self.updateInProgress = NO; - return; - } - - if (rowCountDiff) { - // Insert animation if we're at the top. - if (self.tableView.contentOffset.y <= 0.0 && rowCountDiff > 0) { - [CATransaction begin]; - - [CATransaction setCompletionBlock:^{ - self.updateInProgress = NO; - // This isn't an infinite loop, it won't run a third time - // if there were no new transactions the second time - [self tryUpdateTransactions]; - }]; - - NSMutableArray *indexPathsToReload = [NSMutableArray new]; - for (NSInteger row = 0; row < rowCountDiff; row++) { - [indexPathsToReload addObject:[NSIndexPath indexPathForRow:row inSection:0]]; - } - - [self.tableView insertRowsAtIndexPaths:indexPathsToReload withRowAnimation:UITableViewRowAnimationAutomatic]; - [CATransaction commit]; - } else { - // Maintain the user's position if they've scrolled down. - CGSize existingContentSize = self.tableView.contentSize; - [self.tableView reloadData]; - CGFloat contentHeightChange = self.tableView.contentSize.height - existingContentSize.height; - self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y + contentHeightChange); - self.updateInProgress = NO; - } - } else { - self.updateInProgress = NO; - } - }]; -} - -- (void)handleTransactionUpdatedNotification:(NSNotification *)notification { - [self.HTTPDataSource reloadByteCounts]; - [self.websocketDataSource reloadByteCounts]; - // Don't need to reload Firebase here - - FLEXNetworkTransaction *transaction = notification.userInfo[kFLEXNetworkRecorderUserInfoTransactionKey]; - - // Update both the main table view and search table view if needed. - for (FLEXNetworkTransactionCell *cell in self.tableView.visibleCells) { - if ([cell.transaction isEqual:transaction]) { - // Using -[UITableView reloadRowsAtIndexPaths:withRowAnimation:] is overkill here and kicks off a lot of - // work that can make the table view somewhat unresponsive when lots of updates are streaming in. - // We just need to tell the cell that it needs to re-layout. - [cell setNeedsLayout]; - break; - } - } - - [self updateFirstSectionHeader]; -} - -- (void)handleTransactionsClearedNotification:(NSNotification *)notification { - [self updateTransactions:^{ - [self.tableView reloadData]; - }]; -} - -- (void)handleNetworkObserverEnabledStateChangedNotification:(NSNotification *)notification { - // Update the header, which displays a warning when network debugging is disabled - [self updateFirstSectionHeader]; -} - - -#pragma mark - Table view data source - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.dataSource.transactions.count; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return [self headerText]; -} - -- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { - if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) { - UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view; - headerView.textLabel.font = [UIFont systemFontOfSize:14.0 weight:UIFontWeightSemibold]; - } -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - FLEXNetworkTransactionCell *cell = [tableView - dequeueReusableCellWithIdentifier:FLEXNetworkTransactionCell.reuseID - forIndexPath:indexPath - ]; - - cell.transaction = [self transactionAtIndexPath:indexPath]; - - // Since we insert from the top, assign background colors bottom up to keep them consistent for each transaction. - NSInteger totalRows = [tableView numberOfRowsInSection:indexPath.section]; - if ((totalRows - indexPath.row) % 2 == 0) { - cell.backgroundColor = FLEXColor.secondaryBackgroundColor; - } else { - cell.backgroundColor = FLEXColor.primaryBackgroundColor; - } - - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - switch (self.mode) { - case FLEXNetworkObserverModeREST: { - FLEXHTTPTransaction *transaction = [self HTTPTransactionAtIndexPath:indexPath]; - UIViewController *details = [FLEXHTTPTransactionDetailController withTransaction:transaction]; - [self.navigationController pushViewController:details animated:YES]; - break; - } - - case FLEXNetworkObserverModeWebsockets: { - if (@available(iOS 13.0, *)) { // This check will never fail - FLEXWebsocketTransaction *transaction = [self websocketTransactionAtIndexPath:indexPath]; - - UIViewController *details = nil; - if (transaction.message.type == NSURLSessionWebSocketMessageTypeData) { - details = [FLEXObjectExplorerFactory explorerViewControllerForObject:transaction.message.data]; - } else { - details = [[FLEXWebViewController alloc] initWithText:transaction.message.string]; - } - - [self.navigationController pushViewController:details animated:YES]; - } - break; - } - - case FLEXNetworkObserverModeFirebase: { - FLEXFirebaseTransaction *transaction = [self firebaseTransactionAtIndexPath:indexPath]; -// id obj = transaction.documents.count == 1 ? transaction.documents.firstObject : transaction.documents; - UIViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:transaction]; - [self.navigationController pushViewController:explorer animated:YES]; - } - } -} - - -#pragma mark - Menu Actions - -- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; -} - -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - return action == @selector(copy:); -} - -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - if (action == @selector(copy:)) { - UIPasteboard.generalPasteboard.string = [self transactionAtIndexPath:indexPath].copyString; - } -} - -- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __IOS_AVAILABLE(13.0) { - - FLEXNetworkTransaction *transaction = [self transactionAtIndexPath:indexPath]; - - return [UIContextMenuConfiguration - configurationWithIdentifier:nil - previewProvider:nil - actionProvider:^UIMenu *(NSArray *suggestedActions) { - UIAction *copy = [UIAction - actionWithTitle:@"Copy URL" - image:nil - identifier:nil - handler:^(__kindof UIAction *action) { - UIPasteboard.generalPasteboard.string = transaction.copyString; - } - ]; - - NSArray *children = @[copy]; - if (self.mode == FLEXNetworkObserverModeREST) { - NSURLRequest *request = [self HTTPTransactionAtIndexPath:indexPath].request; - UIAction *denylist = [UIAction - actionWithTitle:[NSString stringWithFormat:@"Exclude '%@'", request.URL.host] - image:nil - identifier:nil - handler:^(__kindof UIAction *action) { - NSMutableArray *denylist = FLEXNetworkRecorder.defaultRecorder.hostDenylist; - [denylist addObject:request.URL.host]; - [FLEXNetworkRecorder.defaultRecorder clearExcludedTransactions]; - [FLEXNetworkRecorder.defaultRecorder synchronizeDenylist]; - [self tryUpdateTransactions]; - } - ]; - - children = [children arrayByAddingObject:denylist]; - } - return [UIMenu - menuWithTitle:@"" image:nil identifier:nil - options:UIMenuOptionsDisplayInline - children:children - ]; - } - ]; -} - -- (FLEXNetworkTransaction *)transactionAtIndexPath:(NSIndexPath *)indexPath { - return self.dataSource.transactions[indexPath.row]; -} - -- (FLEXHTTPTransaction *)HTTPTransactionAtIndexPath:(NSIndexPath *)indexPath { - return self.HTTPDataSource.transactions[indexPath.row]; -} - -- (FLEXWebsocketTransaction *)websocketTransactionAtIndexPath:(NSIndexPath *)indexPath { - return self.websocketDataSource.transactions[indexPath.row]; -} - -- (FLEXFirebaseTransaction *)firebaseTransactionAtIndexPath:(NSIndexPath *)indexPath { - return self.firebaseDataSource.transactions[indexPath.row]; -} - -#pragma mark - Search Bar - -- (void)updateSearchResults:(NSString *)searchString { - id callback = ^(FLEXMITMDataSource *dataSource) { - if (self.dataSource == dataSource) { - [self.tableView reloadData]; - } - }; - - [self.HTTPDataSource filter:searchString completion:callback]; - [self.websocketDataSource filter:searchString completion:callback]; - [self.firebaseDataSource filter:searchString completion:callback]; -} - -- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)newScope { - [self updateFirstSectionHeader]; - [self.tableView reloadData]; - - NSUserDefaults.standardUserDefaults.flex_lastNetworkObserverMode = self.mode; -} - -- (void)willDismissSearchController:(UISearchController *)searchController { - [self.tableView reloadData]; -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkRecorder.h b/Tweaks/FLEX/Network/FLEXNetworkRecorder.h deleted file mode 100644 index b1a2017..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkRecorder.h +++ /dev/null @@ -1,122 +0,0 @@ -// -// FLEXNetworkRecorder.h -// Flipboard -// -// Created by Ryan Olson on 2/4/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -// Notifications posted when the record is updated -extern NSString *const kFLEXNetworkRecorderNewTransactionNotification; -extern NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification; -extern NSString *const kFLEXNetworkRecorderUserInfoTransactionKey; -extern NSString *const kFLEXNetworkRecorderTransactionsClearedNotification; - -@class FLEXNetworkTransaction, FLEXHTTPTransaction, FLEXWebsocketTransaction, FLEXFirebaseTransaction; -@class FIRQuery, FIRDocumentReference, FIRCollectionReference, FIRDocumentSnapshot, FIRQuerySnapshot; - -typedef NS_ENUM(NSUInteger, FLEXNetworkTransactionKind) { - FLEXNetworkTransactionKindFirebase = 0, - FLEXNetworkTransactionKindREST, - FLEXNetworkTransactionKindWebsockets, -}; - -@interface FLEXNetworkRecorder : NSObject - -/// In general, it only makes sense to have one recorder for the entire application. -@property (nonatomic, readonly, class) FLEXNetworkRecorder *defaultRecorder; - -/// Defaults to 25 MB if never set. Values set here are persisted across launches of the app. -@property (nonatomic) NSUInteger responseCacheByteLimit; - -/// If NO, the recorder not cache will not cache response for content types -/// with an "image", "video", or "audio" prefix. -@property (nonatomic) BOOL shouldCacheMediaResponses; - -@property (nonatomic) NSMutableArray *hostDenylist; - -/// Call this after adding to or setting the \c hostDenylist to remove excluded transactions -- (void)clearExcludedTransactions; - -/// Call this to save the denylist to the disk to be loaded next time -- (void)synchronizeDenylist; - - -#pragma mark Accessing recorded network activity - -/// Array of FLEXHTTPTransaction objects ordered by start time with the newest first. -@property (nonatomic, readonly) NSArray *HTTPTransactions; -/// Array of FLEXWebsocketTransaction objects ordered by start time with the newest first. -@property (nonatomic, readonly) NSArray *websocketTransactions API_AVAILABLE(ios(13.0)); -/// Array of FLEXFirebaseTransaction objects ordered by start time with the newest first. -@property (nonatomic, readonly) NSArray *firebaseTransactions; - -/// The full response data IFF it hasn't been purged due to memory pressure. -- (NSData *)cachedResponseBodyForTransaction:(FLEXHTTPTransaction *)transaction; - -/// Dumps all network transactions and cached response bodies. -- (void)clearRecordedActivity; - -/// Clear only transactions matching the given query. -- (void)clearRecordedActivity:(FLEXNetworkTransactionKind)kind matching:(NSString *)query; - - -#pragma mark Recording network activity - -/// Call when app is about to send HTTP request. -- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID - request:(NSURLRequest *)request - redirectResponse:(NSURLResponse *)redirectResponse; - -/// Call when HTTP response is available. -- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response; - -/// Call when data chunk is received over the network. -- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength; - -/// Call when HTTP request has finished loading. -- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody; - -/// Call when HTTP request has failed to load. -- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error; - -/// Call to set the request mechanism anytime after recordRequestWillBeSent... has been called. -/// This string can be set to anything useful about the API used to make the request. -- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID; - -- (void)recordWebsocketMessageSend:(NSURLSessionWebSocketMessage *)message - task:(NSURLSessionWebSocketTask *)task API_AVAILABLE(ios(13.0)); -- (void)recordWebsocketMessageSendCompletion:(NSURLSessionWebSocketMessage *)message - error:(NSError *)error API_AVAILABLE(ios(13.0)); - -- (void)recordWebsocketMessageReceived:(NSURLSessionWebSocketMessage *)message - task:(NSURLSessionWebSocketTask *)task API_AVAILABLE(ios(13.0)); - -- (void)recordFIRQueryWillFetch:(FIRQuery *)query withTransactionID:(NSString *)transactionID; -- (void)recordFIRDocumentWillFetch:(FIRDocumentReference *)document withTransactionID:(NSString *)transactionID; - -- (void)recordFIRQueryDidFetch:(FIRQuerySnapshot *)response error:(NSError *)error - transactionID:(NSString *)transactionID; -- (void)recordFIRDocumentDidFetch:(FIRDocumentSnapshot *)response error:(NSError *)error - transactionID:(NSString *)transactionID; - -- (void)recordFIRWillSetData:(FIRDocumentReference *)doc - data:(NSDictionary *)documentData - merge:(NSNumber *)yesorno - mergeFields:(NSArray *)fields - transactionID:(NSString *)transactionID; -- (void)recordFIRWillUpdateData:(FIRDocumentReference *)doc fields:(NSDictionary *)fields - transactionID:(NSString *)transactionID; -- (void)recordFIRWillDeleteDocument:(FIRDocumentReference *)doc transactionID:(NSString *)transactionID; -- (void)recordFIRWillAddDocument:(FIRCollectionReference *)initiator - document:(FIRDocumentReference *)doc - transactionID:(NSString *)transactionID; - -- (void)recordFIRDidSetData:(NSError *)error transactionID:(NSString *)transactionID; -- (void)recordFIRDidUpdateData:(NSError *)error transactionID:(NSString *)transactionID; -- (void)recordFIRDidDeleteDocument:(NSError *)error transactionID:(NSString *)transactionID; -- (void)recordFIRDidAddDocument:(NSError *)error transactionID:(NSString *)transactionID; - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkRecorder.m b/Tweaks/FLEX/Network/FLEXNetworkRecorder.m deleted file mode 100644 index 908111a..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkRecorder.m +++ /dev/null @@ -1,500 +0,0 @@ -// -// FLEXNetworkRecorder.m -// Flipboard -// -// Created by Ryan Olson on 2/4/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXNetworkRecorder.h" -#import "FLEXNetworkCurlLogger.h" -#import "FLEXNetworkTransaction.h" -#import "FLEXUtility.h" -#import "FLEXResources.h" -#import "NSUserDefaults+FLEX.h" -#import "OSCache.h" - -NSString *const kFLEXNetworkRecorderNewTransactionNotification = @"kFLEXNetworkRecorderNewTransactionNotification"; -NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification = @"kFLEXNetworkRecorderTransactionUpdatedNotification"; -NSString *const kFLEXNetworkRecorderUserInfoTransactionKey = @"transaction"; -NSString *const kFLEXNetworkRecorderTransactionsClearedNotification = @"kFLEXNetworkRecorderTransactionsClearedNotification"; - -NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.responseCacheLimit"; - -@interface FLEXNetworkRecorder () - -@property (nonatomic) OSCache *restCache; -@property (atomic) NSMutableArray *orderedHTTPTransactions; -@property (atomic) NSMutableArray *orderedWSTransactions; -@property (atomic) NSMutableArray *orderedFirebaseTransactions; -@property (atomic) NSMutableDictionary *requestIDsToTransactions; -@property (nonatomic) dispatch_queue_t queue; - -@end - -@implementation FLEXNetworkRecorder - -- (instancetype)init { - self = [super init]; - if (self) { - self.restCache = [OSCache new]; - NSUInteger responseCacheLimit = [[NSUserDefaults.standardUserDefaults - objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey] unsignedIntegerValue - ]; - - // Default to 25 MB max. The cache will purge earlier if there is memory pressure. - self.restCache.totalCostLimit = responseCacheLimit ?: 25 * 1024 * 1024; - [self.restCache setTotalCostLimit:responseCacheLimit]; - - self.orderedWSTransactions = [NSMutableArray new]; - self.orderedHTTPTransactions = [NSMutableArray new]; - self.orderedFirebaseTransactions = [NSMutableArray new]; - self.requestIDsToTransactions = [NSMutableDictionary new]; - self.hostDenylist = NSUserDefaults.standardUserDefaults.flex_networkHostDenylist.mutableCopy; - - // Serial queue used because we use mutable objects that are not thread safe - self.queue = dispatch_queue_create("com.flex.FLEXNetworkRecorder", DISPATCH_QUEUE_SERIAL); - } - - return self; -} - -+ (instancetype)defaultRecorder { - static FLEXNetworkRecorder *defaultRecorder = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - defaultRecorder = [self new]; - }); - - return defaultRecorder; -} - -#pragma mark - Public Data Access - -- (NSUInteger)responseCacheByteLimit { - return self.restCache.totalCostLimit; -} - -- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit { - self.restCache.totalCostLimit = responseCacheByteLimit; - [NSUserDefaults.standardUserDefaults - setObject:@(responseCacheByteLimit) - forKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey - ]; -} - -- (NSArray *)HTTPTransactions { - return self.orderedHTTPTransactions.copy; -} - -- (NSArray *)websocketTransactions { - return self.orderedWSTransactions.copy; -} - -- (NSArray *)firebaseTransactions { - return self.orderedFirebaseTransactions.copy; -} - -- (NSData *)cachedResponseBodyForTransaction:(FLEXHTTPTransaction *)transaction { - return [self.restCache objectForKey:transaction.requestID]; -} - -- (void)clearRecordedActivity { - dispatch_async(self.queue, ^{ - [self.restCache removeAllObjects]; - [self.orderedWSTransactions removeAllObjects]; - [self.orderedHTTPTransactions removeAllObjects]; - [self.orderedFirebaseTransactions removeAllObjects]; - [self.requestIDsToTransactions removeAllObjects]; - - [self notify:kFLEXNetworkRecorderTransactionsClearedNotification transaction:nil]; - }); -} - -- (void)clearRecordedActivity:(FLEXNetworkTransactionKind)kind matching:(NSString *)query { - dispatch_async(self.queue, ^{ - switch (kind) { - case FLEXNetworkTransactionKindFirebase: { - [self.orderedFirebaseTransactions flex_filter:^BOOL(FLEXFirebaseTransaction *obj, NSUInteger idx) { - return ![obj matchesQuery:query]; - }]; - break; - } - case FLEXNetworkTransactionKindREST: { - NSArray *toRemove; - toRemove = [self.orderedHTTPTransactions flex_filtered:^BOOL(FLEXHTTPTransaction *obj, NSUInteger idx) { - return [obj matchesQuery:query]; - }]; - - // Remove from cache - for (FLEXHTTPTransaction *t in toRemove) { - [self.restCache removeObjectForKey:t.requestID]; - } - - // Remove from list - [self.orderedHTTPTransactions removeObjectsInArray:toRemove]; - - break; - } - case FLEXNetworkTransactionKindWebsockets: { - [self.orderedWSTransactions flex_filter:^BOOL(FLEXWebsocketTransaction *obj, NSUInteger idx) { - return ![obj matchesQuery:query]; - }]; - break; - } - } - - [self notify:kFLEXNetworkRecorderTransactionsClearedNotification transaction:nil]; - }); -} - -- (void)clearExcludedTransactions { - dispatch_sync(self.queue, ^{ - self.orderedHTTPTransactions = ({ - [self.orderedHTTPTransactions flex_filtered:^BOOL(FLEXHTTPTransaction *ta, NSUInteger idx) { - NSString *host = ta.request.URL.host; - for (NSString *excluded in self.hostDenylist) { - if ([host hasSuffix:excluded]) { - return NO; - } - } - - return YES; - }]; - }); - }); -} - -- (void)synchronizeDenylist { - NSUserDefaults.standardUserDefaults.flex_networkHostDenylist = self.hostDenylist; -} - -#pragma mark - Network Events - -- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID - request:(NSURLRequest *)request - redirectResponse:(NSURLResponse *)redirectResponse { - for (NSString *host in self.hostDenylist) { - if ([request.URL.host hasSuffix:host]) { - return; - } - } - - FLEXHTTPTransaction *transaction = [FLEXHTTPTransaction request:request identifier:requestID]; - - // Before async block to keep times accurate - if (redirectResponse) { - [self recordResponseReceivedWithRequestID:requestID response:redirectResponse]; - [self recordLoadingFinishedWithRequestID:requestID responseBody:nil]; - } - - // A redirect is always a new request - dispatch_async(self.queue, ^{ - [self.orderedHTTPTransactions insertObject:transaction atIndex:0]; - self.requestIDsToTransactions[requestID] = transaction; - - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response { - // Before async block to stay accurate - NSDate *responseDate = [NSDate date]; - - dispatch_async(self.queue, ^{ - FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID]; - if (!transaction) { - return; - } - - transaction.response = response; - transaction.state = FLEXNetworkTransactionStateReceivingData; - transaction.latency = -[transaction.startTime timeIntervalSinceDate:responseDate]; - - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength { - dispatch_async(self.queue, ^{ - FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID]; - if (!transaction) { - return; - } - - transaction.receivedDataLength += dataLength; - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody { - NSDate *finishedDate = [NSDate date]; - - dispatch_async(self.queue, ^{ - FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID]; - if (!transaction) { - return; - } - - transaction.state = FLEXNetworkTransactionStateFinished; - transaction.duration = -[transaction.startTime timeIntervalSinceDate:finishedDate]; - - BOOL shouldCache = responseBody.length > 0; - if (!self.shouldCacheMediaResponses) { - NSArray *ignoredMIMETypePrefixes = @[ @"audio", @"image", @"video" ]; - for (NSString *ignoredPrefix in ignoredMIMETypePrefixes) { - shouldCache = shouldCache && ![transaction.response.MIMEType hasPrefix:ignoredPrefix]; - } - } - - if (shouldCache) { - [self.restCache setObject:responseBody forKey:requestID cost:responseBody.length]; - } - - NSString *mimeType = transaction.response.MIMEType; - if ([mimeType hasPrefix:@"image/"] && responseBody.length > 0) { - // Thumbnail image previews on a separate background queue - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSInteger maxPixelDimension = UIScreen.mainScreen.scale * 32.0; - transaction.thumbnail = [FLEXUtility - thumbnailedImageWithMaxPixelDimension:maxPixelDimension - fromImageData:responseBody - ]; - [self postUpdateNotificationForTransaction:transaction]; - }); - } else if ([mimeType isEqual:@"application/json"]) { - transaction.thumbnail = FLEXResources.jsonIcon; - } else if ([mimeType isEqual:@"text/plain"]){ - transaction.thumbnail = FLEXResources.textPlainIcon; - } else if ([mimeType isEqual:@"text/html"]) { - transaction.thumbnail = FLEXResources.htmlIcon; - } else if ([mimeType isEqual:@"application/x-plist"]) { - transaction.thumbnail = FLEXResources.plistIcon; - } else if ([mimeType isEqual:@"application/octet-stream"] || [mimeType isEqual:@"application/binary"]) { - transaction.thumbnail = FLEXResources.binaryIcon; - } else if ([mimeType containsString:@"javascript"]) { - transaction.thumbnail = FLEXResources.jsIcon; - } else if ([mimeType containsString:@"xml"]) { - transaction.thumbnail = FLEXResources.xmlIcon; - } else if ([mimeType hasPrefix:@"audio"]) { - transaction.thumbnail = FLEXResources.audioIcon; - } else if ([mimeType hasPrefix:@"video"]) { - transaction.thumbnail = FLEXResources.videoIcon; - } else if ([mimeType hasPrefix:@"text"]) { - transaction.thumbnail = FLEXResources.textIcon; - } - - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error { - dispatch_async(self.queue, ^{ - FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID]; - if (!transaction) { - return; - } - - transaction.state = FLEXNetworkTransactionStateFailed; - transaction.duration = -[transaction.startTime timeIntervalSinceNow]; - transaction.error = error; - - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID { - dispatch_async(self.queue, ^{ - FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID]; - if (!transaction) { - return; - } - - transaction.requestMechanism = mechanism; - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -#pragma mark - Websocket Events - -- (void)recordWebsocketMessageSend:(NSURLSessionWebSocketMessage *)message task:(NSURLSessionWebSocketTask *)task { - dispatch_async(self.queue, ^{ - FLEXWebsocketTransaction *send = [FLEXWebsocketTransaction - withMessage:message task:task direction:FLEXWebsocketOutgoing - ]; - - [self.orderedWSTransactions insertObject:send atIndex:0]; - [self postNewTransactionNotificationWithTransaction:send]; - }); -} - -- (void)recordWebsocketMessageSendCompletion:(NSURLSessionWebSocketMessage *)message error:(NSError *)error { - dispatch_async(self.queue, ^{ - FLEXWebsocketTransaction *send = [self.orderedWSTransactions flex_firstWhere:^BOOL(FLEXWebsocketTransaction *t) { - return t.message == message; - }]; - send.error = error; - send.state = error ? FLEXNetworkTransactionStateFailed : FLEXNetworkTransactionStateFinished; - - [self postUpdateNotificationForTransaction:send]; - }); -} - -- (void)recordWebsocketMessageReceived:(NSURLSessionWebSocketMessage *)message task:(NSURLSessionWebSocketTask *)task { - dispatch_async(self.queue, ^{ - FLEXWebsocketTransaction *receive = [FLEXWebsocketTransaction - withMessage:message task:task direction:FLEXWebsocketIncoming - ]; - - [self.orderedWSTransactions insertObject:receive atIndex:0]; - [self postNewTransactionNotificationWithTransaction:receive]; - }); -} - -#pragma mark - Firebase, Reading - -- (void)recordFIRQueryWillFetch:(FIRQuery *)query withTransactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction queryFetch:query]; - self.requestIDsToTransactions[transactionID] = transaction; - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordFIRDocumentWillFetch:(FIRDocumentReference *)document withTransactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction documentFetch:document]; - self.requestIDsToTransactions[transactionID] = transaction; - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordFIRQueryDidFetch:(FIRQuerySnapshot *)response error:(NSError *)error transactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = self.requestIDsToTransactions[transactionID]; - if (!transaction) { - return; - } - - transaction.error = error; - transaction.documents = response.documents; - transaction.state = FLEXNetworkTransactionStateFinished; - [self.orderedFirebaseTransactions insertObject:transaction atIndex:0]; - - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -- (void)recordFIRDocumentDidFetch:(FIRDocumentSnapshot *)response error:(NSError *)error transactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = self.requestIDsToTransactions[transactionID]; - if (!transaction) { - return; - } - - transaction.error = error; - transaction.documents = response ? @[response] : @[]; - transaction.state = FLEXNetworkTransactionStateFinished; - [self.orderedFirebaseTransactions insertObject:transaction atIndex:0]; - - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -#pragma mark Firebase, Writing - -- (void)recordFIRWillSetData:(FIRDocumentReference *)doc - data:(NSDictionary *)documentData - merge:(NSNumber *)yesorno - mergeFields:(NSArray *)fields - transactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction - setData:doc data:documentData merge:yesorno mergeFields:fields - ]; - self.requestIDsToTransactions[transactionID] = transaction; - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordFIRWillUpdateData:(FIRDocumentReference *)doc fields:(NSDictionary *)fields - transactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction updateData:doc data:fields]; - self.requestIDsToTransactions[transactionID] = transaction; - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordFIRWillDeleteDocument:(FIRDocumentReference *)doc transactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction deleteDocument:doc]; - self.requestIDsToTransactions[transactionID] = transaction; - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordFIRWillAddDocument:(FIRCollectionReference *)initiator document:(FIRDocumentReference *)doc - transactionID:(NSString *)transactionID { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction - addDocument:initiator document:doc - ]; - self.requestIDsToTransactions[transactionID] = transaction; - [self postNewTransactionNotificationWithTransaction:transaction]; - }); -} - -- (void)recordFIRDidSetData:(NSError *)error transactionID:(NSString *)transactionID { - [self firebaseTransaction:transactionID didUpdate:error]; -} - -- (void)recordFIRDidUpdateData:(NSError *)error transactionID:(NSString *)transactionID { - [self firebaseTransaction:transactionID didUpdate:error]; -} - -- (void)recordFIRDidDeleteDocument:(NSError *)error transactionID:(NSString *)transactionID { - [self firebaseTransaction:transactionID didUpdate:error]; -} - -- (void)recordFIRDidAddDocument:(NSError *)error transactionID:(NSString *)transactionID { - [self firebaseTransaction:transactionID didUpdate:error]; -} - -- (void)firebaseTransaction:(NSString *)transactionID didUpdate:(NSError *)error { - dispatch_async(self.queue, ^{ - FLEXFirebaseTransaction *transaction = self.requestIDsToTransactions[transactionID]; - if (!transaction) { - return; - } - - transaction.error = error; - transaction.state = FLEXNetworkTransactionStateFinished; - [self.orderedFirebaseTransactions insertObject:transaction atIndex:0]; - - [self postUpdateNotificationForTransaction:transaction]; - }); -} - -#pragma mark - Notification Posting - -- (void)postNewTransactionNotificationWithTransaction:(FLEXNetworkTransaction *)transaction { - [self notify:kFLEXNetworkRecorderNewTransactionNotification transaction:transaction]; -} - -- (void)postUpdateNotificationForTransaction:(FLEXNetworkTransaction *)transaction { - [self notify:kFLEXNetworkRecorderTransactionUpdatedNotification transaction:transaction]; -} - -- (void)notify:(NSString *)name transaction:(FLEXNetworkTransaction *)transaction { - NSDictionary *userInfo = nil; - if (transaction) { - userInfo = @{ kFLEXNetworkRecorderUserInfoTransactionKey : transaction }; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [NSNotificationCenter.defaultCenter postNotificationName:name object:self userInfo:userInfo]; - }); -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkSettingsController.h b/Tweaks/FLEX/Network/FLEXNetworkSettingsController.h deleted file mode 100644 index 1094fb5..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkSettingsController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// FLEXNetworkSettingsController.h -// FLEXInjected -// -// Created by Ryan Olson on 2/20/15. -// - -#import "FLEXTableViewController.h" - -@interface FLEXNetworkSettingsController : FLEXTableViewController - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkSettingsController.m b/Tweaks/FLEX/Network/FLEXNetworkSettingsController.m deleted file mode 100644 index 7490f52..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkSettingsController.m +++ /dev/null @@ -1,253 +0,0 @@ -// -// FLEXNetworkSettingsController.m -// FLEXInjected -// -// Created by Ryan Olson on 2/20/15. -// - -#import "FLEXNetworkSettingsController.h" -#import "FLEXNetworkObserver.h" -#import "FLEXNetworkRecorder.h" -#import "FLEXUtility.h" -#import "FLEXTableView.h" -#import "FLEXColor.h" -#import "NSUserDefaults+FLEX.h" - -@interface FLEXNetworkSettingsController () -@property (nonatomic) float cacheLimitValue; -@property (nonatomic, readonly) NSString *cacheLimitCellTitle; - -@property (nonatomic, readonly) UISwitch *observerSwitch; -@property (nonatomic, readonly) UISwitch *cacheMediaSwitch; -@property (nonatomic, readonly) UISwitch *jsonViewerSwitch; -@property (nonatomic, readonly) UISlider *cacheLimitSlider; -@property (nonatomic) UILabel *cacheLimitLabel; - -@property (nonatomic) NSMutableArray *hostDenylist; -@end - -@implementation FLEXNetworkSettingsController - -- (void)viewDidLoad { - [super viewDidLoad]; - - [self disableToolbar]; - self.hostDenylist = FLEXNetworkRecorder.defaultRecorder.hostDenylist.mutableCopy; - - NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; - - _observerSwitch = [UISwitch new]; - _cacheMediaSwitch = [UISwitch new]; - _jsonViewerSwitch = [UISwitch new]; - _cacheLimitSlider = [UISlider new]; - - self.observerSwitch.on = FLEXNetworkObserver.enabled; - [self.observerSwitch addTarget:self - action:@selector(networkDebuggingToggled:) - forControlEvents:UIControlEventValueChanged - ]; - - self.cacheMediaSwitch.on = FLEXNetworkRecorder.defaultRecorder.shouldCacheMediaResponses; - [self.cacheMediaSwitch addTarget:self - action:@selector(cacheMediaResponsesToggled:) - forControlEvents:UIControlEventValueChanged - ]; - - self.jsonViewerSwitch.on = defaults.flex_registerDictionaryJSONViewerOnLaunch; - [self.jsonViewerSwitch addTarget:self - action:@selector(jsonViewerSettingToggled:) - forControlEvents:UIControlEventValueChanged - ]; - - [self.cacheLimitSlider addTarget:self - action:@selector(cacheLimitAdjusted:) - forControlEvents:UIControlEventValueChanged - ]; - - UISlider *slider = self.cacheLimitSlider; - self.cacheLimitValue = FLEXNetworkRecorder.defaultRecorder.responseCacheByteLimit; - const NSUInteger fiftyMega = 50 * 1024 * 1024; - slider.minimumValue = 0; - slider.maximumValue = fiftyMega; - slider.value = self.cacheLimitValue; -} - -- (void)setCacheLimitValue:(float)cacheLimitValue { - _cacheLimitValue = cacheLimitValue; - self.cacheLimitLabel.text = self.cacheLimitCellTitle; - [FLEXNetworkRecorder.defaultRecorder setResponseCacheByteLimit:cacheLimitValue]; -} - -- (NSString *)cacheLimitCellTitle { - NSInteger cacheLimit = self.cacheLimitValue; - NSInteger limitInMB = round(cacheLimit / (1024 * 1024)); - return [NSString stringWithFormat:@"Cache Limit (%@ MB)", @(limitInMB)]; -} - - -#pragma mark - Settings Actions - -- (void)networkDebuggingToggled:(UISwitch *)sender { - FLEXNetworkObserver.enabled = sender.isOn; -} - -- (void)cacheMediaResponsesToggled:(UISwitch *)sender { - FLEXNetworkRecorder.defaultRecorder.shouldCacheMediaResponses = sender.isOn; -} - -- (void)jsonViewerSettingToggled:(UISwitch *)sender { - [NSUserDefaults.standardUserDefaults flex_toggleBoolForKey:kFLEXDefaultsRegisterJSONExplorerKey]; -} - -- (void)cacheLimitAdjusted:(UISlider *)sender { - self.cacheLimitValue = sender.value; -} - - -#pragma mark - Table View Data Source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.hostDenylist.count ? 2 : 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - switch (section) { - case 0: return 5; - case 1: return self.hostDenylist.count; - default: return 0; - } -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - switch (section) { - case 0: return @"General"; - case 1: return @"Host Denylist"; - default: return nil; - } -} - -- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { - if (section == 0) { - return @"By default, JSON is rendered in a webview. Turn on " - "\"View JSON as a dictionary/array\" to convert JSON payloads " - "to objects and view them in an object explorer. " - "This setting requires a restart of the app."; - } - - return nil; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [self.tableView - dequeueReusableCellWithIdentifier:kFLEXDefaultCell forIndexPath:indexPath - ]; - - cell.accessoryView = nil; - cell.textLabel.textColor = FLEXColor.primaryTextColor; - - switch (indexPath.section) { - // Settings - case 0: { - switch (indexPath.row) { - case 0: - cell.textLabel.text = @"Network Debugging"; - cell.accessoryView = self.observerSwitch; - break; - case 1: - cell.textLabel.text = @"Cache Media Responses"; - cell.accessoryView = self.cacheMediaSwitch; - break; - case 2: - cell.textLabel.text = @"View JSON as a dictionary/array"; - cell.accessoryView = self.jsonViewerSwitch; - break; - case 3: - cell.textLabel.text = @"Reset Host Denylist"; - cell.textLabel.textColor = tableView.tintColor; - break; - case 4: - cell.textLabel.text = self.cacheLimitCellTitle; - self.cacheLimitLabel = cell.textLabel; - [self.cacheLimitSlider removeFromSuperview]; - [cell.contentView addSubview:self.cacheLimitSlider]; - - CGRect container = cell.contentView.frame; - UISlider *slider = self.cacheLimitSlider; - [slider sizeToFit]; - - CGFloat sliderWidth = 150.f; - CGFloat sliderOriginY = FLEXFloor((container.size.height - slider.frame.size.height) / 2.0); - CGFloat sliderOriginX = CGRectGetMaxX(container) - sliderWidth - tableView.separatorInset.left; - self.cacheLimitSlider.frame = CGRectMake( - sliderOriginX, sliderOriginY, sliderWidth, slider.frame.size.height - ); - - // Make wider, keep in middle of cell, keep to trailing edge of cell - self.cacheLimitSlider.autoresizingMask = ({ - UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleLeftMargin | - UIViewAutoresizingFlexibleTopMargin | - UIViewAutoresizingFlexibleBottomMargin; - }); - break; - } - - break; - } - - // Denylist entries - case 1: { - cell.textLabel.text = self.hostDenylist[indexPath.row]; - break; - } - - default: - @throw NSInternalInconsistencyException; - break; - } - - return cell; -} - -#pragma mark - Table View Delegate - -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)ip { - // Can only select the "Reset Host Denylist" row - return ip.section == 0 && ip.row == 2; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Reset Host Denylist"); - make.message(@"You cannot undo this action. Are you sure?"); - make.button(@"Reset").destructiveStyle().handler(^(NSArray *strings) { - self.hostDenylist = nil; - [FLEXNetworkRecorder.defaultRecorder.hostDenylist removeAllObjects]; - [FLEXNetworkRecorder.defaultRecorder synchronizeDenylist]; - [self.tableView deleteSections: - [NSIndexSet indexSetWithIndex:1] - withRowAnimation:UITableViewRowAnimationAutomatic]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self]; -} - -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - return indexPath.section == 1; -} - -- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)style -forRowAtIndexPath:(NSIndexPath *)indexPath { - NSParameterAssert(style == UITableViewCellEditingStyleDelete); - - NSString *host = self.hostDenylist[indexPath.row]; - [self.hostDenylist removeObjectAtIndex:indexPath.row]; - [FLEXNetworkRecorder.defaultRecorder.hostDenylist removeObject:host]; - [FLEXNetworkRecorder.defaultRecorder synchronizeDenylist]; - - [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkTransaction.h b/Tweaks/FLEX/Network/FLEXNetworkTransaction.h deleted file mode 100644 index dcebe6a..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkTransaction.h +++ /dev/null @@ -1,178 +0,0 @@ -// -// FLEXNetworkTransaction.h -// Flipboard -// -// Created by Ryan Olson on 2/8/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import "Firestore.h" - -typedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) { - FLEXNetworkTransactionStateUnstarted = -1, - /// This is the default; it's usually nonsense for a request to be marked as "unstarted" - FLEXNetworkTransactionStateAwaitingResponse = 0, - FLEXNetworkTransactionStateReceivingData, - FLEXNetworkTransactionStateFinished, - FLEXNetworkTransactionStateFailed -}; - -typedef NS_ENUM(NSUInteger, FLEXWebsocketMessageDirection) { - FLEXWebsocketIncoming = 1, - FLEXWebsocketOutgoing, -}; - -/// The shared base class for all types of network transactions. -/// Subclasses should implement the descriptions and details properties, and assign a thumbnail. -@interface FLEXNetworkTransaction : NSObject { - @protected - - NSString *_primaryDescription; - NSString *_secondaryDescription; - NSString *_tertiaryDescription; -} - -+ (instancetype)withStartTime:(NSDate *)startTime; - -+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state; - -@property (nonatomic) NSError *error; -/// Subclasses can override to provide error state based on response data as well -@property (nonatomic, readonly) BOOL displayAsError; -@property (nonatomic, readonly) NSDate *startTime; - -@property (nonatomic) FLEXNetworkTransactionState state; -@property (nonatomic) int64_t receivedDataLength; -/// A small thumbnail to preview the type of/the response -@property (nonatomic) UIImage *thumbnail; - -/// The most prominent line of the cell. Typically a URL endpoint or other distinguishing attribute. -/// This line turns red when the transaction indicates an error. -@property (nonatomic, readonly) NSString *primaryDescription; -/// Something less important, such as a blob of data or the URL's domain. -@property (nonatomic, readonly) NSString *secondaryDescription; -/// Minor details to display at the bottom of the cell, such as a timestamp, HTTP method, or status. -@property (nonatomic, readonly) NSString *tertiaryDescription; - -/// The string to copy when the user selects the "copy" action -@property (nonatomic, readonly) NSString *copyString; - -/// Whether or not this request should show up when the user searches for a given string -- (BOOL)matchesQuery:(NSString *)filterString; - -/// For internal use -- (NSString *)timestampStringFromRequestDate:(NSDate *)date; - -@end - -/// The shared base class for all NSURL-API-related transactions. -/// Descriptions are generated by this class using the URL provided by subclasses. -@interface FLEXURLTransaction : FLEXNetworkTransaction - -+ (instancetype)withRequest:(NSURLRequest *)request startTime:(NSDate *)startTime; - -@property (nonatomic, readonly) NSURLRequest *request; -/// Subclasses should implement for when the transaction is complete -@property (nonatomic, readonly) NSArray *details; - -@end - - -@interface FLEXHTTPTransaction : FLEXURLTransaction - -+ (instancetype)request:(NSURLRequest *)request identifier:(NSString *)requestID; - -@property (nonatomic, readonly) NSString *requestID; -@property (nonatomic) NSURLResponse *response; -@property (nonatomic, copy) NSString *requestMechanism; - -@property (nonatomic) NSTimeInterval latency; -@property (nonatomic) NSTimeInterval duration; - -/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams. -@property (nonatomic, readonly) NSData *cachedRequestBody; - -@end - - -@interface FLEXWebsocketTransaction : FLEXURLTransaction - -+ (instancetype)withMessage:(NSURLSessionWebSocketMessage *)message - task:(NSURLSessionWebSocketTask *)task - direction:(FLEXWebsocketMessageDirection)direction API_AVAILABLE(ios(13.0)); - -+ (instancetype)withMessage:(NSURLSessionWebSocketMessage *)message - task:(NSURLSessionWebSocketTask *)task - direction:(FLEXWebsocketMessageDirection)direction - startTime:(NSDate *)started API_AVAILABLE(ios(13.0)); - -//@property (nonatomic, readonly) NSURLSessionWebSocketTask *task; -@property (nonatomic, readonly) NSURLSessionWebSocketMessage *message API_AVAILABLE(ios(13.0)); -@property (nonatomic, readonly) FLEXWebsocketMessageDirection direction API_AVAILABLE(ios(13.0)); - -@property (nonatomic, readonly) int64_t dataLength API_AVAILABLE(ios(13.0)); - -@end - - -typedef NS_ENUM(NSUInteger, FLEXFIRTransactionDirection) { - FLEXFIRTransactionDirectionNone, - FLEXFIRTransactionDirectionPush, - FLEXFIRTransactionDirectionPull, -}; - -typedef NS_ENUM(NSUInteger, FLEXFIRRequestType) { - FLEXFIRRequestTypeNotFirebase, - FLEXFIRRequestTypeFetchQuery, - FLEXFIRRequestTypeFetchDocument, - FLEXFIRRequestTypeSetData, - FLEXFIRRequestTypeUpdateData, - FLEXFIRRequestTypeAddDocument, - FLEXFIRRequestTypeDeleteDocument, -}; - -@interface FLEXFirebaseSetDataInfo : NSObject -/// The data that was set -@property (nonatomic, readonly) NSDictionary *documentData; -/// \c nil if \c mergeFields is populated -@property (nonatomic, readonly) NSNumber *merge; -/// \c nil if \c merge is populated -@property (nonatomic, readonly) NSArray *mergeFields; -@end - -@interface FLEXFirebaseTransaction : FLEXNetworkTransaction - -+ (instancetype)queryFetch:(FIRQuery *)initiator; -+ (instancetype)documentFetch:(FIRDocumentReference *)initiator; -+ (instancetype)setData:(FIRDocumentReference *)initiator - data:(NSDictionary *)data - merge:(NSNumber *)merge - mergeFields:(NSArray *)mergeFields; -+ (instancetype)updateData:(FIRDocumentReference *)initiator data:(NSDictionary *)data; -+ (instancetype)addDocument:(FIRCollectionReference *)initiator document:(FIRDocumentReference *)doc; -+ (instancetype)deleteDocument:(FIRDocumentReference *)initiator; - -@property (nonatomic, readonly) FLEXFIRTransactionDirection direction; -@property (nonatomic, readonly) FLEXFIRRequestType requestType; - -@property (nonatomic, readonly) id initiator; -@property (nonatomic, readonly) FIRQuery *initiator_query; -@property (nonatomic, readonly) FIRDocumentReference *initiator_doc; -@property (nonatomic, readonly) FIRCollectionReference *initiator_collection; - -/// Only used for fetch types -@property (nonatomic, copy) NSArray *documents; -/// Only used for the "set data" type -@property (nonatomic, readonly) FLEXFirebaseSetDataInfo *setDataInfo; -/// Only used for the "update data" type -@property (nonatomic, readonly) NSDictionary *updateData; -/// Only used for the "add document" type -@property (nonatomic, readonly) FIRDocumentReference *addedDocument; - -@property (nonatomic, readonly) NSString *path; - -//@property (nonatomic, readonly) NSString *responseString; -//@property (nonatomic, readonly) NSDictionary *responseObject; - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkTransaction.m b/Tweaks/FLEX/Network/FLEXNetworkTransaction.m deleted file mode 100644 index 4604880..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkTransaction.m +++ /dev/null @@ -1,295 +0,0 @@ -// -// FLEXNetworkTransaction.m -// Flipboard -// -// Created by Ryan Olson on 2/8/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXNetworkTransaction.h" -#import "FLEXResources.h" -#import "FLEXUtility.h" - -@implementation FLEXNetworkTransaction - -+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state { - NSString *readableString = nil; - switch (state) { - case FLEXNetworkTransactionStateUnstarted: - readableString = @"Unstarted"; - break; - - case FLEXNetworkTransactionStateAwaitingResponse: - readableString = @"Awaiting Response"; - break; - - case FLEXNetworkTransactionStateReceivingData: - readableString = @"Receiving Data"; - break; - - case FLEXNetworkTransactionStateFinished: - readableString = @"Finished"; - break; - - case FLEXNetworkTransactionStateFailed: - readableString = @"Failed"; - break; - } - return readableString; -} - -+ (instancetype)withStartTime:(NSDate *)startTime { - FLEXNetworkTransaction *transaction = [self new]; - transaction->_startTime = startTime; - return transaction; -} - -- (NSString *)timestampStringFromRequestDate:(NSDate *)date { - static NSDateFormatter *dateFormatter = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - dateFormatter = [NSDateFormatter new]; - dateFormatter.dateFormat = @"HH:mm:ss"; - }); - - return [dateFormatter stringFromDate:date]; -} - -- (void)setState:(FLEXNetworkTransactionState)transactionState { - _state = transactionState; - // Reset bottom description - _tertiaryDescription = nil; -} - -- (BOOL)displayAsError { - return _error != nil; -} - -- (NSString *)copyString { - return nil; -} - -- (BOOL)matchesQuery:(NSString *)filterString { - return NO; -} - -@end - - -@interface FLEXURLTransaction () - -@end - -@implementation FLEXURLTransaction - -+ (instancetype)withRequest:(NSURLRequest *)request startTime:(NSDate *)startTime { - FLEXURLTransaction *transaction = [self withStartTime:startTime]; - transaction->_request = request; - return transaction; -} - -- (NSString *)primaryDescription { - if (!_primaryDescription) { - NSString *name = self.request.URL.lastPathComponent; - if (!name.length) { - name = @"/"; - } - - if (_request.URL.query) { - name = [name stringByAppendingFormat:@"?%@", self.request.URL.query]; - } - - _primaryDescription = name; - } - - return _primaryDescription; -} - -- (NSString *)secondaryDescription { - if (!_secondaryDescription) { - NSMutableArray *mutablePathComponents = self.request.URL.pathComponents.mutableCopy; - if (mutablePathComponents.count > 0) { - [mutablePathComponents removeLastObject]; - } - - NSString *path = self.request.URL.host; - for (NSString *pathComponent in mutablePathComponents) { - path = [path stringByAppendingPathComponent:pathComponent]; - } - - _secondaryDescription = path; - } - - return _secondaryDescription; -} - -- (NSString *)tertiaryDescription { - if (!_tertiaryDescription) { - NSMutableArray *detailComponents = [NSMutableArray new]; - - NSString *timestamp = [self timestampStringFromRequestDate:self.startTime]; - if (timestamp.length > 0) { - [detailComponents addObject:timestamp]; - } - - // Omit method for GET (assumed as default) - NSString *httpMethod = self.request.HTTPMethod; - if (httpMethod.length > 0) { - [detailComponents addObject:httpMethod]; - } - - if (self.state == FLEXNetworkTransactionStateFinished || self.state == FLEXNetworkTransactionStateFailed) { - [detailComponents addObjectsFromArray:self.details]; - } else { - // Unstarted, Awaiting Response, Receiving Data, etc. - NSString *state = [self.class readableStringFromTransactionState:self.state]; - [detailComponents addObject:state]; - } - - _tertiaryDescription = [detailComponents componentsJoinedByString:@" ・ "]; - } - - return _tertiaryDescription; -} - -- (NSString *)copyString { - return self.request.URL.absoluteString; -} - -- (BOOL)matchesQuery:(NSString *)filterString { - return [self.request.URL.absoluteString localizedCaseInsensitiveContainsString:filterString]; -} - -@end - -@interface FLEXHTTPTransaction () -@property (nonatomic, readwrite) NSData *cachedRequestBody; -@end - -@implementation FLEXHTTPTransaction - -+ (instancetype)request:(NSURLRequest *)request identifier:(NSString *)requestID { - FLEXHTTPTransaction *httpt = [self withRequest:request startTime:NSDate.date]; - httpt->_requestID = requestID; - return httpt; -} - -- (NSString *)description { - NSString *description = [super description]; - - description = [description stringByAppendingFormat:@" id = %@;", self.requestID]; - description = [description stringByAppendingFormat:@" url = %@;", self.request.URL]; - description = [description stringByAppendingFormat:@" duration = %f;", self.duration]; - description = [description stringByAppendingFormat:@" receivedDataLength = %lld", self.receivedDataLength]; - - return description; -} - -- (NSData *)cachedRequestBody { - if (!_cachedRequestBody) { - if (self.request.HTTPBody != nil) { - _cachedRequestBody = self.request.HTTPBody; - } else if ([self.request.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) { - NSInputStream *bodyStream = [self.request.HTTPBodyStream copy]; - const NSUInteger bufferSize = 1024; - uint8_t buffer[bufferSize]; - NSMutableData *data = [NSMutableData new]; - [bodyStream open]; - NSInteger readBytes = 0; - do { - readBytes = [bodyStream read:buffer maxLength:bufferSize]; - [data appendBytes:buffer length:readBytes]; - } while (readBytes > 0); - [bodyStream close]; - _cachedRequestBody = data; - } - } - return _cachedRequestBody; -} - -- (NSArray *)detailString { - NSMutableArray *detailComponents = [NSMutableArray new]; - - NSString *statusCodeString = [FLEXUtility statusCodeStringFromURLResponse:self.response]; - if (statusCodeString.length > 0) { - [detailComponents addObject:statusCodeString]; - } - - if (self.receivedDataLength > 0) { - NSString *responseSize = [NSByteCountFormatter - stringFromByteCount:self.receivedDataLength - countStyle:NSByteCountFormatterCountStyleBinary - ]; - [detailComponents addObject:responseSize]; - } - - NSString *totalDuration = [FLEXUtility stringFromRequestDuration:self.duration]; - NSString *latency = [FLEXUtility stringFromRequestDuration:self.latency]; - NSString *duration = [NSString stringWithFormat:@"%@ (%@)", totalDuration, latency]; - [detailComponents addObject:duration]; - - return detailComponents; -} - -- (BOOL)displayAsError { - return [FLEXUtility isErrorStatusCodeFromURLResponse:self.response] || super.displayAsError; -} - -@end - - -@implementation FLEXWebsocketTransaction - -+ (instancetype)withMessage:(NSURLSessionWebSocketMessage *)message - task:(NSURLSessionWebSocketTask *)task - direction:(FLEXWebsocketMessageDirection)direction - startTime:(NSDate *)started { - FLEXWebsocketTransaction *wst = [self withRequest:task.originalRequest startTime:started]; - wst->_message = message; - wst->_direction = direction; - - // Populate receivedDataLength - if (direction == FLEXWebsocketIncoming) { - wst.receivedDataLength = wst.dataLength; - wst.state = FLEXNetworkTransactionStateFinished; - } - - // Populate thumbnail image - if (message.type == NSURLSessionWebSocketMessageTypeData) { - wst.thumbnail = FLEXResources.binaryIcon; - } else { - wst.thumbnail = FLEXResources.textIcon; - } - - return wst; -} - -+ (instancetype)withMessage:(NSURLSessionWebSocketMessage *)message - task:(NSURLSessionWebSocketTask *)task - direction:(FLEXWebsocketMessageDirection)direction { - return [self withMessage:message task:task direction:direction startTime:NSDate.date]; -} - -- (NSArray *)details API_AVAILABLE(ios(13.0)) { - return @[ - self.direction == FLEXWebsocketOutgoing ? @"SENT →" : @"→ RECEIVED", - [NSByteCountFormatter - stringFromByteCount:self.dataLength - countStyle:NSByteCountFormatterCountStyleBinary - ] - ]; -} - -- (int64_t)dataLength { - if (self.message) { - if (self.message.type == NSURLSessionWebSocketMessageTypeString) { - return self.message.string.length; - } - - return self.message.data.length; - } - - return 0; -} - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkTransactionCell.h b/Tweaks/FLEX/Network/FLEXNetworkTransactionCell.h deleted file mode 100644 index dc46237..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkTransactionCell.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FLEXNetworkTransactionCell.h -// Flipboard -// -// Created by Ryan Olson on 2/8/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@class FLEXNetworkTransaction; - -@interface FLEXNetworkTransactionCell : UITableViewCell - -@property (nonatomic) FLEXNetworkTransaction *transaction; - -@property (nonatomic, readonly, class) NSString *reuseID; -@property (nonatomic, readonly, class) CGFloat preferredCellHeight; - -@end diff --git a/Tweaks/FLEX/Network/FLEXNetworkTransactionCell.m b/Tweaks/FLEX/Network/FLEXNetworkTransactionCell.m deleted file mode 100644 index 8a0724d..0000000 --- a/Tweaks/FLEX/Network/FLEXNetworkTransactionCell.m +++ /dev/null @@ -1,116 +0,0 @@ -// -// FLEXNetworkTransactionCell.m -// Flipboard -// -// Created by Ryan Olson on 2/8/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXNetworkTransactionCell.h" -#import "FLEXNetworkTransaction.h" -#import "FLEXUtility.h" -#import "FLEXResources.h" - -NSString * const kFLEXNetworkTransactionCellIdentifier = @"kFLEXNetworkTransactionCellIdentifier"; - -@interface FLEXNetworkTransactionCell () - -@property (nonatomic) UIImageView *thumbnailImageView; -@property (nonatomic) UILabel *nameLabel; -@property (nonatomic) UILabel *pathLabel; -@property (nonatomic) UILabel *transactionDetailsLabel; - -@end - -@implementation FLEXNetworkTransactionCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - self.nameLabel = [UILabel new]; - self.nameLabel.font = UIFont.flex_defaultTableCellFont; - [self.contentView addSubview:self.nameLabel]; - - self.pathLabel = [UILabel new]; - self.pathLabel.font = UIFont.flex_defaultTableCellFont; - self.pathLabel.textColor = [UIColor colorWithWhite:0.4 alpha:1.0]; - self.pathLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - [self.contentView addSubview:self.pathLabel]; - - self.thumbnailImageView = [UIImageView new]; - self.thumbnailImageView.layer.borderColor = UIColor.blackColor.CGColor; - self.thumbnailImageView.layer.borderWidth = 1.0; - self.thumbnailImageView.contentMode = UIViewContentModeScaleAspectFit; - [self.contentView addSubview:self.thumbnailImageView]; - - self.transactionDetailsLabel = [UILabel new]; - self.transactionDetailsLabel.font = [UIFont systemFontOfSize:10.0]; - self.transactionDetailsLabel.textColor = [UIColor colorWithWhite:0.65 alpha:1.0]; - [self.contentView addSubview:self.transactionDetailsLabel]; - } - return self; -} - -- (void)setTransaction:(FLEXNetworkTransaction *)transaction { - if (_transaction != transaction) { - _transaction = transaction; - [self setNeedsLayout]; - } -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - const CGFloat kVerticalPadding = 8.0; - const CGFloat kLeftPadding = 10.0; - const CGFloat kImageDimension = 32.0; - - CGFloat thumbnailOriginY = round((self.contentView.bounds.size.height - kImageDimension) / 2.0); - self.thumbnailImageView.frame = CGRectMake(kLeftPadding, thumbnailOriginY, kImageDimension, kImageDimension); - self.thumbnailImageView.image = self.transaction.thumbnail; - - CGFloat textOriginX = CGRectGetMaxX(self.thumbnailImageView.frame) + kLeftPadding; - CGFloat availableTextWidth = self.contentView.bounds.size.width - textOriginX; - - self.nameLabel.text = [self nameLabelText]; - CGSize nameLabelPreferredSize = [self.nameLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)]; - self.nameLabel.frame = CGRectMake(textOriginX, kVerticalPadding, availableTextWidth, nameLabelPreferredSize.height); - self.nameLabel.textColor = self.transaction.displayAsError ? UIColor.redColor : FLEXColor.primaryTextColor; - - self.pathLabel.text = [self pathLabelText]; - CGSize pathLabelPreferredSize = [self.pathLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)]; - CGFloat pathLabelOriginY = ceil((self.contentView.bounds.size.height - pathLabelPreferredSize.height) / 2.0); - self.pathLabel.frame = CGRectMake(textOriginX, pathLabelOriginY, availableTextWidth, pathLabelPreferredSize.height); - - self.transactionDetailsLabel.text = [self transactionDetailsLabelText]; - CGSize transactionLabelPreferredSize = [self.transactionDetailsLabel sizeThatFits:CGSizeMake(availableTextWidth, CGFLOAT_MAX)]; - CGFloat transactionDetailsOriginX = textOriginX; - CGFloat transactionDetailsLabelOriginY = CGRectGetMaxY(self.contentView.bounds) - kVerticalPadding - transactionLabelPreferredSize.height; - CGFloat transactionDetailsLabelWidth = self.contentView.bounds.size.width - transactionDetailsOriginX; - self.transactionDetailsLabel.frame = CGRectMake(transactionDetailsOriginX, transactionDetailsLabelOriginY, transactionDetailsLabelWidth, transactionLabelPreferredSize.height); -} - -- (NSString *)nameLabelText { - return self.transaction.primaryDescription; -} - -- (NSString *)pathLabelText { - return self.transaction.secondaryDescription; -} - -- (NSString *)transactionDetailsLabelText { - return self.transaction.tertiaryDescription; -} - -+ (CGFloat)preferredCellHeight { - return 65.0; -} - -+ (NSString *)reuseID { - return kFLEXNetworkTransactionCellIdentifier; -} - -@end diff --git a/Tweaks/FLEX/Network/Firestore.h b/Tweaks/FLEX/Network/Firestore.h deleted file mode 100644 index 0377757..0000000 --- a/Tweaks/FLEX/Network/Firestore.h +++ /dev/null @@ -1,190 +0,0 @@ -// -// Firestore.h -// Pods -// -// Created by Tanner Bennett on 10/13/21. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - Forward Declarations - -@class FIRQuery; -@class FIRQuerySnapshot; -@class FIRDocumentReference; -@class FIRDocumentSnapshot; -@class FIRQueryDocumentSnapshot; -@class FIRCollectionReference; -@class FIRFirestore; -@protocol FIRListenerRegistration; - -#define cFIRQuery objc_getClass("FIRQuery") -#define cFIRCollectionReference objc_getClass("FIRCollectionReference") -#define cFIRDocumentReference objc_getClass("FIRDocumentReference") - -typedef void (^FIRDocumentSnapshotBlock)(FIRDocumentSnapshot *_Nullable snapshot, - NSError *_Nullable error); -typedef void (^FIRQuerySnapshotBlock)(FIRQuerySnapshot *_Nullable snapshot, - NSError *_Nullable error); - -typedef NS_ENUM(NSUInteger, FIRFirestoreSource) { - FIRFirestoreSourceDefault, - FIRFirestoreSourceServer, - FIRFirestoreSourceCache -} NS_SWIFT_NAME(FirestoreSource); - -#pragma mark - Query -@interface FIRQuery : NSObject - -- (id)init __attribute__((unavailable())); - -@property(nonatomic, readonly) FIRFirestore *firestore; -@property(nonatomic, readonly) void *query; - -- (void)getDocumentsWithCompletion:(FIRQuerySnapshotBlock)completion - NS_SWIFT_NAME(getDocuments(completion:)); -- (void)getDocumentsWithSource:(FIRFirestoreSource)source - completion:(FIRQuerySnapshotBlock)completion - NS_SWIFT_NAME(getDocuments(source:completion:)); - -@end - - -typedef void (^FIRDocumentSnapshotBlock)(FIRDocumentSnapshot *_Nullable snapshot, - NSError *_Nullable error); - -#pragma mark - DocumentReference -NS_SWIFT_NAME(DocumentReference) -@interface FIRDocumentReference : NSObject - -- (instancetype)init __attribute__((unavailable)); - -@property(nonatomic, readonly) NSString *documentID; -@property(nonatomic, readonly) FIRCollectionReference *parent; -@property(nonatomic, readonly) FIRFirestore *firestore; -@property(nonatomic, readonly) NSString *path; - -- (FIRCollectionReference *)collectionWithPath:(NSString *)collectionPath - NS_SWIFT_NAME(collection(_:)); - -#pragma mark Writing Data - -- (void)setData:(NSDictionary *)documentData; -- (void)setData:(NSDictionary *)documentData merge:(BOOL)merge; -- (void)setData:(NSDictionary *)documentData mergeFields:(NSArray *)mergeFields; -- (void)setData:(NSDictionary *)documentData - completion:(nullable void (^)(NSError *_Nullable error))completion; -- (void)setData:(NSDictionary *)documentData - merge:(BOOL)merge - completion:(nullable void (^)(NSError *_Nullable error))completion; -- (void)setData:(NSDictionary *)documentData - mergeFields:(NSArray *)mergeFields - completion:(nullable void (^)(NSError *_Nullable error))completion; - -- (void)updateData:(NSDictionary *)fields; -- (void)updateData:(NSDictionary *)fields - completion:(nullable void (^)(NSError *_Nullable error))completion; - -- (void)deleteDocument NS_SWIFT_NAME(delete()); -- (void)deleteDocumentWithCompletion:(nullable void (^)(NSError *_Nullable error))completion - NS_SWIFT_NAME(delete(completion:)); - -#pragma mark Retrieving Data - -- (void)getDocumentWithCompletion:(FIRDocumentSnapshotBlock)completion - NS_SWIFT_NAME(getDocument(completion:)); -- (void)getDocumentWithSource:(FIRFirestoreSource)source - completion:(FIRDocumentSnapshotBlock)completion - NS_SWIFT_NAME(getDocument(source:completion:)); - -- (id)addSnapshotListener:(FIRDocumentSnapshotBlock)listener - NS_SWIFT_NAME(addSnapshotListener(_:)); -- (id)addSnapshotListenerWithIncludeMetadataChanges:(BOOL)includeMetadataChanges - listener:(FIRDocumentSnapshotBlock)listener - NS_SWIFT_NAME(addSnapshotListener(includeMetadataChanges:listener:)); - -@end - - -#pragma mark - CollectionReference -NS_SWIFT_NAME(CollectionReference) -@interface FIRCollectionReference : FIRQuery - -- (id)init __attribute__((unavailable())); - -@property(nonatomic, readonly) NSString *collectionID; -@property(nonatomic, nullable, readonly) FIRDocumentReference *parent; -@property(nonatomic, readonly) NSString *path; - -- (FIRDocumentReference *)documentWithAutoID NS_SWIFT_NAME(document()); -- (FIRDocumentReference *)documentWithPath:(NSString *)documentPath NS_SWIFT_NAME(document(_:)); -- (FIRDocumentReference *)addDocumentWithData:(NSDictionary *)data - NS_SWIFT_NAME(addDocument(data:)); -- (FIRDocumentReference *)addDocumentWithData:(NSDictionary *)data - completion:(nullable void (^)(NSError *_Nullable error))completion - NS_SWIFT_NAME(addDocument(data:completion:)); -@end - -#pragma mark - QuerySnapshot -NS_SWIFT_NAME(QuerySnapshot) -@interface FIRQuerySnapshot : NSObject - -- (id)init __attribute__((unavailable())); - -@property(nonatomic, readonly) FIRQuery *query; -@property(nonatomic, readonly, getter=isEmpty) BOOL empty; -@property(nonatomic, readonly) NSInteger count; -@property(nonatomic, readonly) NSArray *documents; - -@end - -#pragma mark - DocumentSnapshot -NS_SWIFT_NAME(DocumentSnapshot) -@interface FIRDocumentSnapshot : NSObject - -- (instancetype)init __attribute__((unavailable())); - -@property(nonatomic, readonly) BOOL exists; -@property(nonatomic, readonly) FIRDocumentReference *reference; -@property(nonatomic, copy, readonly) NSString *documentID; - -@property(nonatomic, readonly, nullable) NSDictionary *data; - -- (nullable id)valueForField:(id)field NS_SWIFT_NAME(get(_:)); -- (nullable id)objectForKeyedSubscript:(id)key; - -@end - -#pragma mark - QueryDocumentSnapshot -NS_SWIFT_NAME(QueryDocumentSnapshot) -@interface FIRQueryDocumentSnapshot : FIRDocumentSnapshot - -- (instancetype)init __attribute__((unavailable())); - -@property(nonatomic, readonly) NSDictionary *data; - -@end - -NS_ASSUME_NONNULL_END - - -#if defined(__clang__) -#if __has_feature(objc_arc) -#define _LOGOS_SELF_TYPE_NORMAL __unsafe_unretained -#define _LOGOS_SELF_TYPE_INIT __attribute__((ns_consumed)) -#define _LOGOS_SELF_CONST const -#define _LOGOS_RETURN_RETAINED __attribute__((ns_returns_retained)) -#else -#define _LOGOS_SELF_TYPE_NORMAL -#define _LOGOS_SELF_TYPE_INIT -#define _LOGOS_SELF_CONST -#define _LOGOS_RETURN_RETAINED -#endif -#else -#define _LOGOS_SELF_TYPE_NORMAL -#define _LOGOS_SELF_TYPE_INIT -#define _LOGOS_SELF_CONST -#define _LOGOS_RETURN_RETAINED -#endif diff --git a/Tweaks/FLEX/Network/OSCache/LICENSE.md b/Tweaks/FLEX/Network/OSCache/LICENSE.md deleted file mode 100644 index f1b63c7..0000000 --- a/Tweaks/FLEX/Network/OSCache/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -OSCache -version 1.2.1, Decembet 18th, 2015 - -Copyright (C) 2014 Charcoal Design - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/Tweaks/FLEX/Network/OSCache/OSCache.h b/Tweaks/FLEX/Network/OSCache/OSCache.h deleted file mode 100644 index bdb277d..0000000 --- a/Tweaks/FLEX/Network/OSCache/OSCache.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// OSCache.h -// -// Version 1.2.1 -// -// Created by Nick Lockwood on 01/01/2014. -// Copyright (C) 2014 Charcoal Design -// -// Distributed under the permissive zlib License -// Get the latest version from here: -// -// https://github.com/nicklockwood/OSCache -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface OSCache : NSCache - -@property (nonatomic, readonly) NSUInteger count; -@property (nonatomic, readonly) NSUInteger totalCost; - -- (id)objectForKeyedSubscript:(KeyType )key; -- (void)setObject:(ObjectType)obj forKeyedSubscript:(KeyType )key; -- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(KeyType key, ObjectType obj, BOOL *stop))block; - -@end - - -@protocol OSCacheDelegate -@optional - -- (BOOL)cache:(OSCache *)cache shouldEvictObject:(id)entry; -- (void)cache:(OSCache *)cache willEvictObject:(id)entry; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Network/OSCache/OSCache.m b/Tweaks/FLEX/Network/OSCache/OSCache.m deleted file mode 100644 index 28e76ce..0000000 --- a/Tweaks/FLEX/Network/OSCache/OSCache.m +++ /dev/null @@ -1,409 +0,0 @@ -// -// OSCache.m -// -// Version 1.2.1 -// -// Created by Nick Lockwood on 01/01/2014. -// Copyright (C) 2014 Charcoal Design -// -// Distributed under the permissive zlib License -// Get the latest version from here: -// -// https://github.com/nicklockwood/OSCache -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// - -#import "OSCache.h" -#import -#if TARGET_OS_IPHONE -#import -#endif - - -#import -#if !__has_feature(objc_arc) -#error This class requires automatic reference counting -#endif - - -#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis" -#pragma GCC diagnostic ignored "-Wdirect-ivar-access" -#pragma GCC diagnostic ignored "-Wgnu" - - -@interface OSCacheEntry : NSObject - -@property (nonatomic, strong) NSObject *object; -@property (nonatomic, assign) NSUInteger cost; -@property (nonatomic, assign) NSInteger sequenceNumber; - -@end - - -@implementation OSCacheEntry - -@end - - -@interface OSCache_Private : NSObject - -@property (nonatomic, unsafe_unretained) id delegate; -@property (nonatomic, assign) NSUInteger countLimit; -@property (nonatomic, assign) NSUInteger totalCostLimit; -@property (nonatomic, copy) NSString *name; - -@property (nonatomic, strong) NSMutableDictionary *cache; -@property (nonatomic, assign) NSUInteger totalCost; -@property (nonatomic, assign) NSInteger sequenceNumber; - -@end - - -@implementation OSCache_Private -{ - BOOL _delegateRespondsToWillEvictObject; - BOOL _delegateRespondsToShouldEvictObject; - BOOL _currentlyCleaning; - NSMutableArray *_entryPool; - NSLock *_lock; -} - -- (instancetype)init -{ - if ((self = [super init])) - { - //create storage - _cache = [[NSMutableDictionary alloc] init]; - _entryPool = [[NSMutableArray alloc] init]; - _lock = [[NSLock alloc] init]; - _totalCost = 0; - -#if TARGET_OS_IPHONE - - //clean up in the event of a memory warning - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cleanUpAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - -#endif - - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)setDelegate:(id)delegate -{ - _delegate = delegate; - _delegateRespondsToShouldEvictObject = [delegate respondsToSelector:@selector(cache:shouldEvictObject:)]; - _delegateRespondsToWillEvictObject = [delegate respondsToSelector:@selector(cache:willEvictObject:)]; -} - -- (void)setCountLimit:(NSUInteger)countLimit -{ - [_lock lock]; - _countLimit = countLimit; - [_lock unlock]; - [self cleanUp:NO]; -} - -- (void)setTotalCostLimit:(NSUInteger)totalCostLimit -{ - [_lock lock]; - _totalCostLimit = totalCostLimit; - [_lock unlock]; - [self cleanUp:NO]; -} - -- (NSUInteger)count -{ - return [_cache count]; -} - -- (void)cleanUp:(BOOL)keepEntries -{ - [_lock lock]; - NSUInteger maxCount = _countLimit ?: INT_MAX; - NSUInteger maxCost = _totalCostLimit ?: INT_MAX; - NSUInteger totalCount = _cache.count; - NSMutableArray *keys = [_cache.allKeys mutableCopy]; - while (totalCount > maxCount || _totalCost > maxCost) - { - NSInteger lowestSequenceNumber = INT_MAX; - OSCacheEntry *lowestEntry = nil; - id lowestKey = nil; - - //remove oldest items until within limit - for (id key in keys) - { - OSCacheEntry *entry = _cache[key]; - if (entry.sequenceNumber < lowestSequenceNumber) - { - lowestSequenceNumber = entry.sequenceNumber; - lowestEntry = entry; - lowestKey = key; - } - } - - if (lowestKey) - { - [keys removeObject:lowestKey]; - if (!_delegateRespondsToShouldEvictObject || - [_delegate cache:(OSCache *)self shouldEvictObject:lowestEntry.object]) - { - if (_delegateRespondsToWillEvictObject) - { - _currentlyCleaning = YES; - [self.delegate cache:(OSCache *)self willEvictObject:lowestEntry.object]; - _currentlyCleaning = NO; - } - [_cache removeObjectForKey:lowestKey]; - _totalCost -= lowestEntry.cost; - totalCount --; - if (keepEntries) - { - [_entryPool addObject:lowestEntry]; - lowestEntry.object = nil; - } - } - } - } - [_lock unlock]; -} - -- (void)cleanUpAllObjects -{ - [_lock lock]; - if (_delegateRespondsToShouldEvictObject || _delegateRespondsToWillEvictObject) - { - NSArray *keys = [_cache allKeys]; - if (_delegateRespondsToShouldEvictObject) - { - //sort, oldest first (in case we want to use that information in our eviction test) - keys = [keys sortedArrayUsingComparator:^NSComparisonResult(id key1, id key2) { - OSCacheEntry *entry1 = self->_cache[key1]; - OSCacheEntry *entry2 = self->_cache[key2]; - return (NSComparisonResult)MIN(1, MAX(-1, entry1.sequenceNumber - entry2.sequenceNumber)); - }]; - } - - //remove all items individually - for (id key in keys) - { - OSCacheEntry *entry = _cache[key]; - if (!_delegateRespondsToShouldEvictObject || [_delegate cache:(OSCache *)self shouldEvictObject:entry.object]) - { - if (_delegateRespondsToWillEvictObject) - { - _currentlyCleaning = YES; - [_delegate cache:(OSCache *)self willEvictObject:entry.object]; - _currentlyCleaning = NO; - } - [_cache removeObjectForKey:key]; - _totalCost -= entry.cost; - } - } - } - else - { - _totalCost = 0; - [_cache removeAllObjects]; - _sequenceNumber = 0; - } - [_lock unlock]; -} - -- (void)resequence -{ - //sort, oldest first - NSArray *entries = [[_cache allValues] sortedArrayUsingComparator:^NSComparisonResult(OSCacheEntry *entry1, OSCacheEntry *entry2) { - return (NSComparisonResult)MIN(1, MAX(-1, entry1.sequenceNumber - entry2.sequenceNumber)); - }]; - - //renumber items - NSInteger index = 0; - for (OSCacheEntry *entry in entries) - { - entry.sequenceNumber = index++; - } -} - -- (id)objectForKey:(id)key -{ - [_lock lock]; - OSCacheEntry *entry = _cache[key]; - entry.sequenceNumber = _sequenceNumber++; - if (_sequenceNumber < 0) - { - [self resequence]; - } - id object = entry.object; - [_lock unlock]; - return object; -} - -- (id)objectForKeyedSubscript:(id)key -{ - return [self objectForKey:key]; -} - -- (void)setObject:(id)obj forKey:(id)key -{ - [self setObject:obj forKey:key cost:0]; -} - -- (void)setObject:(id)obj forKeyedSubscript:(id)key -{ - [self setObject:obj forKey:key cost:0]; -} - -- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g -{ - if (!obj) - { - [self removeObjectForKey:key]; - return; - } - NSAssert(!_currentlyCleaning, @"It is not possible to modify cache from within the implementation of this delegate method."); - [_lock lock]; - _totalCost -= [_cache[key] cost]; - _totalCost += g; - OSCacheEntry *entry = _cache[key]; - if (!entry) { - entry = [[OSCacheEntry alloc] init]; - _cache[key] = entry; - } - entry.object = obj; - entry.cost = g; - entry.sequenceNumber = _sequenceNumber++; - if (_sequenceNumber < 0) - { - [self resequence]; - } - [_lock unlock]; - [self cleanUp:YES]; -} - -- (void)removeObjectForKey:(id)key -{ - NSAssert(!_currentlyCleaning, @"It is not possible to modify cache from within the implementation of this delegate method."); - [_lock lock]; - OSCacheEntry *entry = _cache[key]; - if (entry) { - _totalCost -= entry.cost; - entry.object = nil; - [_entryPool addObject:entry]; - [_cache removeObjectForKey:key]; - } - [_lock unlock]; -} - -- (void)removeAllObjects -{ - NSAssert(!_currentlyCleaning, @"It is not possible to modify cache from within the implementation of this delegate method."); - [_lock lock]; - _totalCost = 0; - _sequenceNumber = 0; - for (OSCacheEntry *entry in _cache.allValues) - { - entry.object = nil; - [_entryPool addObject:entry]; - } - [_cache removeAllObjects]; - [_lock unlock]; -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(id __unsafe_unretained [])buffer - count:(NSUInteger)len -{ - [_lock lock]; - NSUInteger count = [_cache countByEnumeratingWithState:state objects:buffer count:len]; - [_lock unlock]; - return count; -} - -- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block -{ - if (block) - { - [_lock lock]; - [_cache enumerateKeysAndObjectsUsingBlock:^(id key, OSCacheEntry *entry, BOOL *stop) { - block(key, entry.object, stop); - }]; - [_lock unlock]; - } -} - -//handle unimplemented methods - -- (BOOL)isKindOfClass:(Class)aClass -{ - //pretend that we're an NSCache if anyone asks - if (aClass == [OSCache class] || aClass == [NSCache class]) - { - return YES; - } - return [super isKindOfClass:aClass]; -} - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector -{ - //protect against calls to unimplemented NSCache methods - NSMethodSignature *signature = [super methodSignatureForSelector:selector]; - if (!signature) - { - signature = [NSCache instanceMethodSignatureForSelector:selector]; - } - return signature; -} - -- (void)forwardInvocation:(NSInvocation *)invocation -{ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnonnull" - - [invocation invokeWithTarget:nil]; - -#pragma clang diagnostic pop - -} - -@end - - -@implementation OSCache - -+ (instancetype)allocWithZone:(struct _NSZone *)zone -{ - return (OSCache *)[OSCache_Private allocWithZone:zone]; -} - -- (id)objectForKeyedSubscript:(__unused id)key { return nil; } -- (void)setObject:(__unused id)obj forKeyedSubscript:(__unused id)key {} -- (void)enumerateKeysAndObjectsUsingBlock:(__unused void (^)(id, id, BOOL *))block { } -- (NSUInteger)countByEnumeratingWithState:(__unused NSFastEnumerationState *)state - objects:(__unused __unsafe_unretained id [])buffer - count:(__unused NSUInteger)len { return 0; } - -@end diff --git a/Tweaks/FLEX/Network/PonyDebugger/FLEXNetworkObserver.h b/Tweaks/FLEX/Network/PonyDebugger/FLEXNetworkObserver.h deleted file mode 100644 index 6169bd2..0000000 --- a/Tweaks/FLEX/Network/PonyDebugger/FLEXNetworkObserver.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// FLEXNetworkObserver.h -// Derived from: -// -// PDAFNetworkDomainController.h -// PonyDebugger -// -// Created by Mike Lewis on 2/27/12. -// -// Licensed to Square, Inc. under one or more contributor license agreements. -// See the LICENSE file distributed with this work for the terms under -// which Square, Inc. licenses this file to you. -// - -#import - -FOUNDATION_EXTERN NSString *const kFLEXNetworkObserverEnabledStateChangedNotification; - -/// This class swizzles NSURLConnection and NSURLSession delegate methods to observe events in the URL loading system. -/// High level network events are sent to the default FLEXNetworkRecorder instance which maintains the request history and caches response bodies. -@interface FLEXNetworkObserver : NSObject - -/// Swizzling occurs when the observer is enabled for the first time. -/// This reduces the impact of FLEX if network debugging is not desired. -/// NOTE: this setting persists between launches of the app. -@property (nonatomic, class, getter=isEnabled) BOOL enabled; - -@end diff --git a/Tweaks/FLEX/Network/PonyDebugger/FLEXNetworkObserver.m b/Tweaks/FLEX/Network/PonyDebugger/FLEXNetworkObserver.m deleted file mode 100644 index 5245e82..0000000 --- a/Tweaks/FLEX/Network/PonyDebugger/FLEXNetworkObserver.m +++ /dev/null @@ -1,1997 +0,0 @@ -// -// FLEXNetworkObserver.m -// Derived from: -// -// PDAFNetworkDomainController.m -// PonyDebugger -// -// Created by Mike Lewis on 2/27/12. -// -// Licensed to Square, Inc. under one or more contributor license agreements. -// See the LICENSE file distributed with this work for the terms under -// which Square, Inc. licenses this file to you. -// -// Heavily modified and added to by Tanner Bennett and various other contributors. -// git blame details these modifications. -// - -#import "FLEXNetworkObserver.h" -#import "FLEXNetworkRecorder.h" -#import "FLEXUtility.h" -#import "NSUserDefaults+FLEX.h" -#import "NSObject+FLEX_Reflection.h" -#import "FLEXMethod.h" -#import "Firestore.h" - -#import -#import -#import -#include - -NSString *const kFLEXNetworkObserverEnabledStateChangedNotification = @"kFLEXNetworkObserverEnabledStateChangedNotification"; - -typedef void (^NSURLSessionAsyncCompletion)(id fileURLOrData, NSURLResponse *response, NSError *error); -typedef NSURLSessionTask * (^NSURLSessionNewTaskMethod)(NSURLSession *, id, NSURLSessionAsyncCompletion); - -@interface FLEXInternalRequestState : NSObject - -@property (nonatomic, copy) NSURLRequest *request; -@property (nonatomic) NSMutableData *dataAccumulator; - -@end - -@implementation FLEXInternalRequestState - -@end - -@interface FLEXNetworkObserver (NSURLConnectionHelpers) - -- (void)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response delegate:(id)delegate; -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response delegate:(id)delegate; - -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data delegate:(id)delegate; - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection delegate:(id)delegate; -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error delegate:(id)delegate; - -- (void)connectionWillCancel:(NSURLConnection *)connection; - -@end - - -@interface FLEXNetworkObserver (NSURLSessionTaskHelpers) - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler delegate:(id)delegate; -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler delegate:(id)delegate; -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data delegate:(id)delegate; -- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask -didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id)delegate; -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error delegate:(id)delegate; -- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite delegate:(id)delegate; -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location data:(NSData *)data delegate:(id)delegate; - -- (void)URLSessionTaskWillResume:(NSURLSessionTask *)task; - -- (void)websocketTask:(NSURLSessionWebSocketTask *)task - sendMessagage:(NSURLSessionWebSocketMessage *)message API_AVAILABLE(ios(13.0)); -- (void)websocketTaskMessageSendCompletion:(NSURLSessionWebSocketMessage *)message - error:(NSError *)error API_AVAILABLE(ios(13.0)); - -- (void)websocketTask:(NSURLSessionWebSocketTask *)task - receiveMessagage:(NSURLSessionWebSocketMessage *)message - error:(NSError *)error API_AVAILABLE(ios(13.0)); - -@end - -@interface FLEXNetworkObserver () - -@property (nonatomic) NSMutableDictionary *requestStatesForRequestIDs; -@property (nonatomic) dispatch_queue_t queue; - -@end - -@implementation FLEXNetworkObserver - -#pragma mark - Public Methods - -+ (void)setEnabled:(BOOL)enabled { - BOOL previouslyEnabled = [self isEnabled]; - - NSUserDefaults.standardUserDefaults.flex_networkObserverEnabled = enabled; - - if (enabled) { - // Inject if needed. This injection is protected with a dispatch_once, so we're ok calling it multiple times. - // By doing the injection lazily, we keep the impact of the tool lower when this feature isn't enabled. - [self setNetworkMonitorHooks]; - } - - if (previouslyEnabled != enabled) { - [NSNotificationCenter.defaultCenter postNotificationName:kFLEXNetworkObserverEnabledStateChangedNotification object:self]; - } -} - -+ (BOOL)isEnabled { - return NSUserDefaults.standardUserDefaults.flex_networkObserverEnabled; -} - -+ (void)load { - // We don't want to do the swizzling from +load because not all the - // delegate classes we want to hook may be loaded at this point. - // However, Firebase classes will definitely be loaded by now, - // so we can definitely hook those sooner if need be. - dispatch_async(dispatch_get_main_queue(), ^{ - if ([self isEnabled]) { - [self setNetworkMonitorHooks]; - } - }); -} - -#pragma mark - Statics - -+ (instancetype)sharedObserver { - static FLEXNetworkObserver *sharedObserver = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedObserver = [self new]; - }); - return sharedObserver; -} - -+ (NSString *)nextRequestID { - return NSUUID.UUID.UUIDString; -} - -#pragma mark Delegate Injection Convenience Methods - -/// All swizzled delegate methods should make use of this guard. -/// This will prevent duplicated sniffing when the original implementation calls up to a superclass -/// implementation which we've also swizzled. The superclass implementation (and implementations in -/// classes above that) will be executed without interference if called from the original implementation. -+ (void)sniffWithoutDuplicationForObject:(NSObject *)object selector:(SEL)selector - sniffingBlock:(void (^)(void))sniffingBlock originalImplementationBlock:(void (^)(void))originalImplementationBlock { - // If we don't have an object to detect nested calls on, just run the original implementation and bail. - // This case can happen if someone besides the URL loading system calls the delegate methods directly. - // See https://github.com/Flipboard/FLEX/issues/61 for an example. - if (!object) { - originalImplementationBlock(); - return; - } - - const void *key = selector; - - // Don't run the sniffing block if we're inside a nested call - if (!objc_getAssociatedObject(object, key)) { - sniffingBlock(); - } - - // Mark that we're calling through to the original so we can detect nested calls - objc_setAssociatedObject(object, key, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - originalImplementationBlock(); - objc_setAssociatedObject(object, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -#pragma mark - Hooking - -static void (*_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$)( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, FIRDocumentSnapshotBlock); -static void _logos_method$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, FIRDocumentSnapshotBlock); -static void (*_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$)( - _LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST, SEL, FIRQuerySnapshotBlock); -static void _logos_method$_ungrouped$FIRQuery$getDocumentsWithCompletion$( - _LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST, SEL, FIRQuerySnapshotBlock); - -static void (*_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$)( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, BOOL, void (^)(NSError *)); -static void (*_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$)( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, NSArray *, void (^)(NSError *)); -static void (*_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$)( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, void (^)(NSError *)); -static void (*_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$)( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, void (^)(NSError *)); - -static void _logos_register_hook(Class _class, SEL _cmd, IMP _new, IMP *_old) { - unsigned int _count, _i; - Class _searchedClass = _class; - Method *_methods; - while (_searchedClass) { - _methods = class_copyMethodList(_searchedClass, &_count); - for (_i = 0; _i < _count; _i++) { - if (method_getName(_methods[_i]) == _cmd) { - if (_class == _searchedClass) { - *_old = method_getImplementation(_methods[_i]); - *_old = class_replaceMethod(_class, _cmd, _new, method_getTypeEncoding(_methods[_i])); - } else { - class_addMethod(_class, _cmd, _new, method_getTypeEncoding(_methods[_i])); - } - free(_methods); - return; - } - } - free(_methods); - _searchedClass = class_getSuperclass(_searchedClass); - } -} - -static Class _logos_superclass$_ungrouped$FIRDocumentReference; -static void (*_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$)( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, FIRDocumentSnapshotBlock); -static Class _logos_superclass$_ungrouped$FIRQuery; -static void (*_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$)( - _LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST, SEL, FIRQuerySnapshotBlock); -static Class _logos_superclass$_ungrouped$FIRCollectionReference; -static FIRDocumentReference * (*_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$)( - _LOGOS_SELF_TYPE_NORMAL FIRCollectionReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, void (^)(NSError *error)); - -#pragma mark Firebase, Reading Data - -static void _logos_method$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST self, SEL _cmd, FIRDocumentSnapshotBlock completion) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder recordFIRDocumentWillFetch:self withTransactionID:requestID]; - // Hook callback - FIRDocumentSnapshotBlock orig = completion; - completion = ^(FIRDocumentSnapshot *document, NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRDocumentDidFetch:document error:error transactionID:requestID]; - orig(document, error); - }; - - // Forward invocation - (_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$ ? _logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(getDocumentWithCompletion:)))(self, _cmd, completion); -} - -static void _logos_method$_ungrouped$FIRQuery$getDocumentsWithCompletion$( - _LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST self, SEL _cmd, FIRQuerySnapshotBlock completion) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder recordFIRQueryWillFetch:self withTransactionID:requestID]; - // Hook callback - FIRQuerySnapshotBlock orig = completion; - completion = ^(FIRQuerySnapshot *query, NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRQueryDidFetch:query error:error transactionID:requestID]; - orig(query, error); - }; - - // Forward invocation - (_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$ ? _logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$ : (__typeof__(_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRQuery, @selector(getDocumentsWithCompletion:)))(self, _cmd, completion); -} - -#pragma mark Firebase, Writing Data - -static void _logos_method$_ungrouped$FIRDocumentReference$setData$merge$completion$( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self, - SEL __unused _cmd, NSDictionary * documentData, BOOL merge, void (^completion)(NSError *)) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder - recordFIRWillSetData:self - data:documentData - merge:@(merge) - mergeFields:nil - transactionID:requestID - ]; - - // Hook callback - void (^orig)(NSError *) = completion; - completion = ^(NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRDidSetData:error transactionID:requestID]; - orig(error); - }; - - // Forward invocation - (_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$ ? _logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(setData:merge:completion:)))(self, _cmd, documentData, merge, completion); -} - -static void _logos_method$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self, - SEL __unused _cmd, NSDictionary * documentData, - NSArray * mergeFields, void (^completion)(NSError *)) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder - recordFIRWillSetData:self - data:documentData - merge:nil - mergeFields:mergeFields - transactionID:requestID - ]; - - // Hook callback - void (^orig)(NSError *) = completion; - completion = ^(NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRDidSetData:error transactionID:requestID]; - orig(error); - }; - - // Forward invocation - (_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$ ? _logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(setData:mergeFields:completion:)))(self, _cmd, documentData, mergeFields, completion); -} - -static void _logos_method$_ungrouped$FIRDocumentReference$updateData$completion$( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self, - SEL __unused _cmd, NSDictionary * fields, void (^completion)(NSError *)) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder recordFIRWillUpdateData:self fields:fields transactionID:requestID]; - // Hook callback - void (^orig)(NSError *) = completion; - completion = ^(NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRDidUpdateData:error transactionID:requestID]; - orig(error); - }; - - // Forward invocation - (_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$ ? _logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(updateData:completion:)))(self, _cmd, fields, completion); -} - -static void _logos_method$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$( - _LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self, - SEL __unused _cmd, void (^completion)(NSError *)) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder recordFIRWillDeleteDocument:self transactionID:requestID]; - // Hook callback - void (^orig)(NSError *) = completion; - completion = ^(NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRDidDeleteDocument:error transactionID:requestID]; - orig(error); - }; - - // Forward invocation - (_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$ ? _logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(deleteDocumentWithCompletion:)))(self, _cmd, completion); -} - -static FIRDocumentReference * _logos_method$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$( - _LOGOS_SELF_TYPE_NORMAL FIRCollectionReference * _LOGOS_SELF_CONST __unused self, - SEL __unused _cmd, NSDictionary * data, void (^completion)(NSError *error)) { - - // Generate transaction ID - NSString *requestID = [FLEXNetworkObserver nextRequestID]; - - // Hook callback - void (^orig)(NSError *) = completion; - completion = ^(NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordFIRDidAddDocument:error transactionID:requestID]; - orig(error); - }; - - // Forward invocation - FIRDocumentReference *ret = (_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$ ? _logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRCollectionReference, @selector(addDocumentWithData:completion:)))(self, _cmd, data, completion); - - // Record transaction start - [FLEXNetworkRecorder.defaultRecorder recordFIRWillAddDocument:self document:ret transactionID:requestID]; - - // Return - return ret; -} - -+ (void)setNetworkMonitorHooks { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self hookFirebaseThings]; - [self injectIntoAllNSURLThings]; - }); -} - -+ (void)hookFirebaseThings { - Class _logos_class$_ungrouped$FIRDocumentReference = objc_getClass("FIRDocumentReference"); - _logos_superclass$_ungrouped$FIRDocumentReference = class_getSuperclass(_logos_class$_ungrouped$FIRDocumentReference); - Class _logos_class$_ungrouped$FIRQuery = objc_getClass("FIRQuery"); - _logos_superclass$_ungrouped$FIRQuery = class_getSuperclass(_logos_class$_ungrouped$FIRQuery); - Class _logos_class$_ungrouped$FIRCollectionReference = objc_getClass("FIRCollectionReference"); - _logos_superclass$_ungrouped$FIRCollectionReference = class_getSuperclass(_logos_class$_ungrouped$FIRCollectionReference); - - // Reading // - - _logos_register_hook( - _logos_class$_ungrouped$FIRDocumentReference, - @selector(getDocumentWithCompletion:), - (IMP)&_logos_method$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$, - (IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$ - ); - - _logos_register_hook( - _logos_class$_ungrouped$FIRQuery, - @selector(getDocumentsWithCompletion:), - (IMP)&_logos_method$_ungrouped$FIRQuery$getDocumentsWithCompletion$, - (IMP *)&_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$ - ); - - // Writing // - - _logos_register_hook( - _logos_class$_ungrouped$FIRDocumentReference, - @selector(setData:merge:completion:), - (IMP)&_logos_method$_ungrouped$FIRDocumentReference$setData$merge$completion$, - (IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$ - ); - _logos_register_hook( - _logos_class$_ungrouped$FIRDocumentReference, - @selector(setData:mergeFields:completion:), - (IMP)&_logos_method$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$, - (IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$ - ); - _logos_register_hook( - _logos_class$_ungrouped$FIRDocumentReference, - @selector(updateData:completion:), - (IMP)&_logos_method$_ungrouped$FIRDocumentReference$updateData$completion$, - (IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$ - ); - _logos_register_hook( - _logos_class$_ungrouped$FIRDocumentReference, - @selector(deleteDocumentWithCompletion:), - (IMP)&_logos_method$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$, - (IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$ - ); - _logos_register_hook( - _logos_class$_ungrouped$FIRCollectionReference, - @selector(addDocumentWithData:completion:), - (IMP)&_logos_method$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$, - (IMP *)&_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$ - ); -} - -+ (void)injectIntoAllNSURLThings { - // Only allow swizzling once. - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // Swizzle any classes that implement one of these selectors. - const SEL selectors[] = { - @selector(connectionDidFinishLoading:), - @selector(connection:willSendRequest:redirectResponse:), - @selector(connection:didReceiveResponse:), - @selector(connection:didReceiveData:), - @selector(connection:didFailWithError:), - @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:), - @selector(URLSession:dataTask:didReceiveData:), - @selector(URLSession:dataTask:didReceiveResponse:completionHandler:), - @selector(URLSession:task:didCompleteWithError:), - @selector(URLSession:dataTask:didBecomeDownloadTask:), - @selector(URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:), - @selector(URLSession:downloadTask:didFinishDownloadingToURL:) - }; - - const int numSelectors = sizeof(selectors) / sizeof(SEL); - - Class *classes = NULL; - int numClasses = objc_getClassList(NULL, 0); - - if (numClasses > 0) { - classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses); - numClasses = objc_getClassList(classes, numClasses); - for (NSInteger classIndex = 0; classIndex < numClasses; ++classIndex) { - Class class = classes[classIndex]; - - if (class == [FLEXNetworkObserver class]) { - continue; - } - - // Use the C API rather than NSObject methods to avoid sending messages - // to classes we're not interested in swizzling, which could result - // in us calling +initialize on potentially uninitialized classes. - // NOTE: calling class_getInstanceMethod() DOES send +initialize - // to the class. That's why we iterate through the method list. - unsigned int methodCount = 0; - Method *methods = class_copyMethodList(class, &methodCount); - BOOL matchingSelectorFound = NO; - for (unsigned int methodIndex = 0; methodIndex < methodCount; methodIndex++) { - for (int selectorIndex = 0; selectorIndex < numSelectors; ++selectorIndex) { - if (method_getName(methods[methodIndex]) == selectors[selectorIndex]) { - [self injectIntoDelegateClass:class]; - matchingSelectorFound = YES; - break; - } - } - if (matchingSelectorFound) { - break; - } - } - - free(methods); - } - - free(classes); - } - - [self injectIntoNSURLConnectionCancel]; - [self injectIntoNSURLSessionTaskResume]; - - [self injectIntoNSURLConnectionAsynchronousClassMethod]; - [self injectIntoNSURLConnectionSynchronousClassMethod]; - - [self injectIntoNSURLSessionAsyncDataAndDownloadTaskMethods]; - [self injectIntoNSURLSessionAsyncUploadTaskMethods]; - - if (@available(iOS 13.0, *)) { - Class websocketTask = NSClassFromString(@"__NSURLSessionWebSocketTask"); - [self injectWebsocketSendMessage:websocketTask]; - [self injectWebsocketReceiveMessage:websocketTask]; - websocketTask = [NSURLSessionWebSocketTask class]; - [self injectWebsocketSendMessage:websocketTask]; - [self injectWebsocketReceiveMessage:websocketTask]; - } - }); -} - -+ (void)injectIntoDelegateClass:(Class)cls { - // Connections - [self injectWillSendRequestIntoDelegateClass:cls]; - [self injectDidReceiveDataIntoDelegateClass:cls]; - [self injectDidReceiveResponseIntoDelegateClass:cls]; - [self injectDidFinishLoadingIntoDelegateClass:cls]; - [self injectDidFailWithErrorIntoDelegateClass:cls]; - - // Sessions - [self injectTaskWillPerformHTTPRedirectionIntoDelegateClass:cls]; - [self injectTaskDidReceiveDataIntoDelegateClass:cls]; - [self injectTaskDidReceiveResponseIntoDelegateClass:cls]; - [self injectTaskDidCompleteWithErrorIntoDelegateClass:cls]; - [self injectRespondsToSelectorIntoDelegateClass:cls]; - - // Data tasks - [self injectDataTaskDidBecomeDownloadTaskIntoDelegateClass:cls]; - - // Download tasks - [self injectDownloadTaskDidWriteDataIntoDelegateClass:cls]; - [self injectDownloadTaskDidFinishDownloadingIntoDelegateClass:cls]; -} - -+ (void)injectIntoNSURLConnectionCancel { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = [NSURLConnection class]; - SEL selector = @selector(cancel); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - Method originalCancel = class_getInstanceMethod(class, selector); - - void (^swizzleBlock)(NSURLConnection *) = ^(NSURLConnection *slf) { - [FLEXNetworkObserver.sharedObserver connectionWillCancel:slf]; - ((void(*)(id, SEL))objc_msgSend)( - slf, swizzledSelector - ); - }; - - IMP implementation = imp_implementationWithBlock(swizzleBlock); - class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalCancel)); - Method newCancel = class_getInstanceMethod(class, swizzledSelector); - method_exchangeImplementations(originalCancel, newCancel); - }); -} - -+ (void)injectIntoNSURLSessionTaskResume { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // In iOS 7 resume lives in __NSCFLocalSessionTask - // In iOS 8 resume lives in NSURLSessionTask - // In iOS 9 resume lives in __NSCFURLSessionTask - // In iOS 14 resume lives in NSURLSessionTask - Class baseResumeClass = Nil; - if (![NSProcessInfo.processInfo respondsToSelector:@selector(operatingSystemVersion)]) { - // iOS ... 7 - baseResumeClass = NSClassFromString(@"__NSCFLocalSessionTask"); - } else { - NSInteger majorVersion = NSProcessInfo.processInfo.operatingSystemVersion.majorVersion; - if (majorVersion < 9 || majorVersion >= 14) { - // iOS 8 or iOS 14+ - baseResumeClass = [NSURLSessionTask class]; - } else { - // iOS 9 ... 13 - baseResumeClass = NSClassFromString(@"__NSCFURLSessionTask"); - } - } - - // Hook the base implementation of -resume - IMP originalResume = [baseResumeClass instanceMethodForSelector:@selector(resume)]; - [self swizzleResumeSelector:@selector(resume) forClass:baseResumeClass]; - - // *Sigh* - // - // So, multiple versions of AFNetworking 2.5.X swizzle -resume in various and - // short-sighted ways. If you look through the version history from 2.5.0 upwards, - // you'll see a variety of techniques were tried, including taking a private - // subclass of NSURLSessionTask and calling class_addMethod with `originalResume` - // below, so that a duplicate implementation of -resume exists in that class. - // - // This technique in particular is troublesome, because the implementation in - // `baseResumeClass` is never called at all, which means our swizzle is never invoked. - // - // The only solution is a brute-force one: we must loop over the class tree - // below `baseResumeClass` and check for all classes that implement `af_resume`. - // if the IMP corresponding to that method is equal to `originalResume` then we - // swizzle that in addition to swizzling `resume` on `baseResumeClass` above. - // - // However, we only go to the trouble at all if NSSelectorFromString - // can even find an `"af_resume"` selector in the first place. - SEL sel_af_resume = NSSelectorFromString(@"af_resume"); - if (sel_af_resume) { - NSMutableArray *classTree = FLEXGetAllSubclasses(baseResumeClass, NO).mutableCopy; - for (NSInteger i = 0; i < classTree.count; i++) { - [classTree addObjectsFromArray:FLEXGetAllSubclasses(classTree[i], NO)]; - } - - for (Class current in classTree) { - IMP af_resume = [current instanceMethodForSelector:sel_af_resume]; - if (af_resume == originalResume) { - [self swizzleResumeSelector:sel_af_resume forClass:current]; - } - } - } - }); -} - -+ (void)swizzleResumeSelector:(SEL)selector forClass:(Class)class { - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - Method originalResume = class_getInstanceMethod(class, selector); - IMP implementation = imp_implementationWithBlock(^(NSURLSessionTask *slf) { - - // iOS's internal HTTP parser finalization code is mysteriously not thread safe, - // invoking it asynchronously has a chance to cause a `double free` crash. - // This line below will ask for HTTPBody synchronously, make the HTTPParser - // parse the request, and cache them in advance. After that the HTTPParser - // will be finalized. Make sure other threads inspecting the request - // won't trigger a race to finalize the parser. - [slf.currentRequest HTTPBody]; - - [FLEXNetworkObserver.sharedObserver URLSessionTaskWillResume:slf]; - ((void(*)(id, SEL))objc_msgSend)( - slf, swizzledSelector - ); - }); - - class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalResume)); - Method newResume = class_getInstanceMethod(class, swizzledSelector); - method_exchangeImplementations(originalResume, newResume); -} - -+ (void)injectIntoNSURLConnectionAsynchronousClassMethod { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = objc_getMetaClass(class_getName([NSURLConnection class])); - SEL selector = @selector(sendAsynchronousRequest:queue:completionHandler:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - typedef void (^AsyncCompletion)( - NSURLResponse *response, NSData *data, NSError *error - ); - typedef void (^SendAsyncRequestBlock)( - Class, NSURLRequest *, NSOperationQueue *, AsyncCompletion - ); - SendAsyncRequestBlock swizzleBlock = ^(Class slf, - NSURLRequest *request, - NSOperationQueue *queue, - AsyncCompletion completion) { - if (FLEXNetworkObserver.isEnabled) { - NSString *requestID = [self nextRequestID]; - [FLEXNetworkRecorder.defaultRecorder - recordRequestWillBeSentWithRequestID:requestID - request:request - redirectResponse:nil - ]; - - NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class]; - [FLEXNetworkRecorder.defaultRecorder recordMechanism:mechanism forRequestID:requestID]; - - AsyncCompletion wrapper = ^(NSURLResponse *response, NSData *data, NSError *error) { - [FLEXNetworkRecorder.defaultRecorder - recordResponseReceivedWithRequestID:requestID - response:response - ]; - [FLEXNetworkRecorder.defaultRecorder - recordDataReceivedWithRequestID:requestID - dataLength:data.length - ]; - if (error) { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFailedWithRequestID:requestID - error:error - ]; - } else { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFinishedWithRequestID:requestID - responseBody:data - ]; - } - - // Call through to the original completion handler - if (completion) { - completion(response, data, error); - } - }; - ((void(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, request, queue, wrapper - ); - } else { - ((void(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, request, queue, completion - ); - } - }; - - [FLEXUtility replaceImplementationOfKnownSelector:selector - onClass:class withBlock:swizzleBlock swizzledSelector:swizzledSelector - ]; - }); -} - -+ (void)injectIntoNSURLConnectionSynchronousClassMethod { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = objc_getMetaClass(class_getName([NSURLConnection class])); - SEL selector = @selector(sendSynchronousRequest:returningResponse:error:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - typedef NSData * (^AsyncCompletion)(Class, NSURLRequest *, NSURLResponse **, NSError **); - AsyncCompletion swizzleBlock = ^NSData *(Class slf, - NSURLRequest *request, - NSURLResponse **response, - NSError **error) { - NSData *data = nil; - if (FLEXNetworkObserver.isEnabled) { - NSString *requestID = [self nextRequestID]; - [FLEXNetworkRecorder.defaultRecorder - recordRequestWillBeSentWithRequestID:requestID - request:request - redirectResponse:nil - ]; - - NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class]; - [FLEXNetworkRecorder.defaultRecorder recordMechanism:mechanism forRequestID:requestID]; - NSError *temporaryError = nil; - NSURLResponse *temporaryResponse = nil; - data = ((id(*)(id, SEL, id, NSURLResponse **, NSError **))objc_msgSend)( - slf, swizzledSelector, request, &temporaryResponse, &temporaryError - ); - - [FLEXNetworkRecorder.defaultRecorder - recordResponseReceivedWithRequestID:requestID - response:temporaryResponse - ]; - [FLEXNetworkRecorder.defaultRecorder - recordDataReceivedWithRequestID:requestID - dataLength:data.length - ]; - - if (temporaryError) { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFailedWithRequestID:requestID - error:temporaryError - ]; - } else { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFinishedWithRequestID:requestID - responseBody:data - ]; - } - - if (error) { - *error = temporaryError; - } - if (response) { - *response = temporaryResponse; - } - } else { - data = ((id(*)(id, SEL, id, NSURLResponse **, NSError **))objc_msgSend)( - slf, swizzledSelector, request, response, error - ); - } - - return data; - }; - - [FLEXUtility replaceImplementationOfKnownSelector:selector - onClass:class withBlock:swizzleBlock swizzledSelector:swizzledSelector - ]; - }); -} - -+ (void)injectIntoNSURLSessionAsyncDataAndDownloadTaskMethods { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = [NSURLSession class]; - - // The method signatures here are close enough that - // we can use the same logic to inject into all of them. - const SEL selectors[] = { - @selector(dataTaskWithRequest:completionHandler:), - @selector(dataTaskWithURL:completionHandler:), - @selector(downloadTaskWithRequest:completionHandler:), - @selector(downloadTaskWithResumeData:completionHandler:), - @selector(downloadTaskWithURL:completionHandler:) - }; - - const int numSelectors = sizeof(selectors) / sizeof(SEL); - - for (int selectorIndex = 0; selectorIndex < numSelectors; selectorIndex++) { - SEL selector = selectors[selectorIndex]; - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) { - // iOS 7 does not implement these methods on NSURLSession. We actually want to - // swizzle __NSCFURLSession, which we can get from the class of the shared session - class = [NSURLSession.sharedSession class]; - } - - typedef NSURLSessionTask * (^NSURLSessionNewTaskMethod)( - NSURLSession *, id, NSURLSessionAsyncCompletion - ); - NSURLSessionNewTaskMethod swizzleBlock = ^NSURLSessionTask *(NSURLSession *slf, - id argument, - NSURLSessionAsyncCompletion completion) { - NSURLSessionTask *task = nil; - // Check if network observing is on and a callback was provided - if (FLEXNetworkObserver.isEnabled && completion) { - NSString *requestID = [self nextRequestID]; - NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class]; - // "Hook" the completion block - NSURLSessionAsyncCompletion completionWrapper = [self - asyncCompletionWrapperForRequestID:requestID - mechanism:mechanism - completion:completion - ]; - - // Call the original method - task = ((id(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, argument, completionWrapper - ); - [self setRequestID:requestID forConnectionOrTask:task]; - } else { - // Network observer disabled or no callback provided, - // just pass through to the original method - task = ((id(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, argument, completion - ); - } - return task; - }; - - // Actually swizzle - [FLEXUtility replaceImplementationOfKnownSelector:selector - onClass:class withBlock:swizzleBlock swizzledSelector:swizzledSelector - ]; - } - }); -} - -+ (void)injectIntoNSURLSessionAsyncUploadTaskMethods { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = [NSURLSession class]; - - // The method signatures here are close enough that we can use the same logic to inject into both of them. - // Note that they have 3 arguments, so we can't easily combine with the data and download method above. - typedef NSURLSessionUploadTask *(^UploadTaskMethod)( - NSURLSession *, NSURLRequest *, id, NSURLSessionAsyncCompletion - ); - const SEL selectors[] = { - @selector(uploadTaskWithRequest:fromData:completionHandler:), - @selector(uploadTaskWithRequest:fromFile:completionHandler:) - }; - - const int numSelectors = sizeof(selectors) / sizeof(SEL); - - for (int selectorIndex = 0; selectorIndex < numSelectors; selectorIndex++) { - SEL selector = selectors[selectorIndex]; - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) { - // iOS 7 does not implement these methods on NSURLSession. We actually want to - // swizzle __NSCFURLSession, which we can get from the class of the shared session - class = [NSURLSession.sharedSession class]; - } - - - UploadTaskMethod swizzleBlock = ^NSURLSessionUploadTask *(NSURLSession * slf, - NSURLRequest *request, - id argument, - NSURLSessionAsyncCompletion completion) { - NSURLSessionUploadTask *task = nil; - if (FLEXNetworkObserver.isEnabled && completion) { - NSString *requestID = [self nextRequestID]; - NSString *mechanism = [self mechanismFromClassMethod:selector onClass:class]; - NSURLSessionAsyncCompletion completionWrapper = [self - asyncCompletionWrapperForRequestID:requestID - mechanism:mechanism - completion:completion - ]; - - task = ((id(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, request, argument, completionWrapper - ); - [self setRequestID:requestID forConnectionOrTask:task]; - } else { - task = ((id(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, request, argument, completion - ); - } - return task; - }; - - [FLEXUtility replaceImplementationOfKnownSelector:selector - onClass:class withBlock:swizzleBlock swizzledSelector:swizzledSelector - ]; - } - }); -} - -+ (NSString *)mechanismFromClassMethod:(SEL)selector onClass:(Class)class { - return [NSString stringWithFormat:@"+[%@ %@]", NSStringFromClass(class), NSStringFromSelector(selector)]; -} - -+ (NSURLSessionAsyncCompletion)asyncCompletionWrapperForRequestID:(NSString *)requestID - mechanism:(NSString *)mechanism - completion:(NSURLSessionAsyncCompletion)completion { - NSURLSessionAsyncCompletion completionWrapper = ^(id fileURLOrData, NSURLResponse *response, NSError *error) { - [FLEXNetworkRecorder.defaultRecorder recordMechanism:mechanism forRequestID:requestID]; - [FLEXNetworkRecorder.defaultRecorder - recordResponseReceivedWithRequestID:requestID - response:response - ]; - - NSData *data = nil; - if ([fileURLOrData isKindOfClass:[NSURL class]]) { - data = [NSData dataWithContentsOfURL:fileURLOrData]; - } else if ([fileURLOrData isKindOfClass:[NSData class]]) { - data = fileURLOrData; - } - - [FLEXNetworkRecorder.defaultRecorder - recordDataReceivedWithRequestID:requestID - dataLength:data.length - ]; - - if (error) { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFailedWithRequestID:requestID - error:error - ]; - } else { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFinishedWithRequestID:requestID - responseBody:data - ]; - } - - // Call through to the original completion handler - if (completion) { - completion(fileURLOrData, response, error); - } - }; - return completionWrapper; -} - -+ (void)injectWillSendRequestIntoDelegateClass:(Class)cls { - SEL selector = @selector(connection:willSendRequest:redirectResponse:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - Protocol *protocol = @protocol(NSURLConnectionDataDelegate); - protocol = protocol ?: @protocol(NSURLConnectionDelegate); - struct objc_method_description methodDescription = protocol_getMethodDescription( - protocol, selector, NO, YES - ); - - typedef NSURLRequest *(^WillSendRequestBlock)( - id slf, NSURLConnection *connection, - NSURLRequest *request, NSURLResponse *response - ); - - WillSendRequestBlock undefinedBlock = ^NSURLRequest *(id slf, - NSURLConnection *connection, - NSURLRequest *request, - NSURLResponse *response) { - [FLEXNetworkObserver.sharedObserver - connection:connection - willSendRequest:request - redirectResponse:response - delegate:slf - ]; - return request; - }; - - WillSendRequestBlock implementationBlock = ^NSURLRequest *(id slf, - NSURLConnection *connection, - NSURLRequest *request, - NSURLResponse *response) { - __block NSURLRequest *returnValue = nil; - [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{ - undefinedBlock(slf, connection, request, response); - } originalImplementationBlock:^{ - returnValue = ((id(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, connection, request, response - ); - }]; - return returnValue; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:methodDescription - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDidReceiveResponseIntoDelegateClass:(Class)cls { - SEL selector = @selector(connection:didReceiveResponse:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - Protocol *protocol = @protocol(NSURLConnectionDataDelegate); - protocol = protocol ?: @protocol(NSURLConnectionDelegate); - struct objc_method_description description = protocol_getMethodDescription( - protocol, selector, NO, YES - ); - - typedef void (^DidReceiveResponseBlock)( - id slf, NSURLConnection *connection, NSURLResponse *response - ); - - DidReceiveResponseBlock undefinedBlock = ^(id slf, - NSURLConnection *connection, - NSURLResponse *response) { - [FLEXNetworkObserver.sharedObserver connection:connection - didReceiveResponse:response delegate:slf - ]; - }; - - DidReceiveResponseBlock implementationBlock = ^(id slf, - NSURLConnection *connection, - NSURLResponse *response) { - [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{ - undefinedBlock(slf, connection, response); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, connection, response - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDidReceiveDataIntoDelegateClass:(Class)cls { - SEL selector = @selector(connection:didReceiveData:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - Protocol *protocol = @protocol(NSURLConnectionDataDelegate); - protocol = protocol ?: @protocol(NSURLConnectionDelegate); - struct objc_method_description description = protocol_getMethodDescription( - protocol, selector, NO, YES - ); - - typedef void (^DidReceiveDataBlock)( - id slf, NSURLConnection *connection, NSData *data - ); - - DidReceiveDataBlock undefinedBlock = ^(id slf, - NSURLConnection *connection, - NSData *data) { - [FLEXNetworkObserver.sharedObserver connection:connection - didReceiveData:data delegate:slf - ]; - }; - - DidReceiveDataBlock implementationBlock = ^(id slf, - NSURLConnection *connection, - NSData *data) { - [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{ - undefinedBlock(slf, connection, data); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, connection, data - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDidFinishLoadingIntoDelegateClass:(Class)cls { - SEL selector = @selector(connectionDidFinishLoading:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - Protocol *protocol = @protocol(NSURLConnectionDataDelegate); - protocol = protocol ?: @protocol(NSURLConnectionDelegate); - struct objc_method_description description = protocol_getMethodDescription( - protocol, selector, NO, YES - ); - - typedef void (^FinishLoadingBlock)(id slf, NSURLConnection *connection); - - FinishLoadingBlock undefinedBlock = ^(id slf, NSURLConnection *connection) { - [FLEXNetworkObserver.sharedObserver connectionDidFinishLoading:connection delegate:slf]; - }; - - FinishLoadingBlock implementationBlock = ^(id slf, NSURLConnection *connection) { - [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{ - undefinedBlock(slf, connection); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id))objc_msgSend)( - slf, swizzledSelector, connection - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDidFailWithErrorIntoDelegateClass:(Class)cls { - SEL selector = @selector(connection:didFailWithError:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLConnectionDelegate), selector, NO, YES - ); - - typedef void (^DidFailWithErrorBlock)( - id slf, NSURLConnection *connection, NSError *error - ); - - DidFailWithErrorBlock undefinedBlock = ^(id slf, - NSURLConnection *connection, - NSError *error) { - [FLEXNetworkObserver.sharedObserver connection:connection - didFailWithError:error delegate:slf - ]; - }; - - DidFailWithErrorBlock implementationBlock = ^(id slf, - NSURLConnection *connection, - NSError *error) { - [self sniffWithoutDuplicationForObject:connection selector:selector sniffingBlock:^{ - undefinedBlock(slf, connection, error); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, connection, error - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectTaskWillPerformHTTPRedirectionIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionTaskDelegate), selector, NO, YES - ); - - typedef void (^HTTPRedirectionBlock)(id slf, - NSURLSession *session, - NSURLSessionTask *task, - NSHTTPURLResponse *response, - NSURLRequest *newRequest, - void(^completionHandler)(NSURLRequest *)); - - HTTPRedirectionBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionTask *task, - NSHTTPURLResponse *response, - NSURLRequest *newRequest, - void(^completionHandler)(NSURLRequest *)) { - [FLEXNetworkObserver.sharedObserver - URLSession:session task:task - willPerformHTTPRedirection:response - newRequest:newRequest - completionHandler:completionHandler - delegate:slf - ]; - completionHandler(newRequest); - }; - - HTTPRedirectionBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionTask *task, - NSHTTPURLResponse *response, - NSURLRequest *newRequest, - void(^completionHandler)(NSURLRequest *)) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - [FLEXNetworkObserver.sharedObserver - URLSession:session task:task - willPerformHTTPRedirection:response - newRequest:newRequest - completionHandler:completionHandler - delegate:slf - ]; - } originalImplementationBlock:^{ - ((id(*)(id, SEL, id, id, id, id, void(^)(NSURLRequest *)))objc_msgSend)( - slf, swizzledSelector, session, task, response, newRequest, completionHandler - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectTaskDidReceiveDataIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:dataTask:didReceiveData:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionDataDelegate), selector, NO, YES - ); - - typedef void (^DidReceiveDataBlock)(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSData *data); - DidReceiveDataBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSData *data) { - [FLEXNetworkObserver.sharedObserver URLSession:session - dataTask:dataTask didReceiveData:data delegate:slf - ]; - }; - - DidReceiveDataBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSData *data) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - undefinedBlock(slf, session, dataTask, data); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, session, dataTask, data - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDataTaskDidBecomeDownloadTaskIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:dataTask:didBecomeDownloadTask:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionDataDelegate), selector, NO, YES - ); - - typedef void (^DidBecomeDownloadTaskBlock)(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSURLSessionDownloadTask *downloadTask); - - DidBecomeDownloadTaskBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSURLSessionDownloadTask *downloadTask) { - [FLEXNetworkObserver.sharedObserver URLSession:session - dataTask:dataTask didBecomeDownloadTask:downloadTask delegate:slf - ]; - }; - - DidBecomeDownloadTaskBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSURLSessionDownloadTask *downloadTask) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - undefinedBlock(slf, session, dataTask, downloadTask); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, session, dataTask, downloadTask - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectTaskDidReceiveResponseIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:dataTask:didReceiveResponse:completionHandler:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionDataDelegate), selector, NO, YES - ); - - typedef void (^DidReceiveResponseBlock)(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSURLResponse *response, - void(^completion)(NSURLSessionResponseDisposition)); - - DidReceiveResponseBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSURLResponse *response, - void(^completion)(NSURLSessionResponseDisposition)) { - [FLEXNetworkObserver.sharedObserver - URLSession:session - dataTask:dataTask - didReceiveResponse:response - completionHandler:completion - delegate:slf - ]; - completion(NSURLSessionResponseAllow); - }; - - DidReceiveResponseBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDataTask *dataTask, - NSURLResponse *response, - void(^completion)(NSURLSessionResponseDisposition )) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - [FLEXNetworkObserver.sharedObserver - URLSession:session - dataTask:dataTask - didReceiveResponse:response - completionHandler:completion - delegate:slf - ]; - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id, id, void(^)(NSURLSessionResponseDisposition)))objc_msgSend)( - slf, swizzledSelector, session, dataTask, response, completion - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; - -} - -+ (void)injectTaskDidCompleteWithErrorIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:task:didCompleteWithError:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionDataDelegate), selector, NO, YES - ); - - typedef void (^DidCompleteWithErrorBlock)(id slf, - NSURLSession *session, - NSURLSessionTask *task, - NSError *error); - - DidCompleteWithErrorBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionTask *task, - NSError *error) { - [FLEXNetworkObserver.sharedObserver URLSession:session - task:task didCompleteWithError:error delegate:slf - ]; - }; - - DidCompleteWithErrorBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionTask *task, - NSError *error) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - undefinedBlock(slf, session, task, error); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, session, task, error - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -// Used for overriding AFNetworking behavior -+ (void)injectRespondsToSelectorIntoDelegateClass:(Class)cls { - SEL selector = @selector(respondsToSelector:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - //Protocol *protocol = @protocol(NSURLSessionTaskDelegate); - Method method = class_getInstanceMethod(cls, selector); - struct objc_method_description methodDescription = *method_getDescription(method); - - typedef BOOL (^RespondsToSelectorImpl)(id self, SEL sel); - RespondsToSelectorImpl undefinedBlock = ^(id slf, SEL sel) { - return YES; - }; - - RespondsToSelectorImpl implementationBlock = ^(id slf, SEL sel) { - if (sel == @selector(URLSession:dataTask:didReceiveResponse:completionHandler:)) { - return undefinedBlock(slf, sel); - } - return ((BOOL(*)(id, SEL, SEL))objc_msgSend)(slf, swizzledSelector, sel); - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:methodDescription - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDownloadTaskDidFinishDownloadingIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:downloadTask:didFinishDownloadingToURL:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionDownloadDelegate), selector, NO, YES - ); - - typedef void (^DidFinishDownloadingBlock)(id slf, - NSURLSession *session, - NSURLSessionDownloadTask *task, - NSURL *location); - - DidFinishDownloadingBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDownloadTask *task, - NSURL *location) { - NSData *data = [NSData dataWithContentsOfFile:location.relativePath]; - [FLEXNetworkObserver.sharedObserver URLSession:session - task:task didFinishDownloadingToURL:location data:data delegate:slf - ]; - }; - - DidFinishDownloadingBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDownloadTask *task, - NSURL *location) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - undefinedBlock(slf, session, task, location); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id, id))objc_msgSend)( - slf, swizzledSelector, session, task, location - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectDownloadTaskDidWriteDataIntoDelegateClass:(Class)cls { - SEL selector = @selector(URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - struct objc_method_description description = protocol_getMethodDescription( - @protocol(NSURLSessionDownloadDelegate), selector, NO, YES - ); - - typedef void (^DidWriteDataBlock)(id slf, - NSURLSession *session, - NSURLSessionDownloadTask *task, - int64_t bytesWritten, - int64_t totalBytesWritten, - int64_t totalBytesExpectedToWrite); - - DidWriteDataBlock undefinedBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDownloadTask *task, - int64_t bytesWritten, - int64_t totalBytesWritten, - int64_t totalBytesExpectedToWrite) { - [FLEXNetworkObserver.sharedObserver URLSession:session - downloadTask:task didWriteData:bytesWritten - totalBytesWritten:totalBytesWritten - totalBytesExpectedToWrite:totalBytesExpectedToWrite - delegate:slf - ]; - }; - - DidWriteDataBlock implementationBlock = ^(id slf, - NSURLSession *session, - NSURLSessionDownloadTask *task, - int64_t bytesWritten, - int64_t totalBytesWritten, - int64_t totalBytesExpectedToWrite) { - [self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{ - undefinedBlock( - slf, session, task, bytesWritten, - totalBytesWritten, totalBytesExpectedToWrite - ); - } originalImplementationBlock:^{ - ((void(*)(id, SEL, id, id, int64_t, int64_t, int64_t))objc_msgSend)( - slf, swizzledSelector, session, task, bytesWritten, - totalBytesWritten, totalBytesExpectedToWrite - ); - }]; - }; - - [FLEXUtility replaceImplementationOfSelector:selector - withSelector:swizzledSelector - forClass:cls - withMethodDescription:description - implementationBlock:implementationBlock - undefinedBlock:undefinedBlock - ]; -} - -+ (void)injectWebsocketSendMessage:(Class)cls API_AVAILABLE(ios(13.0)) { - SEL selector = @selector(sendMessage:completionHandler:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - typedef void (^SendMessageBlock)( - NSURLSessionWebSocketTask *slf, - NSURLSessionWebSocketMessage *message, - void (^completion)(NSError *error) - ); - - SendMessageBlock implementationBlock = ^( - NSURLSessionWebSocketTask *slf, - NSURLSessionWebSocketMessage *message, - void (^completion)(NSError *error) - ) { - [FLEXNetworkObserver.sharedObserver - websocketTask:slf sendMessagage:message - ]; - completion = ^(NSError *error) { - [FLEXNetworkObserver.sharedObserver - websocketTaskMessageSendCompletion:message - error:error - ]; - }; - - ((void(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, message, completion - ); - }; - - [FLEXUtility replaceImplementationOfKnownSelector:selector - onClass:cls - withBlock:implementationBlock - swizzledSelector:swizzledSelector - ]; -} - -+ (void)injectWebsocketReceiveMessage:(Class)cls API_AVAILABLE(ios(13.0)) { - SEL selector = @selector(receiveMessageWithCompletionHandler:); - SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector]; - - typedef void (^SendMessageBlock)( - NSURLSessionWebSocketTask *slf, - void (^completion)(NSURLSessionWebSocketMessage *message, NSError *error) - ); - - SendMessageBlock implementationBlock = ^( - NSURLSessionWebSocketTask *slf, - void (^completion)(NSURLSessionWebSocketMessage *message, NSError *error) - ) { - id completionHook = ^(NSURLSessionWebSocketMessage *message, NSError *error) { - [FLEXNetworkObserver.sharedObserver - websocketTask:slf receiveMessagage:message error:error - ]; - completion(message, error); - }; - - ((void(*)(id, SEL, id))objc_msgSend)( - slf, swizzledSelector, completionHook - ); - - }; - - [FLEXUtility replaceImplementationOfKnownSelector:selector - onClass:cls - withBlock:implementationBlock - swizzledSelector:swizzledSelector - ]; -} - -static char const * const kFLEXRequestIDKey = "kFLEXRequestIDKey"; - -+ (NSString *)requestIDForConnectionOrTask:(id)connectionOrTask { - NSString *requestID = objc_getAssociatedObject(connectionOrTask, kFLEXRequestIDKey); - if (!requestID) { - requestID = [self nextRequestID]; - [self setRequestID:requestID forConnectionOrTask:connectionOrTask]; - } - return requestID; -} - -+ (void)setRequestID:(NSString *)requestID forConnectionOrTask:(id)connectionOrTask { - objc_setAssociatedObject( - connectionOrTask, kFLEXRequestIDKey, requestID, OBJC_ASSOCIATION_RETAIN_NONATOMIC - ); -} - -#pragma mark - Initialization - -- (id)init { - self = [super init]; - if (self) { - self.requestStatesForRequestIDs = [NSMutableDictionary new]; - self.queue = dispatch_queue_create( - "com.flex.FLEXNetworkObserver", DISPATCH_QUEUE_SERIAL - ); - } - - return self; -} - -#pragma mark - Private Methods - -- (void)performBlock:(dispatch_block_t)block { - if ([[self class] isEnabled]) { - dispatch_async(_queue, block); - } -} - -- (FLEXInternalRequestState *)requestStateForRequestID:(NSString *)requestID { - FLEXInternalRequestState *requestState = self.requestStatesForRequestIDs[requestID]; - if (!requestState) { - requestState = [FLEXInternalRequestState new]; - [self.requestStatesForRequestIDs setObject:requestState forKey:requestID]; - } - - return requestState; -} - -- (void)removeRequestStateForRequestID:(NSString *)requestID { - [self.requestStatesForRequestIDs removeObjectForKey:requestID]; -} - -@end - - -@implementation FLEXNetworkObserver (NSURLConnectionHelpers) - -- (void)connection:(NSURLConnection *)connection - willSendRequest:(NSURLRequest *)request - redirectResponse:(NSURLResponse *)response - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:connection]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - requestState.request = request; - - [FLEXNetworkRecorder.defaultRecorder - recordRequestWillBeSentWithRequestID:requestID - request:request - redirectResponse:response - ]; - - NSString *mechanism = [NSString stringWithFormat: - @"NSURLConnection (delegate: %@)", [delegate class] - ]; - [FLEXNetworkRecorder.defaultRecorder recordMechanism:mechanism forRequestID:requestID]; - }]; -} - -- (void)connection:(NSURLConnection *)connection -didReceiveResponse:(NSURLResponse *)response - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:connection]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - requestState.dataAccumulator = [NSMutableData new]; - - [FLEXNetworkRecorder.defaultRecorder - recordResponseReceivedWithRequestID:requestID - response:response - ]; - }]; -} - -- (void)connection:(NSURLConnection *)connection - didReceiveData:(NSData *)data - delegate:(id)delegate { - // Just to be safe since we're doing this async - data = [data copy]; - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:connection]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - [requestState.dataAccumulator appendData:data]; - - [FLEXNetworkRecorder.defaultRecorder - recordDataReceivedWithRequestID:requestID - dataLength:data.length - ]; - }]; -} - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:connection]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFinishedWithRequestID:requestID - responseBody:requestState.dataAccumulator - ]; - [self removeRequestStateForRequestID:requestID]; - }]; -} - -- (void)connection:(NSURLConnection *)connection - didFailWithError:(NSError *)error - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:connection]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - - // Cancellations can occur prior to the willSendRequest:... - // NSURLConnection delegate call. These are pretty common - // and clutter up the logs. Only record the failure if the - // recorder already knows about the request through willSendRequest:... - if (requestState.request) { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFailedWithRequestID:requestID error:error - ]; - } - - [self removeRequestStateForRequestID:requestID]; - }]; -} - -- (void)connectionWillCancel:(NSURLConnection *)connection { - [self performBlock:^{ - // Mimic the behavior of NSURLSession which is to create an error on cancellation. - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"cancelled" }; - NSError *error = [NSError errorWithDomain:NSURLErrorDomain - code:NSURLErrorCancelled userInfo:userInfo - ]; - [self connection:connection didFailWithError:error delegate:nil]; - }]; -} - -@end - - -@implementation FLEXNetworkObserver (NSURLSessionTaskHelpers) - -- (void)URLSession:(NSURLSession *)session - task:(NSURLSessionTask *)task -willPerformHTTPRedirection:(NSHTTPURLResponse *)response - newRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSURLRequest *))completionHandler - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:task]; - [FLEXNetworkRecorder.defaultRecorder - recordRequestWillBeSentWithRequestID:requestID - request:request - redirectResponse:response - ]; - }]; -} - -- (void)URLSession:(NSURLSession *)session - dataTask:(NSURLSessionDataTask *)dataTask -didReceiveResponse:(NSURLResponse *)response - completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:dataTask]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - requestState.dataAccumulator = [NSMutableData new]; - - NSString *requestMechanism = [NSString stringWithFormat: - @"NSURLSessionDataTask (delegate: %@)", [delegate class] - ]; - [FLEXNetworkRecorder.defaultRecorder - recordMechanism:requestMechanism - forRequestID:requestID - ]; - - [FLEXNetworkRecorder.defaultRecorder - recordResponseReceivedWithRequestID:requestID - response:response - ]; - }]; -} - -- (void)URLSession:(NSURLSession *)session - dataTask:(NSURLSessionDataTask *)dataTask -didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask - delegate:(id)delegate { - [self performBlock:^{ - // By setting the request ID of the download task to match the data task, - // it can pick up where the data task left off. - NSString *requestID = [[self class] requestIDForConnectionOrTask:dataTask]; - [[self class] setRequestID:requestID forConnectionOrTask:downloadTask]; - }]; -} - -- (void)URLSession:(NSURLSession *)session - dataTask:(NSURLSessionDataTask *)dataTask - didReceiveData:(NSData *)data - delegate:(id)delegate { - // Just to be safe since we're doing this async - data = [data copy]; - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:dataTask]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - - [requestState.dataAccumulator appendData:data]; - - [FLEXNetworkRecorder.defaultRecorder - recordDataReceivedWithRequestID:requestID - dataLength:data.length - ]; - }]; -} - -- (void)URLSession:(NSURLSession *)session - task:(NSURLSessionTask *)task -didCompleteWithError:(NSError *)error - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:task]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - - if (error) { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFailedWithRequestID:requestID error:error - ]; - } else { - [FLEXNetworkRecorder.defaultRecorder - recordLoadingFinishedWithRequestID:requestID - responseBody:requestState.dataAccumulator - ]; - } - - [self removeRequestStateForRequestID:requestID]; - }]; -} - -- (void)URLSession:(NSURLSession *)session - downloadTask:(NSURLSessionDownloadTask *)downloadTask - didWriteData:(int64_t)bytesWritten - totalBytesWritten:(int64_t)totalBytesWritten -totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite - delegate:(id)delegate { - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:downloadTask]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - - if (!requestState.dataAccumulator) { - requestState.dataAccumulator = [NSMutableData new]; - [FLEXNetworkRecorder.defaultRecorder - recordResponseReceivedWithRequestID:requestID - response:downloadTask.response - ]; - - NSString *requestMechanism = [NSString stringWithFormat: - @"NSURLSessionDownloadTask (delegate: %@)", [delegate class] - ]; - [FLEXNetworkRecorder.defaultRecorder - recordMechanism:requestMechanism - forRequestID:requestID - ]; - } - - [FLEXNetworkRecorder.defaultRecorder - recordDataReceivedWithRequestID:requestID - dataLength:bytesWritten - ]; - }]; -} - -- (void)URLSession:(NSURLSession *)session - task:(NSURLSessionDownloadTask *)downloadTask -didFinishDownloadingToURL:(NSURL *)location data:(NSData *)data - delegate:(id)delegate { - data = [data copy]; - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:downloadTask]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - [requestState.dataAccumulator appendData:data]; - }]; -} - -- (void)URLSessionTaskWillResume:(NSURLSessionTask *)task { - // Since resume can be called multiple times on the same task, only treat the first resume as - // the equivalent to connection:willSendRequest:... - [self performBlock:^{ - NSString *requestID = [[self class] requestIDForConnectionOrTask:task]; - FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID]; - if (!requestState.request) { - requestState.request = task.currentRequest; - - [FLEXNetworkRecorder.defaultRecorder - recordRequestWillBeSentWithRequestID:requestID - request:task.currentRequest - redirectResponse:nil - ]; - } - }]; -} - -- (void)websocketTask:(NSURLSessionWebSocketTask *)task - sendMessagage:(NSURLSessionWebSocketMessage *)message { - [self performBlock:^{ -// NSString *requestID = [[self class] requestIDForConnectionOrTask:task]; - [FLEXNetworkRecorder.defaultRecorder recordWebsocketMessageSend:message task:task]; - }]; -} - -- (void)websocketTaskMessageSendCompletion:(NSURLSessionWebSocketMessage *)message - error:(NSError *)error { - [self performBlock:^{ - [FLEXNetworkRecorder.defaultRecorder - recordWebsocketMessageSendCompletion:message - error:error - ]; - }]; -} - -- (void)websocketTask:(NSURLSessionWebSocketTask *)task - receiveMessagage:(NSURLSessionWebSocketMessage *)message - error:(NSError *)error { - [self performBlock:^{ - if (!error && message) { - [FLEXNetworkRecorder.defaultRecorder - recordWebsocketMessageReceived:message - task:task - ]; - } - }]; -} - -@end diff --git a/Tweaks/FLEX/Network/PonyDebugger/LICENSE b/Tweaks/FLEX/Network/PonyDebugger/LICENSE deleted file mode 100644 index 23750c6..0000000 --- a/Tweaks/FLEX/Network/PonyDebugger/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ - -PonyDebugger -Copyright 2012 Square Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - diff --git a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorer.h b/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorer.h deleted file mode 100644 index 5b251f3..0000000 --- a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorer.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// FLEXObjectExplorer.h -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntime+UIKitHelpers.h" - -/// Carries state about the current user defaults settings -@interface FLEXObjectExplorerDefaults : NSObject -+ (instancetype)canEdit:(BOOL)editable wantsPreviews:(BOOL)showPreviews; - -/// Only \c YES for properties and ivars -@property (nonatomic, readonly) BOOL isEditable; -/// Only affects properties and ivars -@property (nonatomic, readonly) BOOL wantsDynamicPreviews; -@end - -@interface FLEXObjectExplorer : NSObject - -+ (instancetype)forObject:(id)objectOrClass; - -+ (void)configureDefaultsForItems:(NSArray> *)items; - -@property (nonatomic, readonly) id object; -/// Subclasses can override to provide a more useful description -@property (nonatomic, readonly) NSString *objectDescription; - -/// @return \c YES if \c object is an instance of a class, -/// or \c NO if \c object is a class itself. -@property (nonatomic, readonly) BOOL objectIsInstance; - -/// An index into the `classHierarchy` array. -/// -/// This property determines which set of data comes out of the metadata arrays below -/// For example, \c properties contains the properties of the selected class scope, -/// while \c allProperties is an array of arrays where each array is a set of -/// properties for a class in the class hierarchy of the current object. -@property (nonatomic) NSInteger classScope; - -@property (nonatomic, readonly) NSArray *> *allProperties; -@property (nonatomic, readonly) NSArray *properties; - -@property (nonatomic, readonly) NSArray *> *allClassProperties; -@property (nonatomic, readonly) NSArray *classProperties; - -@property (nonatomic, readonly) NSArray *> *allIvars; -@property (nonatomic, readonly) NSArray *ivars; - -@property (nonatomic, readonly) NSArray *> *allMethods; -@property (nonatomic, readonly) NSArray *methods; - -@property (nonatomic, readonly) NSArray *> *allClassMethods; -@property (nonatomic, readonly) NSArray *classMethods; - -@property (nonatomic, readonly) NSArray *classHierarchyClasses; -@property (nonatomic, readonly) NSArray *classHierarchy; - -@property (nonatomic, readonly) NSArray *> *allConformedProtocols; -@property (nonatomic, readonly) NSArray *conformedProtocols; - -@property (nonatomic, readonly) NSArray *allInstanceSizes; -@property (nonatomic, readonly) FLEXStaticMetadata *instanceSize; - -@property (nonatomic, readonly) NSArray *allImageNames; -@property (nonatomic, readonly) FLEXStaticMetadata *imageName; - -- (void)reloadMetadata; -- (void)reloadClassHierarchy; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorer.m b/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorer.m deleted file mode 100644 index 4413001..0000000 --- a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorer.m +++ /dev/null @@ -1,378 +0,0 @@ -// -// FLEXObjectExplorer.m -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectExplorer.h" -#import "FLEXUtility.h" -#import "FLEXRuntimeUtility.h" -#import "NSObject+FLEX_Reflection.h" -#import "FLEXRuntime+Compare.h" -#import "FLEXRuntime+UIKitHelpers.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXMetadataSection.h" -#import "NSUserDefaults+FLEX.h" - -@implementation FLEXObjectExplorerDefaults - -+ (instancetype)canEdit:(BOOL)editable wantsPreviews:(BOOL)showPreviews { - FLEXObjectExplorerDefaults *defaults = [self new]; - defaults->_isEditable = editable; - defaults->_wantsDynamicPreviews = showPreviews; - return defaults; -} - -@end - -@interface FLEXObjectExplorer () { - NSMutableArray *> *_allProperties; - NSMutableArray *> *_allClassProperties; - NSMutableArray *> *_allIvars; - NSMutableArray *> *_allMethods; - NSMutableArray *> *_allClassMethods; - NSMutableArray *> *_allConformedProtocols; - NSMutableArray *_allInstanceSizes; - NSMutableArray *_allImageNames; - NSString *_objectDescription; -} -@end - -@implementation FLEXObjectExplorer - -#pragma mark - Initialization - -+ (id)forObject:(id)objectOrClass { - return [[self alloc] initWithObject:objectOrClass]; -} - -- (id)initWithObject:(id)objectOrClass { - NSParameterAssert(objectOrClass); - - self = [super init]; - if (self) { - _object = objectOrClass; - _objectIsInstance = !object_isClass(objectOrClass); - - [self reloadMetadata]; - } - - return self; -} - - -#pragma mark - Public - -+ (void)configureDefaultsForItems:(NSArray> *)items { - BOOL hidePreviews = NSUserDefaults.standardUserDefaults.flex_explorerHidesVariablePreviews; - FLEXObjectExplorerDefaults *mutable = [FLEXObjectExplorerDefaults - canEdit:YES wantsPreviews:!hidePreviews - ]; - FLEXObjectExplorerDefaults *immutable = [FLEXObjectExplorerDefaults - canEdit:NO wantsPreviews:!hidePreviews - ]; - - // .tag is used to cache whether the value of .isEditable; - // This could change at runtime so it is important that - // it is cached every time shortcuts are requeted and not - // just once at as shortcuts are initially registered - for (id metadata in items) { - metadata.defaults = metadata.isEditable ? mutable : immutable; - } -} - -- (NSString *)objectDescription { - if (!_objectDescription) { - // Hard-code UIColor description - if ([FLEXRuntimeUtility safeObject:self.object isKindOfClass:[UIColor class]]) { - CGFloat h, s, l, r, g, b, a; - [self.object getRed:&r green:&g blue:&b alpha:&a]; - [self.object getHue:&h saturation:&s brightness:&l alpha:nil]; - - return [NSString stringWithFormat: - @"HSL: (%.3f, %.3f, %.3f)\nRGB: (%.3f, %.3f, %.3f)\nAlpha: %.3f", - h, s, l, r, g, b, a - ]; - } - - NSString *description = [FLEXRuntimeUtility safeDescriptionForObject:self.object]; - - if (!description.length) { - NSString *address = [FLEXUtility addressOfObject:self.object]; - return [NSString stringWithFormat:@"Object at %@ returned empty description", address]; - } - - if (description.length > 10000) { - description = [description substringToIndex:10000]; - } - - _objectDescription = description; - } - - return _objectDescription; -} - -- (void)setClassScope:(NSInteger)classScope { - _classScope = classScope; - - [self reloadScopedMetadata]; -} - -- (void)reloadMetadata { - _allProperties = [NSMutableArray new]; - _allClassProperties = [NSMutableArray new]; - _allIvars = [NSMutableArray new]; - _allMethods = [NSMutableArray new]; - _allClassMethods = [NSMutableArray new]; - _allConformedProtocols = [NSMutableArray new]; - _allInstanceSizes = [NSMutableArray new]; - _allImageNames = [NSMutableArray new]; - _objectDescription = nil; - - [self reloadClassHierarchy]; - - NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; - BOOL hideBackingIvars = defaults.flex_explorerHidesPropertyIvars; - BOOL hidePropertyMethods = defaults.flex_explorerHidesPropertyMethods; - BOOL hidePrivateMethods = defaults.flex_explorerHidesPrivateMethods; - BOOL showMethodOverrides = defaults.flex_explorerShowsMethodOverrides; - - NSMutableArray *> *allProperties = [NSMutableArray new]; - NSMutableArray *> *allClassProps = [NSMutableArray new]; - NSMutableArray *> *allMethods = [NSMutableArray new]; - NSMutableArray *> *allClassMethods = [NSMutableArray new]; - - // Loop over each class and each superclass, collect - // the fresh and unique metadata in each category - Class superclass = nil; - NSInteger count = self.classHierarchyClasses.count; - NSInteger rootIdx = count - 1; - for (NSInteger i = 0; i < count; i++) { - Class cls = self.classHierarchyClasses[i]; - superclass = (i < rootIdx) ? self.classHierarchyClasses[i+1] : nil; - - [allProperties addObject:[self - metadataUniquedByName:[cls flex_allInstanceProperties] - superclass:superclass - kind:FLEXMetadataKindProperties - skip:showMethodOverrides - ]]; - [allClassProps addObject:[self - metadataUniquedByName:[cls flex_allClassProperties] - superclass:superclass - kind:FLEXMetadataKindClassProperties - skip:showMethodOverrides - ]]; - [_allIvars addObject:[self - metadataUniquedByName:[cls flex_allIvars] - superclass:nil - kind:FLEXMetadataKindIvars - skip:NO - ]]; - [allMethods addObject:[self - metadataUniquedByName:[cls flex_allInstanceMethods] - superclass:superclass - kind:FLEXMetadataKindMethods - skip:showMethodOverrides - ]]; - [allClassMethods addObject:[self - metadataUniquedByName:[cls flex_allClassMethods] - superclass:superclass - kind:FLEXMetadataKindClassMethods - skip:showMethodOverrides - ]]; - [_allConformedProtocols addObject:[self - metadataUniquedByName:[cls flex_protocols] - superclass:superclass - kind:FLEXMetadataKindProtocols - skip:NO - ]]; - - // TODO: join instance size, image name, and class hierarchy into a single model object - // This would greatly reduce the laziness that has begun to manifest itself here - [_allInstanceSizes addObject:[FLEXStaticMetadata - style:FLEXStaticMetadataRowStyleKeyValue - title:@"Instance Size" number:@(class_getInstanceSize(cls)) - ]]; - [_allImageNames addObject:[FLEXStaticMetadata - style:FLEXStaticMetadataRowStyleDefault - title:@"Image Name" string:@(class_getImageName(cls) ?: "Created at Runtime") - ]]; - } - - _classHierarchy = [FLEXStaticMetadata classHierarchy:self.classHierarchyClasses]; - - NSArray *> *properties = allProperties; - - // Potentially filter property-backing ivars - if (hideBackingIvars) { - NSArray *> *ivars = _allIvars.copy; - _allIvars = [ivars flex_mapped:^id(NSArray *list, NSUInteger idx) { - // Get a set of all backing ivar names for the current class in the hierarchy - NSSet *ivarNames = [NSSet setWithArray:({ - [properties[idx] flex_mapped:^id(FLEXProperty *p, NSUInteger idx) { - // Nil if no ivar, and array is flatted - return p.likelyIvarName; - }]; - })]; - - // Remove ivars whose name is in the ivar names list - return [list flex_filtered:^BOOL(FLEXIvar *ivar, NSUInteger idx) { - return ![ivarNames containsObject:ivar.name]; - }]; - }]; - } - - // Potentially filter property-backing methods - if (hidePropertyMethods) { - allMethods = [allMethods flex_mapped:^id(NSArray *list, NSUInteger idx) { - // Get a set of all property method names for the current class in the hierarchy - NSSet *methodNames = [NSSet setWithArray:({ - [properties[idx] flex_flatmapped:^NSArray *(FLEXProperty *p, NSUInteger idx) { - if (p.likelyGetterExists) { - if (p.likelySetterExists) { - return @[p.likelyGetterString, p.likelySetterString]; - } - - return @[p.likelyGetterString]; - } else if (p.likelySetterExists) { - return @[p.likelySetterString]; - } - - return nil; - }]; - })]; - - // Remove methods whose name is in the property method names list - return [list flex_filtered:^BOOL(FLEXMethod *method, NSUInteger idx) { - return ![methodNames containsObject:method.selectorString]; - }]; - }]; - } - - if (hidePrivateMethods) { - id methodMapBlock = ^id(NSArray *list, NSUInteger idx) { - // Remove methods which contain an underscore - return [list flex_filtered:^BOOL(FLEXMethod *method, NSUInteger idx) { - return ![method.selectorString containsString:@"_"]; - }]; - }; - id propertyMapBlock = ^id(NSArray *list, NSUInteger idx) { - // Remove methods which contain an underscore - return [list flex_filtered:^BOOL(FLEXProperty *prop, NSUInteger idx) { - return ![prop.name containsString:@"_"]; - }]; - }; - - allMethods = [allMethods flex_mapped:methodMapBlock]; - allClassMethods = [allClassMethods flex_mapped:methodMapBlock]; - allProperties = [allProperties flex_mapped:propertyMapBlock]; - allClassProps = [allClassProps flex_mapped:propertyMapBlock]; - } - - _allProperties = allProperties; - _allClassProperties = allClassProps; - _allMethods = allMethods; - _allClassMethods = allClassMethods; - - // Set up UIKit helper data - // Really, we only need to call this on properties and ivars - // because no other metadata types support editing. - NSArray*metadatas = @[ - _allProperties, _allClassProperties, _allIvars, - /* _allMethods, _allClassMethods, _allConformedProtocols */ - ]; - for (NSArray *matrix in metadatas) { - for (NSArray *metadataByClass in matrix) { - [FLEXObjectExplorer configureDefaultsForItems:metadataByClass]; - } - } - - [self reloadScopedMetadata]; -} - - -#pragma mark - Private - -- (void)reloadScopedMetadata { - _properties = self.allProperties[self.classScope]; - _classProperties = self.allClassProperties[self.classScope]; - _ivars = self.allIvars[self.classScope]; - _methods = self.allMethods[self.classScope]; - _classMethods = self.allClassMethods[self.classScope]; - _conformedProtocols = self.allConformedProtocols[self.classScope]; - _instanceSize = self.allInstanceSizes[self.classScope]; - _imageName = self.allImageNames[self.classScope]; -} - -/// Accepts an array of flex metadata objects and discards objects -/// with duplicate names, as well as properties and methods which -/// aren't "new" (i.e. those which the superclass responds to) -- (NSArray *)metadataUniquedByName:(NSArray *)list - superclass:(Class)superclass - kind:(FLEXMetadataKind)kind - skip:(BOOL)skipUniquing { - if (skipUniquing) { - return list; - } - - // Remove items with same name and return filtered list - NSMutableSet *names = [NSMutableSet new]; - return [list flex_filtered:^BOOL(id obj, NSUInteger idx) { - NSString *name = [obj name]; - if ([names containsObject:name]) { - return NO; - } else { - [names addObject:name]; - - // Skip methods and properties which are just overrides, - // potentially skip ivars and methods associated with properties - switch (kind) { - case FLEXMetadataKindProperties: - if ([superclass instancesRespondToSelector:[obj likelyGetter]]) { - return NO; - } - break; - case FLEXMetadataKindClassProperties: - if ([superclass respondsToSelector:[obj likelyGetter]]) { - return NO; - } - break; - case FLEXMetadataKindMethods: - if ([superclass instancesRespondToSelector:NSSelectorFromString(name)]) { - return NO; - } - break; - case FLEXMetadataKindClassMethods: - if ([superclass respondsToSelector:NSSelectorFromString(name)]) { - return NO; - } - break; - - case FLEXMetadataKindProtocols: - case FLEXMetadataKindClassHierarchy: - case FLEXMetadataKindOther: - return YES; // These types are already uniqued - break; - - // Ivars cannot be overidden - case FLEXMetadataKindIvars: break; - } - - return YES; - } - }]; -} - - -#pragma mark - Superclasses - -- (void)reloadClassHierarchy { - // The class hierarchy will never contain metaclass objects by this logic; - // it is always the same for a given class and instances of it - _classHierarchyClasses = [[self.object class] flex_classHierarchy]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerFactory.h b/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerFactory.h deleted file mode 100644 index 2d5e840..0000000 --- a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerFactory.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// FLEXObjectExplorerFactory.h -// Flipboard -// -// Created by Ryan Olson on 5/15/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXGlobalsEntry.h" - -#ifndef _FLEXObjectExplorerViewController_h -#import "FLEXObjectExplorerViewController.h" -#else -@class FLEXObjectExplorerViewController; -#endif - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXObjectExplorerFactory : NSObject - -+ (nullable FLEXObjectExplorerViewController *)explorerViewControllerForObject:(nullable id)object; - -/// Register a specific explorer view controller class to be used when exploring -/// an object of a specific class. Calls will overwrite existing registrations. -/// Sections must be initialized using \c forObject: like -+ (void)registerExplorerSection:(Class)sectionClass forClass:(Class)objectClass; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerFactory.m b/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerFactory.m deleted file mode 100644 index e5bd791..0000000 --- a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerFactory.m +++ /dev/null @@ -1,243 +0,0 @@ -// -// FLEXObjectExplorerFactory.m -// Flipboard -// -// Created by Ryan Olson on 5/15/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectExplorerFactory.h" -#import "FLEXGlobalsViewController.h" -#import "FLEXClassShortcuts.h" -#import "FLEXViewShortcuts.h" -#import "FLEXViewControllerShortcuts.h" -#import "FLEXUIAppShortcuts.h" -#import "FLEXImageShortcuts.h" -#import "FLEXLayerShortcuts.h" -#import "FLEXColorPreviewSection.h" -#import "FLEXDefaultsContentSection.h" -#import "FLEXBundleShortcuts.h" -#import "FLEXNSStringShortcuts.h" -#import "FLEXNSDataShortcuts.h" -#import "FLEXBlockShortcuts.h" -#import "FLEXUtility.h" - -@implementation FLEXObjectExplorerFactory -static NSMutableDictionary, Class> *classesToRegisteredSections = nil; - -+ (void)initialize { - if (self == [FLEXObjectExplorerFactory class]) { - // DO NOT USE STRING KEYS HERE - // We NEED to use the class as a key, because we CANNOT - // differentiate a class's name from the metaclass's name. - // These mappings are per-class-object, not per-class-name. - // - // For example, if we used class names, this would result in - // the object explorer trying to render a color preview for - // the UIColor class object, which is not a color itself. - #define ClassKey(name) (id)[name class] - #define ClassKeyByName(str) (id)NSClassFromString(@ #str) - #define MetaclassKey(meta) (id)object_getClass([meta class]) - classesToRegisteredSections = [NSMutableDictionary dictionaryWithDictionary:@{ - MetaclassKey(NSObject) : [FLEXClassShortcuts class], - ClassKey(NSArray) : [FLEXCollectionContentSection class], - ClassKey(NSSet) : [FLEXCollectionContentSection class], - ClassKey(NSDictionary) : [FLEXCollectionContentSection class], - ClassKey(NSOrderedSet) : [FLEXCollectionContentSection class], - ClassKey(NSUserDefaults) : [FLEXDefaultsContentSection class], - ClassKey(UIViewController) : [FLEXViewControllerShortcuts class], - ClassKey(UIApplication) : [FLEXUIAppShortcuts class], - ClassKey(UIView) : [FLEXViewShortcuts class], - ClassKey(UIImage) : [FLEXImageShortcuts class], - ClassKey(CALayer) : [FLEXLayerShortcuts class], - ClassKey(UIColor) : [FLEXColorPreviewSection class], - ClassKey(NSBundle) : [FLEXBundleShortcuts class], - ClassKey(NSString) : [FLEXNSStringShortcuts class], - ClassKey(NSData) : [FLEXNSDataShortcuts class], - ClassKeyByName(NSBlock) : [FLEXBlockShortcuts class], - }]; - #undef ClassKey - #undef ClassKeyByName - #undef MetaclassKey - } -} - -+ (FLEXObjectExplorerViewController *)explorerViewControllerForObject:(id)object { - // Can't explore nil - if (!object) { - return nil; - } - - // If we're given an object, this will look up it's class hierarchy - // until it finds a registration. This will work for KVC classes, - // since they are children of the original class, and not siblings. - // If we are given an object, object_getClass will return a metaclass, - // and the same thing will happen. FLEXClassShortcuts is the default - // shortcut section for NSObject. - // - // TODO: rename it to FLEXNSObjectShortcuts or something? - FLEXShortcutsSection *shortcutsSection = [FLEXShortcutsSection forObject:object]; - NSArray *sections = @[shortcutsSection]; - - Class customSectionClass = nil; - Class cls = object_getClass(object); - do { - customSectionClass = classesToRegisteredSections[(id)cls]; - } while (!customSectionClass && (cls = [cls superclass])); - - if (customSectionClass) { - id customSection = [customSectionClass forObject:object]; - BOOL isFLEXShortcutSection = [customSection respondsToSelector:@selector(isNewSection)]; - - // If the section "replaces" the default shortcuts section, - // only return that section. Otherwise, return both this - // section and the default shortcuts section. - if (isFLEXShortcutSection && ![customSection isNewSection]) { - sections = @[customSection]; - } else { - // Custom section will go before shortcuts - sections = @[customSection, shortcutsSection]; - } - } - - return [FLEXObjectExplorerViewController - exploringObject:object - customSections:sections - ]; -} - -+ (void)registerExplorerSection:(Class)explorerClass forClass:(Class)objectClass { - classesToRegisteredSections[(id)objectClass] = explorerClass; -} - -#pragma mark - FLEXGlobalsEntry - -+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { - switch (row) { - case FLEXGlobalsRowAppDelegate: - return @"🎟 App Delegate"; - case FLEXGlobalsRowKeyWindow: - return @"🔑 Key Window"; - case FLEXGlobalsRowRootViewController: - return @"🌴 Root View Controller"; - case FLEXGlobalsRowProcessInfo: - return @"🚦 NSProcessInfo.processInfo"; - case FLEXGlobalsRowUserDefaults: - return @"💾 Preferences"; - case FLEXGlobalsRowMainBundle: - return @"📦 NSBundle.mainBundle"; - case FLEXGlobalsRowApplication: - return @"🚀 UIApplication.sharedApplication"; - case FLEXGlobalsRowMainScreen: - return @"💻 UIScreen.mainScreen"; - case FLEXGlobalsRowCurrentDevice: - return @"📱 UIDevice.currentDevice"; - case FLEXGlobalsRowPasteboard: - return @"📋 UIPasteboard.generalPasteboard"; - case FLEXGlobalsRowURLSession: - return @"📡 NSURLSession.sharedSession"; - case FLEXGlobalsRowURLCache: - return @"⏳ NSURLCache.sharedURLCache"; - case FLEXGlobalsRowNotificationCenter: - return @"🔔 NSNotificationCenter.defaultCenter"; - case FLEXGlobalsRowMenuController: - return @"📎 UIMenuController.sharedMenuController"; - case FLEXGlobalsRowFileManager: - return @"🗄 NSFileManager.defaultManager"; - case FLEXGlobalsRowTimeZone: - return @"🌎 NSTimeZone.systemTimeZone"; - case FLEXGlobalsRowLocale: - return @"🗣 NSLocale.currentLocale"; - case FLEXGlobalsRowCalendar: - return @"📅 NSCalendar.currentCalendar"; - case FLEXGlobalsRowMainRunLoop: - return @"🏃🏻‍♂️ NSRunLoop.mainRunLoop"; - case FLEXGlobalsRowMainThread: - return @"🧵 NSThread.mainThread"; - case FLEXGlobalsRowOperationQueue: - return @"📚 NSOperationQueue.mainQueue"; - default: return nil; - } -} - -+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { - switch (row) { - case FLEXGlobalsRowAppDelegate: { - id appDelegate = UIApplication.sharedApplication.delegate; - return [self explorerViewControllerForObject:appDelegate]; - } - case FLEXGlobalsRowProcessInfo: - return [self explorerViewControllerForObject:NSProcessInfo.processInfo]; - case FLEXGlobalsRowUserDefaults: - return [self explorerViewControllerForObject:NSUserDefaults.standardUserDefaults]; - case FLEXGlobalsRowMainBundle: - return [self explorerViewControllerForObject:NSBundle.mainBundle]; - case FLEXGlobalsRowApplication: - return [self explorerViewControllerForObject:UIApplication.sharedApplication]; - case FLEXGlobalsRowMainScreen: - return [self explorerViewControllerForObject:UIScreen.mainScreen]; - case FLEXGlobalsRowCurrentDevice: - return [self explorerViewControllerForObject:UIDevice.currentDevice]; - case FLEXGlobalsRowPasteboard: - return [self explorerViewControllerForObject:UIPasteboard.generalPasteboard]; - case FLEXGlobalsRowURLSession: - return [self explorerViewControllerForObject:NSURLSession.sharedSession]; - case FLEXGlobalsRowURLCache: - return [self explorerViewControllerForObject:NSURLCache.sharedURLCache]; - case FLEXGlobalsRowNotificationCenter: - return [self explorerViewControllerForObject:NSNotificationCenter.defaultCenter]; - case FLEXGlobalsRowMenuController: - return [self explorerViewControllerForObject:UIMenuController.sharedMenuController]; - case FLEXGlobalsRowFileManager: - return [self explorerViewControllerForObject:NSFileManager.defaultManager]; - case FLEXGlobalsRowTimeZone: - return [self explorerViewControllerForObject:NSTimeZone.systemTimeZone]; - case FLEXGlobalsRowLocale: - return [self explorerViewControllerForObject:NSLocale.currentLocale]; - case FLEXGlobalsRowCalendar: - return [self explorerViewControllerForObject:NSCalendar.currentCalendar]; - case FLEXGlobalsRowMainRunLoop: - return [self explorerViewControllerForObject:NSRunLoop.mainRunLoop]; - case FLEXGlobalsRowMainThread: - return [self explorerViewControllerForObject:NSThread.mainThread]; - case FLEXGlobalsRowOperationQueue: - return [self explorerViewControllerForObject:NSOperationQueue.mainQueue]; - - case FLEXGlobalsRowKeyWindow: - return [FLEXObjectExplorerFactory - explorerViewControllerForObject:FLEXUtility.appKeyWindow - ]; - case FLEXGlobalsRowRootViewController: { - id delegate = UIApplication.sharedApplication.delegate; - if ([delegate respondsToSelector:@selector(window)]) { - return [self explorerViewControllerForObject:delegate.window.rootViewController]; - } - - return nil; - } - default: return nil; - } -} - -+ (FLEXGlobalsEntryRowAction)globalsEntryRowAction:(FLEXGlobalsRow)row { - switch (row) { - case FLEXGlobalsRowRootViewController: { - // Check if the app delegate responds to -window. If not, present an alert - return ^(UITableViewController *host) { - id delegate = UIApplication.sharedApplication.delegate; - if ([delegate respondsToSelector:@selector(window)]) { - UIViewController *explorer = [self explorerViewControllerForObject: - delegate.window.rootViewController - ]; - [host.navigationController pushViewController:explorer animated:YES]; - } else { - NSString *msg = @"The app delegate doesn't respond to -window"; - [FLEXAlert showAlert:@":(" message:msg from:host]; - } - }; - } - default: return nil; - } -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerViewController.h b/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerViewController.h deleted file mode 100644 index 849bea2..0000000 --- a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerViewController.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// FLEXObjectExplorerViewController.h -// Flipboard -// -// Created by Ryan Olson on 2014-05-03. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#ifndef _FLEXObjectExplorerViewController_h -#define _FLEXObjectExplorerViewController_h -#endif - -#import "FLEXFilteringTableViewController.h" -#import "FLEXObjectExplorer.h" -@class FLEXTableViewSection; - -NS_ASSUME_NONNULL_BEGIN - -/// A class that displays information about an object or class. -/// -/// The explorer view controller uses \c FLEXObjectExplorer to provide a description -/// of the object and list it's properties, ivars, methods, and it's superclasses. -/// Below the description and before properties, some shortcuts will be displayed -/// for certain classes like UIViews. At very bottom, there is an option to view -/// a list of other objects found to be referencing the object being explored. -@interface FLEXObjectExplorerViewController : FLEXFilteringTableViewController - -/// Uses the default \c FLEXShortcutsSection for this object as a custom section. -+ (instancetype)exploringObject:(id)objectOrClass; -/// No custom section unless you provide one. -+ (instancetype)exploringObject:(id)objectOrClass customSection:(nullable FLEXTableViewSection *)customSection; -/// No custom sections unless you provide some. -+ (instancetype)exploringObject:(id)objectOrClass - customSections:(nullable NSArray *)customSections; - -/// The object being explored, which may be an instance of a class or a class itself. -@property (nonatomic, readonly) id object; -/// This object provides the object's metadata for the explorer view controller. -@property (nonatomic, readonly) FLEXObjectExplorer *explorer; - -/// Called once to initialize the list of section objects. -/// -/// Subclasses can override this to add, remove, or rearrange sections of the explorer. -- (NSArray *)makeSections; - -/// Whether to allow showing/drilling in to current values for ivars and properties. Default is YES. -@property (nonatomic, readonly) BOOL canHaveInstanceState; - -/// Whether to allow drilling in to method calling interfaces for instance methods. Default is YES. -@property (nonatomic, readonly) BOOL canCallInstanceMethods; - -/// If the custom section data makes the description redundant, subclasses can choose to hide it. Default is YES. -@property (nonatomic, readonly) BOOL shouldShowDescription; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerViewController.m b/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerViewController.m deleted file mode 100644 index d94ada0..0000000 --- a/Tweaks/FLEX/ObjectExplorers/FLEXObjectExplorerViewController.m +++ /dev/null @@ -1,393 +0,0 @@ -// -// FLEXObjectExplorerViewController.m -// Flipboard -// -// Created by Ryan Olson on 2014-05-03. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectExplorerViewController.h" -#import "FLEXUtility.h" -#import "FLEXRuntimeUtility.h" -#import "UIBarButtonItem+FLEX.h" -#import "FLEXMultilineTableViewCell.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXFieldEditorViewController.h" -#import "FLEXMethodCallingViewController.h" -#import "FLEXObjectListViewController.h" -#import "FLEXTabsViewController.h" -#import "FLEXBookmarkManager.h" -#import "FLEXTableView.h" -#import "FLEXResources.h" -#import "FLEXTableViewCell.h" -#import "FLEXScopeCarousel.h" -#import "FLEXMetadataSection.h" -#import "FLEXSingleRowSection.h" -#import "FLEXShortcutsSection.h" -#import "NSUserDefaults+FLEX.h" -#import - -#pragma mark - Private properties -@interface FLEXObjectExplorerViewController () -@property (nonatomic, readonly) FLEXSingleRowSection *descriptionSection; -@property (nonatomic, readonly) NSArray *customSections; -@property (nonatomic) NSIndexSet *customSectionVisibleIndexes; - -@property (nonatomic, readonly) NSArray *observedNotifications; - -@end - -@implementation FLEXObjectExplorerViewController - -#pragma mark - Initialization - -+ (instancetype)exploringObject:(id)target { - return [self exploringObject:target customSection:[FLEXShortcutsSection forObject:target]]; -} - -+ (instancetype)exploringObject:(id)target customSection:(FLEXTableViewSection *)section { - return [self exploringObject:target customSections:@[section]]; -} - -+ (instancetype)exploringObject:(id)target customSections:(NSArray *)customSections { - return [[self alloc] - initWithObject:target - explorer:[FLEXObjectExplorer forObject:target] - customSections:customSections - ]; -} - -- (id)initWithObject:(id)target - explorer:(__kindof FLEXObjectExplorer *)explorer - customSections:(NSArray *)customSections { - NSParameterAssert(target); - - self = [super initWithStyle:UITableViewStyleGrouped]; - if (self) { - _object = target; - _explorer = explorer; - _customSections = customSections; - } - - return self; -} - -- (NSArray *)observedNotifications { - return @[ - kFLEXDefaultsHidePropertyIvarsKey, - kFLEXDefaultsHidePropertyMethodsKey, - kFLEXDefaultsHidePrivateMethodsKey, - kFLEXDefaultsShowMethodOverridesKey, - kFLEXDefaultsHideVariablePreviewsKey, - ]; -} - -#pragma mark - View controller lifecycle - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.showsShareToolbarItem = YES; - self.wantsSectionIndexTitles = YES; - - // Use [object class] here rather than object_getClass - // to avoid the KVO prefix for observed objects - self.title = [FLEXRuntimeUtility safeClassNameForObject:self.object]; - - // Search - self.showsSearchBar = YES; - self.searchBarDebounceInterval = kFLEXDebounceInstant; - self.showsCarousel = YES; - - // Carousel scope bar - [self.explorer reloadClassHierarchy]; - self.carousel.items = [self.explorer.classHierarchyClasses flex_mapped:^id(Class cls, NSUInteger idx) { - return NSStringFromClass(cls); - }]; - - // ... button for extra options - [self addToolbarItems:@[[UIBarButtonItem - flex_itemWithImage:FLEXResources.moreIcon target:self action:@selector(moreButtonPressed:) - ]]]; - - // Swipe gestures to swipe between classes in the hierarchy - UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc] - initWithTarget:self action:@selector(handleSwipeGesture:) - ]; - UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc] - initWithTarget:self action:@selector(handleSwipeGesture:) - ]; - leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft; - rightSwipe.direction = UISwipeGestureRecognizerDirectionRight; - leftSwipe.delegate = self; - rightSwipe.delegate = self; - [self.tableView addGestureRecognizer:leftSwipe]; - [self.tableView addGestureRecognizer:rightSwipe]; - - // Observe preferences which may change on other screens - // - // "If your app targets iOS 9.0 and later or macOS 10.11 and later, - // you don't need to unregister an observer in its dealloc method." - for (NSString *pref in self.observedNotifications) { - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(fullyReloadData) - name:pref - object:nil - ]; - } -} - -- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView { - [self.navigationController setToolbarHidden:NO animated:YES]; - return YES; -} - - -#pragma mark - Overrides - -/// Override to hide the description section when searching -- (NSArray *)nonemptySections { - if (self.shouldShowDescription) { - return super.nonemptySections; - } - - return [super.nonemptySections flex_filtered:^BOOL(FLEXTableViewSection *section, NSUInteger idx) { - return section != self.descriptionSection; - }]; -} - -- (NSArray *)makeSections { - FLEXObjectExplorer *explorer = self.explorer; - - // Description section is only for instances - if (self.explorer.objectIsInstance) { - _descriptionSection = [FLEXSingleRowSection - title:@"Description" reuse:kFLEXMultilineCell cell:^(FLEXTableViewCell *cell) { - cell.titleLabel.font = UIFont.flex_defaultTableCellFont; - cell.titleLabel.text = explorer.objectDescription; - } - ]; - self.descriptionSection.filterMatcher = ^BOOL(NSString *filterText) { - return [explorer.objectDescription localizedCaseInsensitiveContainsString:filterText]; - }; - } - - // Object graph section - FLEXSingleRowSection *referencesSection = [FLEXSingleRowSection - title:@"Object Graph" reuse:kFLEXDefaultCell cell:^(FLEXTableViewCell *cell) { - cell.titleLabel.text = @"See Objects with References to This Object"; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - ]; - referencesSection.selectionAction = ^(UIViewController *host) { - UIViewController *references = [FLEXObjectListViewController - objectsWithReferencesToObject:explorer.object - retained:NO - ]; - [host.navigationController pushViewController:references animated:YES]; - }; - - NSMutableArray *sections = [NSMutableArray arrayWithArray:@[ - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindProperties], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassProperties], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindIvars], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindMethods], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassMethods], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassHierarchy], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindProtocols], - [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindOther], - referencesSection - ]]; - - if (self.customSections) { - [sections insertObjects:self.customSections atIndexes:[NSIndexSet - indexSetWithIndexesInRange:NSMakeRange(0, self.customSections.count) - ]]; - } - if (self.descriptionSection) { - [sections insertObject:self.descriptionSection atIndex:0]; - } - - return sections.copy; -} - -/// In our case, all this does is reload the table view, -/// or reload the sections' data if we changed places -/// in the class hierarchy. Doesn't refresh \c self.explorer -- (void)reloadData { - // Check to see if class scope changed, update accordingly - if (self.explorer.classScope != self.selectedScope) { - self.explorer.classScope = self.selectedScope; - [self reloadSections]; - } - - [super reloadData]; -} - -- (void)shareButtonPressed:(UIBarButtonItem *)sender { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - make.button(@"Add to Bookmarks").handler(^(NSArray *strings) { - [FLEXBookmarkManager.bookmarks addObject:self.object]; - }); - make.button(@"Copy Description").handler(^(NSArray *strings) { - UIPasteboard.generalPasteboard.string = self.explorer.objectDescription; - }); - make.button(@"Copy Address").handler(^(NSArray *strings) { - UIPasteboard.generalPasteboard.string = [FLEXUtility addressOfObject:self.object]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; -} - - -#pragma mark - Private - -/// Unlike \c -reloadData, this refreshes everything, including the explorer. -- (void)fullyReloadData { - [self.explorer reloadMetadata]; - [self reloadSections]; - [self reloadData]; -} - -- (void)handleSwipeGesture:(UISwipeGestureRecognizer *)gesture { - if (gesture.state == UIGestureRecognizerStateEnded) { - switch (gesture.direction) { - case UISwipeGestureRecognizerDirectionRight: - if (self.selectedScope > 0) { - self.selectedScope -= 1; - } - break; - case UISwipeGestureRecognizerDirectionLeft: - if (self.selectedScope != self.explorer.classHierarchy.count - 1) { - self.selectedScope += 1; - } - break; - - default: - break; - } - } -} - -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)g1 shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)g2 { - // Prioritize important pan gestures over our swipe gesture - if ([g2 isKindOfClass:[UIPanGestureRecognizer class]]) { - if (g2 == self.navigationController.interactivePopGestureRecognizer) { - return NO; - } - - if (g2 == self.tableView.panGestureRecognizer) { - return NO; - } - } - - return YES; -} - -- (BOOL)gestureRecognizerShouldBegin:(UISwipeGestureRecognizer *)gesture { - // Don't allow swiping from the carousel - CGPoint location = [gesture locationInView:self.tableView]; - if ([self.carousel hitTest:location withEvent:nil]) { - return NO; - } - - return YES; -} - -- (void)moreButtonPressed:(UIBarButtonItem *)sender { - NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; - // Maps preference keys to a description of what they affect - NSDictionary *explorerToggles = @{ - kFLEXDefaultsHidePropertyIvarsKey: @"Property-Backing Ivars", - kFLEXDefaultsHidePropertyMethodsKey: @"Property-Backing Methods", - kFLEXDefaultsHidePrivateMethodsKey: @"Likely Private Methods", - kFLEXDefaultsShowMethodOverridesKey: @"Method Overrides", - kFLEXDefaultsHideVariablePreviewsKey: @"Variable Previews" - }; - - // Maps the key of the action itself to a map of a description - // of the action ("hide X") mapped to the current state. - // - // So keys that are hidden by default have NO mapped to "Show" - NSDictionary *nextStateDescriptions = @{ - kFLEXDefaultsHidePropertyIvarsKey: @{ @NO: @"Hide ", @YES: @"Show " }, - kFLEXDefaultsHidePropertyMethodsKey: @{ @NO: @"Hide ", @YES: @"Show " }, - kFLEXDefaultsHidePrivateMethodsKey: @{ @NO: @"Hide ", @YES: @"Show " }, - kFLEXDefaultsShowMethodOverridesKey: @{ @NO: @"Show ", @YES: @"Hide " }, - kFLEXDefaultsHideVariablePreviewsKey: @{ @NO: @"Hide ", @YES: @"Show " }, - }; - - [FLEXAlert makeSheet:^(FLEXAlert *make) { - make.title(@"Options"); - - for (NSString *option in explorerToggles.allKeys) { - BOOL current = [defaults boolForKey:option]; - NSString *title = [nextStateDescriptions[option][@(current)] - stringByAppendingString:explorerToggles[option] - ]; - make.button(title).handler(^(NSArray *strings) { - [NSUserDefaults.standardUserDefaults flex_toggleBoolForKey:option]; - [self fullyReloadData]; - }); - } - - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; -} - -#pragma mark - Description - -- (BOOL)shouldShowDescription { - // Hide if we have filter text; it is rarely - // useful to see the description when searching - // since it's already at the top of the screen - if (self.filterText.length) { - return NO; - } - - return YES; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - // For the description section, we want that nice slim/snug looking row. - // Other rows use the automatic size. - FLEXTableViewSection *section = self.filterDelegate.sections[indexPath.section]; - - if (section == self.descriptionSection) { - NSAttributedString *attributedText = [[NSAttributedString alloc] - initWithString:self.explorer.objectDescription - attributes:@{ NSFontAttributeName : UIFont.flex_defaultTableCellFont } - ]; - - return [FLEXMultilineTableViewCell - preferredHeightWithAttributedText:attributedText - maxWidth:tableView.frame.size.width - tableView.separatorInset.right - style:tableView.style - showsAccessory:NO - ]; - } - - return UITableViewAutomaticDimension; -} - -- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - return self.filterDelegate.sections[indexPath.section] == self.descriptionSection; -} - -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - // Only the description section has "actions" - if (self.filterDelegate.sections[indexPath.section] == self.descriptionSection) { - return action == @selector(copy:); - } - - return NO; -} - -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - if (action == @selector(copy:)) { - UIPasteboard.generalPasteboard.string = self.explorer.objectDescription; - } -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXCollectionContentSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXCollectionContentSection.h deleted file mode 100644 index 8ca05f2..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXCollectionContentSection.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// FLEXCollectionContentSection.h -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewSection.h" -#import "FLEXObjectInfoSection.h" -@class FLEXCollectionContentSection, FLEXTableViewCell; -@protocol FLEXCollection, FLEXMutableCollection; - -/// Any foundation collection implicitly conforms to FLEXCollection. -/// This future should return one. We don't explicitly put FLEXCollection -/// here because making generic collections conform to FLEXCollection breaks -/// compile-time features of generic arrays, such as \c someArray[0].property -typedef id(^FLEXCollectionContentFuture)(__kindof FLEXCollectionContentSection *section); - -#pragma mark Collection -/// A protocol that enables \c FLEXCollectionContentSection to operate on any arbitrary collection. -/// \c NSArray, \c NSDictionary, \c NSSet, and \c NSOrderedSet all conform to this protocol. -@protocol FLEXCollection - -@property (nonatomic, readonly) NSUInteger count; - -- (id)copy; -- (id)mutableCopy; - -@optional - -/// Unordered, unkeyed collections must implement this -@property (nonatomic, readonly) NSArray *allObjects; -/// Keyed collections must implement this and \c objectForKeyedSubscript: -@property (nonatomic, readonly) NSArray *allKeys; - -/// Ordered, indexed collections must implement this. -- (id)objectAtIndexedSubscript:(NSUInteger)idx; -/// Keyed, unordered collections must implement this and \c allKeys -- (id)objectForKeyedSubscript:(id)idx; - -@end - -@protocol FLEXMutableCollection -- (void)filterUsingPredicate:(NSPredicate *)predicate; -@end - - -#pragma mark - FLEXCollectionContentSection -/// A custom section for viewing collection elements. -/// -/// Tapping on a row pushes an object explorer for that element. -@interface FLEXCollectionContentSection<__covariant ObjectType> : FLEXTableViewSection { - @protected - /// Unused if initialized with a future - id _collection; - /// Unused if initialized with a collection - FLEXCollectionContentFuture _collectionFuture; - /// The filtered collection from \c _collection or \c _collectionFuture - id _cachedCollection; -} - -+ (instancetype)forCollection:(id)collection; -/// The future given should be safe to call more than once. -/// The result of calling this future multiple times may yield -/// different results each time if the data is changing by nature. -+ (instancetype)forReusableFuture:(FLEXCollectionContentFuture)collectionFuture; - -/// Defaults to \c NO -@property (nonatomic) BOOL hideSectionTitle; -/// Defaults to \c nil -@property (nonatomic, copy) NSString *customTitle; -/// Defaults to \c NO -/// -/// Settings this to \c NO will not display the element index for ordered collections. -/// This property only applies to \c NSArray or \c NSOrderedSet and their subclasses. -@property (nonatomic) BOOL hideOrderIndexes; - -/// Set this property to provide a custom filter matcher. -/// -/// By default, the collection will filter on the title and subtitle of the row. -/// So if you don't ever call \c configureCell: for example, you will need to set -/// this property so that your filter logic will match how you're setting up the cell. -@property (nonatomic) BOOL (^customFilter)(NSString *filterText, ObjectType element); - -/// Get the object in the collection associated with the given row. -/// For dictionaries, this returns the value, not the key. -- (ObjectType)objectForRow:(NSInteger)row; - -/// Subclasses may override. -- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXCollectionContentSection.m b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXCollectionContentSection.m deleted file mode 100644 index 8286232..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXCollectionContentSection.m +++ /dev/null @@ -1,246 +0,0 @@ -// -// FLEXCollectionContentSection.m -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXCollectionContentSection.h" -#import "FLEXUtility.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXSubtitleTableViewCell.h" -#import "FLEXTableView.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXDefaultEditorViewController.h" - -typedef NS_ENUM(NSUInteger, FLEXCollectionType) { - FLEXUnsupportedCollection, - FLEXOrderedCollection, - FLEXUnorderedCollection, - FLEXKeyedCollection -}; - -@interface NSArray (FLEXCollection) @end -@interface NSSet (FLEXCollection) @end -@interface NSOrderedSet (FLEXCollection) @end -@interface NSDictionary (FLEXCollection) @end - -@interface NSMutableArray (FLEXMutableCollection) @end -@interface NSMutableSet (FLEXMutableCollection) @end -@interface NSMutableOrderedSet (FLEXMutableCollection) @end -@interface NSMutableDictionary (FLEXMutableCollection) -- (void)filterUsingPredicate:(NSPredicate *)predicate; -@end - -@interface FLEXCollectionContentSection () -/// Generated from \c collectionFuture or \c collection -@property (nonatomic, copy) id cachedCollection; -/// A static collection to display -@property (nonatomic, readonly) id collection; -/// A collection that may change over time and can be called upon for new data -@property (nonatomic, readonly) FLEXCollectionContentFuture collectionFuture; -@property (nonatomic, readonly) FLEXCollectionType collectionType; -@property (nonatomic, readonly) BOOL isMutable; -@end - -@implementation FLEXCollectionContentSection -@synthesize filterText = _filterText; - -#pragma mark Initialization - -+ (instancetype)forObject:(id)object { - return [self forCollection:object]; -} - -+ (id)forCollection:(id)collection { - FLEXCollectionContentSection *section = [self new]; - section->_collectionType = [self typeForCollection:collection]; - section->_collection = collection; - section.cachedCollection = collection; - section->_isMutable = [collection respondsToSelector:@selector(filterUsingPredicate:)]; - return section; -} - -+ (id)forReusableFuture:(FLEXCollectionContentFuture)collectionFuture { - FLEXCollectionContentSection *section = [self new]; - section->_collectionFuture = collectionFuture; - section.cachedCollection = (id)collectionFuture(section); - section->_collectionType = [self typeForCollection:section.cachedCollection]; - section->_isMutable = [section->_cachedCollection respondsToSelector:@selector(filterUsingPredicate:)]; - return section; -} - - -#pragma mark - Misc - -+ (FLEXCollectionType)typeForCollection:(id)collection { - // Order matters here, as NSDictionary is keyed but it responds to allObjects - if ([collection respondsToSelector:@selector(objectAtIndex:)]) { - return FLEXOrderedCollection; - } - if ([collection respondsToSelector:@selector(objectForKey:)]) { - return FLEXKeyedCollection; - } - if ([collection respondsToSelector:@selector(allObjects)]) { - return FLEXUnorderedCollection; - } - - [NSException raise:NSInvalidArgumentException - format:@"Given collection does not properly conform to FLEXCollection"]; - return FLEXUnsupportedCollection; -} - -/// Row titles -/// - Ordered: the index -/// - Unordered: the object -/// - Keyed: the key -- (NSString *)titleForRow:(NSInteger)row { - switch (self.collectionType) { - case FLEXOrderedCollection: - if (!self.hideOrderIndexes) { - return @(row).stringValue; - } - // Fall-through - case FLEXUnorderedCollection: - return [self describe:[self objectForRow:row]]; - case FLEXKeyedCollection: - return [self describe:self.cachedCollection.allKeys[row]]; - - case FLEXUnsupportedCollection: - return nil; - } -} - -/// Row subtitles -/// - Ordered: the object -/// - Unordered: nothing -/// - Keyed: the value -- (NSString *)subtitleForRow:(NSInteger)row { - switch (self.collectionType) { - case FLEXOrderedCollection: - if (!self.hideOrderIndexes) { - nil; - } - // Fall-through - case FLEXKeyedCollection: - return [self describe:[self objectForRow:row]]; - case FLEXUnorderedCollection: - return nil; - - case FLEXUnsupportedCollection: - return nil; - } -} - -- (NSString *)describe:(id)object { - return [FLEXRuntimeUtility summaryForObject:object]; -} - -- (id)objectForRow:(NSInteger)row { - switch (self.collectionType) { - case FLEXOrderedCollection: - return self.cachedCollection[row]; - case FLEXUnorderedCollection: - return self.cachedCollection.allObjects[row]; - case FLEXKeyedCollection: - return self.cachedCollection[self.cachedCollection.allKeys[row]]; - - case FLEXUnsupportedCollection: - return nil; - } -} - -- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row { - return UITableViewCellAccessoryDisclosureIndicator; -// return self.isMutable ? UITableViewCellAccessoryDetailDisclosureButton : UITableViewCellAccessoryDisclosureIndicator; -} - - -#pragma mark - Overrides - -- (NSString *)title { - if (!self.hideSectionTitle) { - if (self.customTitle) { - return self.customTitle; - } - - return FLEXPluralString(self.cachedCollection.count, @"Entries", @"Entry"); - } - - return nil; -} - -- (NSInteger)numberOfRows { - return self.cachedCollection.count; -} - -- (void)setFilterText:(NSString *)filterText { - super.filterText = filterText; - - if (filterText.length) { - BOOL (^matcher)(id, id) = self.customFilter ?: ^BOOL(NSString *query, id obj) { - return [[self describe:obj] localizedCaseInsensitiveContainsString:query]; - }; - - NSPredicate *filter = [NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *bindings) { - return matcher(filterText, obj); - }]; - - id tmp = self.cachedCollection.mutableCopy; - [tmp filterUsingPredicate:filter]; - self.cachedCollection = tmp; - } else { - self.cachedCollection = self.collection ?: (id)self.collectionFuture(self); - } -} - -- (void)reloadData { - if (self.collectionFuture) { - self.cachedCollection = (id)self.collectionFuture(self); - } else { - self.cachedCollection = self.collection.copy; - } -} - -- (BOOL)canSelectRow:(NSInteger)row { - return YES; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:[self objectForRow:row]]; -} - -- (NSString *)reuseIdentifierForRow:(NSInteger)row { - return kFLEXDetailCell; -} - -- (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row { - cell.titleLabel.text = [self titleForRow:row]; - cell.subtitleLabel.text = [self subtitleForRow:row]; - cell.accessoryType = [self accessoryTypeForRow:row]; -} - -@end - - -#pragma mark - NSMutableDictionary - -@implementation NSMutableDictionary (FLEXMutableCollection) - -- (void)filterUsingPredicate:(NSPredicate *)predicate { - id test = ^BOOL(id key, NSUInteger idx, BOOL *stop) { - if ([predicate evaluateWithObject:key]) { - return NO; - } - - return ![predicate evaluateWithObject:self[key]]; - }; - - NSArray *keys = self.allKeys; - NSIndexSet *remove = [keys indexesOfObjectsPassingTest:test]; - - [self removeObjectsForKeys:[keys objectsAtIndexes:remove]]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXColorPreviewSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXColorPreviewSection.h deleted file mode 100644 index 90e771c..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXColorPreviewSection.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// FLEXColorPreviewSection.h -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXSingleRowSection.h" -#import "FLEXObjectInfoSection.h" - -@interface FLEXColorPreviewSection : FLEXSingleRowSection - -+ (instancetype)forObject:(UIColor *)color; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXColorPreviewSection.m b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXColorPreviewSection.m deleted file mode 100644 index 5fb4c8b..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXColorPreviewSection.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// FLEXColorPreviewSection.m -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColorPreviewSection.h" - -@implementation FLEXColorPreviewSection - -+ (instancetype)forObject:(UIColor *)color { - return [self title:@"Color" reuse:nil cell:^(__kindof UITableViewCell *cell) { - cell.backgroundColor = color; - }]; -} - -- (BOOL)canSelectRow:(NSInteger)row { - return NO; -} - -- (BOOL (^)(NSString *))filterMatcher { - return ^BOOL(NSString *filterText) { - // Hide when searching - return !filterText.length; - }; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXDefaultsContentSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXDefaultsContentSection.h deleted file mode 100644 index d794c76..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXDefaultsContentSection.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// FLEXDefaultsContentSection.h -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXCollectionContentSection.h" -#import "FLEXObjectInfoSection.h" - -@interface FLEXDefaultsContentSection : FLEXCollectionContentSection - -/// Uses \c NSUserDefaults.standardUserDefaults -+ (instancetype)standard; -+ (instancetype)forDefaults:(NSUserDefaults *)userDefaults; - -/// Whether or not to filter out keys not present in the app's user defaults file. -/// -/// This is useful for filtering out some useless keys that seem to appear -/// in every app's defaults but are never actually used or touched by the app. -/// Only applies to instances using \c NSUserDefaults.standardUserDefaults. -/// This is the default for any instance using \c standardUserDefaults, so -/// you must opt-out in those instances if you don't want this behavior. -@property (nonatomic) BOOL onlyShowKeysForAppPrefs; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXDefaultsContentSection.m b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXDefaultsContentSection.m deleted file mode 100644 index 15ef033..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXDefaultsContentSection.m +++ /dev/null @@ -1,117 +0,0 @@ -// -// FLEXDefaultsContentSection.m -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXDefaultsContentSection.h" -#import "FLEXDefaultEditorViewController.h" -#import "FLEXUtility.h" - -@interface FLEXDefaultsContentSection () -@property (nonatomic) NSUserDefaults *defaults; -@property (nonatomic) NSArray *keys; -@property (nonatomic, readonly) NSDictionary *unexcludedDefaults; -@end - -@implementation FLEXDefaultsContentSection -@synthesize keys = _keys; - -#pragma mark Initialization - -+ (instancetype)forObject:(id)object { - return [self forDefaults:object]; -} - -+ (instancetype)standard { - return [self forDefaults:NSUserDefaults.standardUserDefaults]; -} - -+ (instancetype)forDefaults:(NSUserDefaults *)userDefaults { - FLEXDefaultsContentSection *section = [self forReusableFuture:^id(FLEXDefaultsContentSection *section) { - section.defaults = userDefaults; - section.onlyShowKeysForAppPrefs = YES; - return section.unexcludedDefaults; - }]; - return section; -} - -#pragma mark - Overrides - -- (NSString *)title { - return @"Defaults"; -} - -- (void (^)(__kindof UIViewController *))didPressInfoButtonAction:(NSInteger)row { - return ^(UIViewController *host) { - if ([FLEXDefaultEditorViewController canEditDefaultWithValue:[self objectForRow:row]]) { - // We use titleForRow: to get the key because self.keys is not - // necessarily in the same order as the keys being displayed - FLEXVariableEditorViewController *controller = [FLEXDefaultEditorViewController - target:self.defaults key:[self titleForRow:row] commitHandler:^{ - [self reloadData:YES]; - } - ]; - [host.navigationController pushViewController:controller animated:YES]; - } else { - [FLEXAlert showAlert:@"Oh No…" message:@"We can't edit this entry :(" from:host]; - } - }; -} - -- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row { - return UITableViewCellAccessoryDetailDisclosureButton; -} - -#pragma mark - Private - -- (NSArray *)keys { - if (!_keys) { - if (self.onlyShowKeysForAppPrefs) { - // Read keys from preferences file - NSString *bundle = NSBundle.mainBundle.bundleIdentifier; - NSString *prefsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Preferences"]; - NSString *filePath = [NSString stringWithFormat:@"%@/%@.plist", prefsPath, bundle]; - self.keys = [NSDictionary dictionaryWithContentsOfFile:filePath].allKeys; - } else { - self.keys = self.defaults.dictionaryRepresentation.allKeys; - } - } - - return _keys; -} - -- (void)setKeys:(NSArray *)keys { - _keys = [keys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; -} - -- (NSDictionary *)unexcludedDefaults { - // Case: no excluding - if (!self.onlyShowKeysForAppPrefs) { - return self.defaults.dictionaryRepresentation; - } - - // Always regenerate key allowlist when this method is called - _keys = nil; - - // Generate new dictionary from unexcluded keys - NSArray *values = [self.defaults.dictionaryRepresentation - objectsForKeys:self.keys notFoundMarker:NSNull.null - ]; - return [NSDictionary dictionaryWithObjects:values forKeys:self.keys]; -} - -#pragma mark - Public - -- (void)setOnlyShowKeysForAppPrefs:(BOOL)onlyShowKeysForAppPrefs { - if (onlyShowKeysForAppPrefs) { - // This property only applies if we're using standardUserDefaults - if (self.defaults != NSUserDefaults.standardUserDefaults) return; - } - - _onlyShowKeysForAppPrefs = onlyShowKeysForAppPrefs; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMetadataSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMetadataSection.h deleted file mode 100644 index e96724f..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMetadataSection.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// FLEXMetadataSection.h -// FLEX -// -// Created by Tanner Bennett on 9/19/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewSection.h" -#import "FLEXObjectExplorer.h" - -typedef NS_ENUM(NSUInteger, FLEXMetadataKind) { - FLEXMetadataKindProperties = 1, - FLEXMetadataKindClassProperties, - FLEXMetadataKindIvars, - FLEXMetadataKindMethods, - FLEXMetadataKindClassMethods, - FLEXMetadataKindClassHierarchy, - FLEXMetadataKindProtocols, - FLEXMetadataKindOther -}; - -/// This section is used for displaying ObjC runtime metadata -/// about a class or object, such as listing methods, properties, etc. -@interface FLEXMetadataSection : FLEXTableViewSection - -+ (instancetype)explorer:(FLEXObjectExplorer *)explorer kind:(FLEXMetadataKind)metadataKind; - -@property (nonatomic, readonly) FLEXMetadataKind metadataKind; - -/// The names of metadata to exclude. Useful if you wish to group specific -/// properties or methods together in their own section outside of this one. -/// -/// Setting this property calls \c reloadData on this section. -@property (nonatomic) NSSet *excludedMetadata; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMetadataSection.m b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMetadataSection.m deleted file mode 100644 index d716015..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMetadataSection.m +++ /dev/null @@ -1,233 +0,0 @@ -// -// FLEXMetadataSection.m -// FLEX -// -// Created by Tanner Bennett on 9/19/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMetadataSection.h" -#import "FLEXTableView.h" -#import "FLEXTableViewCell.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXFieldEditorViewController.h" -#import "FLEXMethodCallingViewController.h" -#import "FLEXIvar.h" -#import "NSArray+FLEX.h" -#import "FLEXRuntime+UIKitHelpers.h" - -@interface FLEXMetadataSection () -@property (nonatomic, readonly) FLEXObjectExplorer *explorer; -/// Filtered -@property (nonatomic, copy) NSArray> *metadata; -/// Unfiltered -@property (nonatomic, copy) NSArray> *allMetadata; -@end - -@implementation FLEXMetadataSection - -#pragma mark - Initialization - -+ (instancetype)explorer:(FLEXObjectExplorer *)explorer kind:(FLEXMetadataKind)metadataKind { - return [[self alloc] initWithExplorer:explorer kind:metadataKind]; -} - -- (id)initWithExplorer:(FLEXObjectExplorer *)explorer kind:(FLEXMetadataKind)metadataKind { - self = [super init]; - if (self) { - _explorer = explorer; - _metadataKind = metadataKind; - - [self reloadData]; - } - - return self; -} - -#pragma mark - Private - -- (NSString *)titleWithBaseName:(NSString *)baseName { - unsigned long totalCount = self.allMetadata.count; - unsigned long filteredCount = self.metadata.count; - - if (totalCount == filteredCount) { - return [baseName stringByAppendingFormat:@" (%lu)", totalCount]; - } else { - return [baseName stringByAppendingFormat:@" (%lu of %lu)", filteredCount, totalCount]; - } -} - -- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row { - return [self.metadata[row] suggestedAccessoryTypeWithTarget:self.explorer.object]; -} - -#pragma mark - Public - -- (void)setExcludedMetadata:(NSSet *)excludedMetadata { - _excludedMetadata = excludedMetadata; - [self reloadData]; -} - -#pragma mark - Overrides - -- (NSString *)titleForRow:(NSInteger)row { - return [self.metadata[row] description]; -} - -- (NSString *)subtitleForRow:(NSInteger)row { - return [self.metadata[row] previewWithTarget:self.explorer.object]; -} - -- (NSString *)title { - switch (self.metadataKind) { - case FLEXMetadataKindProperties: - return [self titleWithBaseName:@"Properties"]; - case FLEXMetadataKindClassProperties: - return [self titleWithBaseName:@"Class Properties"]; - case FLEXMetadataKindIvars: - return [self titleWithBaseName:@"Ivars"]; - case FLEXMetadataKindMethods: - return [self titleWithBaseName:@"Methods"]; - case FLEXMetadataKindClassMethods: - return [self titleWithBaseName:@"Class Methods"]; - case FLEXMetadataKindClassHierarchy: - return [self titleWithBaseName:@"Class Hierarchy"]; - case FLEXMetadataKindProtocols: - return [self titleWithBaseName:@"Protocols"]; - case FLEXMetadataKindOther: - return @"Miscellaneous"; - } -} - -- (NSInteger)numberOfRows { - return self.metadata.count; -} - -- (void)setFilterText:(NSString *)filterText { - super.filterText = filterText; - - if (!self.filterText.length) { - self.metadata = self.allMetadata; - } else { - self.metadata = [self.allMetadata flex_filtered:^BOOL(id obj, NSUInteger idx) { - return [obj.description localizedCaseInsensitiveContainsString:self.filterText]; - }]; - } -} - -- (void)reloadData { - switch (self.metadataKind) { - case FLEXMetadataKindProperties: - self.allMetadata = self.explorer.properties; - break; - case FLEXMetadataKindClassProperties: - self.allMetadata = self.explorer.classProperties; - break; - case FLEXMetadataKindIvars: - self.allMetadata = self.explorer.ivars; - break; - case FLEXMetadataKindMethods: - self.allMetadata = self.explorer.methods; - break; - case FLEXMetadataKindClassMethods: - self.allMetadata = self.explorer.classMethods; - break; - case FLEXMetadataKindProtocols: - self.allMetadata = self.explorer.conformedProtocols; - break; - case FLEXMetadataKindClassHierarchy: - self.allMetadata = self.explorer.classHierarchy; - break; - case FLEXMetadataKindOther: - self.allMetadata = @[self.explorer.instanceSize, self.explorer.imageName]; - break; - } - - // Remove excluded metadata - if (self.excludedMetadata.count) { - id filterBlock = ^BOOL(id obj, NSUInteger idx) { - return ![self.excludedMetadata containsObject:obj.name]; - }; - - // Filter exclusions and sort - self.allMetadata = [[self.allMetadata flex_filtered:filterBlock] - sortedArrayUsingSelector:@selector(compare:) - ]; - } - - // Re-filter data - self.filterText = self.filterText; -} - -- (BOOL)canSelectRow:(NSInteger)row { - UITableViewCellAccessoryType accessory = [self accessoryTypeForRow:row]; - return accessory == UITableViewCellAccessoryDisclosureIndicator || - accessory == UITableViewCellAccessoryDetailDisclosureButton; -} - -- (NSString *)reuseIdentifierForRow:(NSInteger)row { - return [self.metadata[row] reuseIdentifierWithTarget:self.explorer.object] ?: kFLEXCodeFontCell; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - return [self.metadata[row] viewerWithTarget:self.explorer.object]; -} - -- (void (^)(__kindof UIViewController *))didPressInfoButtonAction:(NSInteger)row { - return ^(UIViewController *host) { - [host.navigationController pushViewController:[self editorForRow:row] animated:YES]; - }; -} - -- (UIViewController *)editorForRow:(NSInteger)row { - return [self.metadata[row] editorWithTarget:self.explorer.object section:self]; -} - -- (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row { - cell.titleLabel.text = [self titleForRow:row]; - cell.subtitleLabel.text = [self subtitleForRow:row]; - cell.accessoryType = [self accessoryTypeForRow:row]; -} - -- (NSString *)menuSubtitleForRow:(NSInteger)row { - return [self.metadata[row] contextualSubtitleWithTarget:self.explorer.object]; -} - -- (NSArray *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender { - NSArray *existingItems = [super menuItemsForRow:row sender:sender]; - - // These two metadata kinds don't any of the additional options below - switch (self.metadataKind) { - case FLEXMetadataKindClassHierarchy: - case FLEXMetadataKindOther: - return existingItems; - - default: break; - } - - id metadata = self.metadata[row]; - NSMutableArray *menuItems = [NSMutableArray new]; - - [menuItems addObject:[UIAction - actionWithTitle:@"Explore Metadata" - image:nil - identifier:nil - handler:^(__kindof UIAction *action) { - [sender.navigationController pushViewController:[FLEXObjectExplorerFactory - explorerViewControllerForObject:metadata - ] animated:YES]; - } - ]]; - [menuItems addObjectsFromArray:[metadata - additionalActionsWithTarget:self.explorer.object sender:sender - ]]; - [menuItems addObjectsFromArray:existingItems]; - - return menuItems.copy; -} - -- (NSArray *)copyMenuItemsForRow:(NSInteger)row { - return [self.metadata[row] copiableMetadataWithTarget:self.explorer.object]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMutableListSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMutableListSection.h deleted file mode 100644 index ad2b10e..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMutableListSection.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// FLEXMutableListSection.h -// FLEX -// -// Created by Tanner on 3/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXCollectionContentSection.h" - -typedef void (^FLEXMutableListCellForElement)(__kindof UITableViewCell *cell, id element, NSInteger row); - -/// A section aimed at meeting the needs of table views with one section -/// (or, a section that shouldn't warrant the code duplication that comes -/// with creating a new section just for some specific table view) -/// -/// Use this section if you want to display a growing list of rows, -/// or even if you want to display a static list of rows. -/// -/// To support editing or inserting, implement the appropriate -/// table view delegate methods in your table view delegate class -/// and call \c mutate: (or \c setList: ) before updating the table view. -/// -/// By default, no section title is shown. Assign one to \c customTitle -/// -/// By default, \c kFLEXDetailCell is the reuse identifier used. If you need -/// to support multiple reuse identifiers in a single section, implement the -/// \c cellForRowAtIndexPath: method, dequeue the cell yourself and call -/// \c -configureCell: on the appropriate section object, passing in the cell -@interface FLEXMutableListSection<__covariant ObjectType> : FLEXCollectionContentSection - -/// Initializes a section with an empty list. -+ (instancetype)list:(NSArray *)list - cellConfiguration:(FLEXMutableListCellForElement)configurationBlock - filterMatcher:(BOOL(^)(NSString *filterText, id element))filterBlock; - -/// By default, rows are not selectable. If you want rows -/// to be selectable, provide a selection handler here. -@property (nonatomic, copy) void (^selectionHandler)(__kindof UIViewController *host, ObjectType element); - -/// The objects representing all possible rows in the section. -@property (nonatomic) NSArray *list; -/// The objects representing the currently unfiltered rows in the section. -@property (nonatomic, readonly) NSArray *filteredList; - -/// A readwrite version of the same property in \c FLEXTableViewSection.h -/// -/// This property expects one entry. An exception is thrown if more than one -/// entry is supplied. If you need more than one reuse identifier within a single -/// section, your view probably has more complexity than this class can handle. -@property (nonatomic, readwrite) NSDictionary *cellRegistrationMapping; - -/// Call this method to mutate the full, unfiltered list. -/// This ensures that \c filteredList is updated after any mutations. -- (void)mutate:(void(^)(NSMutableArray *list))block; - -@end - diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMutableListSection.m b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMutableListSection.m deleted file mode 100644 index d63c344..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXMutableListSection.m +++ /dev/null @@ -1,110 +0,0 @@ -// -// FLEXMutableListSection.m -// FLEX -// -// Created by Tanner on 3/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMutableListSection.h" -#import "FLEXMacros.h" - -@interface FLEXMutableListSection () -@property (nonatomic, readonly) FLEXMutableListCellForElement configureCell; -@end - -@implementation FLEXMutableListSection -@synthesize cellRegistrationMapping = _cellRegistrationMapping; - -#pragma mark - Initialization - -+ (instancetype)list:(NSArray *)list - cellConfiguration:(FLEXMutableListCellForElement)cellConfig - filterMatcher:(BOOL(^)(NSString *, id))filterBlock { - return [[self alloc] initWithList:list configurationBlock:cellConfig filterMatcher:filterBlock]; -} - -- (id)initWithList:(NSArray *)list -configurationBlock:(FLEXMutableListCellForElement)cellConfig - filterMatcher:(BOOL(^)(NSString *, id))filterBlock { - self = [super init]; - if (self) { - _configureCell = cellConfig; - - self.list = list.mutableCopy; - self.customFilter = filterBlock; - self.hideSectionTitle = YES; - } - - return self; -} - - -#pragma mark - Public - -- (NSArray *)list { - return (id)_collection; -} - -- (void)setList:(NSMutableArray *)list { - NSParameterAssert(list); - _collection = (id)list; - - [self reloadData]; -} - -- (NSArray *)filteredList { - return (id)_cachedCollection; -} - -- (void)mutate:(void (^)(NSMutableArray *))block { - block((NSMutableArray *)_collection); - [self reloadData]; -} - - -#pragma mark - Overrides - -- (void)setCustomTitle:(NSString *)customTitle { - super.customTitle = customTitle; - self.hideSectionTitle = customTitle == nil; -} - -- (BOOL)canSelectRow:(NSInteger)row { - return self.selectionHandler != nil; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - return nil; -} - -- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row { - if (self.selectionHandler) { weakify(self) - return ^(UIViewController *host) { strongify(self) - if (self) { - self.selectionHandler(host, self.filteredList[row]); - } - }; - } - - return nil; -} - -- (void)configureCell:(__kindof UITableViewCell *)cell forRow:(NSInteger)row { - self.configureCell(cell, self.filteredList[row], row); -} - -- (NSString *)reuseIdentifierForRow:(NSInteger)row { - if (self.cellRegistrationMapping.count) { - return self.cellRegistrationMapping.allKeys.firstObject; - } - - return [super reuseIdentifierForRow:row]; -} - -- (void)setCellRegistrationMapping:(NSDictionary *)cellRegistrationMapping { - NSParameterAssert(cellRegistrationMapping.count <= 1); - _cellRegistrationMapping = cellRegistrationMapping; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXObjectInfoSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/FLEXObjectInfoSection.h deleted file mode 100644 index 656955b..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/FLEXObjectInfoSection.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXObjectInfoSection.h -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -/// \c FLEXTableViewSection itself doesn't know about the object being explored. -/// Subclasses might need this info to provide useful information about the object. Instead -/// of adding an abstract class to the class hierarchy, subclasses can conform to this protocol -/// to indicate that the only info they need to be initialized is the object being explored. -@protocol FLEXObjectInfoSection - -+ (instancetype)forObject:(id)object; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBlockShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBlockShortcuts.h deleted file mode 100644 index 45cbed5..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBlockShortcuts.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXBlockShortcuts.h -// FLEX -// -// Created by Tanner on 1/30/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -NS_ASSUME_NONNULL_BEGIN - -/// Provides a description of the block's signature -/// and access to an NSMethodSignature of the block -@interface FLEXBlockShortcuts : FLEXShortcutsSection - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBlockShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBlockShortcuts.m deleted file mode 100644 index b2b7136..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBlockShortcuts.m +++ /dev/null @@ -1,59 +0,0 @@ -// -// FLEXBlockShortcuts.m -// FLEX -// -// Created by Tanner on 1/30/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXBlockShortcuts.h" -#import "FLEXShortcut.h" -#import "FLEXBlockDescription.h" -#import "FLEXObjectExplorerFactory.h" - -#pragma mark - -@implementation FLEXBlockShortcuts - -#pragma mark Overrides - -+ (instancetype)forObject:(id)block { - NSParameterAssert([block isKindOfClass:NSClassFromString(@"NSBlock")]); - - FLEXBlockDescription *blockInfo = [FLEXBlockDescription describing:block]; - NSMethodSignature *signature = blockInfo.signature; - NSArray *blockShortcutRows = @[blockInfo.summary]; - - if (signature) { - blockShortcutRows = @[ - blockInfo.summary, - blockInfo.sourceDeclaration, - signature.debugDescription, - [FLEXActionShortcut title:@"View Method Signature" - subtitle:^NSString *(id block) { - return signature.description ?: @"unsupported signature"; - } - viewer:^UIViewController *(id block) { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:signature]; - } - accessoryType:^UITableViewCellAccessoryType(id view) { - if (signature) { - return UITableViewCellAccessoryDisclosureIndicator; - } - return UITableViewCellAccessoryNone; - } - ] - ]; - } - - return [self forObject:block additionalRows:blockShortcutRows]; -} - -- (NSString *)title { - return @"Metadata"; -} - -- (NSInteger)numberOfLines { - return 0; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.h deleted file mode 100644 index b88fb68..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// FLEXBundleShortcuts.h -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -NS_ASSUME_NONNULL_BEGIN - -/// Provides a "Browse Bundle Directory" action -@interface FLEXBundleShortcuts : FLEXShortcutsSection - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.m deleted file mode 100644 index a51db87..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXBundleShortcuts.m +++ /dev/null @@ -1,114 +0,0 @@ -// -// FLEXBundleShortcuts.m -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXBundleShortcuts.h" -#import "FLEXShortcut.h" -#import "FLEXAlert.h" -#import "FLEXMacros.h" -#import "FLEXRuntimeExporter.h" -#import "FLEXTableListViewController.h" -#import "FLEXFileBrowserController.h" - -#pragma mark - -@implementation FLEXBundleShortcuts -#pragma mark Overrides - -+ (instancetype)forObject:(NSBundle *)bundle { weakify(self) - return [self forObject:bundle additionalRows:@[ - [FLEXActionShortcut - title:@"Browse Bundle Directory" subtitle:nil - viewer:^UIViewController *(NSBundle *bundle) { - return [FLEXFileBrowserController path:bundle.bundlePath]; - } - accessoryType:^UITableViewCellAccessoryType(NSBundle *bundle) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ], - [FLEXActionShortcut title:@"Browse Bundle as Database…" subtitle:nil - selectionHandler:^(UIViewController *host, NSBundle *bundle) { strongify(self) - [self promptToExportBundleAsDatabase:bundle host:host]; - } - accessoryType:^UITableViewCellAccessoryType(NSBundle *bundle) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ], - ]]; -} - -+ (void)promptToExportBundleAsDatabase:(NSBundle *)bundle host:(UIViewController *)host { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Save As…").message( - @"The database be saved in the Library folder. " - "Depending on the number of classes, it may take " - "10 minutes or more to finish exporting. 20,000 " - "classes takes about 7 minutes." - ); - make.configuredTextField(^(UITextField *field) { - field.placeholder = @"FLEXRuntimeExport.objc.db"; - field.text = [NSString stringWithFormat: - @"%@.objc.db", bundle.executablePath.lastPathComponent - ]; - }); - make.button(@"Start").handler(^(NSArray *strings) { - [self browseBundleAsDatabase:bundle host:host name:strings[0]]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:host]; -} - -+ (void)browseBundleAsDatabase:(NSBundle *)bundle host:(UIViewController *)host name:(NSString *)name { - NSParameterAssert(name.length); - - UIAlertController *progress = [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Generating Database"); - // Some iOS version glitch out of there is - // no initial message and you add one later - make.message(@"…"); - }]; - - [host presentViewController:progress animated:YES completion:^{ - // Generate path to store db - NSString *path = [NSSearchPathForDirectoriesInDomains( - NSLibraryDirectory, NSUserDomainMask, YES - )[0] stringByAppendingPathComponent:name]; - - progress.message = [path stringByAppendingString:@"\n\nCreating database…"]; - - // Generate db and show progress - [FLEXRuntimeExporter createRuntimeDatabaseAtPath:path - forImages:@[bundle.executablePath] - progressHandler:^(NSString *status) { - dispatch_async(dispatch_get_main_queue(), ^{ - progress.message = [progress.message - stringByAppendingFormat:@"\n%@", status - ]; - [progress.view setNeedsLayout]; - [progress.view layoutIfNeeded]; - }); - } completion:^(NSString *error) { - // Display error if any - if (error) { - progress.title = @"Error"; - progress.message = error; - [progress addAction:[UIAlertAction - actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil] - ]; - } - // Browse database - else { - [progress dismissViewControllerAnimated:YES completion:nil]; - [host.navigationController pushViewController:[ - [FLEXTableListViewController alloc] initWithPath:path - ] animated:YES]; - } - } - ]; - }]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.h deleted file mode 100644 index 706ee2d..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXClassShortcuts.h -// FLEX -// -// Created by Tanner Bennett on 11/22/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -/// Provides handy shortcuts for class objects. -/// This is the default section used for all class objects. -@interface FLEXClassShortcuts : FLEXShortcutsSection - -+ (instancetype)forObject:(Class)cls; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.m deleted file mode 100644 index b650b9f..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXClassShortcuts.m +++ /dev/null @@ -1,73 +0,0 @@ -// -// FLEXClassShortcuts.m -// FLEX -// -// Created by Tanner Bennett on 11/22/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXClassShortcuts.h" -#import "FLEXShortcut.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXObjectListViewController.h" -#import "NSObject+FLEX_Reflection.h" - -@interface FLEXClassShortcuts () -@property (nonatomic, readonly) Class cls; -@end - -@implementation FLEXClassShortcuts - -+ (instancetype)forObject:(Class)cls { - // These additional rows will appear at the beginning of the shortcuts section. - // The methods below are written in such a way that they will not interfere - // with properties/etc being registered alongside these - return [self forObject:cls additionalRows:@[ - [FLEXActionShortcut title:@"Find Live Instances" subtitle:nil - viewer:^UIViewController *(id obj) { - return [FLEXObjectListViewController - instancesOfClassWithName:NSStringFromClass(obj) - retained:NO - ]; - } - accessoryType:^UITableViewCellAccessoryType(id obj) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ], - [FLEXActionShortcut title:@"List Subclasses" subtitle:nil - viewer:^UIViewController *(id obj) { - NSString *name = NSStringFromClass(obj); - return [FLEXObjectListViewController subclassesOfClassWithName:name]; - } - accessoryType:^UITableViewCellAccessoryType(id view) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ], - [FLEXActionShortcut title:@"Explore Bundle for Class" - subtitle:^NSString *(id obj) { - return [self shortNameForBundlePath:[NSBundle bundleForClass:obj].executablePath]; - } - viewer:^UIViewController *(id obj) { - NSBundle *bundle = [NSBundle bundleForClass:obj]; - return [FLEXObjectExplorerFactory explorerViewControllerForObject:bundle]; - } - accessoryType:^UITableViewCellAccessoryType(id view) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ], - ]]; -} - -+ (NSString *)shortNameForBundlePath:(NSString *)imageName { - NSArray *components = [imageName componentsSeparatedByString:@"/"]; - if (components.count >= 2) { - return [NSString stringWithFormat:@"%@/%@", - components[components.count - 2], - components[components.count - 1] - ]; - } - - return imageName.lastPathComponent; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXImageShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXImageShortcuts.h deleted file mode 100644 index 59bbba3..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXImageShortcuts.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// FLEXImageShortcuts.h -// FLEX -// -// Created by Tanner Bennett on 8/29/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -/// Provides "view image" and "save image" shortcuts for UIImage objects -@interface FLEXImageShortcuts : FLEXShortcutsSection - -+ (instancetype)forObject:(UIImage *)image; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXImageShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXImageShortcuts.m deleted file mode 100644 index 9552735..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXImageShortcuts.m +++ /dev/null @@ -1,68 +0,0 @@ -// -// FLEXImageShortcuts.m -// FLEX -// -// Created by Tanner Bennett on 8/29/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXImageShortcuts.h" -#import "FLEXImagePreviewViewController.h" -#import "FLEXShortcut.h" -#import "FLEXAlert.h" -#import "FLEXMacros.h" - -@interface UIAlertController (FLEXImageShortcuts) -- (void)flex_image:(UIImage *)image disSaveWithError:(NSError *)error :(void *)context; -@end - -@implementation FLEXImageShortcuts - -#pragma mark - Overrides - -+ (instancetype)forObject:(UIImage *)image { - // These additional rows will appear at the beginning of the shortcuts section. - // The methods below are written in such a way that they will not interfere - // with properties/etc being registered alongside these - return [self forObject:image additionalRows:@[ - [FLEXActionShortcut title:@"View Image" subtitle:nil - viewer:^UIViewController *(id image) { - return [FLEXImagePreviewViewController forImage:image]; - } - accessoryType:^UITableViewCellAccessoryType(id image) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ], - [FLEXActionShortcut title:@"Save Image" subtitle:nil - selectionHandler:^(UIViewController *host, id image) { - // Present modal alerting user about saving - UIAlertController *alert = [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Saving Image…"); - }]; - [host presentViewController:alert animated:YES completion:nil]; - - // Save the image - UIImageWriteToSavedPhotosAlbum( - image, alert, @selector(flex_image:disSaveWithError::), nil - ); - } - accessoryType:^UITableViewCellAccessoryType(id image) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ] - ]]; -} - -@end - - -@implementation UIAlertController (FLEXImageShortcuts) - -- (void)flex_image:(UIImage *)image disSaveWithError:(NSError *)error :(void *)context { - self.title = @"Image Saved"; - flex_dispatch_after(1, dispatch_get_main_queue(), ^{ - [self dismissViewControllerAnimated:YES completion:nil]; - }); -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXLayerShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXLayerShortcuts.h deleted file mode 100644 index dad8d95..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXLayerShortcuts.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// FLEXLayerShortcuts.h -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -@interface FLEXLayerShortcuts : FLEXShortcutsSection - -+ (instancetype)forObject:(CALayer *)layer; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXLayerShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXLayerShortcuts.m deleted file mode 100644 index 1cf4808..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXLayerShortcuts.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// FLEXLayerShortcuts.m -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXLayerShortcuts.h" -#import "FLEXShortcut.h" -#import "FLEXImagePreviewViewController.h" - -@implementation FLEXLayerShortcuts - -+ (instancetype)forObject:(CALayer *)layer { - return [self forObject:layer additionalRows:@[ - [FLEXActionShortcut title:@"Preview Image" subtitle:nil - viewer:^UIViewController *(CALayer *layer) { - return [FLEXImagePreviewViewController previewForLayer:layer]; - } - accessoryType:^UITableViewCellAccessoryType(CALayer *layer) { - return CGRectIsEmpty(layer.bounds) ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator; - } - ] - ]]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSDataShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSDataShortcuts.h deleted file mode 100644 index 9023e03..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSDataShortcuts.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXNSDataShortcuts.h -// FLEX -// -// Created by Tanner on 3/29/21. -// - -#import "FLEXShortcutsSection.h" - -/// Adds a "UTF-8 String" shortcut -@interface FLEXNSDataShortcuts : FLEXShortcutsSection - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSDataShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSDataShortcuts.m deleted file mode 100644 index 7de28cf..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSDataShortcuts.m +++ /dev/null @@ -1,48 +0,0 @@ -// -// FLEXNSDataShortcuts.m -// FLEX -// -// Created by Tanner on 3/29/21. -// - -#import "FLEXNSDataShortcuts.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXShortcut.h" - -@implementation FLEXNSDataShortcuts - -+ (instancetype)forObject:(NSData *)data { - NSString *string = [self stringForData:data]; - - return [self forObject:data additionalRows:@[ - [FLEXActionShortcut title:@"UTF-8 String" subtitle:^(NSData *object) { - return string.length ? string : (string ? - @"Data is not a UTF8 String" : @"Empty string" - ); - } viewer:^UIViewController *(id object) { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:string]; - } accessoryType:^UITableViewCellAccessoryType(NSData *object) { - if (string.length) { - return UITableViewCellAccessoryDisclosureIndicator; - } - - return UITableViewCellAccessoryNone; - }] - ]]; -} - -+ (NSString *)stringForData:(NSData *)data { - return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; -} - -@end - -@interface NSData (Overrides) @end -@implementation NSData (Overrides) - -// This normally crashes -- (NSUInteger)length { - return 0; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSStringShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSStringShortcuts.h deleted file mode 100644 index 460dfc1..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSStringShortcuts.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXNSStringShortcuts.h -// FLEX -// -// Created by Tanner on 3/29/21. -// - -#import "FLEXShortcutsSection.h" - -/// Adds a "UTF-8 Data" shortcut -@interface FLEXNSStringShortcuts : FLEXShortcutsSection - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSStringShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSStringShortcuts.m deleted file mode 100644 index a236362..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXNSStringShortcuts.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// FLEXNSStringShortcuts.m -// FLEX -// -// Created by Tanner on 3/29/21. -// - -#import "FLEXNSStringShortcuts.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXShortcut.h" - -@implementation FLEXNSStringShortcuts - -+ (instancetype)forObject:(NSString *)string { - NSUInteger length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - NSData *data = [NSData dataWithBytesNoCopy:(void *)string.UTF8String length:length freeWhenDone:NO]; - - return [self forObject:string additionalRows:@[ - [FLEXActionShortcut title:@"UTF-8 Data" subtitle:^NSString *(id _) { - return data.description; - } viewer:^UIViewController *(id _) { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:data]; - } accessoryType:^UITableViewCellAccessoryType(id _) { - return UITableViewCellAccessoryDisclosureIndicator; - }] - ]]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h deleted file mode 100644 index cece75b..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// FLEXShortcut.h -// FLEX -// -// Created by Tanner Bennett on 12/10/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXObjectExplorer.h" - -NS_ASSUME_NONNULL_BEGIN - -/// Represents a row in a shortcut section. -/// -/// The purpsoe of this protocol is to allow delegating a small -/// subset of the responsibilities of a \c FLEXShortcutsSection -/// to another object, for a single arbitrary row. -/// -/// It is useful to make your own shortcuts to append/prepend -/// them to the existing list of shortcuts for a class. -@protocol FLEXShortcut - -- (nonnull NSString *)titleWith:(id)object; -- (nullable NSString *)subtitleWith:(id)object; -- (nullable void (^)(UIViewController *host))didSelectActionWith:(id)object; -/// Called when the row is selected -- (nullable UIViewController *)viewerWith:(id)object; -/// Basically, whether or not to show a detail disclosure indicator -- (UITableViewCellAccessoryType)accessoryTypeWith:(id)object; -/// If nil is returned, the default reuse identifier is used -- (nullable NSString *)customReuseIdentifierWith:(id)object; - -@optional -/// Called when the (i) button is pressed if the accessory type includes it -- (UIViewController *)editorWith:(id)object forSection:(FLEXTableViewSection *)section; - -@end - - -/// Provides default behavior for FLEX metadata objects. Also works in a limited way with strings. -/// Used internally. If you wish to use this object, only pass in \c FLEX* metadata objects. -@interface FLEXShortcut : NSObject - -/// @param item An \c NSString or \c FLEX* metadata object. -/// @note You may also pass a \c FLEXShortcut conforming object, -/// and that object will be returned instead. -+ (id)shortcutFor:(id)item; - -@end - - -/// Provides a quick and dirty implementation of the \c FLEXShortcut protocol, -/// allowing you to specify a static title and dynamic atttributes for everything else. -/// The object passed into each block is the object passed to each \c FLEXShortcut method. -/// -/// Does not support the \c -editorWith: method. -@interface FLEXActionShortcut : NSObject - -+ (instancetype)title:(NSString *)title - subtitle:(nullable NSString *(^)(id object))subtitleFuture - viewer:(nullable UIViewController *(^)(id object))viewerFuture - accessoryType:(nullable UITableViewCellAccessoryType(^)(id object))accessoryTypeFuture; - -+ (instancetype)title:(NSString *)title - subtitle:(nullable NSString *(^)(id object))subtitleFuture - selectionHandler:(nullable void (^)(UIViewController *host, id object))tapAction - accessoryType:(nullable UITableViewCellAccessoryType(^)(id object))accessoryTypeFuture; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.m deleted file mode 100644 index ac9c892..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.m +++ /dev/null @@ -1,254 +0,0 @@ -// -// FLEXShortcut.m -// FLEX -// -// Created by Tanner Bennett on 12/10/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcut.h" -#import "FLEXProperty.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXIvar.h" -#import "FLEXMethod.h" -#import "FLEXRuntime+UIKitHelpers.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXFieldEditorViewController.h" -#import "FLEXMethodCallingViewController.h" -#import "FLEXMetadataSection.h" -#import "FLEXTableView.h" - - -#pragma mark - FLEXShortcut - -@interface FLEXShortcut () { - id _item; -} - -@property (nonatomic, readonly) FLEXMetadataKind metadataKind; -@property (nonatomic, readonly) FLEXProperty *property; -@property (nonatomic, readonly) FLEXMethod *method; -@property (nonatomic, readonly) FLEXIvar *ivar; -@property (nonatomic, readonly) id metadata; -@end - -@implementation FLEXShortcut -@synthesize defaults = _defaults; - -+ (id)shortcutFor:(id)item { - if ([item conformsToProtocol:@protocol(FLEXShortcut)]) { - return item; - } - - FLEXShortcut *shortcut = [self new]; - shortcut->_item = item; - - if ([item isKindOfClass:[FLEXProperty class]]) { - if (shortcut.property.isClassProperty) { - shortcut->_metadataKind = FLEXMetadataKindClassProperties; - } else { - shortcut->_metadataKind = FLEXMetadataKindProperties; - } - } - if ([item isKindOfClass:[FLEXIvar class]]) { - shortcut->_metadataKind = FLEXMetadataKindIvars; - } - if ([item isKindOfClass:[FLEXMethod class]]) { - // We don't care if it's a class method or not - shortcut->_metadataKind = FLEXMetadataKindMethods; - } - - return shortcut; -} - -- (id)propertyOrIvarValue:(id)object { - return [self.metadata currentValueWithTarget:object]; -} - -- (NSString *)titleWith:(id)object { - switch (self.metadataKind) { - case FLEXMetadataKindClassProperties: - case FLEXMetadataKindProperties: - // Since we're outside of the "properties" section, prepend @property for clarity. - return [@"@property " stringByAppendingString:[_item description]]; - - default: - return [_item description]; - } - - NSAssert( - [_item isKindOfClass:[NSString class]], - @"Unexpected type: %@", [_item class] - ); - - return _item; -} - -- (NSString *)subtitleWith:(id)object { - if (self.metadataKind) { - return [self.metadata previewWithTarget:object]; - } - - // Item is probably a string; must return empty string since - // these will be gathered into an array. If the object is a - // just a string, it doesn't get a subtitle. - return @""; -} - -- (void (^)(UIViewController *))didSelectActionWith:(id)object { - return nil; -} - -- (UIViewController *)viewerWith:(id)object { - NSAssert(self.metadataKind, @"Static titles cannot be viewed"); - return [self.metadata viewerWithTarget:object]; -} - -- (UIViewController *)editorWith:(id)object forSection:(FLEXTableViewSection *)section { - NSAssert(self.metadataKind, @"Static titles cannot be edited"); - return [self.metadata editorWithTarget:object section:section]; -} - -- (UITableViewCellAccessoryType)accessoryTypeWith:(id)object { - if (self.metadataKind) { - return [self.metadata suggestedAccessoryTypeWithTarget:object]; - } - - return UITableViewCellAccessoryNone; -} - -- (NSString *)customReuseIdentifierWith:(id)object { - if (self.metadataKind) { - return kFLEXCodeFontCell; - } - - return kFLEXMultilineCell; -} - -#pragma mark FLEXObjectExplorerDefaults - -- (void)setDefaults:(FLEXObjectExplorerDefaults *)defaults { - _defaults = defaults; - - if (_metadataKind) { - self.metadata.defaults = defaults; - } -} - -- (BOOL)isEditable { - if (_metadataKind) { - return self.metadata.isEditable; - } - - return NO; -} - -- (BOOL)isCallable { - if (_metadataKind) { - return self.metadata.isCallable; - } - - return NO; -} - -#pragma mark - Helpers - -- (FLEXProperty *)property { return _item; } -- (FLEXMethodBase *)method { return _item; } -- (FLEXIvar *)ivar { return _item; } -- (id)metadata { return _item; } - -@end - - -#pragma mark - FLEXActionShortcut - -@interface FLEXActionShortcut () -@property (nonatomic, readonly) NSString *title; -@property (nonatomic, readonly) NSString *(^subtitleFuture)(id); -@property (nonatomic, readonly) UIViewController *(^viewerFuture)(id); -@property (nonatomic, readonly) void (^selectionHandler)(UIViewController *, id); -@property (nonatomic, readonly) UITableViewCellAccessoryType (^accessoryTypeFuture)(id); -@end - -@implementation FLEXActionShortcut -@synthesize defaults = _defaults; - -+ (instancetype)title:(NSString *)title - subtitle:(NSString *(^)(id))subtitle - viewer:(UIViewController *(^)(id))viewer - accessoryType:(UITableViewCellAccessoryType (^)(id))type { - return [[self alloc] initWithTitle:title subtitle:subtitle viewer:viewer selectionHandler:nil accessoryType:type]; -} - -+ (instancetype)title:(NSString *)title - subtitle:(NSString * (^)(id))subtitle - selectionHandler:(void (^)(UIViewController *, id))tapAction - accessoryType:(UITableViewCellAccessoryType (^)(id))type { - return [[self alloc] initWithTitle:title subtitle:subtitle viewer:nil selectionHandler:tapAction accessoryType:type]; -} - -- (id)initWithTitle:(NSString *)title - subtitle:(id)subtitleFuture - viewer:(id)viewerFuture - selectionHandler:(id)tapAction - accessoryType:(id)accessoryTypeFuture { - NSParameterAssert(title.length); - - self = [super init]; - if (self) { - id nilBlock = ^id (id obj) { return nil; }; - - _title = title; - _subtitleFuture = subtitleFuture ?: nilBlock; - _viewerFuture = viewerFuture ?: nilBlock; - _selectionHandler = tapAction; - _accessoryTypeFuture = accessoryTypeFuture ?: nilBlock; - } - - return self; -} - -- (NSString *)titleWith:(id)object { - return self.title; -} - -- (NSString *)subtitleWith:(id)object { - if (self.defaults.wantsDynamicPreviews) { - return self.subtitleFuture(object); - } - - return nil; -} - -- (void (^)(UIViewController *))didSelectActionWith:(id)object { - if (self.selectionHandler) { - return ^(UIViewController *host) { - self.selectionHandler(host, object); - }; - } - - return nil; -} - -- (UIViewController *)viewerWith:(id)object { - return self.viewerFuture(object); -} - -- (UITableViewCellAccessoryType)accessoryTypeWith:(id)object { - return self.accessoryTypeFuture(object); -} - -- (NSString *)customReuseIdentifierWith:(id)object { - if (!self.subtitleFuture(object)) { - // The text is more centered with this style if there is no subtitle - return kFLEXDefaultCell; - } - - return nil; -} - -- (BOOL)isEditable { return NO; } -- (BOOL)isCallable { return NO; } - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h deleted file mode 100644 index 2254868..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// FLEXShortcutsFactory+Defaults.h -// FLEX -// -// Created by Tanner Bennett on 8/29/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -@interface FLEXShortcutsFactory (UIApplication) @end - -@interface FLEXShortcutsFactory (Views) @end - -@interface FLEXShortcutsFactory (ViewControllers) @end - -@interface FLEXShortcutsFactory (UIImage) @end - -@interface FLEXShortcutsFactory (NSBundle) @end - -@interface FLEXShortcutsFactory (Classes) @end - -@interface FLEXShortcutsFactory (Activities) @end - -@interface FLEXShortcutsFactory (Blocks) @end - -@interface FLEXShortcutsFactory (Foundation) @end - -@interface FLEXShortcutsFactory (WebKit_Safari) @end - -@interface FLEXShortcutsFactory (Pasteboard) @end - -@interface FLEXShortcutsFactory (FirebaseFirestore) @end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m deleted file mode 100644 index b5b4042..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m +++ /dev/null @@ -1,461 +0,0 @@ -// -// FLEXShortcutsFactory+Defaults.m -// FLEX -// -// Created by Tanner Bennett on 8/29/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsFactory+Defaults.h" -#import "FLEXShortcut.h" -#import "FLEXMacros.h" -#import "FLEXRuntimeUtility.h" -#import "NSArray+FLEX.h" -#import "NSObject+FLEX_Reflection.h" -#import "FLEXObjcInternal.h" -#import "Cocoa+FLEXShortcuts.h" - -#pragma mark - UIApplication - -@implementation FLEXShortcutsFactory (UIApplication) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - // sharedApplication class property possibly not added - // as a literal class property until iOS 10 - FLEXRuntimeUtilityTryAddObjectProperty( - 2, sharedApplication, UIApplication.flex_metaclass, UIApplication, PropertyKey(ReadOnly) - ); - - self.append.classProperties(@[@"sharedApplication"]).forClass(UIApplication.flex_metaclass); - self.append.properties(@[ - @"delegate", @"keyWindow", @"windows" - ]).forClass(UIApplication.class); - - if (@available(iOS 13, *)) { - self.append.properties(@[ - @"connectedScenes", @"openSessions", @"supportsMultipleScenes" - ]).forClass(UIApplication.class); - } -} - -@end - -#pragma mark - Views - -@implementation FLEXShortcutsFactory (Views) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - // A quirk of UIView and some other classes: a lot of the `@property`s are - // not actually properties from the perspective of the runtime. - // - // We add these properties to the class at runtime if they haven't been added yet. - // This way, we can use our property editor to access and change them. - // The property attributes match the declared attributes in their headers. - - // UIView, public - Class UIView_ = UIView.class; - FLEXRuntimeUtilityTryAddNonatomicProperty(2, frame, UIView_, CGRect); - FLEXRuntimeUtilityTryAddNonatomicProperty(2, alpha, UIView_, CGFloat); - FLEXRuntimeUtilityTryAddNonatomicProperty(2, clipsToBounds, UIView_, BOOL); - FLEXRuntimeUtilityTryAddNonatomicProperty(2, opaque, UIView_, BOOL, PropertyKeyGetter(isOpaque)); - FLEXRuntimeUtilityTryAddNonatomicProperty(2, hidden, UIView_, BOOL, PropertyKeyGetter(isHidden)); - FLEXRuntimeUtilityTryAddObjectProperty(2, backgroundColor, UIView_, UIColor, PropertyKey(Copy)); - FLEXRuntimeUtilityTryAddObjectProperty(6, constraints, UIView_, NSArray, PropertyKey(ReadOnly)); - FLEXRuntimeUtilityTryAddObjectProperty(2, subviews, UIView_, NSArray, PropertyKey(ReadOnly)); - FLEXRuntimeUtilityTryAddObjectProperty(2, superview, UIView_, UIView, PropertyKey(ReadOnly)); - FLEXRuntimeUtilityTryAddObjectProperty(7, tintColor, UIView_, UIView); - - // UIButton, private - FLEXRuntimeUtilityTryAddObjectProperty(2, font, UIButton.class, UIFont, PropertyKey(ReadOnly)); - - // Only available since iOS 3.2, but we never supported iOS 3, so who cares - NSArray *ivars = @[@"_gestureRecognizers"]; - NSArray *methods = @[@"sizeToFit", @"setNeedsLayout", @"removeFromSuperview"]; - - // UIView - self.append.ivars(ivars).methods(methods).properties(@[ - @"frame", @"bounds", @"center", @"transform", - @"backgroundColor", @"alpha", @"opaque", @"hidden", - @"clipsToBounds", @"userInteractionEnabled", @"layer", - @"superview", @"subviews", - @"accessibilityIdentifier", @"accessibilityLabel" - ]).forClass(UIView.class); - - // UILabel - self.append.ivars(ivars).methods(methods).properties(@[ - @"text", @"attributedText", @"font", @"frame", - @"textColor", @"textAlignment", @"numberOfLines", - @"lineBreakMode", @"enabled", @"backgroundColor", - @"alpha", @"hidden", @"preferredMaxLayoutWidth", - @"superview", @"subviews", - @"accessibilityIdentifier", @"accessibilityLabel" - ]).forClass(UILabel.class); - - // UIWindow - self.append.ivars(ivars).properties(@[ - @"rootViewController", @"windowLevel", @"keyWindow", - @"frame", @"bounds", @"center", @"transform", - @"backgroundColor", @"alpha", @"opaque", @"hidden", - @"clipsToBounds", @"userInteractionEnabled", @"layer", - @"subviews" - ]).forClass(UIWindow.class); - - if (@available(iOS 13, *)) { - self.append.properties(@[@"windowScene"]).forClass(UIWindow.class); - } - - ivars = @[@"_targetActions", @"_gestureRecognizers"]; - - // Property was added in iOS 10 but we want it on iOS 9 too - FLEXRuntimeUtilityTryAddObjectProperty(9, allTargets, UIControl.class, NSArray, PropertyKey(ReadOnly)); - - // UIControl - self.append.ivars(ivars).methods(methods).properties(@[ - @"enabled", @"allTargets", @"frame", - @"backgroundColor", @"hidden", @"clipsToBounds", - @"userInteractionEnabled", @"superview", @"subviews", - @"accessibilityIdentifier", @"accessibilityLabel" - ]).forClass(UIControl.class); - - // UIButton - self.append.ivars(ivars).properties(@[ - @"titleLabel", @"font", @"imageView", @"tintColor", - @"currentTitle", @"currentImage", @"enabled", @"frame", - @"superview", @"subviews", - @"accessibilityIdentifier", @"accessibilityLabel" - ]).forClass(UIButton.class); - - // UIImageView - self.append.properties(@[ - @"image", @"animationImages", @"frame", @"bounds", @"center", - @"transform", @"alpha", @"hidden", @"clipsToBounds", - @"userInteractionEnabled", @"layer", @"superview", @"subviews", - @"accessibilityIdentifier", @"accessibilityLabel" - ]).forClass(UIImageView.class); -} - -@end - - -#pragma mark - View Controllers - -@implementation FLEXShortcutsFactory (ViewControllers) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - // toolbarItems is not really a property, make it one - FLEXRuntimeUtilityTryAddObjectProperty(3, toolbarItems, UIViewController.class, NSArray); - - // UIViewController - self.append - .properties(@[ - @"viewIfLoaded", @"title", @"navigationItem", @"toolbarItems", @"tabBarItem", - @"childViewControllers", @"navigationController", @"tabBarController", @"splitViewController", - @"parentViewController", @"presentedViewController", @"presentingViewController", - ]) - .methods(@[@"view"]) - .forClass(UIViewController.class); - - // UIAlertController - NSMutableArray *alertControllerProps = @[ - @"title", @"message", @"actions", @"textFields", - @"preferredAction", @"presentingViewController", @"viewIfLoaded", - ].mutableCopy; - if (@available(iOS 14.0, *)) { - [alertControllerProps insertObject:@"image" atIndex:4]; - } - self.append - .properties(alertControllerProps) - .methods(@[@"addAction:"]) - .forClass(UIAlertController.class); - self.append.properties(@[ - @"title", @"style", @"enabled", @"flex_styleName", - @"image", @"keyCommandInput", @"_isPreferred", @"_alertController", - ]).forClass(UIAlertAction.class); -} - -@end - - -#pragma mark - UIImage - -@implementation FLEXShortcutsFactory (UIImage) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - self.append.methods(@[ - @"CGImage", @"CIImage" - ]).properties(@[ - @"scale", @"size", @"capInsets", - @"alignmentRectInsets", @"duration", @"images" - ]).forClass(UIImage.class); - - if (@available(iOS 13, *)) { - self.append.properties(@[@"symbolImage"]).forClass(UIImage.class); - } -} - -@end - - -#pragma mark - NSBundle - -@implementation FLEXShortcutsFactory (NSBundle) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - self.append.properties(@[ - @"bundleIdentifier", @"principalClass", - @"infoDictionary", @"bundlePath", - @"executablePath", @"loaded" - ]).forClass(NSBundle.class); -} - -@end - - -#pragma mark - Classes - -@implementation FLEXShortcutsFactory (Classes) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - self.append.classMethods(@[@"new", @"alloc"]).forClass(NSObject.flex_metaclass); -} - -@end - - -#pragma mark - Activities - -@implementation FLEXShortcutsFactory (Activities) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - // Property was added in iOS 10 but we want it on iOS 9 too - FLEXRuntimeUtilityTryAddNonatomicProperty(9, item, UIActivityItemProvider.class, id, PropertyKey(ReadOnly)); - - self.append.properties(@[ - @"item", @"placeholderItem", @"activityType" - ]).forClass(UIActivityItemProvider.class); - - self.append.properties(@[ - @"activityItems", @"applicationActivities", @"excludedActivityTypes", @"completionHandler" - ]).forClass(UIActivityViewController.class); -} - -@end - - -#pragma mark - Blocks - -@implementation FLEXShortcutsFactory (Blocks) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - self.append.methods(@[@"invoke"]).forClass(NSClassFromString(@"NSBlock")); -} - -@end - -#pragma mark - Foundation - -@implementation FLEXShortcutsFactory (Foundation) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - self.append.properties(@[ - @"configuration", @"delegate", @"delegateQueue", @"sessionDescription", - ]).methods(@[ - @"dataTaskWithURL:", @"finishTasksAndInvalidate", @"invalidateAndCancel", - ]).forClass(NSURLSession.class); - - self.append.methods(@[ - @"cachedResponseForRequest:", @"storeCachedResponse:forRequest:", - @"storeCachedResponse:forDataTask:", @"removeCachedResponseForRequest:", - @"removeCachedResponseForDataTask:", @"removeCachedResponsesSinceDate:", - @"removeAllCachedResponses", - ]).forClass(NSURLCache.class); - - - self.append.methods(@[ - @"postNotification:", @"postNotificationName:object:userInfo:", - @"addObserver:selector:name:object:", @"removeObserver:", - @"removeObserver:name:object:", - ]).forClass(NSNotificationCenter.class); - - // NSTimeZone class properties aren't real properties - FLEXRuntimeUtilityTryAddObjectProperty(2, localTimeZone, NSTimeZone.flex_metaclass, NSTimeZone); - FLEXRuntimeUtilityTryAddObjectProperty(2, systemTimeZone, NSTimeZone.flex_metaclass, NSTimeZone); - FLEXRuntimeUtilityTryAddObjectProperty(2, defaultTimeZone, NSTimeZone.flex_metaclass, NSTimeZone); - FLEXRuntimeUtilityTryAddObjectProperty(2, knownTimeZoneNames, NSTimeZone.flex_metaclass, NSArray); - FLEXRuntimeUtilityTryAddObjectProperty(2, abbreviationDictionary, NSTimeZone.flex_metaclass, NSDictionary); - - self.append.classMethods(@[ - @"timeZoneWithName:", @"timeZoneWithAbbreviation:", @"timeZoneForSecondsFromGMT:", - ]).forClass(NSTimeZone.flex_metaclass); - - self.append.classProperties(@[ - @"defaultTimeZone", @"systemTimeZone", @"localTimeZone", - ]).forClass(NSTimeZone.class); - - // UTF8String is not a real property under the hood - FLEXRuntimeUtilityTryAddNonatomicProperty(2, UTF8String, NSString.class, const char *, PropertyKey(ReadOnly)); - - self.append.properties(@[@"length"]).methods(@[@"characterAtIndex:"]).forClass(NSString.class); - self.append.methods(@[ - @"writeToFile:atomically:", @"subdataWithRange:", @"isEqualToData:", - ]).properties(@[ - @"length", @"bytes", - ]).forClass(NSData.class); - - self.append.classMethods(@[ - @"dataWithJSONObject:options:error:", - @"JSONObjectWithData:options:error:", - @"isValidJSONObject:", - ]).forClass(NSJSONSerialization.class); - - // NSArray - self.append.classMethods(@[ - @"arrayWithObject:", @"arrayWithContentsOfFile:" - ]).forClass(NSArray.flex_metaclass); - self.append.methods(@[ - @"valueForKeyPath:", @"subarrayWithRange:", - @"arrayByAddingObject:", @"arrayByAddingObjectsFromArray:", - @"filteredArrayUsingPredicate:", @"subarrayWithRange:", - @"containsObject:", @"objectAtIndex:", @"indexOfObject:", - @"makeObjectsPerformSelector:", @"makeObjectsPerformSelector:withObject:", - @"sortedArrayUsingSelector:", @"reverseObjectEnumerator", - @"isEqualToArray:", @"mutableCopy", - ]).forClass(NSArray.class); - // NSDictionary - self.append.methods(@[ - @"objectForKey:", @"valueForKeyPath:", - @"isEqualToDictionary:", @"mutableCopy", - ]).forClass(NSDictionary.class); - // NSSet - self.append.classMethods(@[ - @"setWithObject:", @"setWithArray:" - ]).forClass(NSSet.flex_metaclass); - self.append.methods(@[ - @"allObjects", @"valueForKeyPath:", @"containsObject:", - @"setByAddingObject:", @"setByAddingObjectsFromArray:", - @"filteredSetUsingPredicate:", @"isSubsetOfSet:", - @"makeObjectsPerformSelector:", @"makeObjectsPerformSelector:withObject:", - @"reverseObjectEnumerator", @"isEqualToSet:", @"mutableCopy", - ]).forClass(NSSet.class); - - // NSMutableArray - self.prepend.methods(@[ - @"addObject:", @"insertObject:atIndex:", @"addObjectsFromArray:", - @"removeObject:", @"removeObjectAtIndex:", - @"removeObjectsInArray:", @"removeAllObjects", - @"removeLastObject", @"filterUsingPredicate:", - @"sortUsingSelector:", @"copy", - ]).forClass(NSMutableArray.class); - // NSMutableDictionary - self.prepend.methods(@[ - @"setObject:forKey:", @"removeObjectForKey:", - @"removeAllObjects", @"removeObjectsForKeys:", @"copy", - ]).forClass(NSMutableDictionary.class); - // NSMutableSet - self.prepend.methods(@[ - @"addObject:", @"removeObject:", @"filterUsingPredicate:", - @"removeAllObjects", @"addObjectsFromArray:", - @"unionSet:", @"minusSet:", @"intersectSet:", @"copy" - ]).forClass(NSMutableSet.class); - - self.append.methods(@[@"nextObject", @"allObjects"]).forClass(NSEnumerator.class); - - self.append.properties(@[@"flex_observers"]).forClass(NSNotificationCenter.class); -} - -@end - -#pragma mark - WebKit / Safari - -@implementation FLEXShortcutsFactory (WebKit_Safari) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - Class WKWebView = NSClassFromString(@"WKWebView"); - Class SafariVC = NSClassFromString(@"SFSafariViewController"); - - if (WKWebView) { - self.append.properties(@[ - @"configuration", @"scrollView", @"title", @"URL", - @"customUserAgent", @"navigationDelegate" - ]).methods(@[@"reload", @"stopLoading"]).forClass(WKWebView); - } - - if (SafariVC) { - self.append.properties(@[ - @"delegate" - ]).forClass(SafariVC); - if (@available(iOS 10.0, *)) { - self.append.properties(@[ - @"preferredBarTintColor", @"preferredControlTintColor" - ]).forClass(SafariVC); - } - if (@available(iOS 11.0, *)) { - self.append.properties(@[ - @"configuration", @"dismissButtonStyle" - ]).forClass(SafariVC); - } - } -} - -@end - -#pragma mark - Pasteboard - -@implementation FLEXShortcutsFactory (Pasteboard) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - self.append.properties(@[ - @"name", @"numberOfItems", @"items", - @"string", @"image", @"color", @"URL", - ]).forClass(UIPasteboard.class); -} - -@end - -@interface NSNotificationCenter (Observers) -@property (readonly) NSArray *flex_observers; -@end - -@implementation NSNotificationCenter (Observers) -- (id)flex_observers { - NSString *debug = self.debugDescription; - NSArray *observers = [debug componentsSeparatedByString:@"\n"]; - NSArray *> *splitObservers = [observers flex_mapped:^id(NSString *entry, NSUInteger idx) { - return [entry componentsSeparatedByString:@","]; - }]; - - NSArray *names = [splitObservers flex_mapped:^id(NSArray *entry, NSUInteger idx) { - return entry[0]; - }]; - NSArray *objects = [splitObservers flex_mapped:^id(NSArray *entry, NSUInteger idx) { - if (entry.count < 2) return NSNull.null; - NSScanner *scanner = [NSScanner scannerWithString:entry[1]]; - - unsigned long long objectPointerValue; - if ([scanner scanHexLongLong:&objectPointerValue]) { - void *objectPointer = (void *)objectPointerValue; - if (FLEXPointerIsValidObjcObject(objectPointer)) - return (__bridge id)(void *)objectPointer; - } - - return NSNull.null; - }]; - - return [NSArray flex_forEachUpTo:names.count map:^id(NSUInteger i) { - return @[names[i], objects[i]]; - }]; -} -@end - -#pragma mark - Firebase Firestore - -@implementation FLEXShortcutsFactory (FirebaseFirestore) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - Class FIRDocumentSnap = NSClassFromString(@"FIRDocumentSnapshot"); - if (FIRDocumentSnap) { - FLEXRuntimeUtilityTryAddObjectProperty(2, data, FIRDocumentSnap, NSDictionary, PropertyKey(ReadOnly)); - } -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h deleted file mode 100644 index 2bf690a..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h +++ /dev/null @@ -1,134 +0,0 @@ -// -// FLEXShortcutsSection.h -// FLEX -// -// Created by Tanner Bennett on 8/29/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewSection.h" -#import "FLEXObjectInfoSection.h" -@class FLEXProperty, FLEXIvar, FLEXMethod; - -NS_ASSUME_NONNULL_BEGIN - -/// An abstract base class for custom object "shortcuts" where every -/// row can possibly have some action. The section title is "Shortcuts". -/// -/// You should only subclass this class if you need simple shortcuts -/// with plain titles and/or subtitles. This class will automatically -/// configure each cell appropriately. Since this is intended as a -/// static section, subclasses should only need to implement the -/// \c viewControllerToPushForRow: and/or \c didSelectRowAction: methods. -/// -/// If you create the section using \c forObject:rows:numberOfLines: -/// then it will provide a view controller from \c viewControllerToPushForRow: -/// automatically for rows that are a property/ivar/method. -@interface FLEXShortcutsSection : FLEXTableViewSection - -/// Uses \c kFLEXDefaultCell -+ (instancetype)forObject:(id)objectOrClass rowTitles:(nullable NSArray *)titles; -/// Uses \c kFLEXDetailCell for non-empty subtitles, otherwise uses \c kFLEXDefaultCell -+ (instancetype)forObject:(id)objectOrClass - rowTitles:(nullable NSArray *)titles - rowSubtitles:(nullable NSArray *)subtitles; - -/// Uses \c kFLEXDefaultCell for rows that are given a title, otherwise -/// this uses \c kFLEXDetailCell for any other allowed object. -/// -/// The section provide a view controller from \c viewControllerToPushForRow: -/// automatically for rows that are a property/ivar/method. -/// -/// @param rows A mixed array containing any of the following: -/// - any \c FLEXShortcut conforming object -/// - an \c NSString -/// - a \c FLEXProperty -/// - a \c FLEXIvar -/// - a \c FLEXMethodBase (includes \c FLEXMethod of course) -/// Passing one of the latter 3 will provide a shortcut to that property/ivar/method. -+ (instancetype)forObject:(id)objectOrClass rows:(nullable NSArray *)rows; - -/// Same as \c forObject:rows: but the given rows are prepended -/// to the shortcuts already registered for the object's class. -/// \c forObject:rows: does not use the registered shortcuts at all. -+ (instancetype)forObject:(id)objectOrClass additionalRows:(nullable NSArray *)rows; - -/// Calls into \c forObject:rows: using the registered shortcuts for the object's class. -/// @return An empty section if the object has no shortcuts registered at all. -+ (instancetype)forObject:(id)objectOrClass; - -/// Subclasses \e may override this to hide the disclosure indicator -/// for some rows. It is shown for all rows by default, unless -/// you initialize it with \c forObject:rowTitles:rowSubtitles: -/// -/// When you hide the disclosure indicator, the row is not selectable. -- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row; - -/// The number of lines for the title and subtitle labels. Defaults to 1. -@property (nonatomic, readonly) NSInteger numberOfLines; -/// The object used to initialize this section. -@property (nonatomic, readonly) id object; - -/// Whether dynamic subtitles should always be computed as a cell is configured. -/// Defaults to NO. Has no effect on static subtitles that are passed explicitly. -@property (nonatomic) BOOL cacheSubtitles; - -/// Whether this shortcut section overrides the default section or not. -/// Subclasses should not override this method. To provide a second -/// section alongside the default shortcuts section, use \c forObject:rows: -/// @return \c NO if initialized with \c forObject: or \c forObject:additionalRows: -@property (nonatomic, readonly) BOOL isNewSection; - -@end - -@class FLEXShortcutsFactory; -typedef FLEXShortcutsFactory *_Nonnull(^FLEXShortcutsFactoryNames)(NSArray *names); -typedef void (^FLEXShortcutsFactoryTarget)(Class targetClass); - -/// The block properties below are to be used like SnapKit or Masonry. -/// \c FLEXShortcutsSection.append.properties(@[@"frame",@"bounds"]).forClass(UIView.class); -/// -/// To safely register your own classes at launch, subclass this class, -/// override \c +load, and call the appropriate methods on \c self -@interface FLEXShortcutsFactory : NSObject - -/// Returns the list of all registered shortcuts for the given object in this order: -/// Properties, ivars, methods. -/// -/// This method traverses up the object's class hierarchy until it finds -/// something registered. This allows you to show different shortcuts for -/// the same object in different parts of the class hierarchy. -/// -/// As an example, UIView may have a -layer shortcut registered. But if -/// you're inspecting a UIControl, you may not care about the layer or other -/// UIView-specific things; you might rather see the target-actions registered -/// for this control, and so you would register that property or ivar to UIControl, -/// And you would still be able to see the UIView-registered shorcuts by clicking -/// on the UIView "lens" at the top the explorer view controller screen. -+ (NSArray *)shortcutsForObjectOrClass:(id)objectOrClass; - -@property (nonatomic, readonly, class) FLEXShortcutsFactory *append; -@property (nonatomic, readonly, class) FLEXShortcutsFactory *prepend; -@property (nonatomic, readonly, class) FLEXShortcutsFactory *replace; - -@property (nonatomic, readonly) FLEXShortcutsFactoryNames properties; -/// Do not try to set \c classProperties at the same time as \c ivars or other instance things. -@property (nonatomic, readonly) FLEXShortcutsFactoryNames classProperties; -@property (nonatomic, readonly) FLEXShortcutsFactoryNames ivars; -@property (nonatomic, readonly) FLEXShortcutsFactoryNames methods; -/// Do not try to set \c classMethods at the same time as \c ivars or other instance things. -@property (nonatomic, readonly) FLEXShortcutsFactoryNames classMethods; - -/// Accepts the target class. If you pass a regular class object, -/// shortcuts will appear on instances. If you pass a metaclass object, -/// shortcuts will appear when exploring a class object. -/// -/// For example, some class method shortcuts are added to the NSObject meta -/// class by default so that you can see +alloc and +new when exploring -/// a class object. If you wanted these to show up when exploring -/// instances you would pass them to the classMethods method above. -@property (nonatomic, readonly) FLEXShortcutsFactoryTarget forClass; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.m deleted file mode 100644 index cc22741..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.m +++ /dev/null @@ -1,482 +0,0 @@ -// -// FLEXShortcutsSection.m -// FLEX -// -// Created by Tanner Bennett on 8/29/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" -#import "FLEXTableView.h" -#import "FLEXTableViewCell.h" -#import "FLEXUtility.h" -#import "FLEXShortcut.h" -#import "FLEXProperty.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXIvar.h" -#import "FLEXMethod.h" -#import "FLEXRuntime+UIKitHelpers.h" -#import "FLEXObjectExplorer.h" - -#pragma mark Private - -@interface FLEXShortcutsSection () -@property (nonatomic, copy) NSArray *titles; -@property (nonatomic, copy) NSArray *subtitles; - -@property (nonatomic, copy) NSArray *allTitles; -@property (nonatomic, copy) NSArray *allSubtitles; - -// Shortcuts are not used if initialized with static titles and subtitles -@property (nonatomic, copy) NSArray> *shortcuts; -@property (nonatomic, readonly) NSArray> *allShortcuts; -@end - -@implementation FLEXShortcutsSection -@synthesize isNewSection = _isNewSection; - -#pragma mark Initialization - -+ (instancetype)forObject:(id)objectOrClass rowTitles:(NSArray *)titles { - return [self forObject:objectOrClass rowTitles:titles rowSubtitles:nil]; -} - -+ (instancetype)forObject:(id)objectOrClass - rowTitles:(NSArray *)titles - rowSubtitles:(NSArray *)subtitles { - return [[self alloc] initWithObject:objectOrClass titles:titles subtitles:subtitles]; -} - -+ (instancetype)forObject:(id)objectOrClass rows:(NSArray *)rows { - return [[self alloc] initWithObject:objectOrClass rows:rows isNewSection:YES]; -} - -+ (instancetype)forObject:(id)objectOrClass additionalRows:(NSArray *)toPrepend { - NSArray *rows = [FLEXShortcutsFactory shortcutsForObjectOrClass:objectOrClass]; - NSArray *allRows = [toPrepend arrayByAddingObjectsFromArray:rows] ?: rows; - return [[self alloc] initWithObject:objectOrClass rows:allRows isNewSection:NO]; -} - -+ (instancetype)forObject:(id)objectOrClass { - return [self forObject:objectOrClass additionalRows:nil]; -} - -- (id)initWithObject:(id)object - titles:(NSArray *)titles - subtitles:(NSArray *)subtitles { - - NSParameterAssert(titles.count == subtitles.count || !subtitles); - NSParameterAssert(titles.count); - - self = [super init]; - if (self) { - _object = object; - _allTitles = titles.copy; - _allSubtitles = subtitles.copy; - _isNewSection = YES; - _numberOfLines = 1; - } - - return self; -} - -- (id)initWithObject:object rows:(NSArray *)rows isNewSection:(BOOL)newSection { - self = [super init]; - if (self) { - _object = object; - _isNewSection = newSection; - - _allShortcuts = [rows flex_mapped:^id(id obj, NSUInteger idx) { - return [FLEXShortcut shortcutFor:obj]; - }]; - _numberOfLines = 1; - - // Populate titles and subtitles - [self reloadData]; - } - - return self; -} - - -#pragma mark - Public - -- (void)setCacheSubtitles:(BOOL)cacheSubtitles { - if (_cacheSubtitles == cacheSubtitles) return; - - // cacheSubtitles only applies if we have shortcut objects - if (self.allShortcuts) { - _cacheSubtitles = cacheSubtitles; - [self reloadData]; - } else { - NSLog(@"Warning: setting 'cacheSubtitles' on a shortcut section with static subtitles"); - } -} - - -#pragma mark - Overrides - -- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row { - if (_allShortcuts) { - return [self.shortcuts[row] accessoryTypeWith:self.object]; - } - - return UITableViewCellAccessoryNone; -} - -- (void)setFilterText:(NSString *)filterText { - super.filterText = filterText; - - NSAssert( - self.allTitles.count == self.allSubtitles.count, - @"Each title needs a (possibly empty) subtitle" - ); - - if (filterText.length) { - // Tally up indexes of titles and subtitles matching the filter - NSMutableIndexSet *filterMatches = [NSMutableIndexSet new]; - id filterBlock = ^BOOL(NSString *obj, NSUInteger idx) { - if ([obj localizedCaseInsensitiveContainsString:filterText]) { - [filterMatches addIndex:idx]; - return YES; - } - - return NO; - }; - - // Get all matching indexes, including subtitles - [self.allTitles flex_forEach:filterBlock]; - [self.allSubtitles flex_forEach:filterBlock]; - // Filter to matching indexes only - self.titles = [self.allTitles objectsAtIndexes:filterMatches]; - self.subtitles = [self.allSubtitles objectsAtIndexes:filterMatches]; - self.shortcuts = [self.allShortcuts objectsAtIndexes:filterMatches]; - } else { - self.shortcuts = self.allShortcuts; - self.titles = self.allTitles; - self.subtitles = [self.allSubtitles flex_filtered:^BOOL(NSString *sub, NSUInteger idx) { - return sub.length > 0; - }]; - } -} - -- (void)reloadData { - [FLEXObjectExplorer configureDefaultsForItems:self.allShortcuts]; - - // Generate all (sub)titles from shortcuts - if (self.allShortcuts) { - self.allTitles = [self.allShortcuts flex_mapped:^id(id s, NSUInteger idx) { - return [s titleWith:self.object]; - }]; - self.allSubtitles = [self.allShortcuts flex_mapped:^id(id s, NSUInteger idx) { - return [s subtitleWith:self.object] ?: @""; - }]; - } - - // Re-generate filtered (sub)titles and shortcuts - self.filterText = self.filterText; -} - -- (NSString *)title { - return @"Shortcuts"; -} - -- (NSInteger)numberOfRows { - return self.titles.count; -} - -- (BOOL)canSelectRow:(NSInteger)row { - UITableViewCellAccessoryType type = [self.shortcuts[row] accessoryTypeWith:self.object]; - BOOL hasDisclosure = NO; - hasDisclosure |= type == UITableViewCellAccessoryDisclosureIndicator; - hasDisclosure |= type == UITableViewCellAccessoryDetailDisclosureButton; - return hasDisclosure; -} - -- (void (^)(__kindof UIViewController *))didSelectRowAction:(NSInteger)row { - return [self.shortcuts[row] didSelectActionWith:self.object]; -} - -- (UIViewController *)viewControllerToPushForRow:(NSInteger)row { - /// Nil if shortcuts is nil, i.e. if initialized with forObject:rowTitles:rowSubtitles: - return [self.shortcuts[row] viewerWith:self.object]; -} - -- (void (^)(__kindof UIViewController *))didPressInfoButtonAction:(NSInteger)row { - id shortcut = self.shortcuts[row]; - if ([shortcut respondsToSelector:@selector(editorWith:forSection:)]) { - id object = self.object; - return ^(UIViewController *host) { - UIViewController *editor = [shortcut editorWith:object forSection:self]; - [host.navigationController pushViewController:editor animated:YES]; - }; - } - - return nil; -} - -- (NSString *)reuseIdentifierForRow:(NSInteger)row { - FLEXTableViewCellReuseIdentifier defaultReuse = kFLEXDetailCell; - if (@available(iOS 11, *)) { - defaultReuse = kFLEXMultilineDetailCell; - } - - return [self.shortcuts[row] customReuseIdentifierWith:self.object] ?: defaultReuse; -} - -- (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row { - cell.titleLabel.text = [self titleForRow:row]; - cell.titleLabel.numberOfLines = self.numberOfLines; - cell.subtitleLabel.text = [self subtitleForRow:row]; - cell.subtitleLabel.numberOfLines = self.numberOfLines; - cell.accessoryType = [self accessoryTypeForRow:row]; -} - -- (NSString *)titleForRow:(NSInteger)row { - return self.titles[row]; -} - -- (NSString *)subtitleForRow:(NSInteger)row { - // Case: dynamic, uncached subtitles - if (!self.cacheSubtitles) { - NSString *subtitle = [self.shortcuts[row] subtitleWith:self.object]; - return subtitle.length ? subtitle : nil; - } - - // Case: static subtitles, or cached subtitles - return self.subtitles[row]; -} - -@end - - -#pragma mark - Global shortcut registration - -@interface FLEXShortcutsFactory () { - BOOL _append, _prepend, _replace, _notInstance; - NSArray *_properties, *_ivars, *_methods; -} -@end - -#define NewAndSet(ivar) ({ FLEXShortcutsFactory *r = [self sharedFactory]; r->ivar = YES; r; }) -#define SetIvar(ivar) ({ self->ivar = YES; self; }) -#define SetParamBlock(ivar) ^(NSArray *p) { self->ivar = p; return self; } - -typedef NSMutableDictionary> *> RegistrationBuckets; - -@implementation FLEXShortcutsFactory { - // Class buckets - RegistrationBuckets *cProperties; - RegistrationBuckets *cIvars; - RegistrationBuckets *cMethods; - // Metaclass buckets - RegistrationBuckets *mProperties; - RegistrationBuckets *mMethods; -} - -+ (instancetype)sharedFactory { - static FLEXShortcutsFactory *shared = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - shared = [self new]; - }); - - return shared; -} - -- (id)init { - self = [super init]; - if (self) { - cProperties = [NSMutableDictionary new]; - cIvars = [NSMutableDictionary new]; - cMethods = [NSMutableDictionary new]; - - mProperties = [NSMutableDictionary new]; - mMethods = [NSMutableDictionary new]; - } - - return self; -} - -+ (NSArray> *)shortcutsForObjectOrClass:(id)objectOrClass { - return [[self sharedFactory] shortcutsForObjectOrClass:objectOrClass]; -} - -- (NSArray> *)shortcutsForObjectOrClass:(id)objectOrClass { - NSParameterAssert(objectOrClass); - - NSMutableArray> *shortcuts = [NSMutableArray new]; - BOOL isClass = object_isClass(objectOrClass); - // The -class does not give you a metaclass, and we want a metaclass - // if a class is passed in, or a class if an object is passed in - Class classKey = object_getClass(objectOrClass); - - RegistrationBuckets *propertyBucket = isClass ? mProperties : cProperties; - RegistrationBuckets *methodBucket = isClass ? mMethods : cMethods; - RegistrationBuckets *ivarBucket = isClass ? nil : cIvars; - - BOOL stop = NO; - while (!stop && classKey) { - NSArray *properties = propertyBucket[classKey]; - NSArray *ivars = ivarBucket[classKey]; - NSArray *methods = methodBucket[classKey]; - - // Stop if we found anything - stop = properties || ivars || methods; - if (stop) { - // Add things we found to the list - [shortcuts addObjectsFromArray:properties]; - [shortcuts addObjectsFromArray:ivars]; - [shortcuts addObjectsFromArray:methods]; - } else { - classKey = class_getSuperclass(classKey); - } - } - - [FLEXObjectExplorer configureDefaultsForItems:shortcuts]; - return shortcuts; -} - -+ (FLEXShortcutsFactory *)append { - return NewAndSet(_append); -} - -+ (FLEXShortcutsFactory *)prepend { - return NewAndSet(_prepend); -} - -+ (FLEXShortcutsFactory *)replace { - return NewAndSet(_replace); -} - -- (void)_register:(NSArray> *)items to:(RegistrationBuckets *)global class:(Class)key { - @synchronized (self) { - // Get (or initialize) the bucket for this class - NSMutableArray *bucket = ({ - id bucket = global[key]; - if (!bucket) { - bucket = [NSMutableArray new]; - global[(id)key] = bucket; - } - bucket; - }); - - if (self->_append) { [bucket addObjectsFromArray:items]; } - if (self->_replace) { [bucket setArray:items]; } - if (self->_prepend) { - if (bucket.count) { - // Set new items as array, add old items behind them - id copy = bucket.copy; - [bucket setArray:items]; - [bucket addObjectsFromArray:copy]; - } else { - [bucket addObjectsFromArray:items]; - } - } - } -} - -- (void)reset { - _append = NO; - _prepend = NO; - _replace = NO; - _notInstance = NO; - - _properties = nil; - _ivars = nil; - _methods = nil; -} - -- (FLEXShortcutsFactory *)class { - return SetIvar(_notInstance); -} - -- (FLEXShortcutsFactoryNames)properties { - NSAssert(!_notInstance, @"Do not try to set properties+classProperties at the same time"); - return SetParamBlock(_properties); -} - -- (FLEXShortcutsFactoryNames)classProperties { - _notInstance = YES; - return SetParamBlock(_properties); -} - -- (FLEXShortcutsFactoryNames)ivars { - return SetParamBlock(_ivars); -} - -- (FLEXShortcutsFactoryNames)methods { - NSAssert(!_notInstance, @"Do not try to set methods+classMethods at the same time"); - return SetParamBlock(_methods); -} - -- (FLEXShortcutsFactoryNames)classMethods { - _notInstance = YES; - return SetParamBlock(_methods); -} - -- (FLEXShortcutsFactoryTarget)forClass { - return ^(Class cls) { - NSAssert( - ( self->_append && !self->_prepend && !self->_replace) || - (!self->_append && self->_prepend && !self->_replace) || - (!self->_append && !self->_prepend && self->_replace), - @"You can only do one of [append, prepend, replace]" - ); - - - /// Whether the metadata we're about to add is instance or - /// class metadata, i.e. class properties vs instance properties - BOOL instanceMetadata = !self->_notInstance; - /// Whether the given class is a metaclass or not; we need to switch to - /// the metaclass to add class metadata if we are given the normal class object - BOOL isMeta = class_isMetaClass(cls); - /// Whether the shortcuts we're about to add should appear for classes or instances - BOOL instanceShortcut = !isMeta; - - if (instanceMetadata) { - NSAssert(!isMeta, - @"Instance metadata can only be added as an instance shortcut" - ); - } - - Class metaclass = isMeta ? cls : object_getClass(cls); - Class clsForMetadata = instanceMetadata ? cls : metaclass; - - // The factory is a singleton so we don't need to worry about "leaking" it - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wimplicit-retain-self" - - RegistrationBuckets *propertyBucket = instanceShortcut ? cProperties : mProperties; - RegistrationBuckets *methodBucket = instanceShortcut ? cMethods : mMethods; - RegistrationBuckets *ivarBucket = instanceShortcut ? cIvars : nil; - - #pragma clang diagnostic pop - - if (self->_properties) { - NSArray *items = [self->_properties flex_mapped:^id(NSString *name, NSUInteger idx) { - return [FLEXProperty named:name onClass:clsForMetadata]; - }]; - [self _register:items to:propertyBucket class:cls]; - } - - if (self->_methods) { - NSArray *items = [self->_methods flex_mapped:^id(NSString *name, NSUInteger idx) { - return [FLEXMethod selector:NSSelectorFromString(name) class:clsForMetadata]; - }]; - [self _register:items to:methodBucket class:cls]; - } - - if (self->_ivars) { - NSAssert(instanceMetadata, @"Instance metadata can only be added as an instance shortcut (%@)", cls); - NSArray *items = [self->_ivars flex_mapped:^id(NSString *name, NSUInteger idx) { - return [FLEXIvar named:name onClass:clsForMetadata]; - }]; - [self _register:items to:ivarBucket class:cls]; - } - - [self reset]; - }; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.h deleted file mode 100644 index d0b0db1..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXUIAppShortcuts.h -// FLEX -// -// Created by Tanner on 5/25/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -@interface FLEXUIAppShortcuts : FLEXShortcutsSection - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.m deleted file mode 100644 index 7946645..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.m +++ /dev/null @@ -1,77 +0,0 @@ -// -// FLEXUIAppShortcuts.m -// FLEX -// -// Created by Tanner on 5/25/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXUIAppShortcuts.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXShortcut.h" -#import "FLEXAlert.h" - -@implementation FLEXUIAppShortcuts - -#pragma mark - Overrides - -+ (instancetype)forObject:(UIApplication *)application { - return [self forObject:application additionalRows:@[ - [FLEXActionShortcut title:@"Open URL…" - subtitle:^NSString *(UIViewController *controller) { - return nil; - } - selectionHandler:^void(UIViewController *host, UIApplication *app) { - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Open URL"); - make.message( - @"This will call openURL: or openURL:options:completion: " - "with the string below. 'Open if Universal' will only open " - "the URL if it is a registered Universal Link." - ); - - make.textField(@"twitter://user?id=12345"); - make.button(@"Open").handler(^(NSArray *strings) { - [self openURL:strings[0] inApp:app onlyIfUniveral:NO host:host]; - }); - make.button(@"Open if Universal").handler(^(NSArray *strings) { - [self openURL:strings[0] inApp:app onlyIfUniveral:YES host:host]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:host]; - } - accessoryType:^UITableViewCellAccessoryType(UIViewController *controller) { - return UITableViewCellAccessoryDisclosureIndicator; - } - ] - ]]; -} - -+ (void)openURL:(NSString *)urlString - inApp:(UIApplication *)app - onlyIfUniveral:(BOOL)universalOnly - host:(UIViewController *)host { - NSURL *url = [NSURL URLWithString:urlString]; - - if (url) { - if (@available(iOS 10, *)) { - [app openURL:url options:@{ - UIApplicationOpenURLOptionUniversalLinksOnly: @(universalOnly) - } completionHandler:^(BOOL success) { - if (!success) { - [FLEXAlert showAlert:@"No Universal Link Handler" - message:@"No installed application is registered to handle this link." - from:host - ]; - } - }]; - } else { - [app openURL:url]; - } - } else { - [FLEXAlert showAlert:@"Error" message:@"Invalid URL" from:host]; - } -} - -@end - diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.h deleted file mode 100644 index 1d09e69..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// FLEXViewControllerShortcuts.h -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -@interface FLEXViewControllerShortcuts : FLEXShortcutsSection - -+ (instancetype)forObject:(UIViewController *)viewController; - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.m deleted file mode 100644 index 8f906fa..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewControllerShortcuts.m +++ /dev/null @@ -1,58 +0,0 @@ -// -// FLEXViewControllerShortcuts.m -// FLEX -// -// Created by Tanner Bennett on 12/12/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXViewControllerShortcuts.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXShortcut.h" -#import "FLEXAlert.h" - -@interface FLEXViewControllerShortcuts () -@end - -@implementation FLEXViewControllerShortcuts - -#pragma mark - Overrides - -+ (instancetype)forObject:(UIViewController *)viewController { - BOOL (^vcIsInuse)(UIViewController *) = ^BOOL(UIViewController *controller) { - if (controller.viewIfLoaded.window) { - return YES; - } - - return controller.navigationController != nil; - }; - - return [self forObject:viewController additionalRows:@[ - [FLEXActionShortcut title:@"Push View Controller" - subtitle:^NSString *(UIViewController *controller) { - return vcIsInuse(controller) ? @"In use, cannot push" : nil; - } - selectionHandler:^void(UIViewController *host, UIViewController *controller) { - if (!vcIsInuse(controller)) { - [host.navigationController pushViewController:controller animated:YES]; - } else { - [FLEXAlert - showAlert:@"Cannot Push View Controller" - message:@"This view controller's view is currently in use." - from:host - ]; - } - } - accessoryType:^UITableViewCellAccessoryType(UIViewController *controller) { - if (!vcIsInuse(controller)) { - return UITableViewCellAccessoryDisclosureIndicator; - } else { - return UITableViewCellAccessoryNone; - } - } - ] - ]]; -} - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewShortcuts.h b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewShortcuts.h deleted file mode 100644 index f1df0aa..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewShortcuts.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// FLEXViewShortcuts.h -// FLEX -// -// Created by Tanner Bennett on 12/11/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXShortcutsSection.h" - -/// Adds "Nearest View Controller" and "Preview Image" shortcuts to all views -@interface FLEXViewShortcuts : FLEXShortcutsSection - -@end diff --git a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewShortcuts.m b/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewShortcuts.m deleted file mode 100644 index 058cd9b..0000000 --- a/Tweaks/FLEX/ObjectExplorers/Sections/Shortcuts/FLEXViewShortcuts.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// FLEXViewShortcuts.m -// FLEX -// -// Created by Tanner Bennett on 12/11/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXViewShortcuts.h" -#import "FLEXShortcut.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXImagePreviewViewController.h" - -@interface FLEXViewShortcuts () -@property (nonatomic, readonly) UIView *view; -@end - -@implementation FLEXViewShortcuts - -#pragma mark - Internal - -- (UIView *)view { - return self.object; -} - -+ (UIViewController *)viewControllerForView:(UIView *)view { - NSString *viewDelegate = @"viewDelegate"; - if ([view respondsToSelector:NSSelectorFromString(viewDelegate)]) { - return [view valueForKey:viewDelegate]; - } - - return nil; -} - -+ (UIViewController *)viewControllerForAncestralView:(UIView *)view { - NSString *_viewControllerForAncestor = @"_viewControllerForAncestor"; - if ([view respondsToSelector:NSSelectorFromString(_viewControllerForAncestor)]) { - return [view valueForKey:_viewControllerForAncestor]; - } - - return nil; -} - -+ (UIViewController *)nearestViewControllerForView:(UIView *)view { - return [self viewControllerForView:view] ?: [self viewControllerForAncestralView:view]; -} - - -#pragma mark - Overrides - -+ (instancetype)forObject:(UIView *)view { - // In the past, FLEX would not hold a strong reference to something like this. - // After using FLEX for so long, I am certain it is more useful to eagerly - // reference something as useful as a view controller so that the reference - // is not lost and swept out from under you before you can access it. - // - // The alternative here is to use a future in place of `controller` which would - // dynamically grab a reference to the view controller. 99% of the time, however, - // it is not all that useful. If you need it to refresh, you can simply go back - // and go forward again and it will show if the view controller is nil or changed. - UIViewController *controller = [FLEXViewShortcuts nearestViewControllerForView:view]; - - return [self forObject:view additionalRows:@[ - [FLEXActionShortcut title:@"Nearest View Controller" - subtitle:^NSString *(id view) { - return [FLEXRuntimeUtility safeDescriptionForObject:controller]; - } - viewer:^UIViewController *(id view) { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:controller]; - } - accessoryType:^UITableViewCellAccessoryType(id view) { - return controller ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; - } - ], - [FLEXActionShortcut title:@"Preview Image" subtitle:^NSString *(UIView *view) { - return !CGRectIsEmpty(view.bounds) ? @"" : @"Unavailable with empty bounds"; - } - viewer:^UIViewController *(UIView *view) { - return [FLEXImagePreviewViewController previewForView:view]; - } - accessoryType:^UITableViewCellAccessoryType(UIView *view) { - // Disable preview if bounds are CGRectZero - return !CGRectIsEmpty(view.bounds) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; - } - ] - ]]; -} - -@end diff --git a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbar.h b/Tweaks/FLEX/Toolbar/FLEXExplorerToolbar.h deleted file mode 100644 index f6cd0f9..0000000 --- a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbar.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// FLEXExplorerToolbar.h -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@class FLEXExplorerToolbarItem; - -NS_ASSUME_NONNULL_BEGIN - -/// Users of the toolbar can configure the enabled state -/// and event target/actions for each item. -@interface FLEXExplorerToolbar : UIView - -/// The items to be displayed in the toolbar. Defaults to: -/// globalsItem, hierarchyItem, selectItem, moveItem, closeItem -@property (nonatomic, copy) NSArray *toolbarItems; - -/// Toolbar item for selecting views. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *selectItem; - -/// Toolbar item for presenting a list with the view hierarchy. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *hierarchyItem; - -/// Toolbar item for moving views. -/// Its \c sibling is the \c lastTabItem -@property (nonatomic, readonly) FLEXExplorerToolbarItem *moveItem; - -/// Toolbar item for presenting the currently active tab. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *recentItem; - -/// Toolbar item for presenting a screen with various tools for inspecting the app. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *globalsItem; - -/// Toolbar item for hiding the explorer. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *closeItem; - -/// A view for moving the entire toolbar. -/// Users of the toolbar can attach a pan gesture recognizer to decide how to reposition the toolbar. -@property (nonatomic, readonly) UIView *dragHandle; - -/// A color matching the overlay on color on the selected view. -@property (nonatomic) UIColor *selectedViewOverlayColor; - -/// Description text for the selected view displayed below the toolbar items. -@property (nonatomic, copy) NSString *selectedViewDescription; - -/// Area where details of the selected view are shown -/// Users of the toolbar can attach a tap gesture recognizer to show additional details. -@property (nonatomic, readonly) UIView *selectedViewDescriptionContainer; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbar.m b/Tweaks/FLEX/Toolbar/FLEXExplorerToolbar.m deleted file mode 100644 index 022999e..0000000 --- a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbar.m +++ /dev/null @@ -1,256 +0,0 @@ -// -// FLEXExplorerToolbar.m -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXExplorerToolbar.h" -#import "FLEXExplorerToolbarItem.h" -#import "FLEXResources.h" -#import "FLEXUtility.h" - -@interface FLEXExplorerToolbar () - -@property (nonatomic, readwrite) FLEXExplorerToolbarItem *globalsItem; -@property (nonatomic, readwrite) FLEXExplorerToolbarItem *hierarchyItem; -@property (nonatomic, readwrite) FLEXExplorerToolbarItem *selectItem; -@property (nonatomic, readwrite) FLEXExplorerToolbarItem *recentItem; -@property (nonatomic, readwrite) FLEXExplorerToolbarItem *moveItem; -@property (nonatomic, readwrite) FLEXExplorerToolbarItem *closeItem; -@property (nonatomic, readwrite) UIView *dragHandle; - -@property (nonatomic) UIImageView *dragHandleImageView; - -@property (nonatomic) UIView *selectedViewDescriptionContainer; -@property (nonatomic) UIView *selectedViewDescriptionSafeAreaContainer; -@property (nonatomic) UIView *selectedViewColorIndicator; -@property (nonatomic) UILabel *selectedViewDescriptionLabel; - -@property (nonatomic,readwrite) UIView *backgroundView; - -@end - -@implementation FLEXExplorerToolbar - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - // Background - self.backgroundView = [UIView new]; - self.backgroundView.backgroundColor = [FLEXColor secondaryBackgroundColorWithAlpha:0.95]; - [self addSubview:self.backgroundView]; - - // Drag handle - self.dragHandle = [UIView new]; - self.dragHandle.backgroundColor = UIColor.clearColor; - self.dragHandleImageView = [[UIImageView alloc] initWithImage:FLEXResources.dragHandle]; - self.dragHandleImageView.tintColor = [FLEXColor.iconColor colorWithAlphaComponent:0.666]; - [self.dragHandle addSubview:self.dragHandleImageView]; - [self addSubview:self.dragHandle]; - - // Buttons - self.globalsItem = [FLEXExplorerToolbarItem itemWithTitle:@"menu" image:FLEXResources.globalsIcon]; - self.hierarchyItem = [FLEXExplorerToolbarItem itemWithTitle:@"views" image:FLEXResources.hierarchyIcon]; - self.selectItem = [FLEXExplorerToolbarItem itemWithTitle:@"select" image:FLEXResources.selectIcon]; - self.recentItem = [FLEXExplorerToolbarItem itemWithTitle:@"recent" image:FLEXResources.recentIcon]; - self.moveItem = [FLEXExplorerToolbarItem itemWithTitle:@"move" image:FLEXResources.moveIcon sibling:self.recentItem]; - self.closeItem = [FLEXExplorerToolbarItem itemWithTitle:@"close" image:FLEXResources.closeIcon]; - - // Selected view box // - - self.selectedViewDescriptionContainer = [UIView new]; - self.selectedViewDescriptionContainer.backgroundColor = [FLEXColor tertiaryBackgroundColorWithAlpha:0.95]; - self.selectedViewDescriptionContainer.hidden = YES; - [self addSubview:self.selectedViewDescriptionContainer]; - - self.selectedViewDescriptionSafeAreaContainer = [UIView new]; - self.selectedViewDescriptionSafeAreaContainer.backgroundColor = UIColor.clearColor; - [self.selectedViewDescriptionContainer addSubview:self.selectedViewDescriptionSafeAreaContainer]; - - self.selectedViewColorIndicator = [UIView new]; - self.selectedViewColorIndicator.backgroundColor = UIColor.redColor; - [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewColorIndicator]; - - self.selectedViewDescriptionLabel = [UILabel new]; - self.selectedViewDescriptionLabel.backgroundColor = UIColor.clearColor; - self.selectedViewDescriptionLabel.font = [[self class] descriptionLabelFont]; - [self.selectedViewDescriptionSafeAreaContainer addSubview:self.selectedViewDescriptionLabel]; - - // toolbarItems - self.toolbarItems = @[_globalsItem, _hierarchyItem, _selectItem, _moveItem, _closeItem]; - } - - return self; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - - CGRect safeArea = [self safeArea]; - // Drag Handle - const CGFloat kToolbarItemHeight = [[self class] toolbarItemHeight]; - self.dragHandle.frame = CGRectMake(CGRectGetMinX(safeArea), CGRectGetMinY(safeArea), [[self class] dragHandleWidth], kToolbarItemHeight); - CGRect dragHandleImageFrame = self.dragHandleImageView.frame; - dragHandleImageFrame.origin.x = FLEXFloor((self.dragHandle.frame.size.width - dragHandleImageFrame.size.width) / 2.0); - dragHandleImageFrame.origin.y = FLEXFloor((self.dragHandle.frame.size.height - dragHandleImageFrame.size.height) / 2.0); - self.dragHandleImageView.frame = dragHandleImageFrame; - - - // Toolbar Items - CGFloat originX = CGRectGetMaxX(self.dragHandle.frame); - CGFloat originY = CGRectGetMinY(safeArea); - CGFloat height = kToolbarItemHeight; - CGFloat width = FLEXFloor((CGRectGetWidth(safeArea) - CGRectGetWidth(self.dragHandle.frame)) / self.toolbarItems.count); - for (FLEXExplorerToolbarItem *toolbarItem in self.toolbarItems) { - toolbarItem.currentItem.frame = CGRectMake(originX, originY, width, height); - originX = CGRectGetMaxX(toolbarItem.currentItem.frame); - } - - // Make sure the last toolbar item goes to the edge to account for any accumulated rounding effects. - UIView *lastToolbarItem = self.toolbarItems.lastObject.currentItem; - CGRect lastToolbarItemFrame = lastToolbarItem.frame; - lastToolbarItemFrame.size.width = CGRectGetMaxX(safeArea) - lastToolbarItemFrame.origin.x; - lastToolbarItem.frame = lastToolbarItemFrame; - - self.backgroundView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), kToolbarItemHeight); - - const CGFloat kSelectedViewColorDiameter = [[self class] selectedViewColorIndicatorDiameter]; - const CGFloat kDescriptionLabelHeight = [[self class] descriptionLabelHeight]; - const CGFloat kHorizontalPadding = [[self class] horizontalPadding]; - const CGFloat kDescriptionVerticalPadding = [[self class] descriptionVerticalPadding]; - const CGFloat kDescriptionContainerHeight = [[self class] descriptionContainerHeight]; - - CGRect descriptionContainerFrame = CGRectZero; - descriptionContainerFrame.size.width = CGRectGetWidth(self.bounds); - descriptionContainerFrame.size.height = kDescriptionContainerHeight; - descriptionContainerFrame.origin.x = CGRectGetMinX(self.bounds); - descriptionContainerFrame.origin.y = CGRectGetMaxY(self.bounds) - kDescriptionContainerHeight; - self.selectedViewDescriptionContainer.frame = descriptionContainerFrame; - - CGRect descriptionSafeAreaContainerFrame = CGRectZero; - descriptionSafeAreaContainerFrame.size.width = CGRectGetWidth(safeArea); - descriptionSafeAreaContainerFrame.size.height = kDescriptionContainerHeight; - descriptionSafeAreaContainerFrame.origin.x = CGRectGetMinX(safeArea); - descriptionSafeAreaContainerFrame.origin.y = CGRectGetMinY(safeArea); - self.selectedViewDescriptionSafeAreaContainer.frame = descriptionSafeAreaContainerFrame; - - // Selected View Color - CGRect selectedViewColorFrame = CGRectZero; - selectedViewColorFrame.size.width = kSelectedViewColorDiameter; - selectedViewColorFrame.size.height = kSelectedViewColorDiameter; - selectedViewColorFrame.origin.x = kHorizontalPadding; - selectedViewColorFrame.origin.y = FLEXFloor((kDescriptionContainerHeight - kSelectedViewColorDiameter) / 2.0); - self.selectedViewColorIndicator.frame = selectedViewColorFrame; - self.selectedViewColorIndicator.layer.cornerRadius = ceil(selectedViewColorFrame.size.height / 2.0); - - // Selected View Description - CGRect descriptionLabelFrame = CGRectZero; - CGFloat descriptionOriginX = CGRectGetMaxX(selectedViewColorFrame) + kHorizontalPadding; - descriptionLabelFrame.size.height = kDescriptionLabelHeight; - descriptionLabelFrame.origin.x = descriptionOriginX; - descriptionLabelFrame.origin.y = kDescriptionVerticalPadding; - descriptionLabelFrame.size.width = CGRectGetMaxX(self.selectedViewDescriptionContainer.bounds) - kHorizontalPadding - descriptionOriginX; - self.selectedViewDescriptionLabel.frame = descriptionLabelFrame; -} - - -#pragma mark - Setter Overrides - -- (void)setToolbarItems:(NSArray *)toolbarItems { - if (_toolbarItems == toolbarItems) { - return; - } - - // Remove old toolbar items, if any - for (FLEXExplorerToolbarItem *item in _toolbarItems) { - [item.currentItem removeFromSuperview]; - } - - // Trim to 5 items if necessary - if (toolbarItems.count > 5) { - toolbarItems = [toolbarItems subarrayWithRange:NSMakeRange(0, 5)]; - } - - for (FLEXExplorerToolbarItem *item in toolbarItems) { - [self addSubview:item.currentItem]; - } - - _toolbarItems = toolbarItems.copy; - - // Lay out new items - [self setNeedsLayout]; - [self layoutIfNeeded]; -} - -- (void)setSelectedViewOverlayColor:(UIColor *)selectedViewOverlayColor { - if (![_selectedViewOverlayColor isEqual:selectedViewOverlayColor]) { - _selectedViewOverlayColor = selectedViewOverlayColor; - self.selectedViewColorIndicator.backgroundColor = selectedViewOverlayColor; - } -} - -- (void)setSelectedViewDescription:(NSString *)selectedViewDescription { - if (![_selectedViewDescription isEqual:selectedViewDescription]) { - _selectedViewDescription = selectedViewDescription; - self.selectedViewDescriptionLabel.text = selectedViewDescription; - BOOL showDescription = selectedViewDescription.length > 0; - self.selectedViewDescriptionContainer.hidden = !showDescription; - } -} - - -#pragma mark - Sizing Convenience Methods - -+ (UIFont *)descriptionLabelFont { - return [UIFont systemFontOfSize:12.0]; -} - -+ (CGFloat)toolbarItemHeight { - return 44.0; -} - -+ (CGFloat)dragHandleWidth { - return FLEXResources.dragHandle.size.width; -} - -+ (CGFloat)descriptionLabelHeight { - return ceil([[self descriptionLabelFont] lineHeight]); -} - -+ (CGFloat)descriptionVerticalPadding { - return 2.0; -} - -+ (CGFloat)descriptionContainerHeight { - return [self descriptionVerticalPadding] * 2.0 + [self descriptionLabelHeight]; -} - -+ (CGFloat)selectedViewColorIndicatorDiameter { - return ceil([self descriptionLabelHeight] / 2.0); -} - -+ (CGFloat)horizontalPadding { - return 11.0; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat height = 0.0; - height += [[self class] toolbarItemHeight]; - height += [[self class] descriptionContainerHeight]; - return CGSizeMake(size.width, height); -} - -- (CGRect)safeArea { - CGRect safeArea = self.bounds; - if (@available(iOS 11.0, *)) { - safeArea = UIEdgeInsetsInsetRect(self.bounds, self.safeAreaInsets); - } - - return safeArea; -} - -@end diff --git a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbarItem.h b/Tweaks/FLEX/Toolbar/FLEXExplorerToolbarItem.h deleted file mode 100644 index 80db5b2..0000000 --- a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbarItem.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// FLEXExplorerToolbarItem.h -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXExplorerToolbarItem : UIButton - -+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image; - -/// @param backupItem a toolbar item to use in place of this item when it becomes disabled. -/// Items without a sibling item exhibit expected behavior when they become disabled, and are greyed out. -+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image sibling:(nullable FLEXExplorerToolbarItem *)backupItem; - -/// If a toolbar item has a sibling, the item will replace itself with its -/// sibling when it becomes disabled, and vice versa when it becomes enabled again. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *sibling; - -/// When a toolbar item has a sibling and it becomes disabled, the sibling is the view -/// that should be added to or removed from a new or existing toolbar. This property -/// alleviates the programmer from determining whether to use \c item or \c item.sibling -/// or \c item.sibling.sibling and so on. Yes, sibling items can also have siblings so -/// that each item which becomes disabled may present another item in its place, creating -/// a "stack" of toolbar items. This behavior is useful for making buttons which occupy -/// the same space under different states. -/// -/// With this in mind, you should never access a stored toolbar item's view properties -/// such as \c frame or \c superview directly; you should access them on \c currentItem. -/// If you are trying to modify the frame of an item, and the item itself is not currently -/// displayed but instead its sibling is being displayed, then your changes could be ignored. -/// -/// @return the result of the item's sibling's \c currentItem, -/// if this item has a sibling and this item is disabled, otherwise this item. -@property (nonatomic, readonly) FLEXExplorerToolbarItem *currentItem; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbarItem.m b/Tweaks/FLEX/Toolbar/FLEXExplorerToolbarItem.m deleted file mode 100644 index 2c6bdb2..0000000 --- a/Tweaks/FLEX/Toolbar/FLEXExplorerToolbarItem.m +++ /dev/null @@ -1,155 +0,0 @@ -// -// FLEXExplorerToolbarItem.m -// Flipboard -// -// Created by Ryan Olson on 4/4/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXExplorerToolbarItem.h" -#import "FLEXUtility.h" - -@interface FLEXExplorerToolbarItem () - -@property (nonatomic) FLEXExplorerToolbarItem *sibling; -@property (nonatomic, copy) NSString *title; -@property (nonatomic) UIImage *image; - -@property (nonatomic, readonly, class) UIColor *defaultBackgroundColor; -@property (nonatomic, readonly, class) UIColor *highlightedBackgroundColor; -@property (nonatomic, readonly, class) UIColor *selectedBackgroundColor; - -@end - -@implementation FLEXExplorerToolbarItem - -#pragma mark - Public - -+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image { - return [self itemWithTitle:title image:image sibling:nil]; -} - -+ (instancetype)itemWithTitle:(NSString *)title image:(UIImage *)image sibling:(FLEXExplorerToolbarItem *)backupItem { - NSParameterAssert(title); NSParameterAssert(image); - - FLEXExplorerToolbarItem *toolbarItem = [self buttonWithType:UIButtonTypeSystem]; - toolbarItem.sibling = backupItem; - toolbarItem.title = title; - toolbarItem.image = image; - toolbarItem.tintColor = FLEXColor.iconColor; - toolbarItem.backgroundColor = self.defaultBackgroundColor; - toolbarItem.titleLabel.font = [UIFont systemFontOfSize:12.0]; - [toolbarItem setTitle:title forState:UIControlStateNormal]; - [toolbarItem setImage:image forState:UIControlStateNormal]; - [toolbarItem setTitleColor:FLEXColor.primaryTextColor forState:UIControlStateNormal]; - [toolbarItem setTitleColor:FLEXColor.deemphasizedTextColor forState:UIControlStateDisabled]; - return toolbarItem; -} - -- (FLEXExplorerToolbarItem *)currentItem { - if (!self.enabled && self.sibling) { - return self.sibling.currentItem; - } - - return self; -} - - -#pragma mark - Display Defaults - -+ (NSDictionary *)titleAttributes { - return @{ NSFontAttributeName : [UIFont systemFontOfSize:12.0] }; -} - -+ (UIColor *)highlightedBackgroundColor { - return FLEXColor.toolbarItemHighlightedColor; -} - -+ (UIColor *)selectedBackgroundColor { - return FLEXColor.toolbarItemSelectedColor; -} - -+ (UIColor *)defaultBackgroundColor { - return UIColor.clearColor; -} - -+ (CGFloat)topMargin { - return 2.0; -} - - -#pragma mark - State Changes - -- (void)setHighlighted:(BOOL)highlighted { - super.highlighted = highlighted; - [self updateColors]; -} - -- (void)setSelected:(BOOL)selected { - super.selected = selected; - [self updateColors]; -} - -- (void)setEnabled:(BOOL)enabled { - if (self.enabled != enabled) { - if (self.sibling) { - if (enabled) { // Replace sibling with myself - UIView *superview = self.sibling.superview; - [self.sibling removeFromSuperview]; - self.frame = self.sibling.frame; - [superview addSubview:self]; - } else { // Replace myself with sibling - UIView *superview = self.superview; - [self removeFromSuperview]; - self.sibling.frame = self.frame; - [superview addSubview:self.sibling]; - } - } - - super.enabled = enabled; - } -} - -+ (id)_selectedIndicatorImage { return nil; } - -- (void)updateColors { - // Background color - if (self.highlighted) { - self.backgroundColor = self.class.highlightedBackgroundColor; - } else if (self.selected) { - self.backgroundColor = self.class.selectedBackgroundColor; - } else { - self.backgroundColor = self.class.defaultBackgroundColor; - } -} - - -#pragma mark - UIButton Layout Overrides - -- (CGRect)titleRectForContentRect:(CGRect)contentRect { - NSDictionary *attrs = [[self class] titleAttributes]; - // Bottom aligned and centered. - CGRect titleRect = CGRectZero; - CGSize titleSize = [self.title boundingRectWithSize:contentRect.size - options:0 - attributes:attrs - context:nil].size; - titleSize = CGSizeMake(ceil(titleSize.width), ceil(titleSize.height)); - titleRect.size = titleSize; - titleRect.origin.y = contentRect.origin.y + CGRectGetMaxY(contentRect) - titleSize.height; - titleRect.origin.x = contentRect.origin.x + FLEXFloor((contentRect.size.width - titleSize.width) / 2.0); - return titleRect; -} - -- (CGRect)imageRectForContentRect:(CGRect)contentRect { - CGSize imageSize = self.image.size; - CGRect titleRect = [self titleRectForContentRect:contentRect]; - CGFloat availableHeight = contentRect.size.height - titleRect.size.height - [[self class] topMargin]; - CGFloat originY = [[self class] topMargin] + FLEXFloor((availableHeight - imageSize.height) / 2.0); - CGFloat originX = FLEXFloor((contentRect.size.width - imageSize.width) / 2.0); - CGRect imageRect = CGRectMake(originX, originY, imageSize.width, imageSize.height); - return imageRect; -} - -@end diff --git a/Tweaks/FLEX/Utility/APPLE_LICENSE b/Tweaks/FLEX/Utility/APPLE_LICENSE deleted file mode 100644 index c70995d..0000000 --- a/Tweaks/FLEX/Utility/APPLE_LICENSE +++ /dev/null @@ -1,367 +0,0 @@ -APPLE PUBLIC SOURCE LICENSE -Version 2.0 - August 6, 2003 - -Please read this License carefully before downloading this software. -By downloading or using this software, you are agreeing to be bound by -the terms of this License. If you do not or cannot agree to the terms -of this License, please do not download or use the software. - -1. General; Definitions. This License applies to any program or other -work which Apple Computer, Inc. ("Apple") makes publicly available and -which contains a notice placed by Apple identifying such program or -work as "Original Code" and stating that it is subject to the terms of -this Apple Public Source License version 2.0 ("License"). As used in -this License: - -1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is -the grantor of rights, (i) claims of patents that are now or hereafter -acquired, owned by or assigned to Apple and (ii) that cover subject -matter contained in the Original Code, but only to the extent -necessary to use, reproduce and/or distribute the Original Code -without infringement; and (b) in the case where You are the grantor of -rights, (i) claims of patents that are now or hereafter acquired, -owned by or assigned to You and (ii) that cover subject matter in Your -Modifications, taken alone or in combination with Original Code. - -1.2 "Contributor" means any person or entity that creates or -contributes to the creation of Modifications. - -1.3 "Covered Code" means the Original Code, Modifications, the -combination of Original Code and any Modifications, and/or any -respective portions thereof. - -1.4 "Externally Deploy" means: (a) to sublicense, distribute or -otherwise make Covered Code available, directly or indirectly, to -anyone other than You; and/or (b) to use Covered Code, alone or as -part of a Larger Work, in any way to provide a service, including but -not limited to delivery of content, through electronic communication -with a client other than You. - -1.5 "Larger Work" means a work which combines Covered Code or portions -thereof with code not governed by the terms of this License. - -1.6 "Modifications" mean any addition to, deletion from, and/or change -to, the substance and/or structure of the Original Code, any previous -Modifications, the combination of Original Code and any previous -Modifications, and/or any respective portions thereof. When code is -released as a series of files, a Modification is: (a) any addition to -or deletion from the contents of a file containing Covered Code; -and/or (b) any new file or other representation of computer program -statements that contains any part of Covered Code. - -1.7 "Original Code" means (a) the Source Code of a program or other -work as originally made available by Apple under this License, -including the Source Code of any updates or upgrades to such programs -or works made available by Apple under this License, and that has been -expressly identified by Apple as such in the header file(s) of such -work; and (b) the object code compiled from such Source Code and -originally made available by Apple under this License. - -1.8 "Source Code" means the human readable form of a program or other -work that is suitable for making modifications to it, including all -modules it contains, plus any associated interface definition files, -scripts used to control compilation and installation of an executable -(object code). - -1.9 "You" or "Your" means an individual or a legal entity exercising -rights under this License. For legal entities, "You" or "Your" -includes any entity which controls, is controlled by, or is under -common control with, You, where "control" means (a) the power, direct -or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or (b) ownership of fifty percent -(50%) or more of the outstanding shares or beneficial ownership of -such entity. - -2. Permitted Uses; Conditions & Restrictions. Subject to the terms -and conditions of this License, Apple hereby grants You, effective on -the date You accept this License and download the Original Code, a -world-wide, royalty-free, non-exclusive license, to the extent of -Apple's Applicable Patent Rights and copyrights covering the Original -Code, to do the following: - -2.1 Unmodified Code. You may use, reproduce, display, perform, -internally distribute within Your organization, and Externally Deploy -verbatim, unmodified copies of the Original Code, for commercial or -non-commercial purposes, provided that in each instance: - -(a) You must retain and reproduce in all copies of Original Code the -copyright and other proprietary notices and disclaimers of Apple as -they appear in the Original Code, and keep intact all notices in the -Original Code that refer to this License; and - -(b) You must include a copy of this License with every copy of Source -Code of Covered Code and documentation You distribute or Externally -Deploy, and You may not offer or impose any terms on such Source Code -that alter or restrict this License or the recipients' rights -hereunder, except as permitted under Section 6. - -2.2 Modified Code. You may modify Covered Code and use, reproduce, -display, perform, internally distribute within Your organization, and -Externally Deploy Your Modifications and Covered Code, for commercial -or non-commercial purposes, provided that in each instance You also -meet all of these conditions: - -(a) You must satisfy all the conditions of Section 2.1 with respect to -the Source Code of the Covered Code; - -(b) You must duplicate, to the extent it does not already exist, the -notice in Exhibit A in each file of the Source Code of all Your -Modifications, and cause the modified files to carry prominent notices -stating that You changed the files and the date of any change; and - -(c) If You Externally Deploy Your Modifications, You must make -Source Code of all Your Externally Deployed Modifications either -available to those to whom You have Externally Deployed Your -Modifications, or publicly available. Source Code of Your Externally -Deployed Modifications must be released under the terms set forth in -this License, including the license grants set forth in Section 3 -below, for as long as you Externally Deploy the Covered Code or twelve -(12) months from the date of initial External Deployment, whichever is -longer. You should preferably distribute the Source Code of Your -Externally Deployed Modifications electronically (e.g. download from a -web site). - -2.3 Distribution of Executable Versions. In addition, if You -Externally Deploy Covered Code (Original Code and/or Modifications) in -object code, executable form only, You must include a prominent -notice, in the code itself as well as in related documentation, -stating that Source Code of the Covered Code is available under the -terms of this License with information on how and where to obtain such -Source Code. - -2.4 Third Party Rights. You expressly acknowledge and agree that -although Apple and each Contributor grants the licenses to their -respective portions of the Covered Code set forth herein, no -assurances are provided by Apple or any Contributor that the Covered -Code does not infringe the patent or other intellectual property -rights of any other entity. Apple and each Contributor disclaim any -liability to You for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a -condition to exercising the rights and licenses granted hereunder, You -hereby assume sole responsibility to secure any other intellectual -property rights needed, if any. For example, if a third party patent -license is required to allow You to distribute the Covered Code, it is -Your responsibility to acquire that license before distributing the -Covered Code. - -3. Your Grants. In consideration of, and as a condition to, the -licenses granted to You under this License, You hereby grant to any -person or entity receiving or distributing Covered Code under this -License a non-exclusive, royalty-free, perpetual, irrevocable license, -under Your Applicable Patent Rights and other intellectual property -rights (other than patent) owned or controlled by You, to use, -reproduce, display, perform, modify, sublicense, distribute and -Externally Deploy Your Modifications of the same scope and extent as -Apple's licenses under Sections 2.1 and 2.2 above. - -4. Larger Works. You may create a Larger Work by combining Covered -Code with other code not governed by the terms of this License and -distribute the Larger Work as a single product. In each such instance, -You must make sure the requirements of this License are fulfilled for -the Covered Code or any portion thereof. - -5. Limitations on Patent License. Except as expressly stated in -Section 2, no other patent rights, express or implied, are granted by -Apple herein. Modifications and/or Larger Works may require additional -patent licenses from Apple which Apple may grant in its sole -discretion. - -6. Additional Terms. You may choose to offer, and to charge a fee for, -warranty, support, indemnity or liability obligations and/or other -rights consistent with the scope of the license granted herein -("Additional Terms") to one or more recipients of Covered Code. -However, You may do so only on Your own behalf and as Your sole -responsibility, and not on behalf of Apple or any Contributor. You -must obtain the recipient's agreement that any such Additional Terms -are offered by You alone, and You hereby agree to indemnify, defend -and hold Apple and every Contributor harmless for any liability -incurred by or claims asserted against Apple or such Contributor by -reason of any such Additional Terms. - -7. Versions of the License. Apple may publish revised and/or new -versions of this License from time to time. Each version will be given -a distinguishing version number. Once Original Code has been published -under a particular version of this License, You may continue to use it -under the terms of that version. You may also choose to use such -Original Code under the terms of any subsequent version of this -License published by Apple. No one other than Apple has the right to -modify the terms applicable to Covered Code created under this -License. - -8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in -part pre-release, untested, or not fully tested works. The Covered -Code may contain errors that could cause failures or loss of data, and -may be incomplete or contain inaccuracies. You expressly acknowledge -and agree that use of the Covered Code, or any portion thereof, is at -Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND -WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND -APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE -PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM -ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF -MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR -PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD -PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST -INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE -FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, -THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR -ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO -ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE -AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. -You acknowledge that the Covered Code is not intended for use in the -operation of nuclear facilities, aircraft navigation, communication -systems, or air traffic control machines in which case the failure of -the Covered Code could lead to death, personal injury, or severe -physical or environmental damage. - -9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO -EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING -TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR -ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, -TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF -APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY -REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF -INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY -TO YOU. In no event shall Apple's total liability to You for all -damages (other than as may be required by applicable law) under this -License exceed the amount of fifty dollars ($50.00). - -10. Trademarks. This License does not grant any rights to use the -trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", -"QuickTime", "QuickTime Streaming Server" or any other trademarks, -service marks, logos or trade names belonging to Apple (collectively -"Apple Marks") or to any trademark, service mark, logo or trade name -belonging to any Contributor. You agree not to use any Apple Marks in -or as part of the name of products derived from the Original Code or -to endorse or promote products derived from the Original Code other -than as expressly permitted by and in strict compliance at all times -with Apple's third party trademark usage guidelines which are posted -at http://www.apple.com/legal/guidelinesfor3rdparties.html. - -11. Ownership. Subject to the licenses granted under this License, -each Contributor retains all rights, title and interest in and to any -Modifications made by such Contributor. Apple retains all rights, -title and interest in and to the Original Code and any Modifications -made by or on behalf of Apple ("Apple Modifications"), and such Apple -Modifications will not be automatically subject to this License. Apple -may, at its sole discretion, choose to license such Apple -Modifications under this License, or on different terms from those -contained in this License or may choose not to license them at all. - -12. Termination. - -12.1 Termination. This License and the rights granted hereunder will -terminate: - -(a) automatically without notice from Apple if You fail to comply with -any term(s) of this License and fail to cure such breach within 30 -days of becoming aware of such breach; - -(b) immediately in the event of the circumstances described in Section -13.5(b); or - -(c) automatically without notice from Apple if You, at any time during -the term of this License, commence an action for patent infringement -against Apple; provided that Apple did not first commence -an action for patent infringement against You in that instance. - -12.2 Effect of Termination. Upon termination, You agree to immediately -stop any further use, reproduction, modification, sublicensing and -distribution of the Covered Code. All sublicenses to the Covered Code -which have been properly granted prior to termination shall survive -any termination of this License. Provisions which, by their nature, -should remain in effect beyond the termination of this License shall -survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, -12.2 and 13. No party will be liable to any other for compensation, -indemnity or damages of any sort solely as a result of terminating -this License in accordance with its terms, and termination of this -License will be without prejudice to any other right or remedy of -any party. - -13. Miscellaneous. - -13.1 Government End Users. The Covered Code is a "commercial item" as -defined in FAR 2.101. Government software and technical data rights in -the Covered Code include only those rights customarily provided to the -public as defined in this License. This customary commercial license -in technical data and software is provided in accordance with FAR -12.211 (Technical Data) and 12.212 (Computer Software) and, for -Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- -Commercial Items) and 227.7202-3 (Rights in Commercial Computer -Software or Computer Software Documentation). Accordingly, all U.S. -Government End Users acquire Covered Code with only those rights set -forth herein. - -13.2 Relationship of Parties. This License will not be construed as -creating an agency, partnership, joint venture or any other form of -legal association between or among You, Apple or any Contributor, and -You will not represent to the contrary, whether expressly, by -implication, appearance or otherwise. - -13.3 Independent Development. Nothing in this License will impair -Apple's right to acquire, license, develop, have others develop for -it, market and/or distribute technology or products that perform the -same or similar functions as, or otherwise compete with, -Modifications, Larger Works, technology or products that You may -develop, produce, market or distribute. - -13.4 Waiver; Construction. Failure by Apple or any Contributor to -enforce any provision of this License will not be deemed a waiver of -future enforcement of that or any other provision. Any law or -regulation which provides that the language of a contract shall be -construed against the drafter will not apply to this License. - -13.5 Severability. (a) If for any reason a court of competent -jurisdiction finds any provision of this License, or portion thereof, -to be unenforceable, that provision of the License will be enforced to -the maximum extent permissible so as to effect the economic benefits -and intent of the parties, and the remainder of this License will -continue in full force and effect. (b) Notwithstanding the foregoing, -if applicable law prohibits or restricts You from fully and/or -specifically complying with Sections 2 and/or 3 or prevents the -enforceability of either of those Sections, this License will -immediately terminate and You must immediately discontinue any use of -the Covered Code and destroy all copies of it that are in your -possession or control. - -13.6 Dispute Resolution. Any litigation or other dispute resolution -between You and Apple relating to this License shall take place in the -Northern District of California, and You and Apple hereby consent to -the personal jurisdiction of, and venue in, the state and federal -courts within that District with respect to this License. The -application of the United Nations Convention on Contracts for the -International Sale of Goods is expressly excluded. - -13.7 Entire Agreement; Governing Law. This License constitutes the -entire agreement between the parties with respect to the subject -matter hereof. This License shall be governed by the laws of the -United States and the State of California, except that body of -California law concerning conflicts of law. - -Where You are located in the province of Quebec, Canada, the following -clause applies: The parties hereby confirm that they have requested -that this License and all related documents be drafted in English. Les -parties ont exigé que le présent contrat et tous les documents -connexes soient rédigés en anglais. - -EXHIBIT A. - -"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights -Reserved. - -This file contains Original Code and/or Modifications of Original Code -as defined in and that are subject to the Apple Public Source License -Version 2.0 (the 'License'). You may not use this file except in -compliance with the License. Please obtain a copy of the License at -http://www.opensource.apple.com/apsl/ and read it before using this -file. - -The Original Code and all software distributed under the License are -distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -Please see the License for the specific language governing rights and -limitations under the License." diff --git a/Tweaks/FLEX/Utility/Categories/CALayer+FLEX.h b/Tweaks/FLEX/Utility/Categories/CALayer+FLEX.h deleted file mode 100644 index 0f84bd3..0000000 --- a/Tweaks/FLEX/Utility/Categories/CALayer+FLEX.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// CALayer+FLEX.h -// FLEX -// -// Created by Tanner on 2/28/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface CALayer (FLEX) - -@property (nonatomic) BOOL flex_continuousCorners; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/CALayer+FLEX.m b/Tweaks/FLEX/Utility/Categories/CALayer+FLEX.m deleted file mode 100644 index c68f53c..0000000 --- a/Tweaks/FLEX/Utility/Categories/CALayer+FLEX.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// CALayer+FLEX.m -// FLEX -// -// Created by Tanner on 2/28/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "CALayer+FLEX.h" - -@interface CALayer (Private) -@property (nonatomic) BOOL continuousCorners; -@end - -@implementation CALayer (FLEX) - -static BOOL respondsToContinuousCorners = NO; - -+ (void)load { - respondsToContinuousCorners = [CALayer - instancesRespondToSelector:@selector(setContinuousCorners:) - ]; -} - -- (BOOL)flex_continuousCorners { - if (respondsToContinuousCorners) { - return self.continuousCorners; - } - - return NO; -} - -- (void)setFlex_continuousCorners:(BOOL)enabled { - if (respondsToContinuousCorners) { - if (@available(iOS 13, *)) { - self.cornerCurve = kCACornerCurveContinuous; - } else { - self.continuousCorners = enabled; -// self.masksToBounds = NO; - // self.allowsEdgeAntialiasing = YES; - // self.edgeAntialiasingMask = kCALayerLeftEdge | kCALayerRightEdge | kCALayerTopEdge | kCALayerBottomEdge; - } - } -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+Compare.h b/Tweaks/FLEX/Utility/Categories/FLEXRuntime+Compare.h deleted file mode 100644 index 7c602f3..0000000 --- a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+Compare.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// FLEXRuntime+Compare.h -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import "FLEXProperty.h" -#import "FLEXIvar.h" -#import "FLEXMethodBase.h" -#import "FLEXProtocol.h" - -@interface FLEXProperty (Compare) -- (NSComparisonResult)compare:(FLEXProperty *)other; -@end - -@interface FLEXIvar (Compare) -- (NSComparisonResult)compare:(FLEXIvar *)other; -@end - -@interface FLEXMethodBase (Compare) -- (NSComparisonResult)compare:(FLEXMethodBase *)other; -@end - -@interface FLEXProtocol (Compare) -- (NSComparisonResult)compare:(FLEXProtocol *)other; -@end diff --git a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+Compare.m b/Tweaks/FLEX/Utility/Categories/FLEXRuntime+Compare.m deleted file mode 100644 index 9c17a5a..0000000 --- a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+Compare.m +++ /dev/null @@ -1,47 +0,0 @@ -// -// FLEXRuntime+Compare.m -// FLEX -// -// Created by Tanner Bennett on 8/28/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntime+Compare.h" - -@implementation FLEXProperty (Compare) - -- (NSComparisonResult)compare:(FLEXProperty *)other { - NSComparisonResult r = [self.name caseInsensitiveCompare:other.name]; - if (r == NSOrderedSame) { - // TODO make sure empty image name sorts above an image name - return [self.imageName ?: @"" compare:other.imageName]; - } - - return r; -} - -@end - -@implementation FLEXIvar (Compare) - -- (NSComparisonResult)compare:(FLEXIvar *)other { - return [self.name caseInsensitiveCompare:other.name]; -} - -@end - -@implementation FLEXMethodBase (Compare) - -- (NSComparisonResult)compare:(FLEXMethodBase *)other { - return [self.name caseInsensitiveCompare:other.name]; -} - -@end - -@implementation FLEXProtocol (Compare) - -- (NSComparisonResult)compare:(FLEXProtocol *)other { - return [self.name caseInsensitiveCompare:other.name]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+UIKitHelpers.h b/Tweaks/FLEX/Utility/Categories/FLEXRuntime+UIKitHelpers.h deleted file mode 100644 index 888910e..0000000 --- a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+UIKitHelpers.h +++ /dev/null @@ -1,90 +0,0 @@ -// -// FLEXRuntime+UIKitHelpers.h -// FLEX -// -// Created by Tanner Bennett on 12/16/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import "FLEXProperty.h" -#import "FLEXIvar.h" -#import "FLEXMethod.h" -#import "FLEXProtocol.h" -#import "FLEXTableViewSection.h" - -@class FLEXObjectExplorerDefaults; - -/// Model objects of an object explorer screen adopt this -/// protocol in order respond to user defaults changes -@protocol FLEXObjectExplorerItem -/// Current explorer settings. Set when settings change. -@property (nonatomic) FLEXObjectExplorerDefaults *defaults; - -/// YES for properties and ivars which surely support editing, NO for all methods. -@property (nonatomic, readonly) BOOL isEditable; -/// NO for ivars, YES for supported methods and properties -@property (nonatomic, readonly) BOOL isCallable; -@end - -@protocol FLEXRuntimeMetadata -/// Used as the main title of the row -- (NSString *)description; -/// Used to compare metadata objects for uniqueness -@property (nonatomic, readonly) NSString *name; - -/// For internal use -@property (nonatomic) id tag; - -/// Should return \c nil if not applicable -- (id)currentValueWithTarget:(id)object; -/// Used as the subtitle or description of a property, ivar, or method -- (NSString *)previewWithTarget:(id)object; -/// For methods, a method calling screen. For all else, an object explorer. -- (UIViewController *)viewerWithTarget:(id)object; -/// For methods and protocols, nil. For all else, an a field editor screen. -/// The given section is reloaded on commit of any changes. -- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section; -/// Used to determine present which interactions are possible to the user -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object; -/// Return nil to use the default reuse identifier -- (NSString *)reuseIdentifierWithTarget:(id)object; - -/// An array of actions to place in the first section of the context menu. -- (NSArray *)additionalActionsWithTarget:(id)object sender:(UIViewController *)sender API_AVAILABLE(ios(13.0)); -/// An array where every 2 elements are a key-value pair. The key is a description -/// of what to copy like "Name" and the values are what will be copied. -- (NSArray *)copiableMetadataWithTarget:(id)object; -/// Properties and ivars return the address of an object, if they hold one. -- (NSString *)contextualSubtitleWithTarget:(id)object; - -@end - -// Even if a property is readonly, it still may be editable -// via a setter. Checking isEditable will not reflect that -// unless the property was initialized with a class. -@interface FLEXProperty (UIKitHelpers) @end -@interface FLEXIvar (UIKitHelpers) @end -@interface FLEXMethodBase (UIKitHelpers) @end -@interface FLEXMethod (UIKitHelpers) @end -@interface FLEXProtocol (UIKitHelpers) @end - -typedef NS_ENUM(NSUInteger, FLEXStaticMetadataRowStyle) { - FLEXStaticMetadataRowStyleSubtitle, - FLEXStaticMetadataRowStyleKeyValue, - FLEXStaticMetadataRowStyleDefault = FLEXStaticMetadataRowStyleSubtitle, -}; - -/// Displays a small row as a static key-value pair of information. -@interface FLEXStaticMetadata : NSObject - -+ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title string:(NSString *)string; -+ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title number:(NSNumber *)number; - -+ (NSArray *)classHierarchy:(NSArray *)classes; - -@end - - -/// This is assigned to the \c tag property of each metadata. - diff --git a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+UIKitHelpers.m b/Tweaks/FLEX/Utility/Categories/FLEXRuntime+UIKitHelpers.m deleted file mode 100644 index 079ff97..0000000 --- a/Tweaks/FLEX/Utility/Categories/FLEXRuntime+UIKitHelpers.m +++ /dev/null @@ -1,634 +0,0 @@ -// -// FLEXRuntime+UIKitHelpers.m -// FLEX -// -// Created by Tanner Bennett on 12/16/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntime+UIKitHelpers.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXArgumentInputViewFactory.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXFieldEditorViewController.h" -#import "FLEXMethodCallingViewController.h" -#import "FLEXObjectListViewController.h" -#import "FLEXTableView.h" -#import "FLEXUtility.h" -#import "NSArray+FLEX.h" -#import "NSString+FLEX.h" - -#define FLEXObjectExplorerDefaultsImpl \ -- (FLEXObjectExplorerDefaults *)defaults { \ - return self.tag; \ -} \ - \ -- (void)setDefaults:(FLEXObjectExplorerDefaults *)defaults { \ - self.tag = defaults; \ -} - -#pragma mark FLEXProperty -@implementation FLEXProperty (UIKitHelpers) -FLEXObjectExplorerDefaultsImpl - -/// Decide whether to use potentialTarget or [potentialTarget class] to get or set property -- (id)appropriateTargetForPropertyType:(id)potentialTarget { - if (!object_isClass(potentialTarget)) { - if (self.isClassProperty) { - return [potentialTarget class]; - } else { - return potentialTarget; - } - } else { - if (self.isClassProperty) { - return potentialTarget; - } else { - // Instance property with a class object - return nil; - } - } -} - -- (BOOL)isEditable { - if (self.attributes.isReadOnly) { - return self.likelySetterExists; - } - - const FLEXTypeEncoding *typeEncoding = self.attributes.typeEncoding.UTF8String; - return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:nil]; -} - -- (BOOL)isCallable { - return YES; -} - -- (id)currentValueWithTarget:(id)object { - return [self getPotentiallyUnboxedValue: - [self appropriateTargetForPropertyType:object] - ]; -} - -- (id)currentValueBeforeUnboxingWithTarget:(id)object { - return [self getValue: - [self appropriateTargetForPropertyType:object] - ]; -} - -- (NSString *)previewWithTarget:(id)object { - if (object_isClass(object) && !self.isClassProperty) { - return self.attributes.fullDeclaration; - } else if (self.defaults.wantsDynamicPreviews) { - return [FLEXRuntimeUtility - summaryForObject:[self currentValueWithTarget:object] - ]; - } - - return nil; -} - -- (UIViewController *)viewerWithTarget:(id)object { - id value = [self currentValueWithTarget:object]; - return [FLEXObjectExplorerFactory explorerViewControllerForObject:value]; -} - -- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section { - id target = [self appropriateTargetForPropertyType:object]; - return [FLEXFieldEditorViewController target:target property:self commitHandler:^{ - [section reloadData:YES]; - }]; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - id targetForValueCheck = [self appropriateTargetForPropertyType:object]; - if (!targetForValueCheck) { - // Instance property with a class object - return UITableViewCellAccessoryNone; - } - - // We use .tag to store the cached value of .isEditable that is - // initialized by FLEXObjectExplorer in -reloadMetada - if ([self getPotentiallyUnboxedValue:targetForValueCheck]) { - if (self.defaults.isEditable) { - // Editable non-nil value, both - return UITableViewCellAccessoryDetailDisclosureButton; - } else { - // Uneditable non-nil value, chevron only - return UITableViewCellAccessoryDisclosureIndicator; - } - } else { - if (self.defaults.isEditable) { - // Editable nil value, just (i) - return UITableViewCellAccessoryDetailButton; - } else { - // Non-editable nil value, neither - return UITableViewCellAccessoryNone; - } - } -} - -- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; } - -- (NSArray *)additionalActionsWithTarget:(id)object sender:(UIViewController *)sender __IOS_AVAILABLE(13.0) { - BOOL returnsObject = self.attributes.typeEncoding.flex_typeIsObjectOrClass; - BOOL targetNotNil = [self appropriateTargetForPropertyType:object] != nil; - - // "Explore PropertyClass" for properties with a concrete class name - if (returnsObject) { - NSMutableArray *actions = [NSMutableArray new]; - - // Action for exploring class of this property - Class propertyClass = self.attributes.typeEncoding.flex_typeClass; - if (propertyClass) { - NSString *title = [NSString stringWithFormat:@"Explore %@", NSStringFromClass(propertyClass)]; - [actions addObject:[UIAction actionWithTitle:title image:nil identifier:nil handler:^(UIAction *action) { - UIViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:propertyClass]; - [sender.navigationController pushViewController:explorer animated:YES]; - }]]; - } - - // Action for exploring references to this object - if (targetNotNil) { - // Since the property holder is not nil, check if the property value is nil - id value = [self currentValueBeforeUnboxingWithTarget:object]; - if (value) { - NSString *title = @"List all references"; - [actions addObject:[UIAction actionWithTitle:title image:nil identifier:nil handler:^(UIAction *action) { - UIViewController *list = [FLEXObjectListViewController - objectsWithReferencesToObject:value - retained:NO - ]; - [sender.navigationController pushViewController:list animated:YES]; - }]]; - } - } - - return actions; - } - - return nil; -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - BOOL returnsObject = self.attributes.typeEncoding.flex_typeIsObjectOrClass; - BOOL targetNotNil = [self appropriateTargetForPropertyType:object] != nil; - - NSMutableArray *items = [NSMutableArray arrayWithArray:@[ - @"Name", self.name ?: @"", - @"Type", self.attributes.typeEncoding ?: @"", - @"Declaration", self.fullDescription ?: @"", - ]]; - - if (targetNotNil) { - id value = [self currentValueBeforeUnboxingWithTarget:object]; - [items addObjectsFromArray:@[ - @"Value Preview", [self previewWithTarget:object] ?: @"", - @"Value Address", returnsObject ? [FLEXUtility addressOfObject:value] : @"", - ]]; - } - - [items addObjectsFromArray:@[ - @"Getter", NSStringFromSelector(self.likelyGetter) ?: @"", - @"Setter", self.likelySetterExists ? NSStringFromSelector(self.likelySetter) : @"", - @"Image Name", self.imageName ?: @"", - @"Attributes", self.attributes.string ?: @"", - @"objc_property", [FLEXUtility pointerToString:self.objc_property], - @"objc_property_attribute_t", [FLEXUtility pointerToString:self.attributes.list], - ]]; - - return items; -} - -- (NSString *)contextualSubtitleWithTarget:(id)object { - id target = [self appropriateTargetForPropertyType:object]; - if (target && self.attributes.typeEncoding.flex_typeIsObjectOrClass) { - return [FLEXUtility addressOfObject:[self currentValueBeforeUnboxingWithTarget:target]]; - } - - return nil; -} - -@end - - -#pragma mark FLEXIvar -@implementation FLEXIvar (UIKitHelpers) -FLEXObjectExplorerDefaultsImpl - -- (BOOL)isEditable { - const FLEXTypeEncoding *typeEncoding = self.typeEncoding.UTF8String; - return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:nil]; -} - -- (BOOL)isCallable { - return NO; -} - -- (id)currentValueWithTarget:(id)object { - if (!object_isClass(object)) { - return [self getPotentiallyUnboxedValue:object]; - } - - return nil; -} - -- (NSString *)previewWithTarget:(id)object { - if (object_isClass(object)) { - return self.details; - } else if (self.defaults.wantsDynamicPreviews) { - return [FLEXRuntimeUtility - summaryForObject:[self currentValueWithTarget:object] - ]; - } - - return nil; -} - -- (UIViewController *)viewerWithTarget:(id)object { - NSAssert(!object_isClass(object), @"Unreachable state: viewing ivar on class object"); - id value = [self currentValueWithTarget:object]; - return [FLEXObjectExplorerFactory explorerViewControllerForObject:value]; -} - -- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section { - NSAssert(!object_isClass(object), @"Unreachable state: editing ivar on class object"); - return [FLEXFieldEditorViewController target:object ivar:self commitHandler:^{ - [section reloadData:YES]; - }]; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - if (object_isClass(object)) { - return UITableViewCellAccessoryNone; - } - - // Could use .isEditable here, but we use .tag for speed since it is cached - if ([self getPotentiallyUnboxedValue:object]) { - if (self.defaults.isEditable) { - // Editable non-nil value, both - return UITableViewCellAccessoryDetailDisclosureButton; - } else { - // Uneditable non-nil value, chevron only - return UITableViewCellAccessoryDisclosureIndicator; - } - } else { - if (self.defaults.isEditable) { - // Editable nil value, just (i) - return UITableViewCellAccessoryDetailButton; - } else { - // Non-editable nil value, neither - return UITableViewCellAccessoryNone; - } - } -} - -- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; } - -- (NSArray *)additionalActionsWithTarget:(id)object sender:(UIViewController *)sender __IOS_AVAILABLE(13.0) { - Class ivarClass = self.typeEncoding.flex_typeClass; - - // "Explore PropertyClass" for properties with a concrete class name - if (ivarClass) { - NSString *title = [NSString stringWithFormat:@"Explore %@", NSStringFromClass(ivarClass)]; - return @[[UIAction actionWithTitle:title image:nil identifier:nil handler:^(UIAction *action) { - UIViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:ivarClass]; - [sender.navigationController pushViewController:explorer animated:YES]; - }]]; - } - - return nil; -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - BOOL isInstance = !object_isClass(object); - BOOL returnsObject = self.typeEncoding.flex_typeIsObjectOrClass; - id value = isInstance ? [self getValue:object] : nil; - - NSMutableArray *items = [NSMutableArray arrayWithArray:@[ - @"Name", self.name ?: @"", - @"Type", self.typeEncoding ?: @"", - @"Declaration", self.description ?: @"", - ]]; - - if (isInstance) { - [items addObjectsFromArray:@[ - @"Value Preview", isInstance ? [self previewWithTarget:object] : @"", - @"Value Address", returnsObject ? [FLEXUtility addressOfObject:value] : @"", - ]]; - } - - [items addObjectsFromArray:@[ - @"Size", @(self.size).stringValue, - @"Offset", @(self.offset).stringValue, - @"objc_ivar", [FLEXUtility pointerToString:self.objc_ivar], - ]]; - - return items; -} - -- (NSString *)contextualSubtitleWithTarget:(id)object { - if (!object_isClass(object) && self.typeEncoding.flex_typeIsObjectOrClass) { - return [FLEXUtility addressOfObject:[self getValue:object]]; - } - - return nil; -} - -@end - - -#pragma mark FLEXMethod -@implementation FLEXMethodBase (UIKitHelpers) -FLEXObjectExplorerDefaultsImpl - -- (BOOL)isEditable { - return NO; -} - -- (BOOL)isCallable { - return NO; -} - -- (id)currentValueWithTarget:(id)object { - // Methods can't be "edited" and have no "value" - return nil; -} - -- (NSString *)previewWithTarget:(id)object { - return [self.selectorString stringByAppendingFormat:@" — %@", self.typeEncoding]; -} - -- (UIViewController *)viewerWithTarget:(id)object { - // We disallow calling of FLEXMethodBase methods - @throw NSInternalInconsistencyException; - return nil; -} - -- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section { - // Methods cannot be edited - @throw NSInternalInconsistencyException; - return nil; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - // We shouldn't be using any FLEXMethodBase objects for this - @throw NSInternalInconsistencyException; - return UITableViewCellAccessoryNone; -} - -- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; } - -- (NSArray *)additionalActionsWithTarget:(id)object sender:(UIViewController *)sender __IOS_AVAILABLE(13.0) { - return nil; -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - return @[ - @"Selector", self.name ?: @"", - @"Type Encoding", self.typeEncoding ?: @"", - @"Declaration", self.description ?: @"", - ]; -} - -- (NSString *)contextualSubtitleWithTarget:(id)object { - return nil; -} - -@end - -@implementation FLEXMethod (UIKitHelpers) - -- (BOOL)isCallable { - return self.signature != nil; -} - -- (UIViewController *)viewerWithTarget:(id)object { - object = self.isInstanceMethod ? object : (object_isClass(object) ? object : [object class]); - return [FLEXMethodCallingViewController target:object method:self]; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - if (self.isInstanceMethod) { - if (object_isClass(object)) { - // Instance method from class, can't call - return UITableViewCellAccessoryNone; - } else { - // Instance method from instance, can call - return UITableViewCellAccessoryDisclosureIndicator; - } - } else { - return UITableViewCellAccessoryDisclosureIndicator; - } -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - return [[super copiableMetadataWithTarget:object] arrayByAddingObjectsFromArray:@[ - @"NSMethodSignature *", [FLEXUtility addressOfObject:self.signature], - @"Signature String", self.signatureString ?: @"", - @"Number of Arguments", @(self.numberOfArguments).stringValue, - @"Return Type", @(self.returnType ?: ""), - @"Return Size", @(self.returnSize).stringValue, - @"objc_method", [FLEXUtility pointerToString:self.objc_method], - ]]; -} - -@end - - -#pragma mark FLEXProtocol -@implementation FLEXProtocol (UIKitHelpers) -FLEXObjectExplorerDefaultsImpl - -- (BOOL)isEditable { - return NO; -} - -- (BOOL)isCallable { - return NO; -} - -- (id)currentValueWithTarget:(id)object { - return nil; -} - -- (NSString *)previewWithTarget:(id)object { - return nil; -} - -- (UIViewController *)viewerWithTarget:(id)object { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:self]; -} - -- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section { - // Protocols cannot be edited - @throw NSInternalInconsistencyException; - return nil; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - return UITableViewCellAccessoryDisclosureIndicator; -} - -- (NSString *)reuseIdentifierWithTarget:(id)object { return nil; } - -- (NSArray *)additionalActionsWithTarget:(id)object sender:(UIViewController *)sender __IOS_AVAILABLE(13.0) { - return nil; -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - NSArray *conformanceNames = [self.protocols valueForKeyPath:@"name"]; - NSString *conformances = [conformanceNames componentsJoinedByString:@"\n"]; - return @[ - @"Name", self.name ?: @"", - @"Conformances", conformances ?: @"", - ]; -} - -- (NSString *)contextualSubtitleWithTarget:(id)object { - return nil; -} - -@end - - -#pragma mark FLEXStaticMetadata -@interface FLEXStaticMetadata () { - @protected - NSString *_name; -} -@property (nonatomic) FLEXTableViewCellReuseIdentifier reuse; -@property (nonatomic) NSString *subtitle; -@property (nonatomic) id metadata; -@end - -@interface FLEXStaticMetadata_Class : FLEXStaticMetadata -+ (instancetype)withClass:(Class)cls; -@end - -@implementation FLEXStaticMetadata -@synthesize name = _name; -@synthesize tag = _tag; - -FLEXObjectExplorerDefaultsImpl - -+ (NSArray *)classHierarchy:(NSArray *)classes { - return [classes flex_mapped:^id(Class cls, NSUInteger idx) { - return [FLEXStaticMetadata_Class withClass:cls]; - }]; -} - -+ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title string:(NSString *)string { - return [[self alloc] initWithStyle:style title:title subtitle:string]; -} - -+ (instancetype)style:(FLEXStaticMetadataRowStyle)style title:(NSString *)title number:(NSNumber *)number { - return [[self alloc] initWithStyle:style title:title subtitle:number.stringValue]; -} - -- (id)initWithStyle:(FLEXStaticMetadataRowStyle)style title:(NSString *)title subtitle:(NSString *)subtitle { - self = [super init]; - if (self) { - if (style == FLEXStaticMetadataRowStyleKeyValue) { - _reuse = kFLEXKeyValueCell; - } else { - _reuse = kFLEXMultilineDetailCell; - } - - _name = title; - _subtitle = subtitle; - } - - return self; -} - -- (NSString *)description { - return self.name; -} - -- (NSString *)reuseIdentifierWithTarget:(id)object { - return self.reuse; -} - -- (BOOL)isEditable { - return NO; -} - -- (BOOL)isCallable { - return NO; -} - -- (id)currentValueWithTarget:(id)object { - return nil; -} - -- (NSString *)previewWithTarget:(id)object { - return self.subtitle; -} - -- (UIViewController *)viewerWithTarget:(id)object { - return nil; -} - -- (UIViewController *)editorWithTarget:(id)object section:(FLEXTableViewSection *)section { - // Static metadata cannot be edited - @throw NSInternalInconsistencyException; - return nil; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - return UITableViewCellAccessoryNone; -} - -- (NSArray *)additionalActionsWithTarget:(id)object sender:(UIViewController *)sender __IOS_AVAILABLE(13.0) { - return nil; -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - return @[self.name, self.subtitle]; -} - -- (NSString *)contextualSubtitleWithTarget:(id)object { - return nil; -} - -@end - - -#pragma mark FLEXStaticMetadata_Class -@implementation FLEXStaticMetadata_Class - -+ (instancetype)withClass:(Class)cls { - NSParameterAssert(cls); - - FLEXStaticMetadata_Class *metadata = [self new]; - metadata.metadata = cls; - metadata->_name = NSStringFromClass(cls); - metadata.reuse = kFLEXDefaultCell; - return metadata; -} - -- (id)initWithStyle:(FLEXStaticMetadataRowStyle)style title:(NSString *)title subtitle:(NSString *)subtitle { - @throw NSInternalInconsistencyException; - return nil; -} - -- (UIViewController *)viewerWithTarget:(id)object { - return [FLEXObjectExplorerFactory explorerViewControllerForObject:self.metadata]; -} - -- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object { - return UITableViewCellAccessoryDisclosureIndicator; -} - -- (NSArray *)copiableMetadataWithTarget:(id)object { - return @[ - @"Class Name", self.name, - @"Class", [FLEXUtility addressOfObject:self.metadata] - ]; -} - -- (NSString *)contextualSubtitleWithTarget:(id)object { - return [FLEXUtility addressOfObject:self.metadata]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/NSArray+FLEX.h b/Tweaks/FLEX/Utility/Categories/NSArray+FLEX.h deleted file mode 100644 index 885a2a4..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSArray+FLEX.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// NSArray+FLEX.h -// FLEX -// -// Created by Tanner Bennett on 9/25/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface NSArray (Functional) - -/// Actually more like flatmap, but it seems like the objc way to allow returning nil to omit objects. -/// So, return nil from the block to omit objects, and return an object to include it in the new array. -/// Unlike flatmap, however, this will not flatten arrays of arrays into a single array. -- (__kindof NSArray *)flex_mapped:(id(^)(T obj, NSUInteger idx))mapFunc; -/// Like flex_mapped, but expects arrays to be returned, and flattens them into one array. -- (__kindof NSArray *)flex_flatmapped:(NSArray *(^)(id, NSUInteger idx))block; -- (instancetype)flex_filtered:(BOOL(^)(T obj, NSUInteger idx))filterFunc; -- (void)flex_forEach:(void(^)(T obj, NSUInteger idx))block; - -/// Unlike \c subArrayWithRange: this will not throw an exception if \c maxLength -/// is greater than the size of the array. If the array has one element and -/// \c maxLength is greater than 1, you get an array with 1 element back. -- (instancetype)flex_subArrayUpto:(NSUInteger)maxLength; - -+ (instancetype)flex_forEachUpTo:(NSUInteger)bound map:(T(^)(NSUInteger i))block; -+ (instancetype)flex_mapped:(id)collection block:(id(^)(T obj, NSUInteger idx))mapFunc; - -- (instancetype)flex_sortedUsingSelector:(SEL)selector; - -- (T)flex_firstWhere:(BOOL(^)(T obj))meetingCriteria; - -@end - -@interface NSMutableArray (Functional) - -- (void)flex_filter:(BOOL(^)(T obj, NSUInteger idx))filterFunc; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/NSArray+FLEX.m b/Tweaks/FLEX/Utility/Categories/NSArray+FLEX.m deleted file mode 100644 index 0f09c25..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSArray+FLEX.m +++ /dev/null @@ -1,143 +0,0 @@ -// -// NSArray+FLEX.m -// FLEX -// -// Created by Tanner Bennett on 9/25/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "NSArray+FLEX.h" - -#define FLEXArrayClassIsMutable(me) ([[self class] isSubclassOfClass:[NSMutableArray class]]) - -@implementation NSArray (Functional) - -- (__kindof NSArray *)flex_mapped:(id (^)(id, NSUInteger))mapFunc { - NSMutableArray *map = [NSMutableArray new]; - [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - id ret = mapFunc(obj, idx); - if (ret) { - [map addObject:ret]; - } - }]; - - if (self.count < 2048 && !FLEXArrayClassIsMutable(self)) { - return map.copy; - } - - return map; -} - -- (__kindof NSArray *)flex_flatmapped:(NSArray *(^)(id, NSUInteger))block { - NSMutableArray *array = [NSMutableArray new]; - [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - NSArray *toAdd = block(obj, idx); - if (toAdd) { - [array addObjectsFromArray:toAdd]; - } - }]; - - if (array.count < 2048 && !FLEXArrayClassIsMutable(self)) { - return array.copy; - } - - return array; -} - -- (NSArray *)flex_filtered:(BOOL (^)(id, NSUInteger))filterFunc { - return [self flex_mapped:^id(id obj, NSUInteger idx) { - return filterFunc(obj, idx) ? obj : nil; - }]; -} - -- (void)flex_forEach:(void(^)(id, NSUInteger))block { - [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - block(obj, idx); - }]; -} - -- (instancetype)flex_subArrayUpto:(NSUInteger)maxLength { - if (maxLength > self.count) { - if (FLEXArrayClassIsMutable(self)) { - return self.mutableCopy; - } - - return self; - } - - return [self subarrayWithRange:NSMakeRange(0, maxLength)]; -} - -+ (__kindof NSArray *)flex_forEachUpTo:(NSUInteger)bound map:(id(^)(NSUInteger))block { - NSMutableArray *array = [NSMutableArray new]; - for (NSUInteger i = 0; i < bound; i++) { - id obj = block(i); - if (obj) { - [array addObject:obj]; - } - } - - // For performance reasons, don't copy large arrays - if (bound < 2048 && !FLEXArrayClassIsMutable(self)) { - return array.copy; - } - - return array; -} - -+ (instancetype)flex_mapped:(id)collection block:(id(^)(id obj, NSUInteger idx))mapFunc { - NSMutableArray *array = [NSMutableArray new]; - NSInteger idx = 0; - for (id obj in collection) { - id ret = mapFunc(obj, idx++); - if (ret) { - [array addObject:ret]; - } - } - - // For performance reasons, don't copy large arrays - if (array.count < 2048) { - return array.copy; - } - - return array; -} - -- (instancetype)flex_sortedUsingSelector:(SEL)selector { - if (FLEXArrayClassIsMutable(self)) { - NSMutableArray *me = (id)self; - [me sortUsingSelector:selector]; - return me; - } else { - return [self sortedArrayUsingSelector:selector]; - } -} - -- (id)flex_firstWhere:(BOOL (^)(id))meetsCriteria { - for (id e in self) { - if (meetsCriteria(e)) { - return e; - } - } - - return nil; -} - -@end - - -@implementation NSMutableArray (Functional) - -- (void)flex_filter:(BOOL (^)(id, NSUInteger))keepObject { - NSMutableIndexSet *toRemove = [NSMutableIndexSet new]; - - [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - if (!keepObject(obj, idx)) { - [toRemove addIndex:idx]; - } - }]; - - [self removeObjectsAtIndexes:toRemove]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/NSObject+FLEX_Reflection.h b/Tweaks/FLEX/Utility/Categories/NSObject+FLEX_Reflection.h deleted file mode 100644 index 876ff7e..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSObject+FLEX_Reflection.h +++ /dev/null @@ -1,234 +0,0 @@ -// -// NSObject+FLEX_Reflection.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import -@class FLEXMirror, FLEXMethod, FLEXIvar, FLEXProperty, FLEXMethodBase, FLEXPropertyAttributes, FLEXProtocol; - -NS_ASSUME_NONNULL_BEGIN - -/// Returns the type encoding string given the encoding for the return type and parameters, if any. -/// @discussion Example usage for a \c void returning method which takes -/// an \c int: @code FLEXTypeEncoding(@encode(void), @encode(int)); -/// @param returnType The encoded return type. \c void for exmaple would be \c @encode(void). -/// @param count The number of parameters in this type encoding string. -/// @return The type encoding string, or \c nil if \e returnType is \c NULL. -NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...); - -NSArray * _Nullable FLEXGetAllSubclasses(_Nullable Class cls, BOOL includeSelf); -NSArray * _Nullable FLEXGetClassHierarchy(_Nullable Class cls, BOOL includeSelf); -NSArray * _Nullable FLEXGetConformedProtocols(_Nullable Class cls); - -NSArray * _Nullable FLEXGetAllIvars(_Nullable Class cls); -/// @param cls a class object to get instance properties, -/// or a metaclass object to get class properties -NSArray * _Nullable FLEXGetAllProperties(_Nullable Class cls); -/// @param cls a class object to get instance methods, -/// or a metaclass object to get class methods -/// @param instance used to mark methods as instance methods or not. -/// Not used to determine whether to get instance or class methods. -NSArray * _Nullable FLEXGetAllMethods(_Nullable Class cls, BOOL instance); -/// @param cls a class object to get all instance and class methods. -NSArray * _Nullable FLEXGetAllInstanceAndClassMethods(_Nullable Class cls); - - - -#pragma mark Reflection -@interface NSObject (Reflection) - -@property (nonatomic, readonly ) FLEXMirror *flex_reflection; -@property (nonatomic, readonly, class) FLEXMirror *flex_reflection; - -/// Calls into /c FLEXGetAllSubclasses -/// @return Every subclass of the receiving class, including the receiver itself. -@property (nonatomic, readonly, class) NSArray *flex_allSubclasses; - -/// @return The \c Class object for the metaclass of the recieving class, or \c Nil if the class is Nil or not registered. -@property (nonatomic, readonly, class) Class flex_metaclass; -/// @return The size in bytes of instances of the recieving class, or \c 0 if \e cls is \c Nil. -@property (nonatomic, readonly, class) size_t flex_instanceSize; - -/// Changes the class of an object instance. -/// @return The previous value of the objects \c class, or \c Nil if the object is \c nil. -- (Class)flex_setClass:(Class)cls; -/// Sets the recieving class's superclass. "You should not use this method" — Apple. -/// @return The old superclass. -+ (Class)flex_setSuperclass:(Class)superclass; - -/// Calls into \c FLEXGetClassHierarchy() -/// @return a list of classes going up the class hierarchy, -/// starting with the receiver and ending with the root class. -@property (nonatomic, readonly, class) NSArray *flex_classHierarchy; - -/// Calls into \c FLEXGetConformedProtocols -/// @return a list of protocols this class itself conforms to. -@property (nonatomic, readonly, class) NSArray *flex_protocols; - -@end - - -#pragma mark Methods -@interface NSObject (Methods) - -/// All instance and class methods specific to the recieving class. -/// @discussion This method will only retrieve methods specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call this on \c [self superclass]. -/// @return An array of \c FLEXMethod objects. -@property (nonatomic, readonly, class) NSArray *flex_allMethods; -/// All instance methods specific to the recieving class. -/// @discussion This method will only retrieve methods specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call this on \c [self superclass]. -/// @return An array of \c FLEXMethod objects. -@property (nonatomic, readonly, class) NSArray *flex_allInstanceMethods; -/// All class methods specific to the recieving class. -/// @discussion This method will only retrieve methods specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call this on \c [self superclass]. -/// @return An array of \c FLEXMethod objects. -@property (nonatomic, readonly, class) NSArray *flex_allClassMethods; - -/// Retrieves the class's instance method with the given name. -/// @return An initialized \c FLEXMethod object, or \c nil if the method wasn't found. -+ (FLEXMethod *)flex_methodNamed:(NSString *)name; - -/// Retrieves the class's class method with the given name. -/// @return An initialized \c FLEXMethod object, or \c nil if the method wasn't found. -+ (FLEXMethod *)flex_classMethodNamed:(NSString *)name; - -/// Adds a new method to the recieving class with a given name and implementation. -/// @discussion This method will add an override of a superclass's implementation, -/// but will not replace an existing implementation in the class. -/// To change an existing implementation, use \c replaceImplementationOfMethod:with:. -/// -/// Type encodings start with the return type and end with the parameter types in order. -/// The type encoding for \c NSArray's \c count property getter looks like this: -/// @code [NSString stringWithFormat:@"%s%s%s%s", @encode(void), @encode(id), @encode(SEL), @encode(NSUInteger)] @endcode -/// Using the \c FLEXTypeEncoding function for the same method looks like this: -/// @code FLEXTypeEncodingString(@encode(void), 1, @encode(NSUInteger)) @endcode -/// @param typeEncoding The type encoding string. Consider using the \c FLEXTypeEncodingString() function. -/// @param instanceMethod NO to add the method to the class itself or YES to add it as an instance method. -/// @return YES if the method was added successfully, \c NO otherwise -/// (for example, the class already contains a method implementation with that name). -+ (BOOL)addMethod:(SEL)selector - typeEncoding:(NSString *)typeEncoding - implementation:(IMP)implementaiton - toInstances:(BOOL)instanceMethod; - -/// Replaces the implementation of a method in the recieving class. -/// @param instanceMethod YES to replace the instance method, NO to replace the class method. -/// @note This function behaves in two different ways: -/// -/// - If the method does not yet exist in the recieving class, it is added as if -/// \c addMethod:typeEncoding:implementation were called. -/// -/// - If the method does exist, its \c IMP is replaced. -/// @return The previous \c IMP of \e method. -+ (IMP)replaceImplementationOfMethod:(FLEXMethodBase *)method with:(IMP)implementation useInstance:(BOOL)instanceMethod; -/// Swaps the implementations of the given methods. -/// @discussion If one or neither of the given methods exist in the recieving class, -/// they are added to the class with their implementations swapped as if each method did exist. -/// This method will not fail if each \c FLEXSimpleMethod contains a valid selector. -/// @param instanceMethod YES to swizzle the instance method, NO to swizzle the class method. -+ (void)swizzle:(FLEXMethodBase *)original with:(FLEXMethodBase *)other onInstance:(BOOL)instanceMethod; -/// Swaps the implementations of the given methods. -/// @param instanceMethod YES to swizzle the instance method, NO to swizzle the class method. -/// @return \c YES if successful, and \c NO if selectors could not be retrieved from the given strings. -+ (BOOL)swizzleByName:(NSString *)original with:(NSString *)other onInstance:(BOOL)instanceMethod; -/// Swaps the implementations of methods corresponding to the given selectors. -+ (void)swizzleBySelector:(SEL)original with:(SEL)other onInstance:(BOOL)instanceMethod; - -@end - - -#pragma mark Properties -@interface NSObject (Ivars) - -/// All of the instance variables specific to the recieving class. -/// @discussion This method will only retrieve instance varibles specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call \c [[self superclass] allIvars]. -/// @return An array of \c FLEXIvar objects. -@property (nonatomic, readonly, class) NSArray *flex_allIvars; - -/// Retrieves an instance variable with the corresponding name. -/// @return An initialized \c FLEXIvar object, or \c nil if the Ivar wasn't found. -+ (FLEXIvar *)flex_ivarNamed:(NSString *)name; - -/// @return The address of the given ivar in the recieving object in memory, -/// or \c NULL if it could not be found. -- (void *)flex_getIvarAddress:(FLEXIvar *)ivar; -/// @return The address of the given ivar in the recieving object in memory, -/// or \c NULL if it could not be found. -- (void *)flex_getIvarAddressByName:(NSString *)name; -/// @discussion This method faster than creating an \c FLEXIvar and calling -/// \c -getIvarAddress: if you already have an \c Ivar on hand -/// @return The address of the given ivar in the recieving object in memory, -/// or \c NULL if it could not be found\. -- (void *)flex_getObjcIvarAddress:(Ivar)ivar; - -/// Sets the value of the given instance variable on the recieving object. -/// @discussion Use only when the target instance variable is an object. -- (void)flex_setIvar:(FLEXIvar *)ivar object:(id)value; -/// Sets the value of the given instance variable on the recieving object. -/// @discussion Use only when the target instance variable is an object. -/// @return \c YES if successful, or \c NO if the instance variable could not be found. -- (BOOL)flex_setIvarByName:(NSString *)name object:(id)value; -/// @discussion Use only when the target instance variable is an object. -/// This method is faster than creating an \c FLEXIvar and calling -/// \c -setIvar: if you already have an \c Ivar on hand. -- (void)flex_setObjcIvar:(Ivar)ivar object:(id)value; - -/// Sets the value of the given instance variable on the recieving object to the -/// \e size number of bytes of data at \e value. -/// @discussion Use one of the other methods if you can help it. -- (void)flex_setIvar:(FLEXIvar *)ivar value:(void *)value size:(size_t)size; -/// Sets the value of the given instance variable on the recieving object to the -/// \e size number of bytes of data at \e value. -/// @discussion Use one of the other methods if you can help it -/// @return \c YES if successful, or \c NO if the instance variable could not be found. -- (BOOL)flex_setIvarByName:(NSString *)name value:(void *)value size:(size_t)size; -/// Sets the value of the given instance variable on the recieving object to the -/// \e size number of bytes of data at \e value. -/// @discussion This is faster than creating an \c FLEXIvar and calling -/// \c -setIvar:value:size if you already have an \c Ivar on hand. -- (void)flex_setObjcIvar:(Ivar)ivar value:(void *)value size:(size_t)size; - -@end - -#pragma mark Properties -@interface NSObject (Properties) - -/// All instance and class properties specific to the recieving class. -/// @discussion This method will only retrieve properties specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call this on \c [self superclass]. -/// @return An array of \c FLEXProperty objects. -@property (nonatomic, readonly, class) NSArray *flex_allProperties; -/// All instance properties specific to the recieving class. -/// @discussion This method will only retrieve properties specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call this on \c [self superclass]. -/// @return An array of \c FLEXProperty objects. -@property (nonatomic, readonly, class) NSArray *flex_allInstanceProperties; -/// All class properties specific to the recieving class. -/// @discussion This method will only retrieve properties specific to the recieving class. -/// To retrieve instance variables on a parent class, simply call this on \c [self superclass]. -/// @return An array of \c FLEXProperty objects. -@property (nonatomic, readonly, class) NSArray *flex_allClassProperties; - -/// Retrieves the class's property with the given name. -/// @return An initialized \c FLEXProperty object, or \c nil if the property wasn't found. -+ (FLEXProperty *)flex_propertyNamed:(NSString *)name; -/// @return An initialized \c FLEXProperty object, or \c nil if the property wasn't found. -+ (FLEXProperty *)flex_classPropertyNamed:(NSString *)name; - -/// Replaces the given property on the recieving class. -+ (void)flex_replaceProperty:(FLEXProperty *)property; -/// Replaces the given property on the recieving class. Useful for changing a property's attributes. -+ (void)flex_replaceProperty:(NSString *)name attributes:(FLEXPropertyAttributes *)attributes; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Categories/NSObject+FLEX_Reflection.m b/Tweaks/FLEX/Utility/Categories/NSObject+FLEX_Reflection.m deleted file mode 100644 index d3ba9f0..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSObject+FLEX_Reflection.m +++ /dev/null @@ -1,426 +0,0 @@ -// -// NSObject+FLEX_Reflection.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "NSObject+FLEX_Reflection.h" -#import "FLEXClassBuilder.h" -#import "FLEXMirror.h" -#import "FLEXProperty.h" -#import "FLEXMethod.h" -#import "FLEXIvar.h" -#import "FLEXProtocol.h" -#import "FLEXPropertyAttributes.h" -#import "NSArray+FLEX.h" -#import "FLEXUtility.h" - - -NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...) { - if (!returnType) return nil; - - NSMutableString *encoding = [NSMutableString new]; - [encoding appendFormat:@"%s%s%s", returnType, @encode(id), @encode(SEL)]; - - va_list args; - va_start(args, count); - char *type = va_arg(args, char *); - for (NSUInteger i = 0; i < count; i++, type = va_arg(args, char *)) { - [encoding appendFormat:@"%s", type]; - } - va_end(args); - - return encoding.copy; -} - -NSArray *FLEXGetAllSubclasses(Class cls, BOOL includeSelf) { - if (!cls) return nil; - - Class *buffer = NULL; - - int count, size; - do { - count = objc_getClassList(NULL, 0); - buffer = (Class *)realloc(buffer, count * sizeof(*buffer)); - size = objc_getClassList(buffer, count); - } while (size != count); - - NSMutableArray *classes = [NSMutableArray new]; - if (includeSelf) { - [classes addObject:cls]; - } - - for (int i = 0; i < count; i++) { - Class candidate = buffer[i]; - Class superclass = candidate; - while ((superclass = class_getSuperclass(superclass))) { - if (superclass == cls) { - [classes addObject:candidate]; - break; - } - } - } - - free(buffer); - return classes.copy; -} - -NSArray *FLEXGetClassHierarchy(Class cls, BOOL includeSelf) { - if (!cls) return nil; - - NSMutableArray *classes = [NSMutableArray new]; - if (includeSelf) { - [classes addObject:cls]; - } - - while ((cls = [cls superclass])) { - [classes addObject:cls]; - }; - - return classes.copy; -} - -NSArray *FLEXGetConformedProtocols(Class cls) { - if (!cls) return nil; - - unsigned int count = 0; - Protocol *__unsafe_unretained *list = class_copyProtocolList(cls, &count); - NSArray *protocols = [NSArray arrayWithObjects:list count:count]; - free(list); - - return [protocols flex_mapped:^id(Protocol *pro, NSUInteger idx) { - return [FLEXProtocol protocol:pro]; - }]; -} - -NSArray *FLEXGetAllIvars(_Nullable Class cls) { - if (!cls) return nil; - - unsigned int ivcount; - Ivar *objcivars = class_copyIvarList(cls, &ivcount); - NSArray *ivars = [NSArray flex_forEachUpTo:ivcount map:^id(NSUInteger i) { - return [FLEXIvar ivar:objcivars[i]]; - }]; - - free(objcivars); - return ivars; -} - -NSArray *FLEXGetAllProperties(_Nullable Class cls) { - if (!cls) return nil; - - unsigned int pcount; - objc_property_t *objcproperties = class_copyPropertyList(cls, &pcount); - NSArray *properties = [NSArray flex_forEachUpTo:pcount map:^id(NSUInteger i) { - return [FLEXProperty property:objcproperties[i] onClass:cls]; - }]; - - free(objcproperties); - return properties; -} - -NSArray *FLEXGetAllMethods(_Nullable Class cls, BOOL instance) { - if (!cls) return nil; - - unsigned int mcount; - Method *objcmethods = class_copyMethodList(cls, &mcount); - NSArray *methods = [NSArray flex_forEachUpTo:mcount map:^id(NSUInteger i) { - return [FLEXMethod method:objcmethods[i] isInstanceMethod:instance]; - }]; - - free(objcmethods); - return methods; -} - - -#pragma mark NSProxy - -@interface NSProxy (AnyObjectAdditions) @end -@implementation NSProxy (AnyObjectAdditions) - -+ (void)load { FLEX_EXIT_IF_NO_CTORS() - // We need to get all of the methods in this file and add them to NSProxy. - // To do this we we need the class itself and it's metaclass. - // Edit: also add them to Swift._SwiftObject - Class NSProxyClass = [NSProxy class]; - Class NSProxy_meta = object_getClass(NSProxyClass); - Class SwiftObjectClass = ( - NSClassFromString(@"SwiftObject") ?: NSClassFromString(@"Swift._SwiftObject") - ); - - // Copy all of the "flex_" methods from NSObject - id filterFunc = ^BOOL(FLEXMethod *method, NSUInteger idx) { - return [method.name hasPrefix:@"flex_"]; - }; - NSArray *instanceMethods = [NSObject.flex_allInstanceMethods flex_filtered:filterFunc]; - NSArray *classMethods = [NSObject.flex_allClassMethods flex_filtered:filterFunc]; - - FLEXClassBuilder *proxy = [FLEXClassBuilder builderForClass:NSProxyClass]; - FLEXClassBuilder *proxyMeta = [FLEXClassBuilder builderForClass:NSProxy_meta]; - [proxy addMethods:instanceMethods]; - [proxyMeta addMethods:classMethods]; - - if (SwiftObjectClass) { - Class SwiftObject_meta = object_getClass(SwiftObjectClass); - FLEXClassBuilder *swiftObject = [FLEXClassBuilder builderForClass:SwiftObjectClass]; - FLEXClassBuilder *swiftObjectMeta = [FLEXClassBuilder builderForClass:SwiftObject_meta]; - [swiftObject addMethods:instanceMethods]; - [swiftObjectMeta addMethods:classMethods]; - - // So we can put Swift objects into dictionaries... - [swiftObjectMeta addMethods:@[ - [NSObject flex_classMethodNamed:@"copyWithZone:"]] - ]; - } -} - -@end - -#pragma mark Reflection - -@implementation NSObject (Reflection) - -+ (FLEXMirror *)flex_reflection { - return [FLEXMirror reflect:self]; -} - -- (FLEXMirror *)flex_reflection { - return [FLEXMirror reflect:self]; -} - -/// Code borrowed from MAObjCRuntime by Mike Ash -+ (NSArray *)flex_allSubclasses { - return FLEXGetAllSubclasses(self, YES); -} - -- (Class)flex_setClass:(Class)cls { - return object_setClass(self, cls); -} - -+ (Class)flex_metaclass { - return objc_getMetaClass(NSStringFromClass(self.class).UTF8String); -} - -+ (size_t)flex_instanceSize { - return class_getInstanceSize(self.class); -} - -+ (Class)flex_setSuperclass:(Class)superclass { - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - return class_setSuperclass(self, superclass); - #pragma clang diagnostic pop -} - -+ (NSArray *)flex_classHierarchy { - return FLEXGetClassHierarchy(self, YES); -} - -+ (NSArray *)flex_protocols { - return FLEXGetConformedProtocols(self); -} - -@end - - -#pragma mark Methods - -@implementation NSObject (Methods) - -+ (NSArray *)flex_allMethods { - NSMutableArray *instanceMethods = self.flex_allInstanceMethods.mutableCopy; - [instanceMethods addObjectsFromArray:self.flex_allClassMethods]; - return instanceMethods; -} - -+ (NSArray *)flex_allInstanceMethods { - return FLEXGetAllMethods(self, YES); -} - -+ (NSArray *)flex_allClassMethods { - return FLEXGetAllMethods(self.flex_metaclass, NO) ?: @[]; -} - -+ (FLEXMethod *)flex_methodNamed:(NSString *)name { - Method m = class_getInstanceMethod([self class], NSSelectorFromString(name)); - if (m == NULL) { - return nil; - } - - return [FLEXMethod method:m isInstanceMethod:YES]; -} - -+ (FLEXMethod *)flex_classMethodNamed:(NSString *)name { - Method m = class_getClassMethod([self class], NSSelectorFromString(name)); - if (m == NULL) { - return nil; - } - - return [FLEXMethod method:m isInstanceMethod:NO]; -} - -+ (BOOL)addMethod:(SEL)selector - typeEncoding:(NSString *)typeEncoding - implementation:(IMP)implementaiton - toInstances:(BOOL)instance { - return class_addMethod(instance ? self.class : self.flex_metaclass, selector, implementaiton, typeEncoding.UTF8String); -} - -+ (IMP)replaceImplementationOfMethod:(FLEXMethodBase *)method with:(IMP)implementation useInstance:(BOOL)instance { - return class_replaceMethod(instance ? self.class : self.flex_metaclass, method.selector, implementation, method.typeEncoding.UTF8String); -} - -+ (void)swizzle:(FLEXMethodBase *)original with:(FLEXMethodBase *)other onInstance:(BOOL)instance { - [self swizzleBySelector:original.selector with:other.selector onInstance:instance]; -} - -+ (BOOL)swizzleByName:(NSString *)original with:(NSString *)other onInstance:(BOOL)instance { - SEL originalMethod = NSSelectorFromString(original); - SEL newMethod = NSSelectorFromString(other); - if (originalMethod == 0 || newMethod == 0) { - return NO; - } - - [self swizzleBySelector:originalMethod with:newMethod onInstance:instance]; - return YES; -} - -+ (void)swizzleBySelector:(SEL)original with:(SEL)other onInstance:(BOOL)instance { - Class cls = instance ? self.class : self.flex_metaclass; - Method originalMethod = class_getInstanceMethod(cls, original); - Method newMethod = class_getInstanceMethod(cls, other); - if (class_addMethod(cls, original, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) { - class_replaceMethod(cls, other, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); - } else { - method_exchangeImplementations(originalMethod, newMethod); - } -} - -@end - - -#pragma mark Ivars - -@implementation NSObject (Ivars) - -+ (NSArray *)flex_allIvars { - return FLEXGetAllIvars(self); -} - -+ (FLEXIvar *)flex_ivarNamed:(NSString *)name { - Ivar i = class_getInstanceVariable([self class], name.UTF8String); - if (i == NULL) { - return nil; - } - - return [FLEXIvar ivar:i]; -} - -#pragma mark Get address -- (void *)flex_getIvarAddress:(FLEXIvar *)ivar { - return (uint8_t *)(__bridge void *)self + ivar.offset; -} - -- (void *)flex_getObjcIvarAddress:(Ivar)ivar { - return (uint8_t *)(__bridge void *)self + ivar_getOffset(ivar); -} - -- (void *)flex_getIvarAddressByName:(NSString *)name { - Ivar ivar = class_getInstanceVariable(self.class, name.UTF8String); - if (!ivar) return 0; - - return (uint8_t *)(__bridge void *)self + ivar_getOffset(ivar); -} - -#pragma mark Set ivar object -- (void)flex_setIvar:(FLEXIvar *)ivar object:(id)value { - object_setIvar(self, ivar.objc_ivar, value); -} - -- (BOOL)flex_setIvarByName:(NSString *)name object:(id)value { - Ivar ivar = class_getInstanceVariable(self.class, name.UTF8String); - if (!ivar) return NO; - - object_setIvar(self, ivar, value); - return YES; -} - -- (void)flex_setObjcIvar:(Ivar)ivar object:(id)value { - object_setIvar(self, ivar, value); -} - -#pragma mark Set ivar value -- (void)flex_setIvar:(FLEXIvar *)ivar value:(void *)value size:(size_t)size { - void *address = [self flex_getIvarAddress:ivar]; - memcpy(address, value, size); -} - -- (BOOL)flex_setIvarByName:(NSString *)name value:(void *)value size:(size_t)size { - Ivar ivar = class_getInstanceVariable(self.class, name.UTF8String); - if (!ivar) return NO; - - [self flex_setObjcIvar:ivar value:value size:size]; - return YES; -} - -- (void)flex_setObjcIvar:(Ivar)ivar value:(void *)value size:(size_t)size { - void *address = [self flex_getObjcIvarAddress:ivar]; - memcpy(address, value, size); -} - -@end - - -#pragma mark Properties - -@implementation NSObject (Properties) - -+ (NSArray *)flex_allProperties { - NSMutableArray *instanceProperties = self.flex_allInstanceProperties.mutableCopy; - [instanceProperties addObjectsFromArray:self.flex_allClassProperties]; - return instanceProperties; -} - -+ (NSArray *)flex_allInstanceProperties { - return FLEXGetAllProperties(self); -} - -+ (NSArray *)flex_allClassProperties { - return FLEXGetAllProperties(self.flex_metaclass) ?: @[]; -} - -+ (FLEXProperty *)flex_propertyNamed:(NSString *)name { - objc_property_t p = class_getProperty([self class], name.UTF8String); - if (p == NULL) { - return nil; - } - - return [FLEXProperty property:p onClass:self]; -} - -+ (FLEXProperty *)flex_classPropertyNamed:(NSString *)name { - objc_property_t p = class_getProperty(object_getClass(self), name.UTF8String); - if (p == NULL) { - return nil; - } - - return [FLEXProperty property:p onClass:object_getClass(self)]; -} - -+ (void)flex_replaceProperty:(FLEXProperty *)property { - [self flex_replaceProperty:property.name attributes:property.attributes]; -} - -+ (void)flex_replaceProperty:(NSString *)name attributes:(FLEXPropertyAttributes *)attributes { - unsigned int count; - objc_property_attribute_t *objc_attributes = [attributes copyAttributesList:&count]; - class_replaceProperty([self class], name.UTF8String, objc_attributes, count); - free(objc_attributes); -} - -@end - - diff --git a/Tweaks/FLEX/Utility/Categories/NSTimer+FLEX.h b/Tweaks/FLEX/Utility/Categories/NSTimer+FLEX.h deleted file mode 100644 index c1e883c..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSTimer+FLEX.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// NSTimer+Blocks.h -// FLEX -// -// Created by Tanner on 3/23/17. -// - -#import - -typedef void (^VoidBlock)(void); - -@interface NSTimer (Blocks) - -+ (instancetype)flex_fireSecondsFromNow:(NSTimeInterval)delay block:(VoidBlock)block; - -// Forward declaration -//+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/NSTimer+FLEX.m b/Tweaks/FLEX/Utility/Categories/NSTimer+FLEX.m deleted file mode 100644 index 2ea9291..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSTimer+FLEX.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// NSTimer+Blocks.m -// FLEX -// -// Created by Tanner on 3/23/17. -// - -#import "NSTimer+FLEX.h" - -@interface Block : NSObject -- (void)invoke; -@end - -#pragma clang diagnostic ignored "-Wincomplete-implementation" -@implementation NSTimer (Blocks) - -+ (instancetype)flex_fireSecondsFromNow:(NSTimeInterval)delay block:(VoidBlock)block { - if (@available(iOS 10, *)) { - return [self scheduledTimerWithTimeInterval:delay repeats:NO block:(id)block]; - } else { - return [self scheduledTimerWithTimeInterval:delay target:block selector:@selector(invoke) userInfo:nil repeats:NO]; - } -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/NSUserDefaults+FLEX.h b/Tweaks/FLEX/Utility/Categories/NSUserDefaults+FLEX.h deleted file mode 100644 index ed08eee..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSUserDefaults+FLEX.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// NSUserDefaults+FLEX.h -// FLEX -// -// Created by Tanner on 3/10/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -// Only use these if the getters and setters aren't good enough for whatever reason -extern NSString * const kFLEXDefaultsToolbarTopMarginKey; -extern NSString * const kFLEXDefaultsiOSPersistentOSLogKey; -extern NSString * const kFLEXDefaultsHidePropertyIvarsKey; -extern NSString * const kFLEXDefaultsHidePropertyMethodsKey; -extern NSString * const kFLEXDefaultsHidePrivateMethodsKey; -extern NSString * const kFLEXDefaultsShowMethodOverridesKey; -extern NSString * const kFLEXDefaultsHideVariablePreviewsKey; -extern NSString * const kFLEXDefaultsNetworkObserverEnabledKey; -extern NSString * const kFLEXDefaultsNetworkHostDenylistKey; -extern NSString * const kFLEXDefaultsDisableOSLogForceASLKey; -extern NSString * const kFLEXDefaultsRegisterJSONExplorerKey; - -/// All BOOL preferences are NO by default -@interface NSUserDefaults (FLEX) - -- (void)flex_toggleBoolForKey:(NSString *)key; - -@property (nonatomic) double flex_toolbarTopMargin; - -@property (nonatomic) BOOL flex_networkObserverEnabled; -// Not actually stored in defaults, but written to a file -@property (nonatomic) NSArray *flex_networkHostDenylist; - -/// Whether or not to register the object explorer as a JSON viewer on launch -@property (nonatomic) BOOL flex_registerDictionaryJSONViewerOnLaunch; - -/// The last selected screen in the network observer -@property (nonatomic) NSInteger flex_lastNetworkObserverMode; - -/// Disable os_log and re-enable ASL. May break Console.app output. -@property (nonatomic) BOOL flex_disableOSLog; -@property (nonatomic) BOOL flex_cacheOSLogMessages; - -@property (nonatomic) BOOL flex_explorerHidesPropertyIvars; -@property (nonatomic) BOOL flex_explorerHidesPropertyMethods; -@property (nonatomic) BOOL flex_explorerHidesPrivateMethods; -@property (nonatomic) BOOL flex_explorerShowsMethodOverrides; -@property (nonatomic) BOOL flex_explorerHidesVariablePreviews; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/NSUserDefaults+FLEX.m b/Tweaks/FLEX/Utility/Categories/NSUserDefaults+FLEX.m deleted file mode 100644 index d8e5e18..0000000 --- a/Tweaks/FLEX/Utility/Categories/NSUserDefaults+FLEX.m +++ /dev/null @@ -1,188 +0,0 @@ -// -// NSUserDefaults+FLEX.m -// FLEX -// -// Created by Tanner on 3/10/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "NSUserDefaults+FLEX.h" - -NSString * const kFLEXDefaultsToolbarTopMarginKey = @"com.flex.FLEXToolbar.topMargin"; -NSString * const kFLEXDefaultsiOSPersistentOSLogKey = @"com.flipborad.flex.enable_persistent_os_log"; -NSString * const kFLEXDefaultsHidePropertyIvarsKey = @"com.flipboard.FLEX.hide_property_ivars"; -NSString * const kFLEXDefaultsHidePropertyMethodsKey = @"com.flipboard.FLEX.hide_property_methods"; -NSString * const kFLEXDefaultsHidePrivateMethodsKey = @"com.flipboard.FLEX.hide_private_or_namespaced_methods"; -NSString * const kFLEXDefaultsShowMethodOverridesKey = @"com.flipboard.FLEX.show_method_overrides"; -NSString * const kFLEXDefaultsHideVariablePreviewsKey = @"com.flipboard.FLEX.hide_variable_previews"; -NSString * const kFLEXDefaultsNetworkObserverEnabledKey = @"com.flex.FLEXNetworkObserver.enableOnLaunch"; -NSString * const kFLEXDefaultsNetworkObserverLastModeKey = @"com.flex.FLEXNetworkObserver.lastMode"; -NSString * const kFLEXDefaultsNetworkHostDenylistKey = @"com.flipboard.FLEX.network_host_denylist"; -NSString * const kFLEXDefaultsDisableOSLogForceASLKey = @"com.flipboard.FLEX.try_disable_os_log"; -NSString * const kFLEXDefaultsRegisterJSONExplorerKey = @"com.flipboard.FLEX.view_json_as_object"; - -#define FLEXDefaultsPathForFile(name) ({ \ - NSArray *paths = NSSearchPathForDirectoriesInDomains( \ - NSLibraryDirectory, NSUserDomainMask, YES \ - ); \ - [paths[0] stringByAppendingPathComponent:@"Preferences"]; \ -}) - -@implementation NSUserDefaults (FLEX) - -#pragma mark Internal - -/// @param filename the name of a plist file without any extension -- (NSString *)flex_defaultsPathForFile:(NSString *)filename { - filename = [filename stringByAppendingPathExtension:@"plist"]; - - NSArray *paths = NSSearchPathForDirectoriesInDomains( - NSLibraryDirectory, NSUserDomainMask, YES - ); - NSString *preferences = [paths[0] stringByAppendingPathComponent:@"Preferences"]; - return [preferences stringByAppendingPathComponent:filename]; -} - -#pragma mark Helper - -- (void)flex_toggleBoolForKey:(NSString *)key { - [self setBool:![self boolForKey:key] forKey:key]; - [NSNotificationCenter.defaultCenter postNotificationName:key object:nil]; -} - -#pragma mark Misc - -- (double)flex_toolbarTopMargin { - if ([self objectForKey:kFLEXDefaultsToolbarTopMarginKey]) { - return [self doubleForKey:kFLEXDefaultsToolbarTopMarginKey]; - } - - return 100; -} - -- (void)setFlex_toolbarTopMargin:(double)margin { - [self setDouble:margin forKey:kFLEXDefaultsToolbarTopMarginKey]; -} - -- (BOOL)flex_networkObserverEnabled { - return [self boolForKey:kFLEXDefaultsNetworkObserverEnabledKey]; -} - -- (void)setFlex_networkObserverEnabled:(BOOL)enabled { - [self setBool:enabled forKey:kFLEXDefaultsNetworkObserverEnabledKey]; -} - -- (NSArray *)flex_networkHostDenylist { - return [NSArray arrayWithContentsOfFile:[ - self flex_defaultsPathForFile:kFLEXDefaultsNetworkHostDenylistKey - ]] ?: @[]; -} - -- (void)setFlex_networkHostDenylist:(NSArray *)denylist { - NSParameterAssert(denylist); - [denylist writeToFile:[ - self flex_defaultsPathForFile:kFLEXDefaultsNetworkHostDenylistKey - ] atomically:YES]; -} - -- (BOOL)flex_registerDictionaryJSONViewerOnLaunch { - return [self boolForKey:kFLEXDefaultsRegisterJSONExplorerKey]; -} - -- (void)setFlex_registerDictionaryJSONViewerOnLaunch:(BOOL)enable { - [self setBool:enable forKey:kFLEXDefaultsRegisterJSONExplorerKey]; -} - -- (NSInteger)flex_lastNetworkObserverMode { - return [self integerForKey:kFLEXDefaultsNetworkObserverLastModeKey]; -} - -- (void)setFlex_lastNetworkObserverMode:(NSInteger)mode { - [self setInteger:mode forKey:kFLEXDefaultsNetworkObserverLastModeKey]; -} - -#pragma mark System Log - -- (BOOL)flex_disableOSLog { - return [self boolForKey:kFLEXDefaultsDisableOSLogForceASLKey]; -} - -- (void)setFlex_disableOSLog:(BOOL)disable { - [self setBool:disable forKey:kFLEXDefaultsDisableOSLogForceASLKey]; -} - -- (BOOL)flex_cacheOSLogMessages { - return [self boolForKey:kFLEXDefaultsiOSPersistentOSLogKey]; -} - -- (void)setFlex_cacheOSLogMessages:(BOOL)cache { - [self setBool:cache forKey:kFLEXDefaultsiOSPersistentOSLogKey]; - [NSNotificationCenter.defaultCenter - postNotificationName:kFLEXDefaultsiOSPersistentOSLogKey - object:nil - ]; -} - -#pragma mark Object Explorer - -- (BOOL)flex_explorerHidesPropertyIvars { - return [self boolForKey:kFLEXDefaultsHidePropertyIvarsKey]; -} - -- (void)setFlex_explorerHidesPropertyIvars:(BOOL)hide { - [self setBool:hide forKey:kFLEXDefaultsHidePropertyIvarsKey]; - [NSNotificationCenter.defaultCenter - postNotificationName:kFLEXDefaultsHidePropertyIvarsKey - object:nil - ]; -} - -- (BOOL)flex_explorerHidesPropertyMethods { - return [self boolForKey:kFLEXDefaultsHidePropertyMethodsKey]; -} - -- (void)setFlex_explorerHidesPropertyMethods:(BOOL)hide { - [self setBool:hide forKey:kFLEXDefaultsHidePropertyMethodsKey]; - [NSNotificationCenter.defaultCenter - postNotificationName:kFLEXDefaultsHidePropertyMethodsKey - object:nil - ]; -} - -- (BOOL)flex_explorerHidesPrivateMethods { - return [self boolForKey:kFLEXDefaultsHidePrivateMethodsKey]; -} - -- (void)setFlex_explorerHidesPrivateMethods:(BOOL)show { - [self setBool:show forKey:kFLEXDefaultsHidePrivateMethodsKey]; - [NSNotificationCenter.defaultCenter - postNotificationName:kFLEXDefaultsHidePrivateMethodsKey - object:nil - ]; -} - -- (BOOL)flex_explorerShowsMethodOverrides { - return [self boolForKey:kFLEXDefaultsShowMethodOverridesKey]; -} - -- (void)setFlex_explorerShowsMethodOverrides:(BOOL)show { - [self setBool:show forKey:kFLEXDefaultsShowMethodOverridesKey]; - [NSNotificationCenter.defaultCenter - postNotificationName:kFLEXDefaultsShowMethodOverridesKey - object:nil - ]; -} - -- (BOOL)flex_explorerHidesVariablePreviews { - return [self boolForKey:kFLEXDefaultsHideVariablePreviewsKey]; -} - -- (void)setFlex_explorerHidesVariablePreviews:(BOOL)hide { - [self setBool:hide forKey:kFLEXDefaultsHideVariablePreviewsKey]; - [NSNotificationCenter.defaultCenter - postNotificationName:kFLEXDefaultsHideVariablePreviewsKey - object:nil - ]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/Cocoa+FLEXShortcuts.h b/Tweaks/FLEX/Utility/Categories/Private/Cocoa+FLEXShortcuts.h deleted file mode 100644 index 379502f..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/Cocoa+FLEXShortcuts.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Cocoa+FLEXShortcuts.h -// Pods -// -// Created by Tanner on 2/24/21. -// -// - -#import - -@interface UIAlertAction (FLEXShortcuts) -@property (nonatomic, readonly) NSString *flex_styleName; -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/Cocoa+FLEXShortcuts.m b/Tweaks/FLEX/Utility/Categories/Private/Cocoa+FLEXShortcuts.m deleted file mode 100644 index a9561e2..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/Cocoa+FLEXShortcuts.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// Cocoa+FLEXShortcuts.m -// Pods -// -// Created by Tanner on 2/24/21. -// -// - -#import "Cocoa+FLEXShortcuts.h" - -@implementation UIAlertAction (FLEXShortcuts) -- (NSString *)flex_styleName { - switch (self.style) { - case UIAlertActionStyleDefault: - return @"Default style"; - case UIAlertActionStyleCancel: - return @"Cancel style"; - case UIAlertActionStyleDestructive: - return @"Destructive style"; - - default: - return [NSString stringWithFormat:@"Unknown (%@)", @(self.style)]; - } -} -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSDictionary+ObjcRuntime.h b/Tweaks/FLEX/Utility/Categories/Private/NSDictionary+ObjcRuntime.h deleted file mode 100644 index 60d73ed..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSDictionary+ObjcRuntime.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// NSDictionary+ObjcRuntime.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/5/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import - -@interface NSDictionary (ObjcRuntime) - -/// \c kFLEXPropertyAttributeKeyTypeEncoding is the only required key. -/// Keys representing a boolean value should have a value of \c YES instead of an empty string. -- (NSString *)propertyAttributesString; - -+ (instancetype)attributesDictionaryForProperty:(objc_property_t)property; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSDictionary+ObjcRuntime.m b/Tweaks/FLEX/Utility/Categories/Private/NSDictionary+ObjcRuntime.m deleted file mode 100644 index d0d96d3..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSDictionary+ObjcRuntime.m +++ /dev/null @@ -1,107 +0,0 @@ -// -// NSDictionary+ObjcRuntime.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/5/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "NSDictionary+ObjcRuntime.h" -#import "FLEXRuntimeUtility.h" - -@implementation NSDictionary (ObjcRuntime) - -/// See this link on how to construct a proper attributes string: -/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html -- (NSString *)propertyAttributesString { - if (!self[kFLEXPropertyAttributeKeyTypeEncoding]) return nil; - - NSMutableString *attributes = [NSMutableString new]; - [attributes appendFormat:@"T%@,", self[kFLEXPropertyAttributeKeyTypeEncoding]]; - - for (NSString *attribute in self.allKeys) { - FLEXPropertyAttribute c = (FLEXPropertyAttribute)[attribute characterAtIndex:0]; - switch (c) { - case FLEXPropertyAttributeTypeEncoding: - break; - case FLEXPropertyAttributeBackingIvarName: - [attributes appendFormat:@"%@%@,", - kFLEXPropertyAttributeKeyBackingIvarName, - self[kFLEXPropertyAttributeKeyBackingIvarName] - ]; - break; - case FLEXPropertyAttributeCopy: - if ([self[kFLEXPropertyAttributeKeyCopy] boolValue]) - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyCopy]; - break; - case FLEXPropertyAttributeCustomGetter: - [attributes appendFormat:@"%@%@,", - kFLEXPropertyAttributeKeyCustomGetter, - self[kFLEXPropertyAttributeKeyCustomGetter] - ]; - break; - case FLEXPropertyAttributeCustomSetter: - [attributes appendFormat:@"%@%@,", - kFLEXPropertyAttributeKeyCustomSetter, - self[kFLEXPropertyAttributeKeyCustomSetter] - ]; - break; - case FLEXPropertyAttributeDynamic: - if ([self[kFLEXPropertyAttributeKeyDynamic] boolValue]) - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyDynamic]; - break; - case FLEXPropertyAttributeGarbageCollectible: - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyGarbageCollectable]; - break; - case FLEXPropertyAttributeNonAtomic: - if ([self[kFLEXPropertyAttributeKeyNonAtomic] boolValue]) - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyNonAtomic]; - break; - case FLEXPropertyAttributeOldTypeEncoding: - [attributes appendFormat:@"%@%@,", - kFLEXPropertyAttributeKeyOldStyleTypeEncoding, - self[kFLEXPropertyAttributeKeyOldStyleTypeEncoding] - ]; - break; - case FLEXPropertyAttributeReadOnly: - if ([self[kFLEXPropertyAttributeKeyReadOnly] boolValue]) - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyReadOnly]; - break; - case FLEXPropertyAttributeRetain: - if ([self[kFLEXPropertyAttributeKeyRetain] boolValue]) - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyRetain]; - break; - case FLEXPropertyAttributeWeak: - if ([self[kFLEXPropertyAttributeKeyWeak] boolValue]) - [attributes appendFormat:@"%@,", kFLEXPropertyAttributeKeyWeak]; - break; - default: - return nil; - break; - } - } - - [attributes deleteCharactersInRange:NSMakeRange(attributes.length-1, 1)]; - return attributes.copy; -} - -+ (instancetype)attributesDictionaryForProperty:(objc_property_t)property { - NSMutableDictionary *attrs = [NSMutableDictionary new]; - - for (NSString *key in FLEXRuntimeUtility.allPropertyAttributeKeys) { - char *value = property_copyAttributeValue(property, key.UTF8String); - if (value) { - attrs[key] = [[NSString alloc] - initWithBytesNoCopy:value - length:strlen(value) - encoding:NSUTF8StringEncoding - freeWhenDone:YES - ]; - } - } - - return attrs.copy; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSMapTable+FLEX_Subscripting.h b/Tweaks/FLEX/Utility/Categories/Private/NSMapTable+FLEX_Subscripting.h deleted file mode 100644 index f3b660b..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSMapTable+FLEX_Subscripting.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// NSMapTable+FLEX_Subscripting.h -// FLEX -// -// Created by Tanner Bennett on 1/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSMapTable (FLEX_Subscripting) - -- (nullable ObjectType)objectForKeyedSubscript:(KeyType)key; -- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType )key; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSMapTable+FLEX_Subscripting.m b/Tweaks/FLEX/Utility/Categories/Private/NSMapTable+FLEX_Subscripting.m deleted file mode 100644 index 47462d4..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSMapTable+FLEX_Subscripting.m +++ /dev/null @@ -1,21 +0,0 @@ -// -// NSMapTable+FLEX_Subscripting.m -// FLEX -// -// Created by Tanner Bennett on 1/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "NSMapTable+FLEX_Subscripting.h" - -@implementation NSMapTable (FLEX_Subscripting) - -- (id)objectForKeyedSubscript:(id)key { - return [self objectForKey:key]; -} - -- (void)setObject:(id)obj forKeyedSubscript:(id)key { - [self setObject:obj forKey:key]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSString+FLEX.h b/Tweaks/FLEX/Utility/Categories/Private/NSString+FLEX.h deleted file mode 100644 index 8719499..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSString+FLEX.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// NSString+FLEX.h -// FLEX -// -// Created by Tanner on 3/26/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" - -@interface NSString (FLEXTypeEncoding) - -///@return whether this type starts with the const specifier -@property (nonatomic, readonly) BOOL flex_typeIsConst; -/// @return the first char in the type encoding that is not the const specifier -@property (nonatomic, readonly) FLEXTypeEncoding flex_firstNonConstType; -/// @return the first char in the type encoding after the pointer specifier, if it is a pointer -@property (nonatomic, readonly) FLEXTypeEncoding flex_pointeeType; -/// @return whether this type is an objc object of any kind, even if it's const -@property (nonatomic, readonly) BOOL flex_typeIsObjectOrClass; -/// @return the class named in this type encoding if it is of the form \c @"MYClass" -@property (nonatomic, readonly) Class flex_typeClass; -/// Includes C strings and selectors as well as regular pointers -@property (nonatomic, readonly) BOOL flex_typeIsNonObjcPointer; - -@end - -@interface NSString (KeyPaths) - -- (NSString *)flex_stringByRemovingLastKeyPathComponent; -- (NSString *)flex_stringByReplacingLastKeyPathComponent:(NSString *)replacement; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSString+FLEX.m b/Tweaks/FLEX/Utility/Categories/Private/NSString+FLEX.m deleted file mode 100644 index 20b25d3..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSString+FLEX.m +++ /dev/null @@ -1,160 +0,0 @@ -// -// NSString+FLEX.m -// FLEX -// -// Created by Tanner on 3/26/17. -// Copyright © 2017 Tanner Bennett. All rights reserved. -// - -#import "NSString+FLEX.h" - -@interface NSMutableString (Replacement) -- (void)replaceOccurencesOfString:(NSString *)string with:(NSString *)replacement; -- (void)removeLastKeyPathComponent; -@end - -@implementation NSMutableString (Replacement) - -- (void)replaceOccurencesOfString:(NSString *)string with:(NSString *)replacement { - [self replaceOccurrencesOfString:string withString:replacement options:0 range:NSMakeRange(0, self.length)]; -} - -- (void)removeLastKeyPathComponent { - if (![self containsString:@"."]) { - [self deleteCharactersInRange:NSMakeRange(0, self.length)]; - return; - } - - BOOL putEscapesBack = NO; - if ([self containsString:@"\\."]) { - [self replaceOccurencesOfString:@"\\." with:@"\\~"]; - - // Case like "UIKit\.framework" - if (![self containsString:@"."]) { - [self deleteCharactersInRange:NSMakeRange(0, self.length)]; - return; - } - - putEscapesBack = YES; - } - - // Case like "Bund" or "Bundle.cla" - if (![self hasSuffix:@"."]) { - NSUInteger len = self.pathExtension.length; - [self deleteCharactersInRange:NSMakeRange(self.length-len, len)]; - } - - if (putEscapesBack) { - [self replaceOccurencesOfString:@"\\~" with:@"\\."]; - } -} - -@end - -@implementation NSString (FLEXTypeEncoding) - -- (NSCharacterSet *)flex_classNameAllowedCharactersSet { - static NSCharacterSet *classNameAllowedCharactersSet = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSMutableCharacterSet *temp = NSMutableCharacterSet.alphanumericCharacterSet; - [temp addCharactersInString:@"_"]; - classNameAllowedCharactersSet = temp.copy; - }); - - return classNameAllowedCharactersSet; -} - -- (BOOL)flex_typeIsConst { - if (!self.length) return NO; - return [self characterAtIndex:0] == FLEXTypeEncodingConst; -} - -- (FLEXTypeEncoding)flex_firstNonConstType { - if (!self.length) return FLEXTypeEncodingNull; - return [self characterAtIndex:(self.flex_typeIsConst ? 1 : 0)]; -} - -- (FLEXTypeEncoding)flex_pointeeType { - if (!self.length) return FLEXTypeEncodingNull; - - if (self.flex_firstNonConstType == FLEXTypeEncodingPointer) { - return [self characterAtIndex:(self.flex_typeIsConst ? 2 : 1)]; - } - - return FLEXTypeEncodingNull; -} - -- (BOOL)flex_typeIsObjectOrClass { - FLEXTypeEncoding type = self.flex_firstNonConstType; - return type == FLEXTypeEncodingObjcObject || type == FLEXTypeEncodingObjcClass; -} - -- (Class)flex_typeClass { - if (!self.flex_typeIsObjectOrClass) { - return nil; - } - - NSScanner *scan = [NSScanner scannerWithString:self]; - // Skip const - [scan scanString:@"r" intoString:nil]; - // Scan leading @" - if (![scan scanString:@"@\"" intoString:nil]) { - return nil; - } - - // Scan class name - NSString *name = nil; - if (![scan scanCharactersFromSet:self.flex_classNameAllowedCharactersSet intoString:&name]) { - return nil; - } - // Scan trailing quote - if (![scan scanString:@"\"" intoString:nil]) { - return nil; - } - - // Return found class - return NSClassFromString(name); -} - -- (BOOL)flex_typeIsNonObjcPointer { - FLEXTypeEncoding type = self.flex_firstNonConstType; - return type == FLEXTypeEncodingPointer || - type == FLEXTypeEncodingCString || - type == FLEXTypeEncodingSelector; -} - -@end - -@implementation NSString (KeyPaths) - -- (NSString *)flex_stringByRemovingLastKeyPathComponent { - if (![self containsString:@"."]) { - return @""; - } - - NSMutableString *mself = self.mutableCopy; - [mself removeLastKeyPathComponent]; - return mself; -} - -- (NSString *)flex_stringByReplacingLastKeyPathComponent:(NSString *)replacement { - // replacement should not have any escaped '.' in it, - // so we escape all '.' - if ([replacement containsString:@"."]) { - replacement = [replacement stringByReplacingOccurrencesOfString:@"." withString:@"\\."]; - } - - // Case like "Foo" - if (![self containsString:@"."]) { - return [replacement stringByAppendingString:@"."]; - } - - NSMutableString *mself = self.mutableCopy; - [mself removeLastKeyPathComponent]; - [mself appendString:replacement]; - [mself appendString:@"."]; - return mself; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSString+ObjcRuntime.h b/Tweaks/FLEX/Utility/Categories/Private/NSString+ObjcRuntime.h deleted file mode 100644 index 85cdae6..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSString+ObjcRuntime.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// NSString+ObjcRuntime.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/1/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@interface NSString (Utilities) - -/// A dictionary of property attributes if the receiver is a valid property attributes string. -/// Values are either a string or \c YES. Boolean attributes which are false will not be -/// present in the dictionary. See this link on how to construct a proper attributes string: -/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html -/// -/// Note: this method doesn't work properly for certain type encodings, and neither does -/// the property_copyAttributeValue function in the runtime itself. Radar: FB7499230 -- (NSDictionary *)propertyAttributes; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/NSString+ObjcRuntime.m b/Tweaks/FLEX/Utility/Categories/Private/NSString+ObjcRuntime.m deleted file mode 100644 index 4223664..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/NSString+ObjcRuntime.m +++ /dev/null @@ -1,75 +0,0 @@ -// -// NSString+ObjcRuntime.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/1/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "NSString+ObjcRuntime.h" -#import "FLEXRuntimeUtility.h" - -@implementation NSString (Utilities) - -- (NSString *)stringbyDeletingCharacterAtIndex:(NSUInteger)idx { - NSMutableString *string = self.mutableCopy; - [string replaceCharactersInRange:NSMakeRange(idx, 1) withString:@""]; - return string; -} - -/// See this link on how to construct a proper attributes string: -/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html -- (NSDictionary *)propertyAttributes { - if (!self.length) return nil; - - NSMutableDictionary *attributes = [NSMutableDictionary new]; - - NSArray *components = [self componentsSeparatedByString:@","]; - for (NSString *attribute in components) { - FLEXPropertyAttribute c = (FLEXPropertyAttribute)[attribute characterAtIndex:0]; - switch (c) { - case FLEXPropertyAttributeTypeEncoding: - // Note: the type encoding here is not always correct. Radar: FB7499230 - attributes[kFLEXPropertyAttributeKeyTypeEncoding] = [attribute stringbyDeletingCharacterAtIndex:0]; - break; - case FLEXPropertyAttributeBackingIvarName: - attributes[kFLEXPropertyAttributeKeyBackingIvarName] = [attribute stringbyDeletingCharacterAtIndex:0]; - break; - case FLEXPropertyAttributeCopy: - attributes[kFLEXPropertyAttributeKeyCopy] = @YES; - break; - case FLEXPropertyAttributeCustomGetter: - attributes[kFLEXPropertyAttributeKeyCustomGetter] = [attribute stringbyDeletingCharacterAtIndex:0]; - break; - case FLEXPropertyAttributeCustomSetter: - attributes[kFLEXPropertyAttributeKeyCustomSetter] = [attribute stringbyDeletingCharacterAtIndex:0]; - break; - case FLEXPropertyAttributeDynamic: - attributes[kFLEXPropertyAttributeKeyDynamic] = @YES; - break; - case FLEXPropertyAttributeGarbageCollectible: - attributes[kFLEXPropertyAttributeKeyGarbageCollectable] = @YES; - break; - case FLEXPropertyAttributeNonAtomic: - attributes[kFLEXPropertyAttributeKeyNonAtomic] = @YES; - break; - case FLEXPropertyAttributeOldTypeEncoding: - attributes[kFLEXPropertyAttributeKeyOldStyleTypeEncoding] = [attribute stringbyDeletingCharacterAtIndex:0]; - break; - case FLEXPropertyAttributeReadOnly: - attributes[kFLEXPropertyAttributeKeyReadOnly] = @YES; - break; - case FLEXPropertyAttributeRetain: - attributes[kFLEXPropertyAttributeKeyRetain] = @YES; - break; - case FLEXPropertyAttributeWeak: - attributes[kFLEXPropertyAttributeKeyWeak] = @YES; - break; - } - } - - return attributes; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/UIView+FLEX_Layout.h b/Tweaks/FLEX/Utility/Categories/Private/UIView+FLEX_Layout.h deleted file mode 100644 index c50f7d1..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/UIView+FLEX_Layout.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// UIView+FLEX_Layout.h -// FLEX -// -// Created by Tanner Bennett on 7/18/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -#define Padding(p) UIEdgeInsetsMake(p, p, p, p) - -@interface UIView (FLEX_Layout) - -- (void)flex_centerInView:(UIView *)view; -- (void)flex_pinEdgesTo:(UIView *)view; -- (void)flex_pinEdgesTo:(UIView *)view withInsets:(UIEdgeInsets)insets; -- (void)flex_pinEdgesToSuperview; -- (void)flex_pinEdgesToSuperviewWithInsets:(UIEdgeInsets)insets; -- (void)flex_pinEdgesToSuperviewWithInsets:(UIEdgeInsets)insets aboveView:(UIView *)sibling; -- (void)flex_pinEdgesToSuperviewWithInsets:(UIEdgeInsets)insets belowView:(UIView *)sibling; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/Private/UIView+FLEX_Layout.m b/Tweaks/FLEX/Utility/Categories/Private/UIView+FLEX_Layout.m deleted file mode 100644 index c44222e..0000000 --- a/Tweaks/FLEX/Utility/Categories/Private/UIView+FLEX_Layout.m +++ /dev/null @@ -1,66 +0,0 @@ -// -// UIView+FLEX_Layout.m -// FLEX -// -// Created by Tanner Bennett on 7/18/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIView+FLEX_Layout.h" - -@implementation UIView (FLEX_Layout) - -- (void)flex_centerInView:(UIView *)view { - [NSLayoutConstraint activateConstraints:@[ - [self.centerXAnchor constraintEqualToAnchor:view.centerXAnchor], - [self.centerYAnchor constraintEqualToAnchor:view.centerYAnchor], - ]]; -} - -- (void)flex_pinEdgesTo:(UIView *)view { - [NSLayoutConstraint activateConstraints:@[ - [self.topAnchor constraintEqualToAnchor:view.topAnchor], - [self.leftAnchor constraintEqualToAnchor:view.leftAnchor], - [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor], - [self.rightAnchor constraintEqualToAnchor:view.rightAnchor], - ]]; -} - -- (void)flex_pinEdgesTo:(UIView *)view withInsets:(UIEdgeInsets)i { - [NSLayoutConstraint activateConstraints:@[ - [self.topAnchor constraintEqualToAnchor:view.topAnchor constant:i.top], - [self.leftAnchor constraintEqualToAnchor:view.leftAnchor constant:i.left], - [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:-i.bottom], - [self.rightAnchor constraintEqualToAnchor:view.rightAnchor constant:-i.right], - ]]; -} - -- (void)flex_pinEdgesToSuperview { - [self flex_pinEdgesTo:self.superview]; -} - -- (void)flex_pinEdgesToSuperviewWithInsets:(UIEdgeInsets)insets { - [self flex_pinEdgesTo:self.superview withInsets:insets]; -} - -- (void)flex_pinEdgesToSuperviewWithInsets:(UIEdgeInsets)i aboveView:(UIView *)sibling { - UIView *view = self.superview; - [NSLayoutConstraint activateConstraints:@[ - [self.topAnchor constraintEqualToAnchor:view.topAnchor constant:i.top], - [self.leftAnchor constraintEqualToAnchor:view.leftAnchor constant:i.left], - [self.bottomAnchor constraintEqualToAnchor:sibling.topAnchor constant:-i.bottom], - [self.rightAnchor constraintEqualToAnchor:view.rightAnchor constant:-i.right], - ]]; -} - -- (void)flex_pinEdgesToSuperviewWithInsets:(UIEdgeInsets)i belowView:(UIView *)sibling { - UIView *view = self.superview; - [NSLayoutConstraint activateConstraints:@[ - [self.topAnchor constraintEqualToAnchor:sibling.bottomAnchor constant:i.top], - [self.leftAnchor constraintEqualToAnchor:view.leftAnchor constant:i.left], - [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:-i.bottom], - [self.rightAnchor constraintEqualToAnchor:view.rightAnchor constant:-i.right], - ]]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIBarButtonItem+FLEX.h b/Tweaks/FLEX/Utility/Categories/UIBarButtonItem+FLEX.h deleted file mode 100644 index 352b9f0..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIBarButtonItem+FLEX.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// UIBarButtonItem+FLEX.h -// FLEX -// -// Created by Tanner on 2/4/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -#define FLEXBarButtonItem(title, tgt, sel) \ - [UIBarButtonItem flex_itemWithTitle:title target:tgt action:sel] -#define FLEXBarButtonItemSystem(item, tgt, sel) \ - [UIBarButtonItem flex_systemItem:UIBarButtonSystemItem##item target:tgt action:sel] - -@interface UIBarButtonItem (FLEX) - -@property (nonatomic, readonly, class) UIBarButtonItem *flex_flexibleSpace; -@property (nonatomic, readonly, class) UIBarButtonItem *flex_fixedSpace; - -+ (instancetype)flex_itemWithCustomView:(UIView *)customView; -+ (instancetype)flex_backItemWithTitle:(NSString *)title; - -+ (instancetype)flex_systemItem:(UIBarButtonSystemItem)item target:(id)target action:(SEL)action; - -+ (instancetype)flex_itemWithTitle:(NSString *)title target:(id)target action:(SEL)action; -+ (instancetype)flex_doneStyleitemWithTitle:(NSString *)title target:(id)target action:(SEL)action; - -+ (instancetype)flex_itemWithImage:(UIImage *)image target:(id)target action:(SEL)action; - -+ (instancetype)flex_disabledSystemItem:(UIBarButtonSystemItem)item; -+ (instancetype)flex_disabledItemWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style; -+ (instancetype)flex_disabledItemWithImage:(UIImage *)image; - -/// @return the receiver -- (UIBarButtonItem *)flex_withTintColor:(UIColor *)tint; - -- (void)_setWidth:(CGFloat)width; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIBarButtonItem+FLEX.m b/Tweaks/FLEX/Utility/Categories/UIBarButtonItem+FLEX.m deleted file mode 100644 index c20fcff..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIBarButtonItem+FLEX.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// UIBarButtonItem+FLEX.m -// FLEX -// -// Created by Tanner on 2/4/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIBarButtonItem+FLEX.h" - -#pragma clang diagnostic ignored "-Wincomplete-implementation" - -@implementation UIBarButtonItem (FLEX) - -+ (UIBarButtonItem *)flex_flexibleSpace { - return [self flex_systemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; -} - -+ (UIBarButtonItem *)flex_fixedSpace { - UIBarButtonItem *fixed = [self flex_systemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; - fixed.width = 60; - return fixed; -} - -+ (instancetype)flex_systemItem:(UIBarButtonSystemItem)item target:(id)target action:(SEL)action { - return [[self alloc] initWithBarButtonSystemItem:item target:target action:action]; -} - -+ (instancetype)flex_itemWithCustomView:(UIView *)customView { - return [[self alloc] initWithCustomView:customView]; -} - -+ (instancetype)flex_backItemWithTitle:(NSString *)title { - return [self flex_itemWithTitle:title target:nil action:nil]; -} - -+ (instancetype)flex_itemWithTitle:(NSString *)title target:(id)target action:(SEL)action { - return [[self alloc] initWithTitle:title style:UIBarButtonItemStylePlain target:target action:action]; -} - -+ (instancetype)flex_doneStyleitemWithTitle:(NSString *)title target:(id)target action:(SEL)action { - return [[self alloc] initWithTitle:title style:UIBarButtonItemStyleDone target:target action:action]; -} - -+ (instancetype)flex_itemWithImage:(UIImage *)image target:(id)target action:(SEL)action { - return [[self alloc] initWithImage:image style:UIBarButtonItemStylePlain target:target action:action]; -} - -+ (instancetype)flex_disabledSystemItem:(UIBarButtonSystemItem)system { - UIBarButtonItem *item = [self flex_systemItem:system target:nil action:nil]; - item.enabled = NO; - return item; -} - -+ (instancetype)flex_disabledItemWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style { - UIBarButtonItem *item = [self flex_itemWithTitle:title target:nil action:nil]; - item.enabled = NO; - return item; -} - -+ (instancetype)flex_disabledItemWithImage:(UIImage *)image { - UIBarButtonItem *item = [self flex_itemWithImage:image target:nil action:nil]; - item.enabled = NO; - return item; -} - -- (UIBarButtonItem *)flex_withTintColor:(UIColor *)tint { - self.tintColor = tint; - return self; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIFont+FLEX.h b/Tweaks/FLEX/Utility/Categories/UIFont+FLEX.h deleted file mode 100644 index b668ea2..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIFont+FLEX.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// UIFont+FLEX.h -// FLEX -// -// Created by Tanner Bennett on 12/20/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface UIFont (FLEX) - -@property (nonatomic, readonly, class) UIFont *flex_defaultTableCellFont; -@property (nonatomic, readonly, class) UIFont *flex_codeFont; -@property (nonatomic, readonly, class) UIFont *flex_smallCodeFont; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIFont+FLEX.m b/Tweaks/FLEX/Utility/Categories/UIFont+FLEX.m deleted file mode 100644 index 976c37b..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIFont+FLEX.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// UIFont+FLEX.m -// FLEX -// -// Created by Tanner Bennett on 12/20/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIFont+FLEX.h" - -#define kFLEXDefaultCellFontSize 12.0 - -@implementation UIFont (FLEX) - -+ (UIFont *)flex_defaultTableCellFont { - static UIFont *defaultTableCellFont = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - defaultTableCellFont = [UIFont systemFontOfSize:kFLEXDefaultCellFontSize]; - }); - - return defaultTableCellFont; -} - -+ (UIFont *)flex_codeFont { - // Actually only available in iOS 13, the SDK headers are wrong - if (@available(iOS 13, *)) { - return [self monospacedSystemFontOfSize:kFLEXDefaultCellFontSize weight:UIFontWeightRegular]; - } else { - return [self fontWithName:@"Menlo-Regular" size:kFLEXDefaultCellFontSize]; - } -} - -+ (UIFont *)flex_smallCodeFont { - // Actually only available in iOS 13, the SDK headers are wrong - if (@available(iOS 13, *)) { - return [self monospacedSystemFontOfSize:self.smallSystemFontSize weight:UIFontWeightRegular]; - } else { - return [self fontWithName:@"Menlo-Regular" size:self.smallSystemFontSize]; - } -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIGestureRecognizer+Blocks.h b/Tweaks/FLEX/Utility/Categories/UIGestureRecognizer+Blocks.h deleted file mode 100644 index 91b39be..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIGestureRecognizer+Blocks.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// UIGestureRecognizer+Blocks.h -// FLEX -// -// Created by Tanner Bennett on 12/20/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -typedef void (^GestureBlock)(UIGestureRecognizer *gesture); - - -@interface UIGestureRecognizer (Blocks) - -+ (instancetype)flex_action:(GestureBlock)action; - -@property (nonatomic, setter=flex_setAction:) GestureBlock flex_action; - -@end - diff --git a/Tweaks/FLEX/Utility/Categories/UIGestureRecognizer+Blocks.m b/Tweaks/FLEX/Utility/Categories/UIGestureRecognizer+Blocks.m deleted file mode 100644 index 45ed31b..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIGestureRecognizer+Blocks.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// UIGestureRecognizer+Blocks.m -// FLEX -// -// Created by Tanner Bennett on 12/20/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIGestureRecognizer+Blocks.h" -#import - - -@implementation UIGestureRecognizer (Blocks) - -static void * actionKey; - -+ (instancetype)flex_action:(GestureBlock)action { - UIGestureRecognizer *gesture = [[self alloc] initWithTarget:nil action:nil]; - [gesture addTarget:gesture action:@selector(flex_invoke)]; - gesture.flex_action = action; - return gesture; -} - -- (void)flex_invoke { - self.flex_action(self); -} - -- (GestureBlock)flex_action { - return objc_getAssociatedObject(self, &actionKey); -} - -- (void)flex_setAction:(GestureBlock)action { - objc_setAssociatedObject(self, &actionKey, action, OBJC_ASSOCIATION_COPY); -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIMenu+FLEX.h b/Tweaks/FLEX/Utility/Categories/UIMenu+FLEX.h deleted file mode 100644 index 4ec5956..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIMenu+FLEX.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// UIMenu+FLEX.h -// FLEX -// -// Created by Tanner on 1/28/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface UIMenu (FLEX) - -+ (instancetype)flex_inlineMenuWithTitle:(NSString *)title - image:(UIImage *)image - children:(NSArray *)children; - -- (instancetype)flex_collapsed; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIMenu+FLEX.m b/Tweaks/FLEX/Utility/Categories/UIMenu+FLEX.m deleted file mode 100644 index c522ca7..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIMenu+FLEX.m +++ /dev/null @@ -1,39 +0,0 @@ -// -// UIMenu+FLEX.m -// FLEX -// -// Created by Tanner on 1/28/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIMenu+FLEX.h" - -@implementation UIMenu (FLEX) - -+ (instancetype)flex_inlineMenuWithTitle:(NSString *)title image:(UIImage *)image children:(NSArray *)children { - return [UIMenu - menuWithTitle:title - image:image - identifier:nil - options:UIMenuOptionsDisplayInline - children:children - ]; -} - -- (instancetype)flex_collapsed { - return [UIMenu - menuWithTitle:@"" - image:nil - identifier:nil - options:UIMenuOptionsDisplayInline - children:@[[UIMenu - menuWithTitle:self.title - image:self.image - identifier:self.identifier - options:0 - children:self.children - ]] - ]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIPasteboard+FLEX.h b/Tweaks/FLEX/Utility/Categories/UIPasteboard+FLEX.h deleted file mode 100644 index 20f1b0c..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIPasteboard+FLEX.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// UIPasteboard+FLEX.h -// FLEX -// -// Created by Tanner Bennett on 12/9/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface UIPasteboard (FLEX) - -/// For copying an object which could be a string, data, or number -- (void)flex_copy:(id)unknownType; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UIPasteboard+FLEX.m b/Tweaks/FLEX/Utility/Categories/UIPasteboard+FLEX.m deleted file mode 100644 index 3edac66..0000000 --- a/Tweaks/FLEX/Utility/Categories/UIPasteboard+FLEX.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// UIPasteboard+FLEX.m -// FLEX -// -// Created by Tanner Bennett on 12/9/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "UIPasteboard+FLEX.h" - -@implementation UIPasteboard (FLEX) - -- (void)flex_copy:(id)object { - if (!object) { - return; - } - - if ([object isKindOfClass:[NSString class]]) { - UIPasteboard.generalPasteboard.string = object; - } else if([object isKindOfClass:[NSData class]]) { - [UIPasteboard.generalPasteboard setData:object forPasteboardType:@"public.data"]; - } else if ([object isKindOfClass:[NSNumber class]]) { - UIPasteboard.generalPasteboard.string = [object stringValue]; - } else { - // TODO: make this an alert instead of an exception - [NSException raise:NSInternalInconsistencyException - format:@"Tried to copy unsupported type: %@", [object class]]; - } -} - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UITextField+Range.h b/Tweaks/FLEX/Utility/Categories/UITextField+Range.h deleted file mode 100644 index a86a4ce..0000000 --- a/Tweaks/FLEX/Utility/Categories/UITextField+Range.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// UITextField+Range.h -// FLEX -// -// Created by Tanner on 6/13/17. -// - -#import - -@interface UITextField (Range) - -@property (nonatomic, readonly) NSRange flex_selectedRange; - -@end diff --git a/Tweaks/FLEX/Utility/Categories/UITextField+Range.m b/Tweaks/FLEX/Utility/Categories/UITextField+Range.m deleted file mode 100644 index e1edc1c..0000000 --- a/Tweaks/FLEX/Utility/Categories/UITextField+Range.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// UITextField+Range.m -// FLEX -// -// Created by Tanner on 6/13/17. -// - -#import "UITextField+Range.h" - -@implementation UITextField (Range) - -- (NSRange)flex_selectedRange { - UITextRange *r = self.selectedTextRange; - if (r) { - NSInteger loc = [self offsetFromPosition:self.beginningOfDocument toPosition:r.start]; - NSInteger len = [self offsetFromPosition:r.start toPosition:r.end]; - return NSMakeRange(loc, len); - } - - return NSMakeRange(NSNotFound, 0); -} - -@end diff --git a/Tweaks/FLEX/Utility/FLEXAlert.h b/Tweaks/FLEX/Utility/FLEXAlert.h deleted file mode 100644 index 86492e6..0000000 --- a/Tweaks/FLEX/Utility/FLEXAlert.h +++ /dev/null @@ -1,85 +0,0 @@ -// -// FLEXAlert.h -// FLEX -// -// Created by Tanner Bennett on 8/20/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class FLEXAlert, FLEXAlertAction; - -typedef void (^FLEXAlertReveal)(void); -typedef void (^FLEXAlertBuilder)(FLEXAlert *make); -typedef FLEXAlert * _Nonnull (^FLEXAlertStringProperty)(NSString * _Nullable); -typedef FLEXAlert * _Nonnull (^FLEXAlertStringArg)(NSString * _Nullable); -typedef FLEXAlert * _Nonnull (^FLEXAlertTextField)(void(^configurationHandler)(UITextField *textField)); -typedef FLEXAlertAction * _Nonnull (^FLEXAlertAddAction)(NSString *title); -typedef FLEXAlertAction * _Nonnull (^FLEXAlertActionStringProperty)(NSString * _Nullable); -typedef FLEXAlertAction * _Nonnull (^FLEXAlertActionProperty)(void); -typedef FLEXAlertAction * _Nonnull (^FLEXAlertActionBOOLProperty)(BOOL); -typedef FLEXAlertAction * _Nonnull (^FLEXAlertActionHandler)(void(^handler)(NSArray *strings)); - -@interface FLEXAlert : NSObject - -/// Shows a simple alert with one button which says "Dismiss" -+ (void)showAlert:(NSString * _Nullable)title message:(NSString * _Nullable)message from:(UIViewController *)viewController; - -/// Construct and display an alert -+ (void)makeAlert:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController; -/// Construct and display an action sheet-style alert -+ (void)makeSheet:(FLEXAlertBuilder)block - showFrom:(UIViewController *)viewController - source:(id)viewOrBarItem; - -/// Construct an alert -+ (UIAlertController *)makeAlert:(FLEXAlertBuilder)block; -/// Construct an action sheet-style alert -+ (UIAlertController *)makeSheet:(FLEXAlertBuilder)block; - -/// Set the alert's title. -/// -/// Call in succession to append strings to the title. -@property (nonatomic, readonly) FLEXAlertStringProperty title; -/// Set the alert's message. -/// -/// Call in succession to append strings to the message. -@property (nonatomic, readonly) FLEXAlertStringProperty message; -/// Add a button with a given title with the default style and no action. -@property (nonatomic, readonly) FLEXAlertAddAction button; -/// Add a text field with the given (optional) placeholder text. -@property (nonatomic, readonly) FLEXAlertStringArg textField; -/// Add and configure the given text field. -/// -/// Use this if you need to more than set the placeholder, such as -/// supply a delegate, make it secure entry, or change other attributes. -@property (nonatomic, readonly) FLEXAlertTextField configuredTextField; - -@end - -@interface FLEXAlertAction : NSObject - -/// Set the action's title. -/// -/// Call in succession to append strings to the title. -@property (nonatomic, readonly) FLEXAlertActionStringProperty title; -/// Make the action destructive. It appears with red text. -@property (nonatomic, readonly) FLEXAlertActionProperty destructiveStyle; -/// Make the action cancel-style. It appears with a bolder font. -@property (nonatomic, readonly) FLEXAlertActionProperty cancelStyle; -/// Enable or disable the action. Enabled by default. -@property (nonatomic, readonly) FLEXAlertActionBOOLProperty enabled; -/// Give the button an action. The action takes an array of text field strings. -@property (nonatomic, readonly) FLEXAlertActionHandler handler; -/// Access the underlying UIAlertAction, should you need to change it while -/// the encompassing alert is being displayed. For example, you may want to -/// enable or disable a button based on the input of some text fields in the alert. -/// Do not call this more than once per instance. -@property (nonatomic, readonly) UIAlertAction *action; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/FLEXAlert.m b/Tweaks/FLEX/Utility/FLEXAlert.m deleted file mode 100644 index 293a9e6..0000000 --- a/Tweaks/FLEX/Utility/FLEXAlert.m +++ /dev/null @@ -1,233 +0,0 @@ -// -// FLEXAlert.m -// FLEX -// -// Created by Tanner Bennett on 8/20/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXAlert.h" -#import "FLEXMacros.h" - -@interface FLEXAlert () -@property (nonatomic, readonly) UIAlertController *_controller; -@property (nonatomic, readonly) NSMutableArray *_actions; -@end - -#define FLEXAlertActionMutationAssertion() \ -NSAssert(!self._action, @"Cannot mutate action after retreiving underlying UIAlertAction"); - -@interface FLEXAlertAction () -@property (nonatomic) UIAlertController *_controller; -@property (nonatomic) NSString *_title; -@property (nonatomic) UIAlertActionStyle _style; -@property (nonatomic) BOOL _disable; -@property (nonatomic) void(^_handler)(UIAlertAction *action); -@property (nonatomic) UIAlertAction *_action; -@end - -@implementation FLEXAlert - -+ (void)showAlert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController { - [self makeAlert:^(FLEXAlert *make) { - make.title(title).message(message).button(@"Dismiss").cancelStyle(); - } showFrom:viewController]; -} - -#pragma mark Initialization - -- (instancetype)initWithController:(UIAlertController *)controller { - self = [super init]; - if (self) { - __controller = controller; - __actions = [NSMutableArray new]; - } - - return self; -} - -+ (UIAlertController *)make:(FLEXAlertBuilder)block withStyle:(UIAlertControllerStyle)style { - // Create alert builder - FLEXAlert *alert = [[self alloc] initWithController: - [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style] - ]; - - // Configure alert - block(alert); - - // Add actions - for (FLEXAlertAction *builder in alert._actions) { - [alert._controller addAction:builder.action]; - } - - return alert._controller; -} - -+ (void)make:(FLEXAlertBuilder)block - withStyle:(UIAlertControllerStyle)style - showFrom:(UIViewController *)viewController - source:(id)viewOrBarItem { - UIAlertController *alert = [self make:block withStyle:style]; - if ([viewOrBarItem isKindOfClass:[UIBarButtonItem class]]) { - alert.popoverPresentationController.barButtonItem = viewOrBarItem; - } else if ([viewOrBarItem isKindOfClass:[UIView class]]) { - alert.popoverPresentationController.sourceView = viewOrBarItem; - alert.popoverPresentationController.sourceRect = [viewOrBarItem bounds]; - } else if (viewOrBarItem) { - NSParameterAssert( - [viewOrBarItem isKindOfClass:[UIBarButtonItem class]] || - [viewOrBarItem isKindOfClass:[UIView class]] || - !viewOrBarItem - ); - } - [viewController presentViewController:alert animated:YES completion:nil]; -} - -+ (void)makeAlert:(FLEXAlertBuilder)block showFrom:(UIViewController *)controller { - [self make:block withStyle:UIAlertControllerStyleAlert showFrom:controller source:nil]; -} - -+ (void)makeSheet:(FLEXAlertBuilder)block showFrom:(UIViewController *)controller { - [self make:block withStyle:UIAlertControllerStyleActionSheet showFrom:controller source:nil]; -} - -/// Construct and display an action sheet-style alert -+ (void)makeSheet:(FLEXAlertBuilder)block - showFrom:(UIViewController *)controller - source:(id)viewOrBarItem { - [self make:block - withStyle:UIAlertControllerStyleActionSheet - showFrom:controller - source:viewOrBarItem]; -} - -+ (UIAlertController *)makeAlert:(FLEXAlertBuilder)block { - return [self make:block withStyle:UIAlertControllerStyleAlert]; -} - -+ (UIAlertController *)makeSheet:(FLEXAlertBuilder)block { - return [self make:block withStyle:UIAlertControllerStyleActionSheet]; -} - -#pragma mark Configuration - -- (FLEXAlertStringProperty)title { - return ^FLEXAlert *(NSString *title) { - if (self._controller.title) { - self._controller.title = [self._controller.title stringByAppendingString:title ?: @""]; - } else { - self._controller.title = title; - } - return self; - }; -} - -- (FLEXAlertStringProperty)message { - return ^FLEXAlert *(NSString *message) { - if (self._controller.message) { - self._controller.message = [self._controller.message stringByAppendingString:message ?: @""]; - } else { - self._controller.message = message; - } - return self; - }; -} - -- (FLEXAlertAddAction)button { - return ^FLEXAlertAction *(NSString *title) { - FLEXAlertAction *action = FLEXAlertAction.new.title(title); - action._controller = self._controller; - [self._actions addObject:action]; - return action; - }; -} - -- (FLEXAlertStringArg)textField { - return ^FLEXAlert *(NSString *placeholder) { - [self._controller addTextFieldWithConfigurationHandler:^(UITextField *textField) { - textField.placeholder = placeholder; - }]; - - return self; - }; -} - -- (FLEXAlertTextField)configuredTextField { - return ^FLEXAlert *(void(^configurationHandler)(UITextField *)) { - [self._controller addTextFieldWithConfigurationHandler:configurationHandler]; - return self; - }; -} - -@end - -@implementation FLEXAlertAction - -- (FLEXAlertActionStringProperty)title { - return ^FLEXAlertAction *(NSString *title) { - FLEXAlertActionMutationAssertion(); - if (self._title) { - self._title = [self._title stringByAppendingString:title ?: @""]; - } else { - self._title = title; - } - return self; - }; -} - -- (FLEXAlertActionProperty)destructiveStyle { - return ^FLEXAlertAction *() { - FLEXAlertActionMutationAssertion(); - self._style = UIAlertActionStyleDestructive; - return self; - }; -} - -- (FLEXAlertActionProperty)cancelStyle { - return ^FLEXAlertAction *() { - FLEXAlertActionMutationAssertion(); - self._style = UIAlertActionStyleCancel; - return self; - }; -} - -- (FLEXAlertActionBOOLProperty)enabled { - return ^FLEXAlertAction *(BOOL enabled) { - FLEXAlertActionMutationAssertion(); - self._disable = !enabled; - return self; - }; -} - -- (FLEXAlertActionHandler)handler { - return ^FLEXAlertAction *(void(^handler)(NSArray *)) { - FLEXAlertActionMutationAssertion(); - - // Get weak reference to the alert to avoid block <--> alert retain cycle - UIAlertController *controller = self._controller; weakify(controller) - self._handler = ^(UIAlertAction *action) { strongify(controller) - // Strongify that reference and pass the text field strings to the handler - NSArray *strings = [controller.textFields valueForKeyPath:@"text"]; - handler(strings); - }; - - return self; - }; -} - -- (UIAlertAction *)action { - if (self._action) { - return self._action; - } - - self._action = [UIAlertAction - actionWithTitle:self._title - style:self._style - handler:self._handler - ]; - self._action.enabled = !self._disable; - - return self._action; -} - -@end diff --git a/Tweaks/FLEX/Utility/FLEXColor.h b/Tweaks/FLEX/Utility/FLEXColor.h deleted file mode 100644 index e472ba4..0000000 --- a/Tweaks/FLEX/Utility/FLEXColor.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// FLEXColor.h -// FLEX -// -// Created by Benny Wong on 6/18/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXColor : NSObject - -@property (readonly, class) UIColor *primaryBackgroundColor; -+ (UIColor *)primaryBackgroundColorWithAlpha:(CGFloat)alpha; - -@property (readonly, class) UIColor *secondaryBackgroundColor; -+ (UIColor *)secondaryBackgroundColorWithAlpha:(CGFloat)alpha; - -@property (readonly, class) UIColor *tertiaryBackgroundColor; -+ (UIColor *)tertiaryBackgroundColorWithAlpha:(CGFloat)alpha; - -@property (readonly, class) UIColor *groupedBackgroundColor; -+ (UIColor *)groupedBackgroundColorWithAlpha:(CGFloat)alpha; - -@property (readonly, class) UIColor *secondaryGroupedBackgroundColor; -+ (UIColor *)secondaryGroupedBackgroundColorWithAlpha:(CGFloat)alpha; - -// Text colors -@property (readonly, class) UIColor *primaryTextColor; -@property (readonly, class) UIColor *deemphasizedTextColor; - -// UI element colors -@property (readonly, class) UIColor *tintColor; -@property (readonly, class) UIColor *scrollViewBackgroundColor; -@property (readonly, class) UIColor *iconColor; -@property (readonly, class) UIColor *borderColor; -@property (readonly, class) UIColor *toolbarItemHighlightedColor; -@property (readonly, class) UIColor *toolbarItemSelectedColor; -@property (readonly, class) UIColor *hairlineColor; -@property (readonly, class) UIColor *destructiveColor; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/FLEXColor.m b/Tweaks/FLEX/Utility/FLEXColor.m deleted file mode 100644 index 95a995b..0000000 --- a/Tweaks/FLEX/Utility/FLEXColor.m +++ /dev/null @@ -1,136 +0,0 @@ -// -// FLEXColor.m -// FLEX -// -// Created by Benny Wong on 6/18/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXUtility.h" - -#define FLEXDynamicColor(dynamic, static) ({ \ - UIColor *c; \ - if (@available(iOS 13.0, *)) { \ - c = [UIColor dynamic]; \ - } else { \ - c = [UIColor static]; \ - } \ - c; \ -}); - -@implementation FLEXColor - -#pragma mark - Background Colors - -+ (UIColor *)primaryBackgroundColor { - return FLEXDynamicColor(systemBackgroundColor, whiteColor); -} - -+ (UIColor *)primaryBackgroundColorWithAlpha:(CGFloat)alpha { - return [[self primaryBackgroundColor] colorWithAlphaComponent:alpha]; -} - -+ (UIColor *)secondaryBackgroundColor { - return FLEXDynamicColor( - secondarySystemBackgroundColor, - colorWithHue:2.0/3.0 saturation:0.02 brightness:0.97 alpha:1 - ); -} - -+ (UIColor *)secondaryBackgroundColorWithAlpha:(CGFloat)alpha { - return [[self secondaryBackgroundColor] colorWithAlphaComponent:alpha]; -} - -+ (UIColor *)tertiaryBackgroundColor { - // All the background/fill colors are varying shades - // of white and black with really low alpha levels. - // We use systemGray4Color instead to avoid alpha issues. - return FLEXDynamicColor(systemGray4Color, lightGrayColor); -} - -+ (UIColor *)tertiaryBackgroundColorWithAlpha:(CGFloat)alpha { - return [[self tertiaryBackgroundColor] colorWithAlphaComponent:alpha]; -} - -+ (UIColor *)groupedBackgroundColor { - return FLEXDynamicColor( - systemGroupedBackgroundColor, - colorWithHue:2.0/3.0 saturation:0.02 brightness:0.97 alpha:1 - ); -} - -+ (UIColor *)groupedBackgroundColorWithAlpha:(CGFloat)alpha { - return [[self groupedBackgroundColor] colorWithAlphaComponent:alpha]; -} - -+ (UIColor *)secondaryGroupedBackgroundColor { - return FLEXDynamicColor(secondarySystemGroupedBackgroundColor, whiteColor); -} - -+ (UIColor *)secondaryGroupedBackgroundColorWithAlpha:(CGFloat)alpha { - return [[self secondaryGroupedBackgroundColor] colorWithAlphaComponent:alpha]; -} - -#pragma mark - Text colors - -+ (UIColor *)primaryTextColor { - return FLEXDynamicColor(labelColor, blackColor); -} - -+ (UIColor *)deemphasizedTextColor { - return FLEXDynamicColor(secondaryLabelColor, lightGrayColor); -} - -#pragma mark - UI Element Colors - -+ (UIColor *)tintColor { - #if FLEX_AT_LEAST_IOS13_SDK - if (@available(iOS 13.0, *)) { - return UIColor.systemBlueColor; - } else { - return UIApplication.sharedApplication.keyWindow.tintColor; - } - #else - return UIApplication.sharedApplication.keyWindow.tintColor; - #endif -} - -+ (UIColor *)scrollViewBackgroundColor { - return FLEXDynamicColor( - systemGroupedBackgroundColor, - colorWithHue:2.0/3.0 saturation:0.02 brightness:0.95 alpha:1 - ); -} - -+ (UIColor *)iconColor { - return FLEXDynamicColor(labelColor, blackColor); -} - -+ (UIColor *)borderColor { - return [self primaryBackgroundColor]; -} - -+ (UIColor *)toolbarItemHighlightedColor { - return FLEXDynamicColor( - quaternaryLabelColor, - colorWithHue:2.0/3.0 saturation:0.1 brightness:0.25 alpha:0.6 - ); -} - -+ (UIColor *)toolbarItemSelectedColor { - return FLEXDynamicColor( - secondaryLabelColor, - colorWithHue:2.0/3.0 saturation:0.1 brightness:0.25 alpha:0.68 - ); -} - -+ (UIColor *)hairlineColor { - return FLEXDynamicColor(systemGray3Color, colorWithWhite:0.75 alpha:1); -} - -+ (UIColor *)destructiveColor { - return FLEXDynamicColor(systemRedColor, redColor); -} - -@end diff --git a/Tweaks/FLEX/Utility/FLEXHeapEnumerator.h b/Tweaks/FLEX/Utility/FLEXHeapEnumerator.h deleted file mode 100644 index 5c1545b..0000000 --- a/Tweaks/FLEX/Utility/FLEXHeapEnumerator.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// FLEXHeapEnumerator.h -// Flipboard -// -// Created by Ryan Olson on 5/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -@class FLEXObjectRef; - -typedef void (^flex_object_enumeration_block_t)(__unsafe_unretained id object, __unsafe_unretained Class actualClass); - -@interface FLEXHeapEnumerator : NSObject - -+ (void)enumerateLiveObjectsUsingBlock:(flex_object_enumeration_block_t)block; - -/// Returned references are not validated beyond containing a valid isa. -/// To validate them yourself, pass each reference's object to \c FLEXPointerIsValidObjcObject -+ (NSArray *)instancesOfClassWithName:(NSString *)className retained:(BOOL)retain; -+ (NSArray *)subclassesOfClassWithName:(NSString *)className; -/// Returned references have been validated via \c FLEXPointerIsValidObjcObject -+ (NSArray *)objectsWithReferencesToObject:(id)object retained:(BOOL)retain; - -@end diff --git a/Tweaks/FLEX/Utility/FLEXHeapEnumerator.m b/Tweaks/FLEX/Utility/FLEXHeapEnumerator.m deleted file mode 100644 index 11d344b..0000000 --- a/Tweaks/FLEX/Utility/FLEXHeapEnumerator.m +++ /dev/null @@ -1,197 +0,0 @@ -// -// FLEXHeapEnumerator.m -// Flipboard -// -// Created by Ryan Olson on 5/28/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXHeapEnumerator.h" -#import "FLEXObjcInternal.h" -#import "FLEXObjectRef.h" -#import "NSObject+FLEX_Reflection.h" -#import "NSString+FLEX.h" -#import -#import -#import - -static CFMutableSetRef registeredClasses; - -// Mimics the objective-c object structure for checking if a range of memory is an object. -typedef struct { - Class isa; -} flex_maybe_object_t; - -@implementation FLEXHeapEnumerator - -static void range_callback(task_t task, void *context, unsigned type, vm_range_t *ranges, unsigned rangeCount) { - if (!context) { - return; - } - - for (unsigned int i = 0; i < rangeCount; i++) { - vm_range_t range = ranges[i]; - flex_maybe_object_t *tryObject = (flex_maybe_object_t *)range.address; - Class tryClass = NULL; -#ifdef __arm64__ - // See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html - extern uint64_t objc_debug_isa_class_mask WEAK_IMPORT_ATTRIBUTE; - tryClass = (__bridge Class)((void *)((uint64_t)tryObject->isa & objc_debug_isa_class_mask)); -#else - tryClass = tryObject->isa; -#endif - // If the class pointer matches one in our set of class pointers from the runtime, then we should have an object. - if (CFSetContainsValue(registeredClasses, (__bridge const void *)(tryClass))) { - (*(flex_object_enumeration_block_t __unsafe_unretained *)context)((__bridge id)tryObject, tryClass); - } - } -} - -static kern_return_t reader(__unused task_t remote_task, vm_address_t remote_address, __unused vm_size_t size, void **local_memory) { - *local_memory = (void *)remote_address; - return KERN_SUCCESS; -} - -+ (void)enumerateLiveObjectsUsingBlock:(flex_object_enumeration_block_t)block { - if (!block) { - return; - } - - // Refresh the class list on every call in case classes are added to the runtime. - [self updateRegisteredClasses]; - - // Inspired by: - // https://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final/examples/darwin/heap_find/heap/heap_find.cpp - // https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396 - - vm_address_t *zones = NULL; - unsigned int zoneCount = 0; - kern_return_t result = malloc_get_all_zones(TASK_NULL, reader, &zones, &zoneCount); - - if (result == KERN_SUCCESS) { - for (unsigned int i = 0; i < zoneCount; i++) { - malloc_zone_t *zone = (malloc_zone_t *)zones[i]; - malloc_introspection_t *introspection = zone->introspect; - - // This may explain why some zone functions are - // sometimes invalid; perhaps not all zones support them? - if (!introspection) { - continue; - } - - void (*lock_zone)(malloc_zone_t *zone) = introspection->force_lock; - void (*unlock_zone)(malloc_zone_t *zone) = introspection->force_unlock; - - // Callback has to unlock the zone so we freely allocate memory inside the given block - flex_object_enumeration_block_t callback = ^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) { - unlock_zone(zone); - block(object, actualClass); - lock_zone(zone); - }; - - BOOL lockZoneValid = FLEXPointerIsReadable(lock_zone); - BOOL unlockZoneValid = FLEXPointerIsReadable(unlock_zone); - - // There is little documentation on when and why - // any of these function pointers might be NULL - // or garbage, so we resort to checking for NULL - // and whether the pointer is readable - if (introspection->enumerator && lockZoneValid && unlockZoneValid) { - lock_zone(zone); - introspection->enumerator(TASK_NULL, (void *)&callback, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, reader, &range_callback); - unlock_zone(zone); - } - } - } -} - -+ (void)updateRegisteredClasses { - if (!registeredClasses) { - registeredClasses = CFSetCreateMutable(NULL, 0, NULL); - } else { - CFSetRemoveAllValues(registeredClasses); - } - unsigned int count = 0; - Class *classes = objc_copyClassList(&count); - for (unsigned int i = 0; i < count; i++) { - CFSetAddValue(registeredClasses, (__bridge const void *)(classes[i])); - } - free(classes); -} - -+ (NSArray *)instancesOfClassWithName:(NSString *)className retained:(BOOL)retain { - const char *classNameCString = className.UTF8String; - NSMutableArray *instances = [NSMutableArray new]; - [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, __unsafe_unretained Class actualClass) { - if (strcmp(classNameCString, class_getName(actualClass)) == 0) { - // Note: objects of certain classes crash when retain is called. - // It is up to the user to avoid tapping into instance lists for these classes. - // Ex. OS_dispatch_queue_specific_queue - // In the future, we could provide some kind of warning for classes that are known to be problematic. - if (malloc_size((__bridge const void *)(object)) > 0) { - [instances addObject:object]; - } - } - }]; - - NSArray *references = [FLEXObjectRef referencingAll:instances retained:retain]; - return references; -} - -+ (NSArray *)subclassesOfClassWithName:(NSString *)className { - NSArray *classes = FLEXGetAllSubclasses(NSClassFromString(className), NO); - NSArray *references = [FLEXObjectRef referencingClasses:classes]; - return references; -} - -+ (NSArray *)objectsWithReferencesToObject:(id)object retained:(BOOL)retain { - static Class SwiftObjectClass = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - SwiftObjectClass = NSClassFromString(@"SwiftObject"); - if (!SwiftObjectClass) { - SwiftObjectClass = NSClassFromString(@"Swift._SwiftObject"); - } - }); - - NSMutableArray *instances = [NSMutableArray new]; - [FLEXHeapEnumerator enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id tryObject, __unsafe_unretained Class actualClass) { - // Skip known-invalid objects - if (!FLEXPointerIsValidObjcObject((__bridge void *)tryObject)) { - return; - } - - // Get all the ivars on the object. Start with the class and and travel up the - // inheritance chain. Once we find a match, record it and move on to the next object. - // There's no reason to find multiple matches within the same object. - Class tryClass = actualClass; - while (tryClass) { - unsigned int ivarCount = 0; - Ivar *ivars = class_copyIvarList(tryClass, &ivarCount); - - for (unsigned int ivarIndex = 0; ivarIndex < ivarCount; ivarIndex++) { - Ivar ivar = ivars[ivarIndex]; - NSString *typeEncoding = @(ivar_getTypeEncoding(ivar) ?: ""); - - if (typeEncoding.flex_typeIsObjectOrClass) { - ptrdiff_t offset = ivar_getOffset(ivar); - uintptr_t *fieldPointer = (__bridge void *)tryObject + offset; - - if (*fieldPointer == (uintptr_t)(__bridge void *)object) { - NSString *ivarName = @(ivar_getName(ivar) ?: "???"); - id ref = [FLEXObjectRef referencing:tryObject ivar:ivarName retained:retain]; - [instances addObject:ref]; - return; - } - } - } - - free(ivars); - tryClass = class_getSuperclass(tryClass); - } - }]; - - return instances; -} - -@end diff --git a/Tweaks/FLEX/Utility/FLEXMacros.h b/Tweaks/FLEX/Utility/FLEXMacros.h deleted file mode 100644 index 373c9c5..0000000 --- a/Tweaks/FLEX/Utility/FLEXMacros.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// FLEXMacros.h -// FLEX -// -// Created by Tanner on 3/12/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#ifndef FLEXMacros_h -#define FLEXMacros_h - - -#define flex_keywordify class NSObject; -#define ctor flex_keywordify __attribute__((constructor)) void __flex_ctor_##__LINE__() -#define dtor flex_keywordify __attribute__((destructor)) void __flex_dtor_##__LINE__() - -#ifndef strongify - -#define weakify(var) __weak __typeof(var) __weak__##var = var; - -#define strongify(var) \ -_Pragma("clang diagnostic push") \ -_Pragma("clang diagnostic ignored \"-Wshadow\"") \ -__strong typeof(var) var = __weak__##var; \ -_Pragma("clang diagnostic pop") - -#endif - -// A macro to check if we are running in a test environment -#define FLEX_IS_TESTING() (NSClassFromString(@"XCTest") != nil) - -/// Whether we want the majority of constructors to run upon load or not. -extern BOOL FLEXConstructorsShouldRun(void); - -/// A macro to return from the current procedure if we don't want to run constructors -#define FLEX_EXIT_IF_NO_CTORS() if (!FLEXConstructorsShouldRun()) return; - -/// Rounds down to the nearest "point" coordinate -NS_INLINE CGFloat FLEXFloor(CGFloat x) { - return floor(UIScreen.mainScreen.scale * (x)) / UIScreen.mainScreen.scale; -} - -/// Returns the given number of points in pixels -NS_INLINE CGFloat FLEXPointsToPixels(CGFloat points) { - return points / UIScreen.mainScreen.scale; -} - -/// Creates a CGRect with all members rounded down to the nearest "point" coordinate -NS_INLINE CGRect FLEXRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height) { - return CGRectMake(FLEXFloor(x), FLEXFloor(y), FLEXFloor(width), FLEXFloor(height)); -} - -/// Adjusts the origin of an existing rect -NS_INLINE CGRect FLEXRectSetOrigin(CGRect r, CGPoint origin) { - r.origin = origin; return r; -} - -/// Adjusts the size of an existing rect -NS_INLINE CGRect FLEXRectSetSize(CGRect r, CGSize size) { - r.size = size; return r; -} - -/// Adjusts the origin.x of an existing rect -NS_INLINE CGRect FLEXRectSetX(CGRect r, CGFloat x) { - r.origin.x = x; return r; -} - -/// Adjusts the origin.y of an existing rect -NS_INLINE CGRect FLEXRectSetY(CGRect r, CGFloat y) { - r.origin.y = y ; return r; -} - -/// Adjusts the size.width of an existing rect -NS_INLINE CGRect FLEXRectSetWidth(CGRect r, CGFloat width) { - r.size.width = width; return r; -} - -/// Adjusts the size.height of an existing rect -NS_INLINE CGRect FLEXRectSetHeight(CGRect r, CGFloat height) { - r.size.height = height; return r; -} - -#define FLEXPluralString(count, plural, singular) [NSString \ - stringWithFormat:@"%@ %@", @(count), (count == 1 ? singular : plural) \ -] - -#define FLEXPluralFormatString(count, pluralFormat, singularFormat) [NSString \ - stringWithFormat:(count == 1 ? singularFormat : pluralFormat), @(count) \ -] - -#define flex_dispatch_after(nSeconds, onQueue, block) \ - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, \ - (int64_t)(nSeconds * NSEC_PER_SEC)), onQueue, block) - -#endif /* FLEXMacros_h */ diff --git a/Tweaks/FLEX/Utility/FLEXResources.h b/Tweaks/FLEX/Utility/FLEXResources.h deleted file mode 100644 index 563be1e..0000000 --- a/Tweaks/FLEX/Utility/FLEXResources.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// FLEXResources.h -// FLEX -// -// Created by Ryan Olson on 6/8/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXResources : NSObject - -#pragma mark - FLEX Toolbar Icons - -@property (readonly, class) UIImage *closeIcon; -@property (readonly, class) UIImage *dragHandle; -@property (readonly, class) UIImage *globalsIcon; -@property (readonly, class) UIImage *hierarchyIcon; -@property (readonly, class) UIImage *recentIcon; -@property (readonly, class) UIImage *moveIcon; -@property (readonly, class) UIImage *selectIcon; - -#pragma mark - Toolbar Icons - -@property (readonly, class) UIImage *bookmarksIcon; -@property (readonly, class) UIImage *openTabsIcon; -@property (readonly, class) UIImage *moreIcon; -@property (readonly, class) UIImage *gearIcon; -@property (readonly, class) UIImage *scrollToBottomIcon; - -#pragma mark - Content Type Icons - -@property (readonly, class) UIImage *jsonIcon; -@property (readonly, class) UIImage *textPlainIcon; -@property (readonly, class) UIImage *htmlIcon; -@property (readonly, class) UIImage *audioIcon; -@property (readonly, class) UIImage *jsIcon; -@property (readonly, class) UIImage *plistIcon; -@property (readonly, class) UIImage *textIcon; -@property (readonly, class) UIImage *videoIcon; -@property (readonly, class) UIImage *xmlIcon; -@property (readonly, class) UIImage *binaryIcon; - -#pragma mark - 3D Explorer Icons - -@property (readonly, class) UIImage *toggle2DIcon; -@property (readonly, class) UIImage *toggle3DIcon; -@property (readonly, class) UIImage *rangeSliderLeftHandle; -@property (readonly, class) UIImage *rangeSliderRightHandle; -@property (readonly, class) UIImage *rangeSliderTrack; -@property (readonly, class) UIImage *rangeSliderFill; - -#pragma mark - Misc Icons - -@property (readonly, class) UIImage *checkerPattern; -@property (readonly, class) UIColor *checkerPatternColor; -@property (readonly, class) UIImage *hierarchyIndentPattern; - -@end diff --git a/Tweaks/FLEX/Utility/FLEXResources.m b/Tweaks/FLEX/Utility/FLEXResources.m deleted file mode 100644 index c90466e..0000000 --- a/Tweaks/FLEX/Utility/FLEXResources.m +++ /dev/null @@ -1,8861 +0,0 @@ -// -// FLEXResources.m -// FLEX -// -// Created by Ryan Olson on 6/8/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXResources.h" - -// Useful regex for formatting pasted hex -// -// To replace something with a newline, you need to manually copy -// a newline from a text editor and paste it into the replace box. -// For the "find" box, you can simply copy and paste the regexes below. -// -// Split into rows of 16: -// ((?:0x[a-f\d][a-f\d], ){16}) -// Replace with: \n $1 -// -// Split last greater-than-16 row into two rows of 16 and less than 16: -// ((?:0x[a-f\d][a-f\d], ){16})((?:0x[a-f\d][a-f\d](?:, )?)+) -// Replace with: $1\n $2 -// -// Trim trailing spaces: -// , \n -// Replace with: ,\n -// -// Trim trailing newline after hex: -// \n\n\} -// Replace with: \n} - -// The 1x icons are unused now since some new icons don't have a 1x version at all -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused" - - -#pragma mark - FLEX Toolbar Icons - -static const u_int8_t FLEXCloseIcon[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x30, 0xae, - 0xa2, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0xca, 0x41, 0x37, 0x05, 0x00, 0x00, - 0x01, 0xd2, 0x49, 0x44, 0x41, 0x54, 0x48, 0x0d, 0xad, 0x96, 0x3b, 0x4e, 0xc3, 0x40, 0x10, 0x86, - 0xe3, 0x08, 0x51, 0x84, 0x0a, 0x24, 0x1e, 0xa2, 0x41, 0xa2, 0x41, 0x9c, 0x82, 0x82, 0x82, 0x23, - 0x20, 0x1a, 0xe0, 0x0c, 0xb4, 0x3c, 0x7c, 0x85, 0x9c, 0x80, 0x0b, 0xa4, 0x04, 0x51, 0x12, 0xe0, - 0x04, 0x08, 0xf1, 0xa8, 0x29, 0x10, 0x52, 0x3a, 0x1a, 0x40, 0xe2, 0x61, 0xbe, 0x89, 0x32, 0x96, - 0x33, 0xac, 0x37, 0xf6, 0x7a, 0x47, 0xfa, 0xb5, 0x8f, 0xf1, 0xfc, 0xdf, 0xec, 0x26, 0x8a, 0xd3, - 0x6a, 0x8d, 0x22, 0xcb, 0xb2, 0x79, 0xd4, 0xd6, 0x75, 0xec, 0x11, 0xef, 0x69, 0x34, 0x9b, 0xfb, - 0xb2, 0x48, 0x50, 0x0f, 0x7d, 0xa3, 0x67, 0xb4, 0x93, 0x27, 0x23, 0x4d, 0xf0, 0x3c, 0x40, 0x03, - 0xf4, 0x89, 0xba, 0x43, 0x5b, 0x26, 0x9b, 0xa8, 0x18, 0x3f, 0x2c, 0xf6, 0x23, 0x31, 0x5b, 0x78, - 0xa5, 0x45, 0xf3, 0xd1, 0x7c, 0x4d, 0x12, 0x5b, 0x8e, 0x44, 0x14, 0x38, 0xbe, 0xa9, 0xc3, 0x5b, - 0xb6, 0xd6, 0x05, 0xdc, 0x46, 0xb7, 0xb2, 0x32, 0xd1, 0x08, 0x8e, 0xd7, 0x89, 0xf1, 0xd3, 0xe5, - 0x79, 0x7e, 0x9b, 0xec, 0x2c, 0xa0, 0x7b, 0xcd, 0x14, 0xc6, 0x20, 0x38, 0xf5, 0x65, 0xd0, 0x6b, - 0x72, 0x33, 0x39, 0x58, 0x26, 0x6c, 0x44, 0x81, 0xe3, 0x73, 0x8c, 0x5c, 0xf1, 0x1f, 0xaa, 0x1d, - 0xf0, 0x74, 0x23, 0x38, 0xf5, 0x65, 0xd0, 0x2b, 0x72, 0xe3, 0x27, 0x55, 0xa8, 0x8e, 0xa1, 0x70, - 0xea, 0x8e, 0x90, 0x2b, 0x26, 0x43, 0x43, 0xe1, 0xd0, 0x9a, 0x43, 0xeb, 0xc2, 0x81, 0x1e, 0xba, - 0x8e, 0xc9, 0x5e, 0x1f, 0xf9, 0xaf, 0x57, 0x61, 0x76, 0xa4, 0xd0, 0xfb, 0x99, 0x93, 0xf7, 0x41, - 0x3b, 0xd6, 0xaf, 0xd6, 0xda, 0x03, 0xff, 0x25, 0xe7, 0x8a, 0x3e, 0x9b, 0xcd, 0xa0, 0xda, 0x21, - 0x46, 0x65, 0x27, 0xb7, 0xe0, 0xcb, 0x68, 0xd0, 0x1a, 0xf0, 0x5a, 0xd0, 0xca, 0xaf, 0xc1, 0x24, - 0x49, 0x06, 0x34, 0x71, 0xa1, 0x8d, 0x38, 0xc6, 0x1e, 0xcf, 0xbc, 0x3b, 0xf6, 0x9b, 0x6d, 0x71, - 0x85, 0xa9, 0xbd, 0x57, 0xb3, 0x0e, 0xfa, 0x79, 0xf5, 0x76, 0x55, 0x01, 0xaa, 0x3d, 0xc4, 0x83, - 0x7b, 0xa0, 0x37, 0xe4, 0xa2, 0xbd, 0x58, 0xc6, 0x4e, 0xee, 0x81, 0x0e, 0x7f, 0xf0, 0xc9, 0x97, - 0x7d, 0xdb, 0xc3, 0x4f, 0x3e, 0x09, 0xaa, 0x1d, 0x46, 0x85, 0x57, 0x85, 0x1a, 0xf8, 0x03, 0x75, - 0x36, 0xaa, 0x9f, 0x9c, 0xca, 0xd4, 0x56, 0x8f, 0xd6, 0xe5, 0xef, 0x53, 0x3a, 0xe0, 0x19, 0xb9, - 0xf6, 0x30, 0x38, 0x85, 0x29, 0x72, 0x85, 0x17, 0x5a, 0x38, 0xf9, 0x22, 0xc5, 0xf5, 0xe0, 0x14, - 0xa4, 0x2e, 0x22, 0x7b, 0x95, 0xa0, 0x41, 0x70, 0xcc, 0xab, 0xff, 0x47, 0x52, 0x82, 0x67, 0xc4, - 0x4f, 0x4e, 0xfe, 0x88, 0x6c, 0xc8, 0x67, 0xbe, 0x3b, 0x2c, 0x65, 0xb2, 0x82, 0x64, 0xc3, 0x46, - 0xad, 0x93, 0xda, 0x3e, 0x30, 0x2b, 0x83, 0xbf, 0x91, 0xeb, 0xc8, 0x97, 0x62, 0x0f, 0xd9, 0x68, - 0x04, 0xd5, 0x26, 0x30, 0x5d, 0x42, 0xae, 0x93, 0x6f, 0x08, 0x78, 0x0e, 0x7d, 0x20, 0x8d, 0x28, - 0x50, 0x03, 0x7f, 0x52, 0x73, 0xc6, 0x17, 0x34, 0x95, 0xc8, 0x03, 0x4c, 0x56, 0x19, 0xe4, 0xee, - 0xef, 0xd0, 0x19, 0x6f, 0x99, 0x2f, 0xc6, 0x68, 0x81, 0xbf, 0xfc, 0x31, 0xd8, 0x46, 0xcb, 0xe8, - 0x14, 0xff, 0xd7, 0x3f, 0x44, 0x89, 0xd3, 0x05, 0x85, 0xe7, 0xc6, 0x3e, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXCloseIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x30, 0xae, - 0xa2, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0xca, 0x41, 0x37, 0x05, 0x00, 0x00, - 0x01, 0xd2, 0x49, 0x44, 0x41, 0x54, 0x48, 0x0d, 0xad, 0x96, 0x3b, 0x4e, 0xc3, 0x40, 0x10, 0x86, - 0xe3, 0x08, 0x51, 0x84, 0x0a, 0x24, 0x1e, 0xa2, 0x41, 0xa2, 0x41, 0x9c, 0x82, 0x82, 0x82, 0x23, - 0x20, 0x1a, 0xe0, 0x0c, 0xb4, 0x3c, 0x7c, 0x85, 0x9c, 0x80, 0x0b, 0xa4, 0x04, 0x51, 0x12, 0xe0, - 0x04, 0x08, 0xf1, 0xa8, 0x29, 0x10, 0x52, 0x3a, 0x1a, 0x40, 0xe2, 0x61, 0xbe, 0x89, 0x32, 0x96, - 0x33, 0xac, 0x37, 0xf6, 0x7a, 0x47, 0xfa, 0xb5, 0x8f, 0xf1, 0xfc, 0xdf, 0xec, 0x26, 0x8a, 0xd3, - 0x6a, 0x8d, 0x22, 0xcb, 0xb2, 0x79, 0xd4, 0xd6, 0x75, 0xec, 0x11, 0xef, 0x69, 0x34, 0x9b, 0xfb, - 0xb2, 0x48, 0x50, 0x0f, 0x7d, 0xa3, 0x67, 0xb4, 0x93, 0x27, 0x23, 0x4d, 0xf0, 0x3c, 0x40, 0x03, - 0xf4, 0x89, 0xba, 0x43, 0x5b, 0x26, 0x9b, 0xa8, 0x18, 0x3f, 0x2c, 0xf6, 0x23, 0x31, 0x5b, 0x78, - 0xa5, 0x45, 0xf3, 0xd1, 0x7c, 0x4d, 0x12, 0x5b, 0x8e, 0x44, 0x14, 0x38, 0xbe, 0xa9, 0xc3, 0x5b, - 0xb6, 0xd6, 0x05, 0xdc, 0x46, 0xb7, 0xb2, 0x32, 0xd1, 0x08, 0x8e, 0xd7, 0x89, 0xf1, 0xd3, 0xe5, - 0x79, 0x7e, 0x9b, 0xec, 0x2c, 0xa0, 0x7b, 0xcd, 0x14, 0xc6, 0x20, 0x38, 0xf5, 0x65, 0xd0, 0x6b, - 0x72, 0x33, 0x39, 0x58, 0x26, 0x6c, 0x44, 0x81, 0xe3, 0x73, 0x8c, 0x5c, 0xf1, 0x1f, 0xaa, 0x1d, - 0xf0, 0x74, 0x23, 0x38, 0xf5, 0x65, 0xd0, 0x2b, 0x72, 0xe3, 0x27, 0x55, 0xa8, 0x8e, 0xa1, 0x70, - 0xea, 0x8e, 0x90, 0x2b, 0x26, 0x43, 0x43, 0xe1, 0xd0, 0x9a, 0x43, 0xeb, 0xc2, 0x81, 0x1e, 0xba, - 0x8e, 0xc9, 0x5e, 0x1f, 0xf9, 0xaf, 0x57, 0x61, 0x76, 0xa4, 0xd0, 0xfb, 0x99, 0x93, 0xf7, 0x41, - 0x3b, 0xd6, 0xaf, 0xd6, 0xda, 0x03, 0xff, 0x25, 0xe7, 0x8a, 0x3e, 0x9b, 0xcd, 0xa0, 0xda, 0x21, - 0x46, 0x65, 0x27, 0xb7, 0xe0, 0xcb, 0x68, 0xd0, 0x1a, 0xf0, 0x5a, 0xd0, 0xca, 0xaf, 0xc1, 0x24, - 0x49, 0x06, 0x34, 0x71, 0xa1, 0x8d, 0x38, 0xc6, 0x1e, 0xcf, 0xbc, 0x3b, 0xf6, 0x9b, 0x6d, 0x71, - 0x85, 0xa9, 0xbd, 0x57, 0xb3, 0x0e, 0xfa, 0x79, 0xf5, 0x76, 0x55, 0x01, 0xaa, 0x3d, 0xc4, 0x83, - 0x7b, 0xa0, 0x37, 0xe4, 0xa2, 0xbd, 0x58, 0xc6, 0x4e, 0xee, 0x81, 0x0e, 0x7f, 0xf0, 0xc9, 0x97, - 0x7d, 0xdb, 0xc3, 0x4f, 0x3e, 0x09, 0xaa, 0x1d, 0x46, 0x85, 0x57, 0x85, 0x1a, 0xf8, 0x03, 0x75, - 0x36, 0xaa, 0x9f, 0x9c, 0xca, 0xd4, 0x56, 0x8f, 0xd6, 0xe5, 0xef, 0x53, 0x3a, 0xe0, 0x19, 0xb9, - 0xf6, 0x30, 0x38, 0x85, 0x29, 0x72, 0x85, 0x17, 0x5a, 0x38, 0xf9, 0x22, 0xc5, 0xf5, 0xe0, 0x14, - 0xa4, 0x2e, 0x22, 0x7b, 0x95, 0xa0, 0x41, 0x70, 0xcc, 0xab, 0xff, 0x47, 0x52, 0x82, 0x67, 0xc4, - 0x4f, 0x4e, 0xfe, 0x88, 0x6c, 0xc8, 0x67, 0xbe, 0x3b, 0x2c, 0x65, 0xb2, 0x82, 0x64, 0xc3, 0x46, - 0xad, 0x93, 0xda, 0x3e, 0x30, 0x2b, 0x83, 0xbf, 0x91, 0xeb, 0xc8, 0x97, 0x62, 0x0f, 0xd9, 0x68, - 0x04, 0xd5, 0x26, 0x30, 0x5d, 0x42, 0xae, 0x93, 0x6f, 0x08, 0x78, 0x0e, 0x7d, 0x20, 0x8d, 0x28, - 0x50, 0x03, 0x7f, 0x52, 0x73, 0xc6, 0x17, 0x34, 0x95, 0xc8, 0x03, 0x4c, 0x56, 0x19, 0xe4, 0xee, - 0xef, 0xd0, 0x19, 0x6f, 0x99, 0x2f, 0xc6, 0x68, 0x81, 0xbf, 0xfc, 0x31, 0xd8, 0x46, 0xcb, 0xe8, - 0x14, 0xff, 0xd7, 0x3f, 0x44, 0x89, 0xd3, 0x05, 0x85, 0xe7, 0xc6, 0x3e, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXCloseIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2d, 0x08, 0x06, 0x00, 0x00, 0x00, 0x3a, 0x1a, 0xe2, - 0x9a, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2d, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa8, 0x05, 0x50, 0x00, 0x00, - 0x02, 0xc0, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xd5, 0x99, 0xbf, 0x6b, 0x14, 0x41, 0x14, 0x80, - 0x6f, 0x4f, 0x0b, 0x83, 0x20, 0xb6, 0x42, 0xe2, 0xd8, 0x08, 0xe9, 0x2c, 0x15, 0xec, 0x2c, 0xb5, - 0x14, 0xff, 0x0a, 0xc1, 0xf8, 0x23, 0x88, 0x65, 0x2a, 0x3b, 0x3b, 0x5b, 0xe3, 0xaf, 0xc2, 0x4a, - 0x4b, 0x41, 0x50, 0x50, 0xac, 0xec, 0x45, 0x2c, 0x34, 0x03, 0x56, 0xc1, 0xd6, 0x42, 0x82, 0x9a, - 0xcb, 0x37, 0x61, 0xdf, 0xb2, 0xb7, 0x77, 0xb3, 0x6f, 0x76, 0x77, 0x66, 0x16, 0x1f, 0x7c, 0x79, - 0xbb, 0xfb, 0x66, 0xe6, 0x7d, 0x3b, 0xec, 0x91, 0x5c, 0x76, 0x32, 0xf9, 0x9f, 0x63, 0x36, 0x9b, - 0x5d, 0x83, 0x57, 0xf0, 0x1a, 0x36, 0xe0, 0xe8, 0x98, 0xf7, 0x43, 0xff, 0x13, 0x70, 0x1f, 0xde, - 0xc2, 0x73, 0x38, 0x3f, 0xe7, 0xc3, 0x85, 0x7b, 0xd0, 0x8c, 0xf7, 0x5c, 0x38, 0x3e, 0x37, 0x30, - 0xd3, 0x09, 0x7d, 0xcf, 0xc0, 0x4e, 0x43, 0xe8, 0x1f, 0xe7, 0x97, 0x0f, 0x15, 0x38, 0x38, 0x06, - 0xbf, 0x1b, 0x03, 0xe4, 0xf4, 0x03, 0x07, 0x59, 0xc5, 0xe9, 0x67, 0xc0, 0xc2, 0xb2, 0xf8, 0x2c, - 0xd2, 0xeb, 0xcb, 0xaa, 0xb5, 0x6b, 0xd9, 0xc4, 0xe9, 0x69, 0xc0, 0x82, 0x2f, 0xfe, 0x50, 0x98, - 0x4e, 0xf8, 0xb1, 0x02, 0x7b, 0xbe, 0x51, 0xe5, 0xf5, 0xe4, 0xe2, 0xf4, 0x31, 0x60, 0xa1, 0x2d, - 0xbe, 0x56, 0x4f, 0x28, 0xa3, 0xb6, 0xda, 0x46, 0x96, 0xb5, 0x64, 0xe2, 0xac, 0x6f, 0xa0, 0xf9, - 0x0c, 0x97, 0x6d, 0xe7, 0xd2, 0xd5, 0xba, 0xf4, 0x94, 0xd2, 0xa3, 0xb9, 0xf2, 0xf2, 0x93, 0xe8, - 0xe2, 0xb4, 0x39, 0x0d, 0x21, 0xc2, 0x9b, 0x95, 0xb0, 0x1c, 0x30, 0x31, 0xbb, 0x78, 0x07, 0xe1, - 0x3b, 0xe2, 0xb9, 0x90, 0x73, 0x8a, 0x47, 0x11, 0x96, 0x3b, 0xc8, 0x21, 0x5e, 0x0a, 0x7f, 0x27, - 0x6b, 0xe1, 0xdf, 0x61, 0x11, 0x96, 0xcc, 0x4a, 0xc9, 0x1e, 0x15, 0xd6, 0x5e, 0x83, 0x10, 0xe1, - 0xdb, 0xe2, 0x13, 0x9c, 0x53, 0x88, 0x27, 0x15, 0x96, 0x3b, 0x8b, 0x29, 0xde, 0x41, 0xf8, 0x96, - 0xf4, 0xef, 0x9d, 0x63, 0x88, 0x97, 0xc2, 0xdf, 0xc8, 0x5a, 0x0c, 0x17, 0x96, 0x3b, 0xa5, 0x53, - 0xef, 0x67, 0x9c, 0xb9, 0xab, 0x10, 0x22, 0x7c, 0x53, 0xfa, 0x45, 0xcb, 0x7d, 0xc4, 0x47, 0x15, - 0x96, 0x3b, 0xef, 0x28, 0xee, 0xfe, 0x10, 0x1b, 0x67, 0x87, 0x45, 0x58, 0x72, 0x07, 0xf1, 0xbf, - 0x8c, 0xd5, 0x62, 0x43, 0xd6, 0x4d, 0x9e, 0x31, 0x09, 0x7d, 0xc6, 0xdb, 0xa4, 0xf3, 0x09, 0xcb, - 0x8e, 0x94, 0xe2, 0xdb, 0x6d, 0x56, 0x2d, 0xb5, 0x1b, 0xb2, 0x4e, 0xf6, 0xdc, 0x53, 0x7c, 0x3c, - 0x61, 0xd9, 0xa1, 0x52, 0xfc, 0x45, 0xcb, 0xae, 0xd6, 0x4b, 0x77, 0x65, 0xde, 0x90, 0x3c, 0x1d, - 0x32, 0xb9, 0x9c, 0xbb, 0x46, 0xbe, 0x10, 0xb8, 0xce, 0x15, 0xee, 0x20, 0xeb, 0x77, 0xce, 0x05, - 0x2f, 0x04, 0x0c, 0x58, 0xe8, 0x12, 0xd1, 0xbf, 0x48, 0x2c, 0x88, 0xf9, 0x2e, 0x60, 0x69, 0xc0, - 0x42, 0x9f, 0xc8, 0x2f, 0x8e, 0xa5, 0x01, 0x0b, 0x43, 0x22, 0x9f, 0x38, 0x96, 0x06, 0x2c, 0x68, - 0xf1, 0x49, 0x1b, 0x40, 0x3d, 0xbd, 0x38, 0x4d, 0x0c, 0x58, 0xd0, 0x62, 0x93, 0x01, 0xa1, 0xbf, - 0x80, 0xd2, 0x89, 0x23, 0x61, 0xc0, 0x82, 0x16, 0xd5, 0xb7, 0x66, 0x06, 0x3a, 0xf1, 0x6d, 0x6d, - 0x02, 0xf5, 0xf8, 0xe2, 0x2c, 0x6a, 0xc0, 0x82, 0x16, 0x95, 0xb0, 0x7c, 0x80, 0x99, 0x90, 0x5f, - 0x9c, 0xa6, 0x06, 0x2c, 0x68, 0xb1, 0x20, 0xdc, 0x10, 0x7f, 0xac, 0x2d, 0x40, 0x7d, 0xf8, 0x8e, - 0xb3, 0x88, 0x01, 0x0b, 0x5a, 0x78, 0x85, 0xb3, 0x8a, 0x63, 0x69, 0xc0, 0x82, 0x16, 0xaa, 0x70, - 0x16, 0x71, 0x2c, 0x0d, 0x58, 0xd0, 0x22, 0x58, 0xb8, 0x21, 0xfe, 0x44, 0x5b, 0x98, 0x7a, 0xf8, - 0xa3, 0xc2, 0x60, 0x03, 0x16, 0xb4, 0xe8, 0x2c, 0x9c, 0x44, 0x1c, 0x4b, 0x03, 0x16, 0xb4, 0xe8, - 0x2d, 0xdc, 0x10, 0x7f, 0xaa, 0x35, 0xa2, 0xee, 0xdf, 0x71, 0x8a, 0x06, 0x2c, 0x68, 0x31, 0x58, - 0x38, 0x8a, 0x38, 0x96, 0xee, 0x5f, 0x55, 0x56, 0xb3, 0xa5, 0x1e, 0x4d, 0xb8, 0x21, 0xfe, 0x2c, - 0xa0, 0xb7, 0xdb, 0xf1, 0x15, 0x99, 0xe7, 0xde, 0x06, 0xbc, 0x0b, 0x98, 0x14, 0x5d, 0x58, 0x04, - 0xe8, 0xed, 0x7e, 0x01, 0x85, 0x88, 0x3f, 0x38, 0x9c, 0xc3, 0xe0, 0x53, 0x63, 0x0a, 0x77, 0x14, - 0xff, 0x29, 0xd2, 0x67, 0x15, 0xe9, 0x64, 0x3b, 0x2c, 0xc2, 0x92, 0xf1, 0x70, 0x3b, 0xee, 0xde, - 0x19, 0xfa, 0xe2, 0x17, 0x85, 0xc2, 0x3d, 0x1a, 0x6e, 0xe0, 0x8e, 0x67, 0x54, 0x36, 0xe1, 0x9a, - 0xf8, 0x11, 0x5c, 0x7c, 0xe2, 0x2f, 0x65, 0x9c, 0x13, 0xbf, 0x08, 0xbb, 0x35, 0x71, 0xf7, 0x5e, - 0xf1, 0x7a, 0x35, 0x20, 0xf3, 0x01, 0xbd, 0x9d, 0xf8, 0x43, 0xd8, 0x07, 0x89, 0x2f, 0x1c, 0xac, - 0x3a, 0x95, 0x42, 0x7c, 0xb8, 0x70, 0x92, 0xe3, 0x4b, 0xe0, 0x3e, 0xa1, 0x1f, 0x8b, 0xa2, 0xf8, - 0x21, 0xb5, 0xb1, 0x32, 0x4e, 0xe7, 0xe8, 0xed, 0x5e, 0x2f, 0xef, 0xc2, 0x1b, 0x9c, 0xf6, 0x9c, - 0xcb, 0x01, 0x48, 0xaa, 0xb6, 0x3e, 0x0f, 0xf9, 0xdb, 0x52, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXDragHandle[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x14, 0x08, 0x06, 0x00, 0x00, 0x01, 0x6d, 0xdf, 0x8a, - 0x41, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x50, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x00, 0xbf, 0x5b, 0x90, 0xfc, 0x00, 0x00, 0x00, 0x95, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, - 0x96, 0x51, 0x12, 0x00, 0x11, 0x08, 0x86, 0x73, 0xff, 0xeb, 0xac, 0xf3, 0xd9, 0xf6, 0xa1, 0x17, - 0x9b, 0xc9, 0x43, 0x46, 0xf4, 0x1b, 0xc6, 0x20, 0x93, 0x3e, 0x45, 0x85, 0x94, 0xd2, 0x88, 0xb8, - 0xae, 0x2e, 0xa5, 0x57, 0xa0, 0xa9, 0x65, 0xa1, 0x9f, 0x5c, 0xbf, 0x2f, 0xe5, 0x98, 0x61, 0xd5, - 0x0f, 0x98, 0xd5, 0x52, 0xc2, 0x81, 0xd1, 0x37, 0x13, 0x98, 0x75, 0x7d, 0x2b, 0x34, 0x64, 0xfd, - 0x66, 0x56, 0xba, 0x6d, 0xe1, 0x09, 0xca, 0xd5, 0x38, 0xf5, 0x55, 0xc7, 0x80, 0x59, 0x10, 0x38, - 0x98, 0x80, 0x53, 0x70, 0x48, 0x0a, 0xf1, 0x1c, 0x8c, 0x02, 0x47, 0xdf, 0x44, 0xc0, 0xd9, 0x07, - 0x63, 0x3e, 0xd4, 0x6c, 0xe4, 0x54, 0xae, 0xed, 0x0c, 0x43, 0x02, 0xd3, 0xea, 0x11, 0xb8, 0x9b, - 0x9c, 0x1f, 0x6a, 0x41, 0x20, 0x0b, 0x81, 0xe0, 0x6f, 0x60, 0xcc, 0x8f, 0x23, 0x8b, 0x73, 0xc0, - 0x4e, 0x10, 0x00, 0x01, 0x10, 0xb0, 0x08, 0x04, 0xff, 0x44, 0x86, 0x89, 0xf4, 0x0b, 0xbf, 0x81, - 0xca, 0xc9, 0x10, 0xe6, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, - 0x60, 0x82 -}; - -static const u_int8_t FLEXDragHandle2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x14, 0x08, 0x06, 0x00, 0x00, 0x01, 0x6d, 0xdf, 0x8a, - 0x41, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x50, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x00, 0xbf, 0x5b, 0x90, 0xfc, 0x00, 0x00, 0x00, 0x95, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, - 0x96, 0x51, 0x12, 0x00, 0x11, 0x08, 0x86, 0x73, 0xff, 0xeb, 0xac, 0xf3, 0xd9, 0xf6, 0xa1, 0x17, - 0x9b, 0xc9, 0x43, 0x46, 0xf4, 0x1b, 0xc6, 0x20, 0x93, 0x3e, 0x45, 0x85, 0x94, 0xd2, 0x88, 0xb8, - 0xae, 0x2e, 0xa5, 0x57, 0xa0, 0xa9, 0x65, 0xa1, 0x9f, 0x5c, 0xbf, 0x2f, 0xe5, 0x98, 0x61, 0xd5, - 0x0f, 0x98, 0xd5, 0x52, 0xc2, 0x81, 0xd1, 0x37, 0x13, 0x98, 0x75, 0x7d, 0x2b, 0x34, 0x64, 0xfd, - 0x66, 0x56, 0xba, 0x6d, 0xe1, 0x09, 0xca, 0xd5, 0x38, 0xf5, 0x55, 0xc7, 0x80, 0x59, 0x10, 0x38, - 0x98, 0x80, 0x53, 0x70, 0x48, 0x0a, 0xf1, 0x1c, 0x8c, 0x02, 0x47, 0xdf, 0x44, 0xc0, 0xd9, 0x07, - 0x63, 0x3e, 0xd4, 0x6c, 0xe4, 0x54, 0xae, 0xed, 0x0c, 0x43, 0x02, 0xd3, 0xea, 0x11, 0xb8, 0x9b, - 0x9c, 0x1f, 0x6a, 0x41, 0x20, 0x0b, 0x81, 0xe0, 0x6f, 0x60, 0xcc, 0x8f, 0x23, 0x8b, 0x73, 0xc0, - 0x4e, 0x10, 0x00, 0x01, 0x10, 0xb0, 0x08, 0x04, 0xff, 0x44, 0x86, 0x89, 0xf4, 0x0b, 0xbf, 0x81, - 0xca, 0xc9, 0x10, 0xe6, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, - 0x60, 0x82 -}; - -static const u_int8_t FLEXDragHandle3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x1e, 0x08, 0x06, 0x00, 0x00, 0x01, 0x9d, 0xd0, 0x9a, - 0x44, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x7e, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x00, 0x9a, 0x6c, 0x42, 0x31, 0x00, 0x00, 0x01, 0x8f, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, - 0x9a, 0x4d, 0x4e, 0xc3, 0x30, 0x10, 0x46, 0x5d, 0x84, 0xca, 0x06, 0x4e, 0x01, 0xbd, 0x0b, 0x27, - 0x60, 0xc7, 0x41, 0xd8, 0x65, 0xc3, 0x49, 0xd8, 0x71, 0x25, 0xe8, 0x29, 0xca, 0xa6, 0x2b, 0xf8, - 0xbc, 0xa8, 0xd4, 0x4a, 0x1e, 0xb7, 0x8c, 0xd3, 0xb1, 0x62, 0x3d, 0x2b, 0x51, 0x5a, 0x3b, 0xdf, - 0xfc, 0x3c, 0x3b, 0x71, 0x9a, 0x7a, 0x95, 0x2a, 0xe5, 0x37, 0x25, 0x6d, 0xe5, 0xb2, 0x4a, 0x49, - 0xdb, 0x0c, 0xa5, 0x6a, 0x45, 0xee, 0x27, 0xcb, 0x87, 0x84, 0x66, 0x9b, 0xa5, 0x29, 0xd6, 0x9b, - 0x11, 0xc8, 0xfb, 0x5e, 0x8a, 0x75, 0x51, 0xa5, 0x4a, 0x09, 0x4d, 0xad, 0xa5, 0x29, 0xd6, 0x9b, - 0x56, 0x14, 0xc1, 0x9b, 0x14, 0x77, 0x45, 0x95, 0x2a, 0x25, 0x9c, 0xac, 0x36, 0xea, 0x97, 0x45, - 0xc0, 0x1c, 0x04, 0xb5, 0x34, 0x34, 0x40, 0xb4, 0xf9, 0x8a, 0x1c, 0xba, 0x7c, 0x9e, 0x78, 0xcb, - 0x01, 0x38, 0xf7, 0xf7, 0x13, 0x43, 0x7c, 0xe9, 0x41, 0xc0, 0x35, 0x00, 0xd4, 0xdf, 0x93, 0x33, - 0xd8, 0x0f, 0x39, 0xdc, 0x3a, 0xb5, 0x03, 0xc9, 0xbc, 0xd8, 0xbd, 0xd7, 0xfa, 0x8f, 0x1c, 0x3e, - 0x84, 0xf3, 0x53, 0xb4, 0x7b, 0xe7, 0xbd, 0xc1, 0x7b, 0x4f, 0xc9, 0x3a, 0xee, 0x2b, 0xe1, 0x3d, - 0xbd, 0x04, 0x87, 0xae, 0x6b, 0xce, 0x93, 0x58, 0x1e, 0xf2, 0x1e, 0x5d, 0xa3, 0xe6, 0x5b, 0x09, - 0x6e, 0x1a, 0x6d, 0x20, 0x87, 0x00, 0x04, 0xfe, 0x49, 0x20, 0x4f, 0x39, 0xf9, 0x9a, 0x0f, 0xde, - 0xf3, 0x4f, 0xd3, 0x6a, 0xb9, 0xa9, 0xb6, 0xd2, 0x08, 0x01, 0x08, 0x40, 0x00, 0x02, 0x63, 0x10, - 0x08, 0x79, 0xbc, 0xd5, 0x14, 0xf7, 0x25, 0x5c, 0x4f, 0xd1, 0xc8, 0x94, 0x5c, 0x35, 0xbf, 0xdb, - 0xa0, 0x80, 0x9e, 0xe5, 0xe7, 0x35, 0xc8, 0xd7, 0xc1, 0xcd, 0xd9, 0x79, 0xfe, 0x70, 0x22, 0x47, - 0x08, 0x40, 0x00, 0x02, 0xc3, 0x13, 0xa8, 0x4e, 0x05, 0x73, 0x65, 0xaf, 0xa9, 0x6e, 0x27, 0x5b, - 0xf7, 0x73, 0xd9, 0xbb, 0xd4, 0xce, 0xb9, 0xa9, 0x2e, 0x24, 0xf9, 0x4b, 0x83, 0x6d, 0x3d, 0xaf, - 0x17, 0xe4, 0xd6, 0xb8, 0x9d, 0xfa, 0x3e, 0xaf, 0xe1, 0x9d, 0xc1, 0x22, 0x83, 0x00, 0x04, 0x20, - 0x00, 0x01, 0x08, 0x40, 0x00, 0x02, 0x10, 0xb8, 0x22, 0x81, 0xd1, 0x9e, 0xea, 0x1f, 0xc5, 0xea, - 0x45, 0xbb, 0xb9, 0x72, 0xf1, 0x8a, 0x2c, 0x23, 0x4d, 0xe7, 0x97, 0x73, 0x9f, 0xea, 0x3c, 0xf7, - 0x9a, 0xa6, 0xd1, 0x3a, 0xbe, 0xcb, 0xeb, 0xe1, 0xc8, 0x1e, 0x3f, 0xf2, 0xc5, 0x8a, 0x8b, 0x23, - 0x18, 0x7c, 0x84, 0x00, 0x04, 0x20, 0x00, 0x01, 0x08, 0x40, 0x00, 0x02, 0x10, 0x18, 0x85, 0x80, - 0xfe, 0xa4, 0xc9, 0xeb, 0x1b, 0x7b, 0x2c, 0xe5, 0x0f, 0x5f, 0x53, 0x99, 0x73, 0x6d, 0xe9, 0x37, - 0xd6, 0x5c, 0xb6, 0xd0, 0x5b, 0xb0, 0xf6, 0x0f, 0x6b, 0x93, 0x2d, 0x3b, 0x32, 0x91, 0xf4, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXGlobalsIcon[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x26, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa8, 0x3d, 0xe9, - 0xae, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x84, 0xf2, 0x20, 0x5b, 0x00, 0x00, - 0x03, 0x06, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xcd, 0x98, 0xc9, 0x6b, 0x14, 0x41, 0x14, 0x87, - 0x33, 0x31, 0x8a, 0x22, 0x44, 0x24, 0x0b, 0x6a, 0xc0, 0x10, 0x24, 0x2e, 0x88, 0x42, 0x84, 0x88, - 0x10, 0x24, 0x44, 0x3d, 0x84, 0x78, 0x50, 0x10, 0xd4, 0xa3, 0x20, 0xb8, 0xfc, 0x05, 0x1e, 0x24, - 0x10, 0x15, 0x0f, 0x41, 0x51, 0x24, 0x9e, 0x3d, 0xe8, 0xc1, 0x8b, 0x22, 0xb8, 0x5d, 0x3c, 0x0c, - 0x2a, 0xc4, 0x25, 0x68, 0x04, 0x15, 0xcd, 0x41, 0xdc, 0x0e, 0x8a, 0x5b, 0xa2, 0x12, 0xa2, 0x66, - 0x99, 0x7c, 0x6f, 0x98, 0x32, 0x8f, 0xb2, 0x6b, 0xba, 0x27, 0xa9, 0x6a, 0xfc, 0xc1, 0x47, 0xbd, - 0xae, 0xaa, 0x79, 0xef, 0x37, 0xd3, 0xdd, 0xd5, 0xd5, 0x53, 0x56, 0xf6, 0x9f, 0x2a, 0x13, 0xda, - 0x57, 0x2e, 0x97, 0xab, 0xa7, 0xc6, 0x36, 0x58, 0x05, 0x2b, 0x61, 0x3e, 0xf4, 0xc1, 0x03, 0xb8, - 0x9d, 0xc9, 0x64, 0xde, 0xd2, 0xa6, 0x27, 0x0c, 0xcd, 0x86, 0x43, 0x30, 0x0c, 0x2e, 0xfd, 0x61, - 0xa0, 0x13, 0x2a, 0x52, 0x71, 0x46, 0xa1, 0x3a, 0x78, 0x06, 0x49, 0xf5, 0x88, 0x89, 0x2b, 0x82, - 0x9a, 0xa3, 0xc0, 0x3c, 0xe8, 0x4b, 0xea, 0x48, 0xcd, 0x7b, 0x43, 0xbc, 0x30, 0x98, 0x39, 0x92, - 0x77, 0xab, 0x62, 0x71, 0xe1, 0x20, 0x13, 0x2e, 0xc3, 0x41, 0x68, 0x0c, 0x69, 0xaa, 0x92, 0x02, - 0xdf, 0xa1, 0x98, 0xc6, 0x18, 0x3c, 0x0b, 0xeb, 0xa1, 0x3c, 0x98, 0x19, 0x9d, 0x98, 0x42, 0x3b, - 0x21, 0x4e, 0x27, 0xf4, 0x67, 0x5c, 0xb1, 0x6f, 0xc7, 0xcd, 0xae, 0x42, 0xaa, 0xff, 0x9d, 0x8a, - 0x9d, 0xa1, 0x6f, 0x63, 0x4b, 0x9d, 0x95, 0xa6, 0x06, 0xaa, 0xa6, 0x42, 0x77, 0xe4, 0xdb, 0x58, - 0x75, 0x44, 0xa9, 0x51, 0xfa, 0x1e, 0xc2, 0x58, 0x61, 0xac, 0x3d, 0x62, 0x4e, 0xd8, 0x2e, 0x2e, - 0xae, 0xe7, 0xea, 0x02, 0xbb, 0x44, 0xdc, 0x01, 0xab, 0x61, 0x2f, 0xfc, 0x04, 0xd1, 0x38, 0xfc, - 0xf3, 0x05, 0xe8, 0x6b, 0x80, 0x7d, 0x70, 0x01, 0xca, 0x7d, 0xaf, 0xb8, 0x8b, 0xd5, 0x57, 0xaf, - 0x23, 0x3e, 0x03, 0xf2, 0x08, 0xba, 0x05, 0xf2, 0x18, 0x6a, 0x03, 0x39, 0x4b, 0xed, 0x14, 0xff, - 0x40, 0x2b, 0x8f, 0xa8, 0x35, 0xb0, 0x05, 0x96, 0x81, 0x28, 0xcb, 0x63, 0x6a, 0xc2, 0x9b, 0x31, - 0x0a, 0xcd, 0x25, 0xa9, 0x5e, 0x20, 0xe7, 0x70, 0xbc, 0x1b, 0x16, 0xc0, 0x66, 0x68, 0x05, 0xa3, - 0x0e, 0x82, 0x5e, 0xe8, 0x31, 0x1d, 0xaa, 0xcd, 0xaa, 0x78, 0xe6, 0x21, 0xc6, 0x5a, 0x41, 0x6b, - 0x82, 0x83, 0x1f, 0xd0, 0x0b, 0x47, 0x61, 0x0f, 0x18, 0x7d, 0x25, 0x68, 0x34, 0x07, 0xaa, 0xfd, - 0x48, 0x5c, 0x33, 0x73, 0x37, 0x2a, 0x03, 0x09, 0xcf, 0xab, 0x02, 0x26, 0xdc, 0x4e, 0x20, 0xd7, - 0xd7, 0x45, 0xf8, 0x64, 0x3a, 0x0b, 0x6d, 0x0b, 0xed, 0x0b, 0xab, 0x4f, 0x7e, 0x49, 0x7f, 0x22, - 0xf9, 0x56, 0x90, 0x5f, 0xa8, 0x14, 0x1d, 0x67, 0xf2, 0x49, 0xf5, 0x81, 0x63, 0xfe, 0x1c, 0x91, - 0x89, 0xc4, 0x1b, 0x40, 0x4e, 0x4d, 0xa9, 0xea, 0xe7, 0x03, 0x6d, 0x30, 0x04, 0x3b, 0x7c, 0x9b, - 0xda, 0x45, 0xd2, 0x11, 0x98, 0x8e, 0xe4, 0xcb, 0xd4, 0x40, 0x43, 0x94, 0xa9, 0x69, 0xef, 0x60, - 0x49, 0xd8, 0x49, 0xc2, 0x23, 0x10, 0x97, 0xe3, 0x31, 0x73, 0xee, 0xc1, 0x53, 0x18, 0x84, 0x61, - 0x18, 0x80, 0x57, 0x2c, 0x0b, 0x39, 0x5a, 0x3f, 0xc2, 0x50, 0x35, 0x5c, 0x81, 0x38, 0x7d, 0x61, - 0x82, 0xdf, 0x8b, 0xd9, 0xf5, 0x15, 0x28, 0x94, 0x5f, 0x18, 0xe3, 0x1c, 0x31, 0xfe, 0x19, 0x96, - 0xbb, 0xf2, 0x78, 0xeb, 0xa7, 0x88, 0xec, 0x4a, 0x7b, 0x20, 0x89, 0x7e, 0x31, 0xa9, 0xc5, 0x5b, - 0x71, 0x57, 0x22, 0x8a, 0x34, 0xc3, 0xcb, 0x24, 0x8e, 0x98, 0x23, 0x4b, 0x86, 0xac, 0xf6, 0xe1, - 0x44, 0x81, 0x0a, 0xe8, 0x82, 0x51, 0x48, 0xaa, 0xc3, 0xe1, 0x1c, 0x91, 0x19, 0x17, 0x8b, 0x40, - 0x1e, 0x25, 0xa5, 0xe8, 0x7a, 0x68, 0x53, 0xeb, 0x70, 0xf3, 0xbe, 0x14, 0x47, 0xcc, 0x95, 0x67, - 0x5c, 0x6d, 0x30, 0x63, 0x24, 0x97, 0xfd, 0x53, 0xb1, 0x17, 0x54, 0x86, 0x23, 0x15, 0x6e, 0xf3, - 0x47, 0xb9, 0x7a, 0x90, 0xd7, 0x29, 0xd1, 0x6f, 0xb8, 0x0a, 0xe7, 0x60, 0x00, 0x8a, 0x49, 0xf6, - 0x5c, 0xe1, 0x44, 0xe5, 0x6c, 0xa1, 0xba, 0xac, 0x41, 0xb2, 0x79, 0xcb, 0x8b, 0x58, 0x6e, 0x82, - 0x53, 0x85, 0x31, 0xbb, 0x91, 0x1d, 0xab, 0xec, 0xc3, 0xc2, 0x88, 0xe4, 0x72, 0xb1, 0x1b, 0xed, - 0xb7, 0xab, 0x30, 0x30, 0x0b, 0xec, 0x25, 0x43, 0xfe, 0x77, 0x68, 0xb2, 0xe7, 0xfa, 0x3a, 0x36, - 0x2f, 0x23, 0x1b, 0x55, 0xc2, 0x3b, 0x2a, 0xce, 0x87, 0x3c, 0xd3, 0xc6, 0x09, 0xee, 0x5b, 0xfd, - 0x5d, 0xf4, 0xf7, 0x5b, 0x7d, 0xde, 0x0e, 0x8d, 0xb1, 0x21, 0x95, 0xd1, 0x75, 0x77, 0xc9, 0x1e, - 0xde, 0x48, 0xcc, 0x77, 0x9b, 0x83, 0x60, 0x2d, 0xa7, 0xa4, 0x16, 0xcc, 0x46, 0xef, 0x9a, 0x5d, - 0x88, 0x31, 0x59, 0xfd, 0xe5, 0xed, 0x46, 0xf4, 0x1a, 0xfc, 0x6e, 0x7f, 0xed, 0x82, 0xfa, 0x98, - 0x62, 0xa7, 0xc1, 0xe8, 0x06, 0xc1, 0x26, 0x90, 0x57, 0xaf, 0x03, 0x60, 0x36, 0x82, 0xf2, 0x0a, - 0xf6, 0xf7, 0xc6, 0xd0, 0x9f, 0x0f, 0x16, 0x53, 0x50, 0x1e, 0xd4, 0x4f, 0xc0, 0x25, 0xb9, 0x5b, - 0xe5, 0x35, 0x2b, 0x7d, 0x51, 0x58, 0xcc, 0xc9, 0x2f, 0x67, 0x4e, 0x2b, 0x61, 0xfe, 0x14, 0xde, - 0xa4, 0x5d, 0x92, 0xa6, 0xa3, 0xc8, 0xdd, 0x27, 0x26, 0xaa, 0x30, 0xb1, 0x16, 0x2a, 0xe1, 0x2e, - 0x77, 0xdf, 0xb7, 0x34, 0x4d, 0x49, 0xad, 0x49, 0x44, 0x7e, 0xb1, 0xbc, 0xea, 0x50, 0x60, 0xc4, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXGlobalsIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x26, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa8, 0x3d, 0xe9, - 0xae, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x84, 0xf2, 0x20, 0x5b, 0x00, 0x00, - 0x03, 0x06, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xcd, 0x98, 0xc9, 0x6b, 0x14, 0x41, 0x14, 0x87, - 0x33, 0x31, 0x8a, 0x22, 0x44, 0x24, 0x0b, 0x6a, 0xc0, 0x10, 0x24, 0x2e, 0x88, 0x42, 0x84, 0x88, - 0x10, 0x24, 0x44, 0x3d, 0x84, 0x78, 0x50, 0x10, 0xd4, 0xa3, 0x20, 0xb8, 0xfc, 0x05, 0x1e, 0x24, - 0x10, 0x15, 0x0f, 0x41, 0x51, 0x24, 0x9e, 0x3d, 0xe8, 0xc1, 0x8b, 0x22, 0xb8, 0x5d, 0x3c, 0x0c, - 0x2a, 0xc4, 0x25, 0x68, 0x04, 0x15, 0xcd, 0x41, 0xdc, 0x0e, 0x8a, 0x5b, 0xa2, 0x12, 0xa2, 0x66, - 0x99, 0x7c, 0x6f, 0x98, 0x32, 0x8f, 0xb2, 0x6b, 0xba, 0x27, 0xa9, 0x6a, 0xfc, 0xc1, 0x47, 0xbd, - 0xae, 0xaa, 0x79, 0xef, 0x37, 0xd3, 0xdd, 0xd5, 0xd5, 0x53, 0x56, 0xf6, 0x9f, 0x2a, 0x13, 0xda, - 0x57, 0x2e, 0x97, 0xab, 0xa7, 0xc6, 0x36, 0x58, 0x05, 0x2b, 0x61, 0x3e, 0xf4, 0xc1, 0x03, 0xb8, - 0x9d, 0xc9, 0x64, 0xde, 0xd2, 0xa6, 0x27, 0x0c, 0xcd, 0x86, 0x43, 0x30, 0x0c, 0x2e, 0xfd, 0x61, - 0xa0, 0x13, 0x2a, 0x52, 0x71, 0x46, 0xa1, 0x3a, 0x78, 0x06, 0x49, 0xf5, 0x88, 0x89, 0x2b, 0x82, - 0x9a, 0xa3, 0xc0, 0x3c, 0xe8, 0x4b, 0xea, 0x48, 0xcd, 0x7b, 0x43, 0xbc, 0x30, 0x98, 0x39, 0x92, - 0x77, 0xab, 0x62, 0x71, 0xe1, 0x20, 0x13, 0x2e, 0xc3, 0x41, 0x68, 0x0c, 0x69, 0xaa, 0x92, 0x02, - 0xdf, 0xa1, 0x98, 0xc6, 0x18, 0x3c, 0x0b, 0xeb, 0xa1, 0x3c, 0x98, 0x19, 0x9d, 0x98, 0x42, 0x3b, - 0x21, 0x4e, 0x27, 0xf4, 0x67, 0x5c, 0xb1, 0x6f, 0xc7, 0xcd, 0xae, 0x42, 0xaa, 0xff, 0x9d, 0x8a, - 0x9d, 0xa1, 0x6f, 0x63, 0x4b, 0x9d, 0x95, 0xa6, 0x06, 0xaa, 0xa6, 0x42, 0x77, 0xe4, 0xdb, 0x58, - 0x75, 0x44, 0xa9, 0x51, 0xfa, 0x1e, 0xc2, 0x58, 0x61, 0xac, 0x3d, 0x62, 0x4e, 0xd8, 0x2e, 0x2e, - 0xae, 0xe7, 0xea, 0x02, 0xbb, 0x44, 0xdc, 0x01, 0xab, 0x61, 0x2f, 0xfc, 0x04, 0xd1, 0x38, 0xfc, - 0xf3, 0x05, 0xe8, 0x6b, 0x80, 0x7d, 0x70, 0x01, 0xca, 0x7d, 0xaf, 0xb8, 0x8b, 0xd5, 0x57, 0xaf, - 0x23, 0x3e, 0x03, 0xf2, 0x08, 0xba, 0x05, 0xf2, 0x18, 0x6a, 0x03, 0x39, 0x4b, 0xed, 0x14, 0xff, - 0x40, 0x2b, 0x8f, 0xa8, 0x35, 0xb0, 0x05, 0x96, 0x81, 0x28, 0xcb, 0x63, 0x6a, 0xc2, 0x9b, 0x31, - 0x0a, 0xcd, 0x25, 0xa9, 0x5e, 0x20, 0xe7, 0x70, 0xbc, 0x1b, 0x16, 0xc0, 0x66, 0x68, 0x05, 0xa3, - 0x0e, 0x82, 0x5e, 0xe8, 0x31, 0x1d, 0xaa, 0xcd, 0xaa, 0x78, 0xe6, 0x21, 0xc6, 0x5a, 0x41, 0x6b, - 0x82, 0x83, 0x1f, 0xd0, 0x0b, 0x47, 0x61, 0x0f, 0x18, 0x7d, 0x25, 0x68, 0x34, 0x07, 0xaa, 0xfd, - 0x48, 0x5c, 0x33, 0x73, 0x37, 0x2a, 0x03, 0x09, 0xcf, 0xab, 0x02, 0x26, 0xdc, 0x4e, 0x20, 0xd7, - 0xd7, 0x45, 0xf8, 0x64, 0x3a, 0x0b, 0x6d, 0x0b, 0xed, 0x0b, 0xab, 0x4f, 0x7e, 0x49, 0x7f, 0x22, - 0xf9, 0x56, 0x90, 0x5f, 0xa8, 0x14, 0x1d, 0x67, 0xf2, 0x49, 0xf5, 0x81, 0x63, 0xfe, 0x1c, 0x91, - 0x89, 0xc4, 0x1b, 0x40, 0x4e, 0x4d, 0xa9, 0xea, 0xe7, 0x03, 0x6d, 0x30, 0x04, 0x3b, 0x7c, 0x9b, - 0xda, 0x45, 0xd2, 0x11, 0x98, 0x8e, 0xe4, 0xcb, 0xd4, 0x40, 0x43, 0x94, 0xa9, 0x69, 0xef, 0x60, - 0x49, 0xd8, 0x49, 0xc2, 0x23, 0x10, 0x97, 0xe3, 0x31, 0x73, 0xee, 0xc1, 0x53, 0x18, 0x84, 0x61, - 0x18, 0x80, 0x57, 0x2c, 0x0b, 0x39, 0x5a, 0x3f, 0xc2, 0x50, 0x35, 0x5c, 0x81, 0x38, 0x7d, 0x61, - 0x82, 0xdf, 0x8b, 0xd9, 0xf5, 0x15, 0x28, 0x94, 0x5f, 0x18, 0xe3, 0x1c, 0x31, 0xfe, 0x19, 0x96, - 0xbb, 0xf2, 0x78, 0xeb, 0xa7, 0x88, 0xec, 0x4a, 0x7b, 0x20, 0x89, 0x7e, 0x31, 0xa9, 0xc5, 0x5b, - 0x71, 0x57, 0x22, 0x8a, 0x34, 0xc3, 0xcb, 0x24, 0x8e, 0x98, 0x23, 0x4b, 0x86, 0xac, 0xf6, 0xe1, - 0x44, 0x81, 0x0a, 0xe8, 0x82, 0x51, 0x48, 0xaa, 0xc3, 0xe1, 0x1c, 0x91, 0x19, 0x17, 0x8b, 0x40, - 0x1e, 0x25, 0xa5, 0xe8, 0x7a, 0x68, 0x53, 0xeb, 0x70, 0xf3, 0xbe, 0x14, 0x47, 0xcc, 0x95, 0x67, - 0x5c, 0x6d, 0x30, 0x63, 0x24, 0x97, 0xfd, 0x53, 0xb1, 0x17, 0x54, 0x86, 0x23, 0x15, 0x6e, 0xf3, - 0x47, 0xb9, 0x7a, 0x90, 0xd7, 0x29, 0xd1, 0x6f, 0xb8, 0x0a, 0xe7, 0x60, 0x00, 0x8a, 0x49, 0xf6, - 0x5c, 0xe1, 0x44, 0xe5, 0x6c, 0xa1, 0xba, 0xac, 0x41, 0xb2, 0x79, 0xcb, 0x8b, 0x58, 0x6e, 0x82, - 0x53, 0x85, 0x31, 0xbb, 0x91, 0x1d, 0xab, 0xec, 0xc3, 0xc2, 0x88, 0xe4, 0x72, 0xb1, 0x1b, 0xed, - 0xb7, 0xab, 0x30, 0x30, 0x0b, 0xec, 0x25, 0x43, 0xfe, 0x77, 0x68, 0xb2, 0xe7, 0xfa, 0x3a, 0x36, - 0x2f, 0x23, 0x1b, 0x55, 0xc2, 0x3b, 0x2a, 0xce, 0x87, 0x3c, 0xd3, 0xc6, 0x09, 0xee, 0x5b, 0xfd, - 0x5d, 0xf4, 0xf7, 0x5b, 0x7d, 0xde, 0x0e, 0x8d, 0xb1, 0x21, 0x95, 0xd1, 0x75, 0x77, 0xc9, 0x1e, - 0xde, 0x48, 0xcc, 0x77, 0x9b, 0x83, 0x60, 0x2d, 0xa7, 0xa4, 0x16, 0xcc, 0x46, 0xef, 0x9a, 0x5d, - 0x88, 0x31, 0x59, 0xfd, 0xe5, 0xed, 0x46, 0xf4, 0x1a, 0xfc, 0x6e, 0x7f, 0xed, 0x82, 0xfa, 0x98, - 0x62, 0xa7, 0xc1, 0xe8, 0x06, 0xc1, 0x26, 0x90, 0x57, 0xaf, 0x03, 0x60, 0x36, 0x82, 0xf2, 0x0a, - 0xf6, 0xf7, 0xc6, 0xd0, 0x9f, 0x0f, 0x16, 0x53, 0x50, 0x1e, 0xd4, 0x4f, 0xc0, 0x25, 0xb9, 0x5b, - 0xe5, 0x35, 0x2b, 0x7d, 0x51, 0x58, 0xcc, 0xc9, 0x2f, 0x67, 0x4e, 0x2b, 0x61, 0xfe, 0x14, 0xde, - 0xa4, 0x5d, 0x92, 0xa6, 0xa3, 0xc8, 0xdd, 0x27, 0x26, 0xaa, 0x30, 0xb1, 0x16, 0x2a, 0xe1, 0x2e, - 0x77, 0xdf, 0xb7, 0x34, 0x4d, 0x49, 0xad, 0x49, 0x44, 0x7e, 0xb1, 0xbc, 0xea, 0x50, 0x60, 0xc4, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXGlobalsIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x08, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x18, 0x83, - 0x85, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x91, 0x8a, 0xa0, 0x00, 0x00, - 0x04, 0xf1, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xe5, 0x9a, 0x6b, 0x88, 0x16, 0x55, 0x1c, 0xc6, - 0xf7, 0xf5, 0xb2, 0xa2, 0x82, 0x4a, 0x79, 0x43, 0x51, 0x89, 0x4c, 0x45, 0x83, 0x0c, 0x51, 0x04, - 0x2f, 0xa9, 0x6c, 0x45, 0x42, 0x5e, 0x82, 0x54, 0xf0, 0x83, 0x20, 0xa8, 0x81, 0x81, 0x10, 0x42, - 0x20, 0x91, 0x90, 0x12, 0x7d, 0x49, 0x08, 0xfa, 0x20, 0xda, 0x07, 0x05, 0xf1, 0x82, 0x60, 0x18, - 0x4a, 0x65, 0x42, 0xfa, 0x41, 0xb7, 0x22, 0x96, 0x50, 0x50, 0x5c, 0xf2, 0xb2, 0x25, 0xab, 0x99, - 0xe5, 0xad, 0x52, 0x33, 0x77, 0xfb, 0x3d, 0xaf, 0x33, 0xcb, 0xd9, 0xd3, 0xcc, 0xbc, 0xaf, 0x67, - 0xe6, 0x9d, 0x39, 0x2f, 0xfd, 0xe1, 0xc7, 0x9c, 0xf3, 0x9f, 0x73, 0xe6, 0x3c, 0xcf, 0xcc, 0xce, - 0x7b, 0xce, 0xcc, 0x6c, 0x43, 0xc3, 0xff, 0x20, 0x4a, 0x3e, 0x7b, 0xec, 0xec, 0xec, 0x1c, 0x88, - 0xbe, 0x51, 0x30, 0x08, 0x1a, 0xe1, 0x67, 0x51, 0x2a, 0x95, 0xee, 0xb1, 0xad, 0xdf, 0xc0, 0xd8, - 0x28, 0x78, 0x1f, 0xbe, 0x87, 0x87, 0x60, 0x47, 0x07, 0x89, 0x66, 0x78, 0x1b, 0x46, 0xd7, 0x95, - 0x53, 0x04, 0x3f, 0x09, 0x9f, 0xc0, 0xdf, 0x50, 0x6d, 0xdc, 0xa7, 0xe1, 0x47, 0x30, 0xc4, 0x7b, - 0xb3, 0x88, 0x9c, 0x06, 0x6d, 0xe0, 0x1a, 0xd7, 0xe8, 0x38, 0xdb, 0x5b, 0xa3, 0x88, 0x9b, 0x05, - 0xba, 0x22, 0x69, 0x43, 0x7f, 0x01, 0x2b, 0xbc, 0x33, 0x8a, 0xa8, 0x31, 0xa0, 0xab, 0x90, 0x55, - 0x3c, 0xe0, 0x40, 0x73, 0x6c, 0xa3, 0x3d, 0xec, 0x44, 0x5e, 0x75, 0xc4, 0xf4, 0x65, 0xac, 0x83, - 0x90, 0xd5, 0xfd, 0xf4, 0x90, 0x63, 0xb5, 0xc0, 0x64, 0xe8, 0x16, 0xbd, 0xba, 0xd5, 0xf2, 0xad, - 0xac, 0x62, 0xb8, 0xe7, 0x52, 0x0e, 0xd9, 0x4a, 0xff, 0xa3, 0x01, 0x5f, 0x33, 0xb5, 0xdc, 0x4c, - 0x79, 0xbc, 0xec, 0xba, 0x73, 0x15, 0x7b, 0xc2, 0x45, 0x70, 0x89, 0xe3, 0x74, 0x5a, 0x09, 0x7e, - 0x4f, 0x1f, 0x08, 0x5c, 0xe4, 0xe0, 0x4e, 0x73, 0xe6, 0x62, 0x97, 0x53, 0x5d, 0xd4, 0x3d, 0xf9, - 0x82, 0x83, 0xd8, 0x5d, 0xfc, 0x39, 0x7e, 0xea, 0xd0, 0xaf, 0xa1, 0x28, 0x93, 0x53, 0x1d, 0xc4, - 0x9e, 0x76, 0xe8, 0x53, 0xee, 0x52, 0x94, 0xc9, 0x49, 0x0e, 0x82, 0xb5, 0x86, 0x75, 0x8a, 0xdc, - 0x4d, 0x72, 0x5f, 0xe9, 0x17, 0x5d, 0x0b, 0xee, 0xc7, 0x0d, 0xe7, 0x15, 0x4d, 0xee, 0x26, 0x71, - 0xf6, 0xc4, 0xe3, 0xba, 0x0b, 0xda, 0x4f, 0xe6, 0x04, 0x8d, 0x70, 0xe9, 0x5b, 0x84, 0xc9, 0xa4, - 0xab, 0x78, 0x09, 0x13, 0xdb, 0x61, 0x29, 0xc8, 0xd0, 0x31, 0x30, 0x63, 0xbe, 0x59, 0x49, 0x2a, - 0x73, 0x42, 0x7a, 0xc0, 0xb0, 0xa4, 0x36, 0x35, 0xdb, 0xc7, 0xc0, 0x53, 0xc0, 0x8e, 0x8f, 0x49, - 0x3c, 0xad, 0x41, 0xd9, 0x8e, 0x06, 0xcd, 0x83, 0xbb, 0xc1, 0x7e, 0x22, 0x39, 0x90, 0x24, 0x8c, - 0xf6, 0x4f, 0xc1, 0x6a, 0xd8, 0x0f, 0xbf, 0xc1, 0x7b, 0x6a, 0x5f, 0xc4, 0x8a, 0x27, 0xea, 0x4a, - 0x4e, 0x44, 0xcb, 0x5b, 0x88, 0x6a, 0x62, 0x3b, 0x4e, 0xc2, 0x88, 0x36, 0xb8, 0x08, 0x61, 0x5d, - 0xb9, 0x26, 0xda, 0xf4, 0x66, 0x2b, 0xee, 0xc2, 0x50, 0x98, 0x09, 0xea, 0xf7, 0x22, 0x94, 0x4f, - 0x14, 0xdb, 0x30, 0xce, 0x85, 0x85, 0x5c, 0xb7, 0x88, 0x5c, 0x05, 0x51, 0x71, 0x8b, 0xe4, 0x41, - 0x58, 0x0b, 0x65, 0x63, 0x6c, 0xa7, 0x83, 0x1d, 0xf3, 0x48, 0x2c, 0x87, 0x7f, 0xec, 0x1d, 0x56, - 0x5d, 0xfb, 0x75, 0x12, 0x0a, 0x99, 0x27, 0x9f, 0x89, 0x38, 0xab, 0xbf, 0x92, 0x1b, 0x0e, 0x7a, - 0x54, 0x6a, 0x87, 0x75, 0x08, 0xd4, 0x55, 0x68, 0x06, 0x3b, 0x74, 0x5f, 0x7e, 0x01, 0x95, 0x5e, - 0xdd, 0x7c, 0xc5, 0xe2, 0xe1, 0x9a, 0xdd, 0x39, 0x97, 0x3a, 0xe2, 0xf5, 0xea, 0x22, 0x2a, 0x7e, - 0x24, 0x19, 0x5e, 0x9d, 0xdb, 0x94, 0x3f, 0x03, 0x99, 0x3d, 0x0c, 0x66, 0x9c, 0x95, 0x50, 0x12, - 0x27, 0xcc, 0x64, 0x44, 0x79, 0x56, 0x2e, 0x86, 0xec, 0x41, 0x10, 0x32, 0x2e, 0x42, 0x4c, 0x98, - 0xfa, 0x89, 0xc2, 0x46, 0x98, 0x01, 0xbd, 0x60, 0x10, 0x2c, 0x86, 0x56, 0xb0, 0x43, 0x3f, 0x30, - 0x1b, 0xec, 0xa4, 0x51, 0xdf, 0x67, 0x8f, 0x9d, 0x5b, 0x1d, 0x11, 0x5b, 0x0c, 0x21, 0x76, 0x71, - 0x27, 0x89, 0xb9, 0xb0, 0x09, 0xbe, 0x81, 0xf0, 0xaa, 0x52, 0xfc, 0x4f, 0xe8, 0xbe, 0xd5, 0xbc, - 0x19, 0x15, 0xe7, 0x49, 0x0e, 0xce, 0xcd, 0x94, 0x39, 0x10, 0x03, 0xcb, 0x40, 0xd4, 0xdb, 0xb7, - 0x28, 0xa1, 0x95, 0x72, 0x87, 0x75, 0x6c, 0x1a, 0x5d, 0xb6, 0x1a, 0xfe, 0x4e, 0x7d, 0x82, 0x39, - 0x6e, 0x6e, 0x65, 0x06, 0x1e, 0x06, 0x57, 0x2c, 0x41, 0x69, 0xaa, 0x7f, 0xd1, 0xb9, 0x2f, 0x6c, - 0x33, 0x0e, 0x72, 0x81, 0x72, 0x61, 0x06, 0xc7, 0x32, 0xf8, 0x39, 0x43, 0x4c, 0x56, 0xc5, 0x57, - 0x38, 0xd0, 0xc2, 0xe0, 0x60, 0x5f, 0xb2, 0x2d, 0x4f, 0x17, 0xb9, 0x5d, 0xb9, 0x70, 0x20, 0x06, - 0x9e, 0x0d, 0xd7, 0x03, 0x21, 0x59, 0x6f, 0xb4, 0x4a, 0xea, 0x0f, 0xcb, 0xc2, 0xf1, 0xe2, 0xb6, - 0x95, 0xe6, 0x9a, 0xb8, 0x7e, 0x15, 0xf3, 0x0c, 0xae, 0x39, 0x6f, 0x1b, 0x34, 0x56, 0x6c, 0x5c, - 0xb9, 0x41, 0x07, 0x4d, 0xb4, 0xc2, 0xb9, 0x01, 0x5a, 0x05, 0x7d, 0x07, 0x07, 0x98, 0x07, 0x4f, - 0xb2, 0xad, 0x18, 0x99, 0x9b, 0xc4, 0x9c, 0x8e, 0xb9, 0x19, 0x36, 0x54, 0x1c, 0x3d, 0xba, 0x81, - 0x16, 0x00, 0x7a, 0x39, 0xf5, 0x43, 0x40, 0x3b, 0x66, 0xfc, 0xf9, 0xf6, 0x81, 0xc1, 0xa1, 0x70, - 0x08, 0x5c, 0xa2, 0x8d, 0x4e, 0x2f, 0x45, 0xfb, 0xf6, 0x24, 0x8b, 0xc0, 0x57, 0xe1, 0x17, 0x17, - 0x77, 0xf4, 0xd1, 0xea, 0xa5, 0x98, 0x1f, 0x8e, 0x6a, 0xce, 0x1f, 0xe2, 0x74, 0xf3, 0x6f, 0x05, - 0xd7, 0x38, 0x45, 0xc7, 0x01, 0xd5, 0x8c, 0x55, 0x48, 0x1b, 0xc4, 0x4d, 0x85, 0x34, 0xd3, 0x43, - 0x3b, 0xfd, 0x9d, 0xdf, 0xdd, 0xd4, 0xd4, 0x34, 0xc2, 0xb4, 0xb6, 0xdc, 0x08, 0x0f, 0xc0, 0x35, - 0xfe, 0xa0, 0xe3, 0x94, 0x9a, 0x0a, 0x75, 0x3d, 0x38, 0xc2, 0xc6, 0xc3, 0xb7, 0xae, 0xce, 0x82, - 0x7e, 0x5a, 0xde, 0x2d, 0x70, 0xd5, 0x50, 0xb3, 0x7e, 0x88, 0x2a, 0xc1, 0x9b, 0xa0, 0x25, 0x55, - 0xda, 0x58, 0x57, 0x33, 0xa1, 0xae, 0x07, 0xc6, 0xd1, 0x48, 0x38, 0x92, 0xd6, 0x59, 0xd0, 0x5f, - 0x0b, 0x04, 0xbf, 0x02, 0x61, 0x4d, 0x90, 0xd5, 0x37, 0xc4, 0xb3, 0x1c, 0xab, 0x9f, 0x57, 0x0e, - 0x11, 0xa4, 0x07, 0xd3, 0xac, 0x1e, 0x8f, 0xf4, 0x35, 0xf9, 0x79, 0x6f, 0x0c, 0x22, 0x46, 0x9f, - 0xd6, 0xcc, 0xc7, 0x18, 0xaa, 0xa9, 0x63, 0xbd, 0x37, 0x06, 0x25, 0x04, 0x3b, 0x7b, 0x52, 0x5b, - 0xea, 0x7e, 0x80, 0xa3, 0x54, 0x33, 0x5f, 0x27, 0x3b, 0x9f, 0x34, 0xc4, 0xbc, 0xd1, 0x5d, 0x5f, - 0x57, 0x4d, 0x0f, 0xbd, 0x77, 0xba, 0x6a, 0xd5, 0x17, 0xf4, 0xa8, 0xa5, 0xb7, 0xe1, 0x7e, 0x04, - 0x62, 0x26, 0x81, 0x39, 0x45, 0xe8, 0x7e, 0xfc, 0x10, 0xf4, 0xba, 0x50, 0x57, 0x58, 0xd3, 0xc8, - 0xb3, 0xf0, 0x39, 0x54, 0x1b, 0xaf, 0xf9, 0xe1, 0x2e, 0x50, 0x81, 0xea, 0x66, 0x4b, 0xf9, 0xf2, - 0x38, 0x81, 0xb4, 0x4b, 0x7a, 0x29, 0x15, 0x1e, 0x66, 0x47, 0x5c, 0xff, 0x42, 0xf2, 0xa8, 0x1a, - 0x0c, 0x1d, 0xa1, 0x3a, 0xb6, 0x87, 0x92, 0x84, 0xb0, 0xbf, 0x0f, 0x24, 0xad, 0x5b, 0x2f, 0xb1, - 0xdf, 0x8b, 0x85, 0xb7, 0xf9, 0x55, 0x6b, 0x2e, 0xa6, 0xcc, 0x1f, 0x87, 0xbd, 0x49, 0x26, 0x79, - 0x90, 0xbd, 0xcf, 0xfe, 0xf2, 0x5b, 0xb3, 0x88, 0x76, 0x7a, 0x92, 0x5f, 0x41, 0x9b, 0xdb, 0x11, - 0xfb, 0x72, 0x4f, 0x99, 0x26, 0xa7, 0x5b, 0xa3, 0x97, 0xdf, 0x54, 0x5b, 0x39, 0xbb, 0xda, 0x6a, - 0x27, 0x82, 0xfa, 0x16, 0x0c, 0x1e, 0x8f, 0xd9, 0x97, 0x7b, 0xda, 0x34, 0xa9, 0x6f, 0x10, 0x66, - 0x8c, 0x31, 0x2b, 0x31, 0xe5, 0xb1, 0x11, 0xf9, 0x53, 0xe4, 0xde, 0x89, 0xc8, 0x17, 0x96, 0x32, - 0x4d, 0x4a, 0x9c, 0x19, 0xfa, 0x14, 0x16, 0x1b, 0xdc, 0x6f, 0x3d, 0xd9, 0xf9, 0xb2, 0xd5, 0xe0, - 0x0e, 0xf5, 0x25, 0xc1, 0x9f, 0xb2, 0xb5, 0xcb, 0x83, 0x2a, 0xa2, 0x87, 0x80, 0xf9, 0x6a, 0x5e, - 0xd3, 0xc7, 0x8c, 0x38, 0x69, 0xec, 0x5b, 0x0f, 0x76, 0xbc, 0x1e, 0xd7, 0xde, 0x9b, 0x3c, 0x8a, - 0xf5, 0x1d, 0xc2, 0x8c, 0x9b, 0x54, 0xd6, 0x40, 0xd7, 0x0f, 0x12, 0x65, 0xfd, 0xaa, 0x7e, 0x00, - 0xe6, 0x09, 0xa1, 0xfa, 0xe8, 0xab, 0xae, 0x37, 0x66, 0xe2, 0x84, 0x20, 0xb4, 0x37, 0xb4, 0x48, - 0xb1, 0x15, 0xfa, 0xc6, 0x70, 0x0c, 0x4e, 0xc2, 0x9f, 0xd6, 0x3e, 0x55, 0xf5, 0x9d, 0xbf, 0x7e, - 0x02, 0xc1, 0x5a, 0xf5, 0x5c, 0x95, 0xf2, 0x2a, 0x42, 0x57, 0xf3, 0x5d, 0x30, 0xef, 0xed, 0xfa, - 0x30, 0x8b, 0x68, 0x2d, 0x0c, 0xf6, 0x43, 0x52, 0x68, 0xb2, 0x8f, 0xbd, 0x67, 0xeb, 0xc3, 0x29, - 0x2a, 0x31, 0xb1, 0x04, 0xf6, 0xc1, 0x19, 0xd0, 0x4b, 0x2b, 0x3d, 0x3c, 0xef, 0x05, 0xfd, 0x87, - 0xc5, 0xc0, 0xba, 0x31, 0x52, 0xad, 0x50, 0x4c, 0x35, 0x42, 0xd7, 0x0f, 0x50, 0xb5, 0xfd, 0x7c, - 0x68, 0xf7, 0x2f, 0xa6, 0x49, 0x6c, 0x47, 0x4c, 0x46, 0x1e, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHierarchyIcon[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x50, 0x21, 0x2b, - 0x21, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xeb, 0x6b, 0x49, 0x00, 0x00, - 0x01, 0xe9, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x98, 0xbf, 0x2f, 0x04, 0x41, 0x14, 0xc7, - 0x77, 0xb9, 0x82, 0x88, 0x82, 0x56, 0x4f, 0x68, 0x88, 0x48, 0x88, 0x6b, 0x2e, 0x21, 0x41, 0xe9, - 0x3f, 0x50, 0x88, 0x46, 0xc5, 0x3f, 0xa0, 0xd2, 0x8a, 0x44, 0xab, 0xf0, 0x0f, 0xe8, 0x28, 0x50, - 0x9f, 0x46, 0xa3, 0x11, 0x09, 0x11, 0xc5, 0x35, 0x2a, 0x91, 0x08, 0x22, 0x7e, 0x9c, 0xcf, 0x3b, - 0x7b, 0xc9, 0x4e, 0x76, 0x2e, 0xe6, 0xe6, 0x47, 0xf6, 0x24, 0xfb, 0x92, 0x6f, 0x76, 0xe6, 0xcd, - 0x7b, 0xdf, 0x79, 0x6f, 0xde, 0xde, 0xcc, 0xec, 0xc5, 0xf5, 0x7a, 0x3d, 0x8e, 0xa2, 0x68, 0x0b, - 0x2c, 0x83, 0x21, 0xe0, 0x2a, 0x6f, 0x10, 0x9c, 0x80, 0xed, 0x38, 0x8e, 0xef, 0x5d, 0xc9, 0x8c, - 0xfd, 0x49, 0xa4, 0x0c, 0x42, 0xc8, 0x8e, 0x71, 0x10, 0x1e, 0x0c, 0x4b, 0x70, 0x2c, 0x79, 0xe0, - 0xd1, 0x51, 0x2c, 0xa2, 0xdc, 0xd4, 0x0d, 0xa4, 0x75, 0xac, 0xe0, 0x00, 0xfd, 0xf1, 0xb4, 0xce, - 0xb0, 0x5d, 0xa3, 0xe2, 0x77, 0x4d, 0x5b, 0x49, 0xa4, 0xa7, 0xd9, 0xf1, 0xfc, 0xfc, 0x93, 0x97, - 0x24, 0x76, 0x99, 0x73, 0x1d, 0x48, 0x1c, 0x6d, 0x0b, 0xfe, 0x97, 0x38, 0xcd, 0x90, 0xd0, 0x7b, - 0x57, 0xdb, 0xde, 0x9e, 0x1c, 0x08, 0xa2, 0x0f, 0xaa, 0x35, 0x60, 0x95, 0x44, 0x12, 0xc6, 0x04, - 0xcf, 0x05, 0x69, 0xe7, 0x96, 0x08, 0x73, 0x8f, 0x81, 0x5e, 0x09, 0xc2, 0x51, 0xa6, 0xc4, 0x3f, - 0xcf, 0x44, 0x1c, 0xe3, 0x57, 0xdd, 0x8b, 0x44, 0xd4, 0xf5, 0xc8, 0xbf, 0x57, 0x54, 0x24, 0xff, - 0x1a, 0xa8, 0x11, 0x48, 0x45, 0x5e, 0x54, 0x95, 0xb7, 0x5e, 0x28, 0x5e, 0x6d, 0x80, 0x92, 0xc8, - 0x91, 0x76, 0xc4, 0x5d, 0x79, 0xec, 0x4e, 0x61, 0xce, 0x50, 0xe2, 0x54, 0xbc, 0xe0, 0x70, 0xda, - 0xc0, 0xc5, 0xd7, 0xa5, 0xf1, 0x15, 0x2e, 0xb9, 0x34, 0xee, 0x99, 0x87, 0xe1, 0x6e, 0xd9, 0x38, - 0x55, 0x49, 0x46, 0xae, 0x0a, 0x82, 0x7f, 0x2b, 0xc5, 0xae, 0xd5, 0x69, 0xa5, 0x2b, 0x2a, 0xd2, - 0x69, 0x15, 0xd1, 0x5e, 0xa1, 0xd9, 0xc5, 0x46, 0x09, 0x74, 0x15, 0x94, 0x41, 0xb7, 0x65, 0xd0, - 0x5f, 0xf8, 0x55, 0xc1, 0x3e, 0x9b, 0xc9, 0xb5, 0x25, 0x87, 0xb1, 0x9b, 0x36, 0x11, 0xbc, 0x65, - 0xeb, 0x9c, 0x33, 0x66, 0x69, 0x6d, 0x38, 0xcd, 0x90, 0x7c, 0xfd, 0xcd, 0xb7, 0x36, 0xf1, 0x33, - 0x92, 0xf9, 0x8d, 0x50, 0x8d, 0x7e, 0xa8, 0x2b, 0x7e, 0xe8, 0x1b, 0x2c, 0x95, 0x84, 0xd3, 0x23, - 0x65, 0x96, 0x2a, 0x93, 0x08, 0x26, 0xf2, 0xe5, 0x66, 0xfb, 0x3a, 0x65, 0x67, 0xf8, 0xe5, 0x12, - 0xce, 0xa0, 0xa2, 0x4b, 0x24, 0xe8, 0x84, 0xa1, 0xc8, 0x8b, 0x44, 0x42, 0xad, 0xac, 0x2d, 0x6f, - 0x9e, 0x15, 0xb9, 0x25, 0xe8, 0x0f, 0xdb, 0xc0, 0x53, 0x7e, 0x57, 0xd2, 0xce, 0x2d, 0x11, 0xce, - 0x96, 0x27, 0xe6, 0x3f, 0x4c, 0x05, 0x64, 0xd3, 0x7c, 0xc0, 0xa9, 0xf1, 0x19, 0x22, 0xff, 0xfb, - 0x2a, 0x92, 0x6c, 0x95, 0x8f, 0x28, 0x5b, 0x9d, 0x31, 0x8a, 0xbd, 0x41, 0xe7, 0x13, 0x9b, 0x41, - 0x02, 0x7f, 0xd6, 0xd9, 0x32, 0xdf, 0x08, 0xfa, 0x49, 0x90, 0x89, 0x45, 0x67, 0x9f, 0xd2, 0xd5, - 0x68, 0x57, 0xe1, 0xfd, 0x4e, 0xe9, 0xd4, 0x26, 0xe4, 0x67, 0xc0, 0x97, 0x9c, 0xaa, 0xec, 0x61, - 0x7a, 0xda, 0x55, 0x20, 0x83, 0x61, 0xa6, 0x5b, 0x01, 0xb3, 0xc0, 0xf6, 0x4c, 0x91, 0x2b, 0xca, - 0x39, 0x38, 0x60, 0xd5, 0x6e, 0x78, 0x16, 0x62, 0xb2, 0x02, 0x3f, 0xb2, 0x15, 0xf7, 0xb1, 0x2c, - 0xc1, 0x90, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHierarchyIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x50, 0x21, 0x2b, - 0x21, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xeb, 0x6b, 0x49, 0x00, 0x00, - 0x01, 0xe9, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x98, 0xbf, 0x2f, 0x04, 0x41, 0x14, 0xc7, - 0x77, 0xb9, 0x82, 0x88, 0x82, 0x56, 0x4f, 0x68, 0x88, 0x48, 0x88, 0x6b, 0x2e, 0x21, 0x41, 0xe9, - 0x3f, 0x50, 0x88, 0x46, 0xc5, 0x3f, 0xa0, 0xd2, 0x8a, 0x44, 0xab, 0xf0, 0x0f, 0xe8, 0x28, 0x50, - 0x9f, 0x46, 0xa3, 0x11, 0x09, 0x11, 0xc5, 0x35, 0x2a, 0x91, 0x08, 0x22, 0x7e, 0x9c, 0xcf, 0x3b, - 0x7b, 0xc9, 0x4e, 0x76, 0x2e, 0xe6, 0xe6, 0x47, 0xf6, 0x24, 0xfb, 0x92, 0x6f, 0x76, 0xe6, 0xcd, - 0x7b, 0xdf, 0x79, 0x6f, 0xde, 0xde, 0xcc, 0xec, 0xc5, 0xf5, 0x7a, 0x3d, 0x8e, 0xa2, 0x68, 0x0b, - 0x2c, 0x83, 0x21, 0xe0, 0x2a, 0x6f, 0x10, 0x9c, 0x80, 0xed, 0x38, 0x8e, 0xef, 0x5d, 0xc9, 0x8c, - 0xfd, 0x49, 0xa4, 0x0c, 0x42, 0xc8, 0x8e, 0x71, 0x10, 0x1e, 0x0c, 0x4b, 0x70, 0x2c, 0x79, 0xe0, - 0xd1, 0x51, 0x2c, 0xa2, 0xdc, 0xd4, 0x0d, 0xa4, 0x75, 0xac, 0xe0, 0x00, 0xfd, 0xf1, 0xb4, 0xce, - 0xb0, 0x5d, 0xa3, 0xe2, 0x77, 0x4d, 0x5b, 0x49, 0xa4, 0xa7, 0xd9, 0xf1, 0xfc, 0xfc, 0x93, 0x97, - 0x24, 0x76, 0x99, 0x73, 0x1d, 0x48, 0x1c, 0x6d, 0x0b, 0xfe, 0x97, 0x38, 0xcd, 0x90, 0xd0, 0x7b, - 0x57, 0xdb, 0xde, 0x9e, 0x1c, 0x08, 0xa2, 0x0f, 0xaa, 0x35, 0x60, 0x95, 0x44, 0x12, 0xc6, 0x04, - 0xcf, 0x05, 0x69, 0xe7, 0x96, 0x08, 0x73, 0x8f, 0x81, 0x5e, 0x09, 0xc2, 0x51, 0xa6, 0xc4, 0x3f, - 0xcf, 0x44, 0x1c, 0xe3, 0x57, 0xdd, 0x8b, 0x44, 0xd4, 0xf5, 0xc8, 0xbf, 0x57, 0x54, 0x24, 0xff, - 0x1a, 0xa8, 0x11, 0x48, 0x45, 0x5e, 0x54, 0x95, 0xb7, 0x5e, 0x28, 0x5e, 0x6d, 0x80, 0x92, 0xc8, - 0x91, 0x76, 0xc4, 0x5d, 0x79, 0xec, 0x4e, 0x61, 0xce, 0x50, 0xe2, 0x54, 0xbc, 0xe0, 0x70, 0xda, - 0xc0, 0xc5, 0xd7, 0xa5, 0xf1, 0x15, 0x2e, 0xb9, 0x34, 0xee, 0x99, 0x87, 0xe1, 0x6e, 0xd9, 0x38, - 0x55, 0x49, 0x46, 0xae, 0x0a, 0x82, 0x7f, 0x2b, 0xc5, 0xae, 0xd5, 0x69, 0xa5, 0x2b, 0x2a, 0xd2, - 0x69, 0x15, 0xd1, 0x5e, 0xa1, 0xd9, 0xc5, 0x46, 0x09, 0x74, 0x15, 0x94, 0x41, 0xb7, 0x65, 0xd0, - 0x5f, 0xf8, 0x55, 0xc1, 0x3e, 0x9b, 0xc9, 0xb5, 0x25, 0x87, 0xb1, 0x9b, 0x36, 0x11, 0xbc, 0x65, - 0xeb, 0x9c, 0x33, 0x66, 0x69, 0x6d, 0x38, 0xcd, 0x90, 0x7c, 0xfd, 0xcd, 0xb7, 0x36, 0xf1, 0x33, - 0x92, 0xf9, 0x8d, 0x50, 0x8d, 0x7e, 0xa8, 0x2b, 0x7e, 0xe8, 0x1b, 0x2c, 0x95, 0x84, 0xd3, 0x23, - 0x65, 0x96, 0x2a, 0x93, 0x08, 0x26, 0xf2, 0xe5, 0x66, 0xfb, 0x3a, 0x65, 0x67, 0xf8, 0xe5, 0x12, - 0xce, 0xa0, 0xa2, 0x4b, 0x24, 0xe8, 0x84, 0xa1, 0xc8, 0x8b, 0x44, 0x42, 0xad, 0xac, 0x2d, 0x6f, - 0x9e, 0x15, 0xb9, 0x25, 0xe8, 0x0f, 0xdb, 0xc0, 0x53, 0x7e, 0x57, 0xd2, 0xce, 0x2d, 0x11, 0xce, - 0x96, 0x27, 0xe6, 0x3f, 0x4c, 0x05, 0x64, 0xd3, 0x7c, 0xc0, 0xa9, 0xf1, 0x19, 0x22, 0xff, 0xfb, - 0x2a, 0x92, 0x6c, 0x95, 0x8f, 0x28, 0x5b, 0x9d, 0x31, 0x8a, 0xbd, 0x41, 0xe7, 0x13, 0x9b, 0x41, - 0x02, 0x7f, 0xd6, 0xd9, 0x32, 0xdf, 0x08, 0xfa, 0x49, 0x90, 0x89, 0x45, 0x67, 0x9f, 0xd2, 0xd5, - 0x68, 0x57, 0xe1, 0xfd, 0x4e, 0xe9, 0xd4, 0x26, 0xe4, 0x67, 0xc0, 0x97, 0x9c, 0xaa, 0xec, 0x61, - 0x7a, 0xda, 0x55, 0x20, 0x83, 0x61, 0xa6, 0x5b, 0x01, 0xb3, 0xc0, 0xf6, 0x4c, 0x91, 0x2b, 0xca, - 0x39, 0x38, 0x60, 0xd5, 0x6e, 0x78, 0x16, 0x62, 0xb2, 0x02, 0x3f, 0xb2, 0x15, 0xf7, 0xb1, 0x2c, - 0xc1, 0x90, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHierarchyIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x59, 0xab, 0x87, - 0xe8, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4b, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x09, 0xb6, 0x65, 0x00, 0x00, - 0x02, 0x81, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x9b, 0x3d, 0x4b, 0xc4, 0x40, 0x10, 0x86, - 0x8d, 0x1f, 0xa0, 0x88, 0x82, 0x95, 0x36, 0x5a, 0x9c, 0x82, 0xf8, 0x07, 0x2c, 0xc5, 0x4a, 0x2c, - 0xac, 0x6c, 0xfc, 0x05, 0x5a, 0x9d, 0x56, 0x76, 0x36, 0xd7, 0x58, 0xc8, 0x29, 0x36, 0xfe, 0x03, - 0x7b, 0xc5, 0x4a, 0x0b, 0x11, 0x3c, 0x6b, 0x41, 0xad, 0x04, 0x3f, 0x8a, 0x03, 0xf1, 0xaa, 0x43, - 0x94, 0x13, 0x44, 0x24, 0xbe, 0x03, 0x6e, 0x8a, 0x80, 0xbb, 0x99, 0x4b, 0x76, 0xb3, 0xe1, 0x66, - 0x60, 0x88, 0x31, 0xb3, 0xf3, 0xce, 0x3c, 0x6e, 0x72, 0xd9, 0xe4, 0x0c, 0xba, 0x60, 0x61, 0x18, - 0x8e, 0x60, 0xb3, 0x05, 0x9f, 0x83, 0x8f, 0xc1, 0x03, 0xb8, 0x6d, 0x0b, 0x21, 0xd0, 0x80, 0x5f, - 0xc2, 0xb7, 0x83, 0x20, 0x78, 0xb3, 0x2d, 0x98, 0x49, 0x7e, 0xc0, 0xba, 0x80, 0xe7, 0x69, 0xe7, - 0x99, 0x34, 0x62, 0x39, 0x49, 0x00, 0x42, 0xd3, 0xd0, 0xb8, 0xb7, 0xac, 0x93, 0x24, 0xfd, 0x14, - 0x66, 0xd7, 0x53, 0x92, 0xc0, 0xbc, 0x62, 0xba, 0x21, 0x3c, 0x99, 0x97, 0x78, 0x4c, 0xb7, 0x14, - 0xdb, 0xf7, 0x6e, 0xb7, 0x17, 0x15, 0xf5, 0x7b, 0x52, 0x15, 0xbb, 0x0e, 0x9c, 0x15, 0x8b, 0xa8, - 0x7d, 0x03, 0x4e, 0xa0, 0x07, 0x32, 0xec, 0xa3, 0x85, 0x5c, 0x0f, 0xf0, 0x3d, 0xcc, 0xf6, 0x9a, - 0xca, 0x4b, 0xb0, 0x0a, 0x69, 0x00, 0x35, 0x8f, 0xc2, 0x4f, 0x2d, 0x16, 0x3f, 0x83, 0xdc, 0x4b, - 0xd0, 0x99, 0x05, 0xb0, 0x6b, 0xd2, 0xa1, 0xd3, 0xb0, 0xa8, 0xb6, 0xe6, 0xa0, 0x70, 0xe2, 0xb3, - 0xaa, 0x74, 0x8a, 0x0c, 0xab, 0xa4, 0x9a, 0xb0, 0xbc, 0x8d, 0xae, 0xe9, 0x45, 0x86, 0xc5, 0xbe, - 0xc6, 0xb5, 0x09, 0x35, 0xd2, 0x29, 0x32, 0xac, 0x36, 0x7b, 0x6f, 0x7f, 0x98, 0xc0, 0x62, 0xb0, - 0x13, 0x58, 0x02, 0x8b, 0x41, 0x80, 0x11, 0x2a, 0x33, 0x4b, 0x60, 0x31, 0x08, 0x30, 0x42, 0x65, - 0x66, 0x09, 0x2c, 0x06, 0x01, 0x46, 0x28, 0xcd, 0x2c, 0x5a, 0x34, 0xfa, 0x60, 0xbe, 0xd4, 0xf1, - 0x2f, 0x0b, 0x82, 0x45, 0xab, 0x6b, 0x1f, 0xec, 0xd1, 0x87, 0x22, 0x74, 0x35, 0x74, 0x63, 0x45, - 0xfd, 0x8c, 0x80, 0x13, 0x5d, 0x90, 0x83, 0x63, 0x47, 0xa8, 0xa3, 0xee, 0x40, 0x27, 0x95, 0x84, - 0x7a, 0x44, 0xb3, 0x82, 0x2c, 0xeb, 0x70, 0x7a, 0x06, 0x3f, 0x0a, 0x77, 0xf9, 0x0c, 0xbe, 0x06, - 0xbd, 0x03, 0xb8, 0x98, 0x2d, 0x02, 0x78, 0xce, 0x74, 0x03, 0x77, 0x61, 0x57, 0xaa, 0x07, 0xba, - 0x66, 0x89, 0x25, 0x24, 0x20, 0xb0, 0x12, 0x82, 0xa2, 0x30, 0x81, 0x25, 0xb0, 0x18, 0x04, 0x18, - 0xa1, 0x32, 0xb3, 0x04, 0x16, 0x83, 0x00, 0x23, 0x54, 0xdd, 0x67, 0x69, 0x87, 0xe0, 0xf3, 0xb9, - 0x0f, 0x01, 0x13, 0xf0, 0x61, 0x6d, 0x60, 0xba, 0x83, 0xef, 0x18, 0x5e, 0xc7, 0xcd, 0xe9, 0x77, - 0xba, 0x34, 0xf6, 0x46, 0x1b, 0x61, 0x01, 0xd4, 0x26, 0xe4, 0x2b, 0xf0, 0x41, 0x7b, 0x65, 0x44, - 0x99, 0x5b, 0xd0, 0xab, 0x00, 0xd8, 0x6e, 0xf4, 0x1b, 0x8f, 0x7e, 0xd0, 0x5e, 0xb3, 0x50, 0x38, - 0xdd, 0xd1, 0x57, 0xe1, 0x2e, 0x40, 0x11, 0x16, 0xd2, 0xa9, 0xfe, 0xe9, 0xd2, 0xbe, 0x57, 0xa6, - 0x85, 0x85, 0x4a, 0x17, 0x72, 0xaa, 0x36, 0x2f, 0x5d, 0x6d, 0xbb, 0x26, 0x58, 0xe3, 0xda, 0xd1, - 0xf6, 0x0e, 0xe6, 0xa5, 0xab, 0xed, 0xc8, 0x04, 0xab, 0x47, 0x3b, 0xda, 0xde, 0xc1, 0xbc, 0x74, - 0xb5, 0x1d, 0x99, 0x60, 0x69, 0x07, 0x77, 0xda, 0x41, 0x81, 0xc5, 0xf8, 0x8b, 0x0b, 0x2c, 0x81, - 0xc5, 0x20, 0xc0, 0x08, 0x95, 0x99, 0xd5, 0x21, 0xb0, 0x9a, 0x8c, 0x3e, 0xd3, 0x84, 0x46, 0x3a, - 0x45, 0x9e, 0x59, 0x77, 0x69, 0x08, 0x30, 0xc6, 0xde, 0xaa, 0xd8, 0x22, 0xc3, 0xda, 0x41, 0x13, - 0x2f, 0xaa, 0x11, 0x4b, 0x5b, 0xfa, 0xaa, 0xf9, 0xbe, 0xca, 0x6d, 0x5a, 0x48, 0xff, 0xa8, 0x40, - 0xc7, 0x5b, 0xa3, 0x2e, 0x16, 0xdb, 0xaf, 0x58, 0x43, 0xd2, 0x77, 0xf8, 0x97, 0xe1, 0x25, 0x78, - 0xf4, 0x0d, 0xbd, 0x0c, 0x6a, 0xfd, 0x44, 0x0e, 0x7a, 0x9f, 0x7a, 0x0c, 0x9d, 0x2f, 0x95, 0xcf, - 0x04, 0xab, 0xae, 0x02, 0x1d, 0x6f, 0x13, 0xe9, 0xa2, 0x11, 0x7a, 0x8b, 0x7d, 0xe8, 0xaa, 0x36, - 0xd3, 0x69, 0x78, 0xe6, 0xaa, 0x90, 0x98, 0x4e, 0x5e, 0xba, 0xb1, 0x32, 0x98, 0xbb, 0x98, 0xea, - 0x65, 0x78, 0x13, 0xee, 0xc2, 0x48, 0xa7, 0xcc, 0x2c, 0xd1, 0x59, 0x78, 0xe2, 0x37, 0xcf, 0x68, - 0x82, 0xfe, 0x5b, 0x6c, 0xc8, 0x62, 0x65, 0x1f, 0x38, 0xad, 0x1a, 0x16, 0xf3, 0x4b, 0x6a, 0x97, - 0x04, 0x7e, 0x01, 0x1e, 0xdc, 0xbb, 0x6b, 0x41, 0x9a, 0x28, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRecentTabIcon[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x28, 0x08, 0x06, 0x00, 0x00, 0x00, 0x9b, 0xdc, 0x28, - 0xa4, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x48, 0xca, 0xb9, 0xf5, 0x00, 0x00, - 0x02, 0x99, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xdd, 0x98, 0xcf, 0x6f, 0x0d, 0x51, 0x14, 0xc7, - 0x67, 0x8a, 0x60, 0x41, 0xfc, 0x4a, 0x10, 0x45, 0x35, 0x84, 0x26, 0x24, 0x62, 0x61, 0x41, 0xf0, - 0x22, 0x12, 0x1b, 0x61, 0x53, 0xec, 0x24, 0x76, 0x36, 0xfe, 0x00, 0x6b, 0x89, 0xa5, 0x85, 0xb5, - 0xb4, 0x76, 0x92, 0xb2, 0x22, 0xd6, 0x15, 0x0b, 0x56, 0x7e, 0x84, 0x1d, 0x41, 0xc2, 0x13, 0x21, - 0x0d, 0x0b, 0x91, 0x94, 0xb4, 0x9e, 0xcf, 0xf7, 0x71, 0xd3, 0xd3, 0xd7, 0x3b, 0xbd, 0xf7, 0xcd, - 0x9b, 0x3b, 0x1a, 0x27, 0xf9, 0x66, 0xce, 0x3d, 0x73, 0xee, 0xf7, 0x7c, 0xdf, 0xbd, 0xa7, 0x77, - 0x66, 0x9a, 0x65, 0x7f, 0xad, 0xd5, 0x6a, 0x9d, 0x01, 0xf7, 0xc1, 0x47, 0xd0, 0x8b, 0x4d, 0x33, - 0xf9, 0x2d, 0xb8, 0x07, 0x0e, 0x38, 0xfe, 0xa8, 0x2b, 0x13, 0xae, 0x82, 0x14, 0xf6, 0x0b, 0xd2, - 0x73, 0x31, 0x22, 0x72, 0x12, 0x77, 0x93, 0xf8, 0x0c, 0x2c, 0x32, 0x13, 0xbe, 0xe0, 0x4f, 0x9b, - 0x71, 0x37, 0xee, 0x52, 0x92, 0x57, 0x9a, 0x09, 0x13, 0xf8, 0x83, 0x79, 0x9e, 0x7f, 0x33, 0xb1, - 0xb9, 0x2e, 0x42, 0x2e, 0x9a, 0xa5, 0x78, 0x82, 0xbf, 0x69, 0x6e, 0x56, 0x77, 0x11, 0x38, 0xf6, - 0x82, 0x09, 0xc3, 0x7b, 0x28, 0xc4, 0xd0, 0x47, 0xc2, 0x76, 0x93, 0x74, 0x0d, 0xe5, 0x1f, 0xcc, - 0xb8, 0x94, 0x0b, 0x87, 0x56, 0xf8, 0xa6, 0x99, 0x6c, 0x6b, 0x98, 0xf0, 0x8c, 0x2b, 0x21, 0x2b, - 0x66, 0x86, 0x99, 0x96, 0xb1, 0x2a, 0xb3, 0x5c, 0xb6, 0x86, 0x97, 0x5f, 0x42, 0x16, 0x84, 0x2d, - 0x8e, 0x55, 0xc1, 0x7e, 0xef, 0x27, 0x77, 0x08, 0xa8, 0x87, 0x62, 0x7e, 0xc0, 0x61, 0xc3, 0x7d, - 0x9c, 0xf9, 0x6a, 0xe0, 0x16, 0xf8, 0x04, 0x5e, 0x82, 0x87, 0x6c, 0xe1, 0x14, 0xd7, 0x3f, 0x46, - 0xc2, 0x88, 0x69, 0xaa, 0x13, 0x2e, 0xee, 0xae, 0xdc, 0x1b, 0x00, 0xe3, 0x26, 0xa7, 0x2a, 0xf7, - 0x39, 0x44, 0xfb, 0x5c, 0x9d, 0x98, 0x5f, 0x76, 0x83, 0xe4, 0x86, 0x9b, 0x50, 0xe1, 0x75, 0x0f, - 0x5c, 0xb7, 0x11, 0xb3, 0x4c, 0x9c, 0xf3, 0x0a, 0x21, 0x49, 0x27, 0xe3, 0x11, 0x25, 0x26, 0xb2, - 0x6d, 0xf0, 0x9e, 0x15, 0xf7, 0xbc, 0x42, 0xb8, 0xaf, 0x9e, 0x48, 0x6d, 0xbb, 0x54, 0x20, 0x24, - 0x64, 0x4b, 0x6a, 0x15, 0xf0, 0x6f, 0x8e, 0x11, 0x12, 0x12, 0x5a, 0x85, 0xce, 0xf6, 0xa3, 0x25, - 0xfa, 0xcf, 0xd7, 0x53, 0xf1, 0x2e, 0xb1, 0xd8, 0x53, 0x78, 0x15, 0xb9, 0xc3, 0xa0, 0xb0, 0x5e, - 0xe1, 0x0d, 0x4f, 0x61, 0x1b, 0x6a, 0x72, 0x06, 0x9c, 0xb4, 0x81, 0x90, 0x4f, 0xe3, 0x6f, 0x20, - 0xa7, 0x51, 0x94, 0x57, 0x56, 0x48, 0x3f, 0xc4, 0x63, 0x90, 0xbe, 0x2b, 0x22, 0xee, 0x88, 0xaf, - 0x61, 0x7c, 0xb0, 0x23, 0x36, 0x6b, 0x58, 0x56, 0x88, 0x48, 0x4e, 0xcf, 0x62, 0xea, 0x71, 0x50, - 0x47, 0x33, 0x46, 0x49, 0xec, 0x65, 0x45, 0xee, 0x50, 0xa1, 0x19, 0x55, 0x25, 0xcb, 0x56, 0x93, - 0xa7, 0x66, 0x5d, 0x52, 0x94, 0x5f, 0x56, 0x88, 0x9a, 0xf5, 0x54, 0x11, 0xa9, 0x2f, 0x4e, 0x4f, - 0x6d, 0x24, 0xde, 0xf0, 0xdd, 0x53, 0xac, 0xac, 0x10, 0x35, 0xeb, 0x2d, 0xe6, 0xbf, 0x2f, 0x22, - 0xee, 0x88, 0x27, 0x6d, 0x56, 0x2d, 0x75, 0x65, 0xf6, 0xdf, 0x34, 0xab, 0x6f, 0x6b, 0x8e, 0xb2, - 0x4c, 0x5d, 0x3f, 0x2c, 0xcb, 0xf6, 0x48, 0x61, 0xb3, 0xd2, 0x3b, 0x0d, 0x84, 0x8c, 0x77, 0xbb, - 0x67, 0x12, 0xa2, 0xd7, 0x37, 0x67, 0xb9, 0x73, 0x02, 0x57, 0xd7, 0xac, 0x4d, 0x4f, 0xde, 0x31, - 0x4f, 0x2c, 0x18, 0x92, 0x90, 0xcf, 0x26, 0x6b, 0x87, 0xf1, 0x43, 0x6e, 0xa5, 0xcd, 0x2a, 0x21, - 0xaf, 0x4c, 0xc5, 0x4b, 0x2c, 0xad, 0xbe, 0xf2, 0x5e, 0x00, 0xbd, 0xd8, 0xae, 0x37, 0xf7, 0x92, - 0xba, 0x12, 0xa2, 0x13, 0xf2, 0x2b, 0xd0, 0xe9, 0xb7, 0x0e, 0x8c, 0x82, 0xda, 0xad, 0x8f, 0x13, - 0x52, 0x1f, 0x42, 0x17, 0xc0, 0xf7, 0xda, 0xab, 0x9b, 0x82, 0x5a, 0x91, 0x0c, 0x31, 0x63, 0x6c, - 0xc9, 0x23, 0xdc, 0xf3, 0x60, 0x27, 0xd0, 0xbb, 0x83, 0x1a, 0x77, 0x10, 0x6c, 0x05, 0xff, 0xd6, - 0x10, 0x77, 0x19, 0xa4, 0xb6, 0xf6, 0x37, 0xf2, 0x82, 0x39, 0x59, 0x43, 0x42, 0x7e, 0xd6, 0xb0, - 0x27, 0xed, 0x1a, 0x21, 0x21, 0x6f, 0x6a, 0x10, 0xd2, 0xae, 0x11, 0x12, 0xf2, 0x14, 0x21, 0xf6, - 0xe4, 0x4d, 0xa1, 0xeb, 0x71, 0x14, 0x29, 0x9d, 0x3a, 0x9a, 0xb0, 0x5b, 0x1f, 0x44, 0x89, 0x50, - 0x12, 0x22, 0x96, 0x83, 0x2b, 0x60, 0xb2, 0x42, 0x41, 0x53, 0x70, 0x5d, 0x07, 0x6b, 0x9d, 0x90, - 0xd8, 0x87, 0x9c, 0x04, 0xe9, 0xcc, 0x19, 0x00, 0xfd, 0x20, 0xb4, 0xa5, 0xa4, 0x78, 0x4d, 0xdb, - 0xac, 0xff, 0x8f, 0xbc, 0xe6, 0xec, 0xfa, 0x61, 0x33, 0x7e, 0x03, 0xf9, 0x2d, 0xce, 0xa7, 0xa9, - 0x35, 0x85, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRecentTabIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x28, 0x08, 0x06, 0x00, 0x00, 0x00, 0x9b, 0xdc, 0x28, - 0xa4, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x48, 0xca, 0xb9, 0xf5, 0x00, 0x00, - 0x02, 0x99, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xdd, 0x98, 0xcf, 0x6f, 0x0d, 0x51, 0x14, 0xc7, - 0x67, 0x8a, 0x60, 0x41, 0xfc, 0x4a, 0x10, 0x45, 0x35, 0x84, 0x26, 0x24, 0x62, 0x61, 0x41, 0xf0, - 0x22, 0x12, 0x1b, 0x61, 0x53, 0xec, 0x24, 0x76, 0x36, 0xfe, 0x00, 0x6b, 0x89, 0xa5, 0x85, 0xb5, - 0xb4, 0x76, 0x92, 0xb2, 0x22, 0xd6, 0x15, 0x0b, 0x56, 0x7e, 0x84, 0x1d, 0x41, 0xc2, 0x13, 0x21, - 0x0d, 0x0b, 0x91, 0x94, 0xb4, 0x9e, 0xcf, 0xf7, 0x71, 0xd3, 0xd3, 0xd7, 0x3b, 0xbd, 0xf7, 0xcd, - 0x9b, 0x3b, 0x1a, 0x27, 0xf9, 0x66, 0xce, 0x3d, 0x73, 0xee, 0xf7, 0x7c, 0xdf, 0xbd, 0xa7, 0x77, - 0x66, 0x9a, 0x65, 0x7f, 0xad, 0xd5, 0x6a, 0x9d, 0x01, 0xf7, 0xc1, 0x47, 0xd0, 0x8b, 0x4d, 0x33, - 0xf9, 0x2d, 0xb8, 0x07, 0x0e, 0x38, 0xfe, 0xa8, 0x2b, 0x13, 0xae, 0x82, 0x14, 0xf6, 0x0b, 0xd2, - 0x73, 0x31, 0x22, 0x72, 0x12, 0x77, 0x93, 0xf8, 0x0c, 0x2c, 0x32, 0x13, 0xbe, 0xe0, 0x4f, 0x9b, - 0x71, 0x37, 0xee, 0x52, 0x92, 0x57, 0x9a, 0x09, 0x13, 0xf8, 0x83, 0x79, 0x9e, 0x7f, 0x33, 0xb1, - 0xb9, 0x2e, 0x42, 0x2e, 0x9a, 0xa5, 0x78, 0x82, 0xbf, 0x69, 0x6e, 0x56, 0x77, 0x11, 0x38, 0xf6, - 0x82, 0x09, 0xc3, 0x7b, 0x28, 0xc4, 0xd0, 0x47, 0xc2, 0x76, 0x93, 0x74, 0x0d, 0xe5, 0x1f, 0xcc, - 0xb8, 0x94, 0x0b, 0x87, 0x56, 0xf8, 0xa6, 0x99, 0x6c, 0x6b, 0x98, 0xf0, 0x8c, 0x2b, 0x21, 0x2b, - 0x66, 0x86, 0x99, 0x96, 0xb1, 0x2a, 0xb3, 0x5c, 0xb6, 0x86, 0x97, 0x5f, 0x42, 0x16, 0x84, 0x2d, - 0x8e, 0x55, 0xc1, 0x7e, 0xef, 0x27, 0x77, 0x08, 0xa8, 0x87, 0x62, 0x7e, 0xc0, 0x61, 0xc3, 0x7d, - 0x9c, 0xf9, 0x6a, 0xe0, 0x16, 0xf8, 0x04, 0x5e, 0x82, 0x87, 0x6c, 0xe1, 0x14, 0xd7, 0x3f, 0x46, - 0xc2, 0x88, 0x69, 0xaa, 0x13, 0x2e, 0xee, 0xae, 0xdc, 0x1b, 0x00, 0xe3, 0x26, 0xa7, 0x2a, 0xf7, - 0x39, 0x44, 0xfb, 0x5c, 0x9d, 0x98, 0x5f, 0x76, 0x83, 0xe4, 0x86, 0x9b, 0x50, 0xe1, 0x75, 0x0f, - 0x5c, 0xb7, 0x11, 0xb3, 0x4c, 0x9c, 0xf3, 0x0a, 0x21, 0x49, 0x27, 0xe3, 0x11, 0x25, 0x26, 0xb2, - 0x6d, 0xf0, 0x9e, 0x15, 0xf7, 0xbc, 0x42, 0xb8, 0xaf, 0x9e, 0x48, 0x6d, 0xbb, 0x54, 0x20, 0x24, - 0x64, 0x4b, 0x6a, 0x15, 0xf0, 0x6f, 0x8e, 0x11, 0x12, 0x12, 0x5a, 0x85, 0xce, 0xf6, 0xa3, 0x25, - 0xfa, 0xcf, 0xd7, 0x53, 0xf1, 0x2e, 0xb1, 0xd8, 0x53, 0x78, 0x15, 0xb9, 0xc3, 0xa0, 0xb0, 0x5e, - 0xe1, 0x0d, 0x4f, 0x61, 0x1b, 0x6a, 0x72, 0x06, 0x9c, 0xb4, 0x81, 0x90, 0x4f, 0xe3, 0x6f, 0x20, - 0xa7, 0x51, 0x94, 0x57, 0x56, 0x48, 0x3f, 0xc4, 0x63, 0x90, 0xbe, 0x2b, 0x22, 0xee, 0x88, 0xaf, - 0x61, 0x7c, 0xb0, 0x23, 0x36, 0x6b, 0x58, 0x56, 0x88, 0x48, 0x4e, 0xcf, 0x62, 0xea, 0x71, 0x50, - 0x47, 0x33, 0x46, 0x49, 0xec, 0x65, 0x45, 0xee, 0x50, 0xa1, 0x19, 0x55, 0x25, 0xcb, 0x56, 0x93, - 0xa7, 0x66, 0x5d, 0x52, 0x94, 0x5f, 0x56, 0x88, 0x9a, 0xf5, 0x54, 0x11, 0xa9, 0x2f, 0x4e, 0x4f, - 0x6d, 0x24, 0xde, 0xf0, 0xdd, 0x53, 0xac, 0xac, 0x10, 0x35, 0xeb, 0x2d, 0xe6, 0xbf, 0x2f, 0x22, - 0xee, 0x88, 0x27, 0x6d, 0x56, 0x2d, 0x75, 0x65, 0xf6, 0xdf, 0x34, 0xab, 0x6f, 0x6b, 0x8e, 0xb2, - 0x4c, 0x5d, 0x3f, 0x2c, 0xcb, 0xf6, 0x48, 0x61, 0xb3, 0xd2, 0x3b, 0x0d, 0x84, 0x8c, 0x77, 0xbb, - 0x67, 0x12, 0xa2, 0xd7, 0x37, 0x67, 0xb9, 0x73, 0x02, 0x57, 0xd7, 0xac, 0x4d, 0x4f, 0xde, 0x31, - 0x4f, 0x2c, 0x18, 0x92, 0x90, 0xcf, 0x26, 0x6b, 0x87, 0xf1, 0x43, 0x6e, 0xa5, 0xcd, 0x2a, 0x21, - 0xaf, 0x4c, 0xc5, 0x4b, 0x2c, 0xad, 0xbe, 0xf2, 0x5e, 0x00, 0xbd, 0xd8, 0xae, 0x37, 0xf7, 0x92, - 0xba, 0x12, 0xa2, 0x13, 0xf2, 0x2b, 0xd0, 0xe9, 0xb7, 0x0e, 0x8c, 0x82, 0xda, 0xad, 0x8f, 0x13, - 0x52, 0x1f, 0x42, 0x17, 0xc0, 0xf7, 0xda, 0xab, 0x9b, 0x82, 0x5a, 0x91, 0x0c, 0x31, 0x63, 0x6c, - 0xc9, 0x23, 0xdc, 0xf3, 0x60, 0x27, 0xd0, 0xbb, 0x83, 0x1a, 0x77, 0x10, 0x6c, 0x05, 0xff, 0xd6, - 0x10, 0x77, 0x19, 0xa4, 0xb6, 0xf6, 0x37, 0xf2, 0x82, 0x39, 0x59, 0x43, 0x42, 0x7e, 0xd6, 0xb0, - 0x27, 0xed, 0x1a, 0x21, 0x21, 0x6f, 0x6a, 0x10, 0xd2, 0xae, 0x11, 0x12, 0xf2, 0x14, 0x21, 0xf6, - 0xe4, 0x4d, 0xa1, 0xeb, 0x71, 0x14, 0x29, 0x9d, 0x3a, 0x9a, 0xb0, 0x5b, 0x1f, 0x44, 0x89, 0x50, - 0x12, 0x22, 0x96, 0x83, 0x2b, 0x60, 0xb2, 0x42, 0x41, 0x53, 0x70, 0x5d, 0x07, 0x6b, 0x9d, 0x90, - 0xd8, 0x87, 0x9c, 0x04, 0xe9, 0xcc, 0x19, 0x00, 0xfd, 0x20, 0xb4, 0xa5, 0xa4, 0x78, 0x4d, 0xdb, - 0xac, 0xff, 0x8f, 0xbc, 0xe6, 0xec, 0xfa, 0x61, 0x33, 0x7e, 0x03, 0xf9, 0x2d, 0xce, 0xa7, 0xa9, - 0x35, 0x85, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRecentTabIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x06, 0x00, 0x00, 0x00, 0xcb, 0xf7, 0x82, - 0xff, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x33, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x5d, 0xda, 0x89, 0x00, 0x00, - 0x04, 0x11, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x9a, 0xcb, 0x6f, 0x0d, 0x51, 0x1c, 0xc7, - 0x5d, 0x55, 0xb4, 0x44, 0x3c, 0x42, 0xbc, 0x42, 0x51, 0x8f, 0xa8, 0x56, 0xda, 0x84, 0x90, 0xc6, - 0x42, 0x54, 0x22, 0xc1, 0x86, 0x58, 0x49, 0x2c, 0x88, 0x34, 0x22, 0x65, 0xc3, 0xdf, 0x80, 0xa5, - 0xc4, 0x63, 0xd9, 0x74, 0x69, 0x61, 0x63, 0xd3, 0x04, 0xf1, 0x08, 0xb1, 0x13, 0x89, 0x54, 0x82, - 0xa6, 0x08, 0x8a, 0x8d, 0x44, 0x28, 0x25, 0x15, 0xd7, 0xe7, 0x7b, 0x73, 0x67, 0x32, 0x3d, 0x9d, - 0xa9, 0x39, 0x73, 0xe7, 0xdc, 0x19, 0xe5, 0x97, 0x7c, 0x73, 0xe6, 0x9c, 0x39, 0xbf, 0xdf, 0xf9, - 0x7e, 0xe7, 0xbc, 0xe6, 0xdc, 0xb9, 0x85, 0x49, 0x01, 0x2b, 0x16, 0x8b, 0xb5, 0x64, 0x8f, 0x81, - 0x6d, 0x60, 0x0d, 0x68, 0x04, 0xf5, 0xc0, 0x95, 0x7d, 0x24, 0xf0, 0xf3, 0x32, 0xae, 0x14, 0x0a, - 0x85, 0xde, 0x54, 0x1a, 0x42, 0x48, 0x3b, 0x78, 0x02, 0xb2, 0xb4, 0xab, 0x34, 0xbe, 0x28, 0xa9, - 0xa0, 0x82, 0x1c, 0x09, 0x30, 0x9f, 0x44, 0x4f, 0x68, 0xb6, 0xf2, 0x19, 0xdb, 0x4d, 0x7a, 0x68, - 0x67, 0x12, 0x0e, 0x93, 0xcb, 0x4e, 0xe7, 0x48, 0xf3, 0x20, 0x44, 0x74, 0x3a, 0x78, 0xb8, 0x07, - 0xca, 0xbc, 0xac, 0x92, 0x02, 0x8e, 0x75, 0x78, 0x7c, 0x05, 0xa5, 0x5e, 0x0a, 0x78, 0xdf, 0xe2, - 0xfa, 0x3a, 0xf8, 0x10, 0x28, 0x4b, 0xf3, 0xb2, 0x86, 0x60, 0x0d, 0xe0, 0x20, 0x58, 0x09, 0x82, - 0x76, 0x87, 0xde, 0xd9, 0x1e, 0x2c, 0x88, 0x75, 0x8d, 0x98, 0x66, 0x60, 0xda, 0xf9, 0x58, 0xce, - 0x29, 0x54, 0xa2, 0xe1, 0x3a, 0xd0, 0x67, 0x10, 0x18, 0x4c, 0x14, 0x9a, 0x20, 0xfb, 0x8c, 0x40, - 0xca, 0x2e, 0x4e, 0x14, 0x2c, 0xa1, 0x13, 0xed, 0x75, 0x86, 0x70, 0x98, 0x61, 0x1b, 0x4e, 0x73, - 0xc6, 0x24, 0x3e, 0x4c, 0x17, 0xbf, 0xb3, 0x0d, 0x54, 0x61, 0xfd, 0x81, 0x10, 0x7f, 0xeb, 0x55, - 0x4d, 0x62, 0xcc, 0xb9, 0xf2, 0x33, 0x24, 0xb0, 0xeb, 0xa2, 0x91, 0x90, 0x06, 0x4c, 0x5e, 0x21, - 0x55, 0x46, 0x17, 0x79, 0xab, 0xd9, 0xe8, 0xd2, 0xbf, 0x34, 0x37, 0xa1, 0xc4, 0x4c, 0x49, 0xda, - 0x09, 0x4c, 0x58, 0x0d, 0x03, 0x6d, 0x6e, 0x1b, 0x80, 0x5e, 0x7d, 0x96, 0x03, 0x2d, 0xb7, 0x49, - 0x6c, 0x4e, 0x88, 0x53, 0x37, 0x6d, 0x7c, 0x2b, 0x97, 0x17, 0x49, 0xdf, 0x03, 0x6d, 0xec, 0xcf, - 0x40, 0x2f, 0xf3, 0xda, 0xbb, 0x47, 0xb6, 0x6c, 0x38, 0x74, 0x81, 0xa0, 0x7d, 0xf6, 0xee, 0x45, - 0xa5, 0x54, 0x6e, 0x01, 0x0f, 0x82, 0x4e, 0x55, 0xbe, 0x7e, 0x45, 0x7b, 0x7b, 0x4d, 0x7e, 0xd6, - 0xc3, 0x8c, 0x20, 0x6d, 0x04, 0x79, 0x08, 0xb6, 0x9a, 0xc1, 0xaa, 0x98, 0xd7, 0x28, 0xb8, 0x06, - 0x97, 0xa3, 0xc1, 0x36, 0xad, 0xc4, 0xe0, 0xac, 0xa1, 0x75, 0x11, 0x24, 0x1e, 0x9e, 0xc1, 0xc6, - 0x53, 0xb8, 0x3e, 0x03, 0xa7, 0x79, 0x5e, 0x1c, 0x2b, 0x31, 0x38, 0xed, 0x06, 0x5b, 0x3c, 0xe7, - 0x1c, 0xa4, 0x12, 0x72, 0xd2, 0xe3, 0x61, 0x2b, 0xa6, 0xd9, 0x73, 0xcc, 0x51, 0xda, 0xe2, 0x71, - 0xb1, 0x15, 0xb3, 0xda, 0x73, 0xcc, 0x51, 0xea, 0x73, 0xb2, 0x15, 0xb3, 0x22, 0x47, 0x22, 0x3c, - 0x2a, 0x0d, 0xde, 0x85, 0xad, 0x98, 0x5a, 0xcf, 0x31, 0x47, 0xa9, 0xcf, 0xc9, 0x56, 0x4c, 0x8e, - 0x34, 0x8c, 0xa5, 0xe2, 0x6a, 0x89, 0xd5, 0x8e, 0x3d, 0x08, 0x94, 0x26, 0x35, 0x1d, 0xe5, 0xa7, - 0xdb, 0x38, 0xbb, 0x10, 0xa3, 0x37, 0x88, 0x56, 0x5e, 0x37, 0x5e, 0xd8, 0x10, 0x31, 0xeb, 0xb2, - 0x7f, 0xe8, 0x18, 0xaf, 0x93, 0xee, 0x26, 0xf3, 0x5e, 0x54, 0xde, 0xc5, 0x30, 0x1b, 0xa8, 0x54, - 0x88, 0xc8, 0x12, 0xe3, 0x13, 0x89, 0xde, 0x34, 0x62, 0x9b, 0x6d, 0xcf, 0xc4, 0x39, 0x63, 0xb4, - 0xf2, 0x54, 0x2f, 0xc0, 0xe0, 0x76, 0x6c, 0x16, 0xe1, 0x15, 0xd7, 0x51, 0xac, 0xdf, 0x07, 0x62, - 0x9b, 0xad, 0x98, 0xb8, 0x73, 0xe0, 0x38, 0x0c, 0x84, 0xaa, 0x9a, 0x8b, 0x61, 0x56, 0x55, 0x01, - 0xc1, 0xc6, 0xfe, 0x8b, 0x09, 0x3e, 0x8d, 0x3c, 0x5d, 0xdb, 0xce, 0x99, 0xb8, 0xdc, 0xbb, 0xa9, - 0x78, 0x0f, 0xc4, 0x9d, 0x63, 0x61, 0x71, 0x75, 0x7a, 0x3d, 0x01, 0x62, 0xff, 0xe4, 0xe4, 0x42, - 0xcc, 0x23, 0x96, 0xd5, 0xc3, 0x61, 0xec, 0x6c, 0xcb, 0x58, 0x15, 0xe7, 0xe2, 0xd3, 0x19, 0xd7, - 0xcf, 0xc5, 0x9c, 0x59, 0x05, 0x89, 0x25, 0x71, 0x09, 0x44, 0xd5, 0x23, 0x86, 0x7a, 0xa4, 0x35, - 0xea, 0x7e, 0x58, 0xb9, 0x8b, 0x9e, 0x99, 0x45, 0x43, 0x3a, 0xa3, 0xeb, 0xc7, 0x87, 0x4a, 0x6c, - 0x29, 0xce, 0x8a, 0x15, 0xdb, 0x5c, 0x88, 0x51, 0xe3, 0x8a, 0xbb, 0x3e, 0x36, 0x8b, 0x94, 0x2a, - 0xba, 0x18, 0x66, 0x29, 0x51, 0xb3, 0x0f, 0x33, 0xa1, 0xc4, 0xb8, 0x1a, 0x66, 0xbf, 0x78, 0xae, - 0xaf, 0x41, 0xd4, 0xd2, 0xac, 0x77, 0xbc, 0x65, 0x20, 0xd5, 0x87, 0xe9, 0x42, 0xcc, 0x17, 0x48, - 0x6e, 0x64, 0x79, 0x7e, 0x49, 0x1a, 0x69, 0x2c, 0x10, 0x3a, 0xbb, 0x3f, 0x06, 0x56, 0x67, 0x96, - 0xc8, 0x80, 0xdc, 0x48, 0xf5, 0xc9, 0x94, 0x1b, 0xea, 0xff, 0x93, 0x10, 0xd5, 0xa3, 0x4e, 0x3f, - 0x89, 0x7a, 0x2f, 0x35, 0x73, 0xd1, 0x33, 0x6d, 0x3c, 0xf5, 0x4b, 0x30, 0xbc, 0x0b, 0xc6, 0x1b, - 0x66, 0x1d, 0xdc, 0xd7, 0x2e, 0x9f, 0x9a, 0x49, 0xcc, 0x77, 0x23, 0x5a, 0x3d, 0x64, 0x6a, 0x79, - 0x72, 0x95, 0x7c, 0x33, 0xd1, 0x7f, 0x09, 0x84, 0xaa, 0x9a, 0x86, 0x99, 0xf9, 0xd5, 0x4a, 0xbf, - 0xe4, 0x6f, 0x8e, 0x60, 0x11, 0xf5, 0xa4, 0x23, 0xaa, 0x57, 0xb7, 0x58, 0x62, 0x34, 0x76, 0x4d, - 0xbb, 0x4c, 0xef, 0xac, 0x35, 0x0b, 0xf3, 0x9e, 0xd7, 0xa7, 0x73, 0x2d, 0x93, 0xfa, 0x86, 0xb9, - 0xd0, 0x20, 0xeb, 0x2d, 0xaf, 0xc1, 0x4f, 0xe7, 0xfa, 0x16, 0x33, 0xd3, 0xa8, 0x97, 0x75, 0x76, - 0x84, 0x29, 0x31, 0x55, 0x24, 0x4a, 0x67, 0x7a, 0x04, 0x1d, 0xe2, 0xba, 0x27, 0x6b, 0x56, 0x09, - 0xdb, 0x1f, 0x23, 0x46, 0xa2, 0x6e, 0x80, 0x1d, 0x09, 0x03, 0x66, 0xe9, 0xe6, 0x8b, 0x29, 0xed, - 0x33, 0x74, 0x93, 0x26, 0xf6, 0x2e, 0x70, 0x0a, 0x0c, 0x65, 0xc9, 0xac, 0x92, 0xb6, 0x4b, 0xc3, - 0x2c, 0x18, 0x80, 0x21, 0xa7, 0x5f, 0x12, 0xf5, 0x75, 0x4c, 0x7b, 0x80, 0x76, 0xe9, 0xe0, 0x49, - 0x6f, 0x0f, 0xf9, 0x05, 0x20, 0x4f, 0xe6, 0xf7, 0xcc, 0x18, 0x31, 0xe3, 0xb1, 0x44, 0xe8, 0x7d, - 0xee, 0xb7, 0x8f, 0x57, 0x27, 0x83, 0x7b, 0xbe, 0x98, 0xd2, 0x30, 0xcb, 0x80, 0x80, 0x93, 0x26, - 0xff, 0x69, 0x31, 0xda, 0x7b, 0xf2, 0x66, 0x3e, 0x27, 0xdb, 0x9e, 0x79, 0x93, 0x37, 0x25, 0xf0, - 0xf1, 0x39, 0xd9, 0x8a, 0xa9, 0xf4, 0x47, 0x0a, 0x17, 0xcf, 0xc2, 0xe7, 0x64, 0x2b, 0xe6, 0xa9, - 0x0b, 0x36, 0x15, 0xc6, 0xf4, 0x39, 0xd9, 0x2e, 0xcd, 0xd3, 0x68, 0xb8, 0x0f, 0x34, 0x56, 0x48, - 0x20, 0x2d, 0xf7, 0x61, 0x02, 0x35, 0xb1, 0xe9, 0x97, 0x4e, 0xb5, 0x56, 0x3d, 0x83, 0xd3, 0x0f, - 0x9c, 0xbb, 0xd2, 0x62, 0x92, 0x42, 0x9c, 0xb3, 0x9e, 0x90, 0xc4, 0xb1, 0xd8, 0x3c, 0xf7, 0x83, - 0xb7, 0x20, 0x2b, 0x1b, 0xa2, 0xe1, 0xd3, 0x40, 0x87, 0x4b, 0xdf, 0xac, 0x86, 0x99, 0xef, 0xc5, - 0x05, 0x81, 0x74, 0x14, 0x38, 0x02, 0x9a, 0x80, 0x5e, 0x7d, 0x1a, 0x40, 0x0d, 0x70, 0x61, 0x7a, - 0x77, 0xd4, 0x5f, 0xb4, 0xf4, 0xf7, 0x2c, 0x4d, 0xf8, 0x1e, 0x7a, 0xc4, 0x5f, 0xc5, 0xc8, 0x4f, - 0x3c, 0xfb, 0x0d, 0x29, 0x80, 0xc0, 0x68, 0xf7, 0x99, 0xb2, 0x13, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXMoveIcon[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x7a, 0x91, 0xda, - 0x8e, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x8e, 0x45, 0x3c, 0x00, 0x00, - 0x02, 0xa9, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x97, 0x3b, 0x68, 0x14, 0x51, 0x14, 0x86, - 0x77, 0x4c, 0x14, 0x1f, 0x60, 0x20, 0x22, 0x82, 0x8f, 0x80, 0x10, 0xd1, 0xa8, 0x08, 0x0a, 0x42, - 0x8a, 0x58, 0x18, 0x11, 0x8c, 0xa0, 0x95, 0x85, 0x69, 0xd2, 0x89, 0xa0, 0x8d, 0xd8, 0x58, 0x58, - 0x2b, 0xd8, 0x89, 0x95, 0x85, 0xd8, 0x68, 0x21, 0xd8, 0x88, 0x92, 0x20, 0x5a, 0xd9, 0x58, 0x85, - 0x24, 0x45, 0x50, 0x41, 0xc4, 0x80, 0x0a, 0xd1, 0x90, 0xd7, 0x82, 0x12, 0x0c, 0x71, 0xfd, 0x4e, - 0x9c, 0xbb, 0x9c, 0x3d, 0xf7, 0xcc, 0xce, 0xce, 0x82, 0x58, 0xb8, 0x17, 0x7e, 0xce, 0xeb, 0xff, - 0xcf, 0xbd, 0x73, 0x77, 0x76, 0xe6, 0x4e, 0xa9, 0xf4, 0x0f, 0x46, 0xa5, 0x52, 0x59, 0x03, 0x8e, - 0x8b, 0x6d, 0x7a, 0x7a, 0xc4, 0x9d, 0xe0, 0x04, 0x38, 0x07, 0xba, 0x41, 0xd2, 0x4c, 0x33, 0x74, - 0xb2, 0x98, 0xe7, 0x40, 0xc6, 0x30, 0x28, 0xd6, 0x07, 0xc1, 0x25, 0x30, 0x05, 0xec, 0x58, 0x24, - 0xf1, 0x00, 0x74, 0x16, 0x59, 0x18, 0xfc, 0x6b, 0xa6, 0xd1, 0xd5, 0x86, 0xf4, 0x88, 0xb6, 0x01, - 0xb9, 0x82, 0xbc, 0xf1, 0x05, 0xc2, 0xc9, 0x46, 0x9a, 0xc2, 0x3b, 0x02, 0x7e, 0x9a, 0x86, 0x4b, - 0xc4, 0x87, 0x72, 0xf5, 0x90, 0x5e, 0x19, 0x61, 0xbd, 0x50, 0x26, 0xd9, 0x57, 0xaf, 0x29, 0xf5, - 0x8d, 0xe0, 0x5d, 0x46, 0x93, 0x49, 0xf2, 0xeb, 0x33, 0xf5, 0x14, 0x07, 0x8d, 0x70, 0x8e, 0x58, - 0x7e, 0xba, 0x03, 0x60, 0x3b, 0x38, 0x0d, 0xec, 0x82, 0x5f, 0x66, 0x36, 0xa4, 0x00, 0xff, 0x2e, - 0xa8, 0x37, 0xee, 0xb8, 0x7a, 0x14, 0x6b, 0xc1, 0x67, 0xa5, 0xfc, 0x86, 0xbf, 0xcb, 0x92, 0xc9, - 0xc9, 0xcd, 0x79, 0x4f, 0xf1, 0xc4, 0x3d, 0x6b, 0x79, 0x12, 0x4b, 0xde, 0xf0, 0xb2, 0xc2, 0x53, - 0x91, 0x1e, 0x66, 0x8f, 0x61, 0x5f, 0x88, 0x48, 0x69, 0x02, 0x5e, 0x07, 0xf8, 0xaa, 0xf8, 0xb7, - 0x2d, 0x97, 0x5a, 0x3b, 0xf8, 0xa4, 0x38, 0xf5, 0xdc, 0x8f, 0xde, 0x73, 0x60, 0xbf, 0x69, 0xfa, - 0xd8, 0xc4, 0xd5, 0x30, 0x49, 0x92, 0x45, 0x82, 0x17, 0xd5, 0x44, 0xa9, 0x64, 0xb5, 0x52, 0x92, - 0xbf, 0xf5, 0xa4, 0xe2, 0xd4, 0x73, 0xdf, 0xb4, 0x3b, 0xd5, 0x1e, 0x95, 0x9b, 0x66, 0xd2, 0x05, - 0x15, 0x7b, 0xee, 0x5b, 0x95, 0x8c, 0x16, 0x84, 0x7e, 0x99, 0xfa, 0x00, 0xdb, 0xb2, 0x19, 0xdb, - 0x06, 0x7a, 0xc1, 0x08, 0x08, 0xa3, 0x1f, 0x67, 0x02, 0xac, 0xc0, 0x2d, 0x7b, 0x0b, 0xda, 0x19, - 0x98, 0xd8, 0x39, 0xe5, 0x67, 0xb9, 0xb3, 0xaa, 0xb0, 0x83, 0x89, 0xe9, 0x9b, 0x54, 0x54, 0x6e, - 0xd5, 0x95, 0xc9, 0xc4, 0xa1, 0xbe, 0x6a, 0x55, 0xbd, 0x4c, 0x6d, 0x3e, 0xc4, 0xde, 0x4f, 0x16, - 0x6a, 0xcd, 0xda, 0x62, 0x4f, 0x5e, 0x33, 0xcb, 0xdf, 0x58, 0x90, 0x99, 0xa2, 0x58, 0xd8, 0x5a, - 0x50, 0xde, 0x7e, 0xb5, 0x76, 0xa8, 0xb5, 0x43, 0x79, 0x3b, 0x90, 0x57, 0x6f, 0xdd, 0x43, 0xff, - 0xe5, 0x0e, 0x55, 0xdf, 0x43, 0xe9, 0xd5, 0x6f, 0xc8, 0xd9, 0x05, 0x5b, 0xaf, 0x7d, 0x5f, 0xf2, - 0xb2, 0xdb, 0x03, 0x9e, 0x80, 0x0f, 0x29, 0xca, 0xd8, 0x30, 0xe4, 0x68, 0x1a, 0xf2, 0xaf, 0xf1, - 0xfb, 0xed, 0x64, 0xe4, 0x0e, 0x06, 0x72, 0x6a, 0x0f, 0x5b, 0x8e, 0x8e, 0xe1, 0xc8, 0xc9, 0x33, - 0x8c, 0x1f, 0x38, 0xb5, 0xf7, 0x31, 0x89, 0xf3, 0xa1, 0xda, 0x80, 0x8d, 0x8e, 0x99, 0x68, 0xd6, - 0x81, 0x65, 0xa5, 0xbd, 0xa2, 0x17, 0x60, 0x7d, 0x78, 0x8f, 0x14, 0x77, 0xdc, 0xd6, 0xe5, 0x38, - 0x20, 0x47, 0xd6, 0x51, 0x45, 0xca, 0x72, 0x17, 0x28, 0x74, 0x45, 0x0d, 0x48, 0x90, 0x9f, 0x50, - 0xa2, 0x59, 0xfc, 0x2d, 0x19, 0xbc, 0x5e, 0x6a, 0xbf, 0x14, 0xf7, 0xbe, 0xc7, 0x93, 0x86, 0x7b, - 0xc1, 0x77, 0x45, 0xf4, 0xdc, 0x41, 0x57, 0xfc, 0x67, 0x41, 0x67, 0x8c, 0xe0, 0x3d, 0x71, 0x5f, - 0xe0, 0xe3, 0xb7, 0x01, 0xf9, 0x25, 0xe6, 0x41, 0x18, 0x4b, 0x38, 0xdd, 0x81, 0x13, 0x59, 0x8a, - 0x17, 0x03, 0xd3, 0xb1, 0x0f, 0x23, 0x81, 0x49, 0xa0, 0x79, 0xe6, 0xe8, 0xe4, 0x6b, 0x65, 0x0c, - 0x78, 0x17, 0x7b, 0xc3, 0xb4, 0x88, 0x43, 0x84, 0x4f, 0x9d, 0xa6, 0x53, 0xe4, 0x3a, 0x62, 0x76, - 0x6d, 0x06, 0x4e, 0x17, 0x18, 0x77, 0xf4, 0x5e, 0x6a, 0x84, 0xe4, 0xa6, 0xda, 0x0e, 0x4e, 0x04, - 0x69, 0x2b, 0x98, 0x56, 0x1d, 0x56, 0xf0, 0x8f, 0x39, 0x54, 0x37, 0x05, 0x57, 0x6e, 0xf0, 0x5b, - 0x40, 0x74, 0xde, 0x90, 0x7f, 0xd5, 0x65, 0x57, 0x9c, 0x26, 0xa3, 0xe3, 0x26, 0x82, 0x01, 0x6a, - 0xc3, 0x40, 0x6a, 0x37, 0x39, 0xef, 0x5e, 0x4f, 0xb9, 0x0d, 0x1b, 0x7a, 0xc8, 0x77, 0xdc, 0x51, - 0x20, 0x8f, 0x80, 0xdd, 0x40, 0x3e, 0x04, 0xc6, 0xc0, 0x28, 0xfd, 0x66, 0xb0, 0xc5, 0x06, 0x0d, - 0xfb, 0xc0, 0x10, 0x88, 0x16, 0x5c, 0xac, 0x53, 0x71, 0xf6, 0x6f, 0x9b, 0x02, 0x54, 0xeb, 0x7d, - 0xaa, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXMoveIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x7a, 0x91, 0xda, - 0x8e, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x8e, 0x45, 0x3c, 0x00, 0x00, - 0x02, 0xa9, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x97, 0x3b, 0x68, 0x14, 0x51, 0x14, 0x86, - 0x77, 0x4c, 0x14, 0x1f, 0x60, 0x20, 0x22, 0x82, 0x8f, 0x80, 0x10, 0xd1, 0xa8, 0x08, 0x0a, 0x42, - 0x8a, 0x58, 0x18, 0x11, 0x8c, 0xa0, 0x95, 0x85, 0x69, 0xd2, 0x89, 0xa0, 0x8d, 0xd8, 0x58, 0x58, - 0x2b, 0xd8, 0x89, 0x95, 0x85, 0xd8, 0x68, 0x21, 0xd8, 0x88, 0x92, 0x20, 0x5a, 0xd9, 0x58, 0x85, - 0x24, 0x45, 0x50, 0x41, 0xc4, 0x80, 0x0a, 0xd1, 0x90, 0xd7, 0x82, 0x12, 0x0c, 0x71, 0xfd, 0x4e, - 0x9c, 0xbb, 0x9c, 0x3d, 0xf7, 0xcc, 0xce, 0xce, 0x82, 0x58, 0xb8, 0x17, 0x7e, 0xce, 0xeb, 0xff, - 0xcf, 0xbd, 0x73, 0x77, 0x76, 0xe6, 0x4e, 0xa9, 0xf4, 0x0f, 0x46, 0xa5, 0x52, 0x59, 0x03, 0x8e, - 0x8b, 0x6d, 0x7a, 0x7a, 0xc4, 0x9d, 0xe0, 0x04, 0x38, 0x07, 0xba, 0x41, 0xd2, 0x4c, 0x33, 0x74, - 0xb2, 0x98, 0xe7, 0x40, 0xc6, 0x30, 0x28, 0xd6, 0x07, 0xc1, 0x25, 0x30, 0x05, 0xec, 0x58, 0x24, - 0xf1, 0x00, 0x74, 0x16, 0x59, 0x18, 0xfc, 0x6b, 0xa6, 0xd1, 0xd5, 0x86, 0xf4, 0x88, 0xb6, 0x01, - 0xb9, 0x82, 0xbc, 0xf1, 0x05, 0xc2, 0xc9, 0x46, 0x9a, 0xc2, 0x3b, 0x02, 0x7e, 0x9a, 0x86, 0x4b, - 0xc4, 0x87, 0x72, 0xf5, 0x90, 0x5e, 0x19, 0x61, 0xbd, 0x50, 0x26, 0xd9, 0x57, 0xaf, 0x29, 0xf5, - 0x8d, 0xe0, 0x5d, 0x46, 0x93, 0x49, 0xf2, 0xeb, 0x33, 0xf5, 0x14, 0x07, 0x8d, 0x70, 0x8e, 0x58, - 0x7e, 0xba, 0x03, 0x60, 0x3b, 0x38, 0x0d, 0xec, 0x82, 0x5f, 0x66, 0x36, 0xa4, 0x00, 0xff, 0x2e, - 0xa8, 0x37, 0xee, 0xb8, 0x7a, 0x14, 0x6b, 0xc1, 0x67, 0xa5, 0xfc, 0x86, 0xbf, 0xcb, 0x92, 0xc9, - 0xc9, 0xcd, 0x79, 0x4f, 0xf1, 0xc4, 0x3d, 0x6b, 0x79, 0x12, 0x4b, 0xde, 0xf0, 0xb2, 0xc2, 0x53, - 0x91, 0x1e, 0x66, 0x8f, 0x61, 0x5f, 0x88, 0x48, 0x69, 0x02, 0x5e, 0x07, 0xf8, 0xaa, 0xf8, 0xb7, - 0x2d, 0x97, 0x5a, 0x3b, 0xf8, 0xa4, 0x38, 0xf5, 0xdc, 0x8f, 0xde, 0x73, 0x60, 0xbf, 0x69, 0xfa, - 0xd8, 0xc4, 0xd5, 0x30, 0x49, 0x92, 0x45, 0x82, 0x17, 0xd5, 0x44, 0xa9, 0x64, 0xb5, 0x52, 0x92, - 0xbf, 0xf5, 0xa4, 0xe2, 0xd4, 0x73, 0xdf, 0xb4, 0x3b, 0xd5, 0x1e, 0x95, 0x9b, 0x66, 0xd2, 0x05, - 0x15, 0x7b, 0xee, 0x5b, 0x95, 0x8c, 0x16, 0x84, 0x7e, 0x99, 0xfa, 0x00, 0xdb, 0xb2, 0x19, 0xdb, - 0x06, 0x7a, 0xc1, 0x08, 0x08, 0xa3, 0x1f, 0x67, 0x02, 0xac, 0xc0, 0x2d, 0x7b, 0x0b, 0xda, 0x19, - 0x98, 0xd8, 0x39, 0xe5, 0x67, 0xb9, 0xb3, 0xaa, 0xb0, 0x83, 0x89, 0xe9, 0x9b, 0x54, 0x54, 0x6e, - 0xd5, 0x95, 0xc9, 0xc4, 0xa1, 0xbe, 0x6a, 0x55, 0xbd, 0x4c, 0x6d, 0x3e, 0xc4, 0xde, 0x4f, 0x16, - 0x6a, 0xcd, 0xda, 0x62, 0x4f, 0x5e, 0x33, 0xcb, 0xdf, 0x58, 0x90, 0x99, 0xa2, 0x58, 0xd8, 0x5a, - 0x50, 0xde, 0x7e, 0xb5, 0x76, 0xa8, 0xb5, 0x43, 0x79, 0x3b, 0x90, 0x57, 0x6f, 0xdd, 0x43, 0xff, - 0xe5, 0x0e, 0x55, 0xdf, 0x43, 0xe9, 0xd5, 0x6f, 0xc8, 0xd9, 0x05, 0x5b, 0xaf, 0x7d, 0x5f, 0xf2, - 0xb2, 0xdb, 0x03, 0x9e, 0x80, 0x0f, 0x29, 0xca, 0xd8, 0x30, 0xe4, 0x68, 0x1a, 0xf2, 0xaf, 0xf1, - 0xfb, 0xed, 0x64, 0xe4, 0x0e, 0x06, 0x72, 0x6a, 0x0f, 0x5b, 0x8e, 0x8e, 0xe1, 0xc8, 0xc9, 0x33, - 0x8c, 0x1f, 0x38, 0xb5, 0xf7, 0x31, 0x89, 0xf3, 0xa1, 0xda, 0x80, 0x8d, 0x8e, 0x99, 0x68, 0xd6, - 0x81, 0x65, 0xa5, 0xbd, 0xa2, 0x17, 0x60, 0x7d, 0x78, 0x8f, 0x14, 0x77, 0xdc, 0xd6, 0xe5, 0x38, - 0x20, 0x47, 0xd6, 0x51, 0x45, 0xca, 0x72, 0x17, 0x28, 0x74, 0x45, 0x0d, 0x48, 0x90, 0x9f, 0x50, - 0xa2, 0x59, 0xfc, 0x2d, 0x19, 0xbc, 0x5e, 0x6a, 0xbf, 0x14, 0xf7, 0xbe, 0xc7, 0x93, 0x86, 0x7b, - 0xc1, 0x77, 0x45, 0xf4, 0xdc, 0x41, 0x57, 0xfc, 0x67, 0x41, 0x67, 0x8c, 0xe0, 0x3d, 0x71, 0x5f, - 0xe0, 0xe3, 0xb7, 0x01, 0xf9, 0x25, 0xe6, 0x41, 0x18, 0x4b, 0x38, 0xdd, 0x81, 0x13, 0x59, 0x8a, - 0x17, 0x03, 0xd3, 0xb1, 0x0f, 0x23, 0x81, 0x49, 0xa0, 0x79, 0xe6, 0xe8, 0xe4, 0x6b, 0x65, 0x0c, - 0x78, 0x17, 0x7b, 0xc3, 0xb4, 0x88, 0x43, 0x84, 0x4f, 0x9d, 0xa6, 0x53, 0xe4, 0x3a, 0x62, 0x76, - 0x6d, 0x06, 0x4e, 0x17, 0x18, 0x77, 0xf4, 0x5e, 0x6a, 0x84, 0xe4, 0xa6, 0xda, 0x0e, 0x4e, 0x04, - 0x69, 0x2b, 0x98, 0x56, 0x1d, 0x56, 0xf0, 0x8f, 0x39, 0x54, 0x37, 0x05, 0x57, 0x6e, 0xf0, 0x5b, - 0x40, 0x74, 0xde, 0x90, 0x7f, 0xd5, 0x65, 0x57, 0x9c, 0x26, 0xa3, 0xe3, 0x26, 0x82, 0x01, 0x6a, - 0xc3, 0x40, 0x6a, 0x37, 0x39, 0xef, 0x5e, 0x4f, 0xb9, 0x0d, 0x1b, 0x7a, 0xc8, 0x77, 0xdc, 0x51, - 0x20, 0x8f, 0x80, 0xdd, 0x40, 0x3e, 0x04, 0xc6, 0xc0, 0x28, 0xfd, 0x66, 0xb0, 0xc5, 0x06, 0x0d, - 0xfb, 0xc0, 0x10, 0x88, 0x16, 0x5c, 0xac, 0x53, 0x71, 0xf6, 0x6f, 0x9b, 0x02, 0x54, 0xeb, 0x7d, - 0xaa, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXMoveIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5a, 0x1c, 0x89, - 0xc0, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x03, 0xdb, 0x04, 0x00, 0x00, - 0x04, 0x37, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x9a, 0x5b, 0x88, 0x8d, 0x51, 0x14, 0xc7, - 0xcf, 0x71, 0x8b, 0x71, 0x9b, 0xdc, 0x72, 0x8f, 0x22, 0x11, 0x73, 0x49, 0x4a, 0xb9, 0x24, 0x45, - 0xd2, 0x24, 0x25, 0xc2, 0x8b, 0xbc, 0xe0, 0x49, 0x52, 0xca, 0x25, 0xa4, 0xa6, 0x14, 0x4f, 0xca, - 0x93, 0xa4, 0x10, 0x29, 0xb7, 0x21, 0x2f, 0xf2, 0xe4, 0x49, 0x79, 0x10, 0xc6, 0x25, 0xa2, 0x91, - 0x72, 0x1d, 0x63, 0x34, 0xc8, 0x8c, 0xdb, 0xf8, 0xad, 0xa9, 0x73, 0x7c, 0xdf, 0x3e, 0x6b, 0xed, - 0xfd, 0x7d, 0xc7, 0xd0, 0x51, 0x67, 0xd5, 0xbf, 0xd9, 0xfb, 0xbf, 0xd6, 0xfa, 0xaf, 0xfd, 0x7d, - 0xfb, 0x3b, 0xfb, 0x7c, 0xb3, 0xf7, 0xc9, 0x64, 0xfe, 0x43, 0xeb, 0xec, 0xec, 0xac, 0xf8, 0x0f, - 0x87, 0xed, 0x1f, 0x32, 0x17, 0xb5, 0x13, 0x7c, 0x03, 0xf7, 0xc0, 0x18, 0x2b, 0x3a, 0x6b, 0x39, - 0x42, 0x3c, 0xa2, 0x7d, 0x88, 0x99, 0x0f, 0xa6, 0x82, 0x91, 0x60, 0x00, 0x78, 0x03, 0x5e, 0x82, - 0xeb, 0xd9, 0x6c, 0xb6, 0x89, 0xbf, 0xdd, 0x6a, 0xd4, 0x5c, 0x8e, 0xe0, 0xc5, 0x88, 0xe8, 0x0d, - 0xda, 0xf3, 0xa8, 0xf5, 0x23, 0xc2, 0x15, 0xd7, 0x44, 0x7c, 0x22, 0x38, 0x0e, 0xda, 0x80, 0xcf, - 0xe4, 0x8e, 0x6e, 0x00, 0x3d, 0x8b, 0xab, 0x14, 0xcf, 0x42, 0x67, 0x14, 0x78, 0x07, 0x5c, 0xdb, - 0x13, 0x8f, 0x4c, 0xd9, 0x43, 0x2d, 0x0b, 0xf6, 0x82, 0x76, 0x90, 0xc6, 0xee, 0x13, 0x5c, 0x9d, - 0xb2, 0x5c, 0x2c, 0x9c, 0x7c, 0xa9, 0x7d, 0xd5, 0x28, 0x2a, 0x8f, 0xe5, 0xec, 0x58, 0x42, 0xd2, - 0x0e, 0x89, 0x7d, 0xc0, 0x29, 0x43, 0x38, 0x09, 0x2d, 0xb3, 0xbb, 0x38, 0x69, 0x3d, 0x37, 0x8e, - 0xdc, 0x2d, 0x81, 0x22, 0x4f, 0xf0, 0xcb, 0x47, 0x21, 0x9d, 0x91, 0xb4, 0x3b, 0x20, 0x9c, 0xc4, - 0x2d, 0x17, 0x37, 0x3a, 0x5d, 0xe5, 0x4c, 0x86, 0x9c, 0x2a, 0x90, 0xe4, 0x29, 0x39, 0x96, 0x4a, - 0x1b, 0xd1, 0xf1, 0xe0, 0x33, 0xb0, 0xec, 0x15, 0x8e, 0x2b, 0xe0, 0x28, 0xb8, 0x09, 0xbe, 0x00, - 0xcb, 0x4e, 0xa7, 0x29, 0x8e, 0x48, 0x5f, 0xd0, 0x68, 0x89, 0x29, 0xfc, 0x8a, 0xc4, 0xfa, 0x24, - 0x9f, 0x55, 0x04, 0x84, 0x7a, 0x04, 0x66, 0xb9, 0x42, 0x70, 0xbd, 0xc0, 0x76, 0xf0, 0x15, 0x68, - 0xb6, 0xc0, 0xcd, 0xb1, 0xfa, 0x24, 0x1f, 0xd2, 0x04, 0x3c, 0x5c, 0x0b, 0xbe, 0xf0, 0x53, 0x41, - 0xd0, 0x42, 0x43, 0xa4, 0x01, 0xde, 0xfb, 0x25, 0x89, 0xbf, 0x16, 0x48, 0x21, 0xd7, 0x64, 0xb5, - 0xec, 0x65, 0x5d, 0x4c, 0x8e, 0x27, 0x66, 0x09, 0xf8, 0xe9, 0x26, 0x27, 0xe8, 0x5f, 0x23, 0xc6, - 0xff, 0x35, 0x46, 0xc0, 0x39, 0x45, 0xe8, 0x03, 0xdc, 0x88, 0xdc, 0x00, 0x7c, 0x7f, 0x89, 0xdb, - 0xa4, 0xe4, 0x0b, 0xb5, 0x28, 0x90, 0x57, 0x49, 0x8c, 0x3c, 0xe2, 0xc5, 0xda, 0x66, 0x53, 0x1f, - 0x45, 0x59, 0x62, 0x9b, 0x15, 0xe5, 0xad, 0x66, 0x92, 0xe3, 0x20, 0xb7, 0x07, 0xb8, 0xa5, 0x68, - 0xec, 0x77, 0x42, 0x63, 0x5d, 0xe2, 0x77, 0x28, 0x39, 0x69, 0xa8, 0xb7, 0x3d, 0x62, 0x8a, 0xf1, - 0xce, 0x14, 0xba, 0xc3, 0xe2, 0x54, 0x57, 0xaf, 0x41, 0xe1, 0x54, 0x8a, 0x37, 0x82, 0x9f, 0x38, - 0x2e, 0x29, 0xce, 0x79, 0x0a, 0x17, 0xa5, 0xbc, 0x8f, 0x79, 0x34, 0xd0, 0x68, 0x57, 0xf8, 0x9e, - 0xf5, 0x51, 0x4a, 0x52, 0x3b, 0xdc, 0x33, 0x85, 0xf7, 0x51, 0x0f, 0x15, 0x67, 0xe8, 0x03, 0x5e, - 0x4f, 0x4e, 0x33, 0x90, 0xd7, 0xb5, 0xe8, 0x9b, 0xcb, 0x2a, 0xfa, 0x83, 0x41, 0xd4, 0xae, 0xd2, - 0x79, 0x1e, 0x21, 0x5a, 0x68, 0x9f, 0x8b, 0xf4, 0xe3, 0x4d, 0xe6, 0x7d, 0xa5, 0x32, 0xf7, 0x77, - 0xe2, 0x51, 0xe1, 0x1e, 0x1a, 0xd3, 0x15, 0x9d, 0xb6, 0x70, 0x66, 0x61, 0x04, 0x3a, 0xb2, 0x12, - 0xbb, 0x56, 0x57, 0x18, 0x99, 0xc9, 0xf8, 0x1e, 0x45, 0xf7, 0xce, 0x48, 0x7e, 0xab, 0x26, 0x12, - 0xe0, 0xb4, 0x9c, 0x81, 0x8c, 0xce, 0x57, 0x3b, 0x20, 0x19, 0x76, 0xfb, 0xc4, 0xfd, 0x4b, 0x66, - 0x58, 0x3b, 0x14, 0xf1, 0x57, 0xf5, 0x7d, 0x17, 0x16, 0x1a, 0x58, 0x49, 0xfb, 0xcb, 0x17, 0x56, - 0xd2, 0xd3, 0xa3, 0x0c, 0xae, 0x3c, 0x63, 0xca, 0x4d, 0x29, 0x69, 0xaa, 0x3c, 0x63, 0x25, 0x3d, - 0x3d, 0xca, 0xe0, 0xca, 0x33, 0xa6, 0xdc, 0x94, 0x92, 0xa6, 0xca, 0x33, 0x56, 0xd2, 0xd3, 0xa3, - 0x0c, 0xae, 0x3c, 0x63, 0xca, 0x4d, 0x29, 0x69, 0xaa, 0x3c, 0x63, 0x25, 0x3d, 0x3d, 0xca, 0xe0, - 0xca, 0x33, 0xa6, 0xdc, 0x94, 0xa4, 0x54, 0x87, 0x11, 0xe8, 0xdb, 0x6f, 0x31, 0x52, 0x32, 0xbd, - 0x15, 0x87, 0xec, 0xc3, 0x14, 0x58, 0x97, 0x38, 0xff, 0xa6, 0xf7, 0xc7, 0x53, 0x0b, 0x2a, 0x23, - 0x11, 0x55, 0x91, 0x76, 0xae, 0x39, 0x94, 0xd8, 0xe8, 0x1e, 0xc3, 0x37, 0x1c, 0x8d, 0xec, 0x46, - 0xc9, 0x99, 0x98, 0x65, 0xef, 0x71, 0xc8, 0x6e, 0x95, 0xfb, 0x74, 0x4c, 0x82, 0xbb, 0x6f, 0x25, - 0xb9, 0x3c, 0x75, 0xe5, 0xa2, 0xc6, 0xb9, 0x3c, 0x7d, 0xd9, 0xbc, 0x29, 0x34, 0x12, 0x06, 0x80, - 0x26, 0x50, 0xac, 0x7d, 0x27, 0x31, 0xb4, 0x01, 0xaa, 0xed, 0x4f, 0xae, 0x2c, 0x1c, 0x8d, 0xcd, - 0x50, 0x63, 0x9a, 0x31, 0xc0, 0xb1, 0x5a, 0x96, 0xdc, 0x45, 0x99, 0xa5, 0x09, 0x9a, 0x33, 0x21, - 0x27, 0xdb, 0x63, 0x33, 0x02, 0xb1, 0xda, 0xee, 0xd6, 0xcc, 0x40, 0x8e, 0xeb, 0xd6, 0xe2, 0xe5, - 0x69, 0x78, 0xe1, 0x06, 0xe6, 0xfb, 0xdc, 0x09, 0x39, 0x2d, 0x29, 0xd6, 0xe4, 0x24, 0x46, 0xdb, - 0x83, 0x8c, 0xea, 0xcb, 0xb9, 0xb1, 0x6b, 0x1f, 0x21, 0x42, 0xfb, 0x8b, 0x5d, 0x1a, 0xc4, 0xc9, - 0xf9, 0xdc, 0x63, 0x57, 0x80, 0xfe, 0x85, 0x7c, 0x11, 0xad, 0x41, 0xc0, 0x38, 0xd0, 0xaa, 0x24, - 0x26, 0xa1, 0x36, 0x69, 0x9a, 0x51, 0x0e, 0x11, 0xd9, 0x5b, 0xfc, 0xa1, 0x88, 0x9d, 0x89, 0xc6, - 0x59, 0x6d, 0xf2, 0xe4, 0xf4, 0x46, 0xb3, 0x75, 0x56, 0x4e, 0x9e, 0x27, 0x6b, 0xb5, 0x96, 0x19, - 0xe0, 0x2e, 0xe7, 0x05, 0x02, 0x0d, 0x74, 0x8e, 0x18, 0x5a, 0xe7, 0xe1, 0x87, 0x6a, 0xe9, 0xf0, - 0x32, 0x53, 0x07, 0x80, 0x76, 0xea, 0x22, 0x67, 0x02, 0xee, 0x82, 0xa4, 0xc9, 0x74, 0x9d, 0x1e, - 0x9e, 0x24, 0x38, 0xa9, 0xbd, 0x26, 0x70, 0xb8, 0xae, 0x54, 0xc8, 0x12, 0x2b, 0x2b, 0xaa, 0x76, - 0xac, 0x24, 0xf5, 0xe4, 0x64, 0xe5, 0x20, 0x58, 0x0b, 0x6a, 0xc0, 0x32, 0xb0, 0x0f, 0xdc, 0x05, - 0x96, 0xcd, 0x29, 0xac, 0x62, 0x30, 0x28, 0x0c, 0x02, 0x4d, 0x96, 0x92, 0xc3, 0x2f, 0x35, 0x64, - 0x4c, 0x9a, 0xfc, 0x8d, 0x8e, 0x46, 0xb1, 0xdd, 0x13, 0x66, 0x11, 0xcb, 0x41, 0xa5, 0xb9, 0x40, - 0x96, 0x70, 0x9f, 0x1d, 0xb6, 0xf2, 0x7d, 0x3c, 0x82, 0x72, 0xac, 0x24, 0x07, 0x73, 0x7f, 0x62, - 0xcf, 0x49, 0xf6, 0x2e, 0x56, 0xe6, 0x18, 0x48, 0xac, 0xf7, 0x54, 0x7e, 0x80, 0xaf, 0x9f, 0x99, - 0x1c, 0x70, 0x90, 0xfb, 0x27, 0xbf, 0x40, 0xb8, 0x4d, 0x7e, 0xa2, 0x95, 0x54, 0x1d, 0x06, 0xc9, - 0x72, 0x8e, 0x2c, 0x07, 0xe5, 0xae, 0x75, 0x40, 0xd4, 0xa8, 0x49, 0x29, 0x49, 0x74, 0x56, 0x81, - 0xa7, 0x6e, 0x01, 0xa3, 0x2f, 0xbf, 0x38, 0xd8, 0x05, 0x8a, 0xbe, 0xa1, 0xf9, 0xe1, 0x21, 0x32, - 0x19, 0x7c, 0x02, 0x51, 0xdb, 0x96, 0x0f, 0xe8, 0x86, 0x06, 0xc2, 0x32, 0x7b, 0x75, 0x40, 0x56, - 0x4c, 0xf9, 0xa1, 0x4b, 0xee, 0x2b, 0x47, 0xbe, 0x1b, 0xe5, 0xa2, 0x2f, 0x80, 0xf5, 0x60, 0x48, - 0x37, 0x94, 0xfb, 0x2d, 0x81, 0xe0, 0x1a, 0x90, 0xfb, 0xbc, 0x35, 0xd0, 0xfe, 0xab, 0x27, 0x24, - 0x52, 0x99, 0x1a, 0xc5, 0xbc, 0x1c, 0xff, 0x1e, 0x74, 0xd2, 0x16, 0x85, 0xaa, 0x81, 0x2c, 0xbf, - 0xda, 0x9b, 0x75, 0x52, 0x99, 0x7f, 0x1e, 0xf7, 0x0b, 0x20, 0xe5, 0xc9, 0x35, 0x1c, 0xb8, 0x12, - 0x47, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXSelectIcon[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x33, 0x17, 0x79, - 0x08, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd7, 0xce, 0x93, 0x00, 0x00, - 0x04, 0x7e, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x99, 0x5b, 0x88, 0x0e, 0x61, 0x18, 0xc7, - 0x7d, 0xd6, 0x3a, 0x6c, 0x12, 0x42, 0x24, 0x17, 0x48, 0xb1, 0x21, 0x09, 0x37, 0x5c, 0x2d, 0xe5, - 0x74, 0x23, 0x11, 0x39, 0xad, 0xc3, 0x86, 0x12, 0x17, 0x8b, 0x52, 0xd2, 0xda, 0xa4, 0xb4, 0x29, - 0xa7, 0x24, 0xe4, 0xc2, 0x31, 0x57, 0x12, 0x52, 0x88, 0x1b, 0x09, 0xed, 0x0d, 0xc9, 0x46, 0x88, - 0x9c, 0x6e, 0x24, 0xe7, 0x8d, 0x65, 0xf7, 0xf3, 0x7b, 0x3e, 0x33, 0xdb, 0xe3, 0x6d, 0x66, 0xbe, - 0x99, 0xf9, 0xde, 0xd9, 0xa1, 0xe6, 0xa9, 0xff, 0xf7, 0x3e, 0xef, 0x73, 0x7e, 0xde, 0x99, 0xf9, - 0x66, 0xe6, 0x9d, 0x4e, 0x9d, 0x32, 0xca, 0x56, 0x20, 0x5b, 0x81, 0x6c, 0x05, 0xb2, 0x15, 0xc8, - 0x56, 0x20, 0xd9, 0x15, 0xc8, 0xe7, 0xf3, 0xd3, 0xc1, 0x33, 0xb0, 0x3d, 0xd9, 0x4c, 0x29, 0x45, - 0xa7, 0xb1, 0x8b, 0x40, 0xe8, 0x07, 0x28, 0x4b, 0xa9, 0x0c, 0xcf, 0xb4, 0x9d, 0x3d, 0xa5, 0xd1, - 0x85, 0xdd, 0x1d, 0x97, 0xae, 0x8c, 0xb6, 0x62, 0x46, 0xaf, 0xc2, 0xc3, 0xe3, 0x9f, 0x2a, 0xc6, - 0xa3, 0xbe, 0x92, 0x45, 0xbe, 0x0d, 0x72, 0xaa, 0x55, 0x80, 0x31, 0x25, 0x67, 0xf0, 0x08, 0x40, - 0xdc, 0xc1, 0x60, 0x88, 0x87, 0xaa, 0x63, 0x44, 0x24, 0xcf, 0x81, 0xc7, 0x40, 0xe8, 0x04, 0x08, - 0xbc, 0xae, 0xd0, 0x5f, 0x13, 0x43, 0x87, 0xca, 0x83, 0xaa, 0xc4, 0xa6, 0x1a, 0xfc, 0x04, 0xbf, - 0xc0, 0xc8, 0x20, 0xdb, 0xc4, 0x74, 0x24, 0xee, 0x02, 0xde, 0x02, 0x97, 0x4e, 0xc3, 0xf8, 0x36, - 0x89, 0xae, 0xce, 0x31, 0xbc, 0x1b, 0x54, 0x14, 0x36, 0xcb, 0x41, 0xab, 0x63, 0x2b, 0xc3, 0xc4, - 0x20, 0xfb, 0x44, 0x75, 0x24, 0x9f, 0x06, 0x9a, 0xa5, 0x0a, 0x87, 0xce, 0x30, 0x7a, 0x36, 0x89, - 0x5c, 0x8e, 0xf8, 0x44, 0xd0, 0xc3, 0xaf, 0x28, 0x74, 0x2b, 0x41, 0x1b, 0x70, 0x69, 0xa7, 0x9f, - 0x6d, 0x87, 0xc9, 0xa9, 0x64, 0x2a, 0xd0, 0x4d, 0x36, 0xc4, 0x49, 0x4e, 0x8c, 0x2a, 0xa0, 0x9b, - 0xdb, 0x11, 0x27, 0x4e, 0x22, 0x3e, 0x4e, 0x71, 0xdf, 0x18, 0x85, 0x6e, 0xc7, 0x49, 0x82, 0xdf, - 0xb6, 0x82, 0xf7, 0x9f, 0x9f, 0xfa, 0x38, 0x31, 0x12, 0xf5, 0xa1, 0xae, 0xf1, 0x60, 0x8f, 0x8c, - 0x71, 0x12, 0xe1, 0xd7, 0x0f, 0xec, 0x02, 0x0b, 0xe2, 0xf8, 0x67, 0x3e, 0xd9, 0x0a, 0x64, 0x2b, - 0xf0, 0xff, 0xae, 0x40, 0x4e, 0x97, 0xce, 0x9f, 0xc0, 0x5f, 0xf3, 0x5c, 0x2e, 0x97, 0xd7, 0x7a, - 0x3f, 0xde, 0xf1, 0x9b, 0x89, 0xbe, 0x15, 0x9f, 0x2b, 0x7e, 0x76, 0x5a, 0x6e, 0xe6, 0x12, 0x5d, - 0xd8, 0x7c, 0x3a, 0x4e, 0x28, 0x9e, 0x64, 0x4b, 0xc0, 0x47, 0x60, 0x92, 0xbc, 0xe3, 0x55, 0x16, - 0x0b, 0x82, 0xcd, 0x71, 0xe5, 0x78, 0x28, 0xc8, 0x1e, 0xbb, 0x32, 0x70, 0x55, 0xd9, 0xbb, 0xac, - 0x3c, 0xba, 0x1d, 0x0e, 0xf2, 0x8d, 0xad, 0x23, 0xf0, 0x05, 0x37, 0x8b, 0xc7, 0xb8, 0xbe, 0x58, - 0x60, 0x7c, 0xe4, 0x3d, 0x50, 0xd3, 0x58, 0x3f, 0x1f, 0x8c, 0x86, 0x6b, 0x43, 0x83, 0x97, 0x87, - 0x0a, 0x79, 0xe5, 0xb2, 0x46, 0x5d, 0x9c, 0x48, 0x75, 0x8c, 0xdf, 0x41, 0x6f, 0x23, 0xf2, 0x53, - 0xe6, 0xa7, 0x0d, 0x99, 0xd7, 0xb4, 0x09, 0xe1, 0x38, 0xa5, 0xa8, 0x85, 0x5f, 0xae, 0xe6, 0xed, - 0x2c, 0xa7, 0xa1, 0x9c, 0x15, 0x9b, 0x10, 0x4c, 0x6f, 0x17, 0xfe, 0x61, 0x5a, 0x19, 0x4e, 0xa2, - 0x6f, 0x31, 0xe4, 0xe9, 0x4f, 0x29, 0x78, 0xb5, 0x71, 0x24, 0xe4, 0x88, 0x0e, 0x4a, 0xbf, 0x32, - 0x4b, 0x15, 0xd0, 0x4c, 0x77, 0xf0, 0xce, 0x68, 0x32, 0xfd, 0x87, 0x69, 0x4b, 0xfd, 0x15, 0xc2, - 0xd0, 0xdc, 0x76, 0xa3, 0xc1, 0xf7, 0xcc, 0x2b, 0x6c, 0xe6, 0x48, 0x35, 0x16, 0xcd, 0x0c, 0x00, - 0xdf, 0x8d, 0x26, 0xd7, 0x15, 0x2b, 0x0a, 0xfb, 0x51, 0x60, 0x26, 0xe8, 0xeb, 0xda, 0xc2, 0xcb, - 0xdb, 0xc7, 0x26, 0x90, 0xde, 0xfb, 0xa2, 0x5b, 0x8c, 0x1e, 0x29, 0xe8, 0x28, 0xd0, 0xf4, 0x84, - 0x49, 0x67, 0x50, 0x0e, 0xe4, 0x56, 0xf2, 0x09, 0x3c, 0x00, 0x53, 0xc4, 0x8f, 0x71, 0x3e, 0x70, - 0x49, 0x8e, 0xb8, 0x2b, 0x77, 0x77, 0x13, 0x44, 0x77, 0x04, 0xf8, 0x6e, 0xad, 0xe8, 0xfc, 0xb1, - 0x79, 0x12, 0x6c, 0x00, 0x4d, 0x60, 0x45, 0x50, 0x10, 0xf4, 0x95, 0x40, 0xbf, 0xf7, 0x31, 0xcd, - 0xcf, 0x01, 0x3d, 0x81, 0xdc, 0xe7, 0x5c, 0xfa, 0x00, 0x33, 0x10, 0xc8, 0x91, 0xd3, 0xf4, 0x82, - 0x89, 0x5c, 0xcf, 0x9b, 0xb5, 0x10, 0x7e, 0x77, 0x50, 0xde, 0x92, 0x74, 0x04, 0xaf, 0x53, 0xc9, - 0x1a, 0x8b, 0x05, 0xc3, 0xf6, 0xb2, 0xb2, 0x17, 0xf6, 0xa6, 0xf8, 0x30, 0x9e, 0x35, 0xe4, 0xfb, - 0x99, 0xcb, 0x4e, 0xc0, 0x23, 0x43, 0xbe, 0x91, 0xb9, 0x9c, 0xa2, 0x9a, 0x7e, 0x32, 0xb1, 0xbf, - 0x01, 0x46, 0xd0, 0x7a, 0x95, 0x45, 0x8e, 0xcc, 0xa2, 0x10, 0x0d, 0xca, 0x2e, 0x80, 0x49, 0xb2, - 0x9d, 0x31, 0xc9, 0x10, 0x7e, 0x61, 0x2e, 0xd7, 0x6d, 0x83, 0x21, 0x97, 0x3d, 0x1b, 0xf3, 0x5a, - 0x16, 0x93, 0xf3, 0xc5, 0x72, 0x47, 0xd2, 0x13, 0x70, 0xab, 0x44, 0x75, 0x48, 0x9a, 0xab, 0x09, - 0x1b, 0x00, 0xdb, 0x7b, 0xae, 0xa3, 0x33, 0x9e, 0x15, 0x5f, 0xf8, 0x9b, 0x86, 0xfc, 0x29, 0x73, - 0xf3, 0xf6, 0x62, 0x98, 0xb4, 0x4f, 0xa5, 0xf1, 0x11, 0x61, 0x6b, 0x08, 0xb4, 0x23, 0x50, 0x57, - 0xd0, 0xec, 0x84, 0x96, 0xe6, 0x56, 0x05, 0x3a, 0x18, 0x4a, 0xec, 0x97, 0x39, 0xbe, 0xee, 0x20, - 0xd7, 0xdf, 0x50, 0xb0, 0xc6, 0x15, 0xc4, 0x1c, 0x0f, 0x1a, 0xa9, 0xe2, 0x4f, 0x29, 0xe0, 0x18, - 0x90, 0xad, 0xc3, 0xa5, 0x51, 0xa3, 0xe0, 0x23, 0xff, 0x9a, 0x6f, 0x80, 0x26, 0xf9, 0xf7, 0x6c, - 0xd4, 0x82, 0x18, 0xfc, 0x57, 0x7c, 0x7a, 0x46, 0xad, 0x27, 0x11, 0x7b, 0x0a, 0xd9, 0x12, 0xa3, - 0x81, 0x30, 0x2e, 0xd5, 0x89, 0x14, 0xec, 0x15, 0x94, 0x6a, 0xe4, 0x1e, 0x57, 0x0b, 0xe4, 0x1e, - 0x57, 0xa5, 0x6d, 0x98, 0xf7, 0x01, 0xb2, 0xe2, 0xb6, 0xe9, 0xba, 0xce, 0x93, 0x28, 0x4f, 0xe5, - 0x35, 0xaa, 0x7a, 0xb9, 0x56, 0x37, 0xe8, 0x84, 0xcc, 0x0f, 0x28, 0xbd, 0x2d, 0xb6, 0x85, 0x40, - 0xdd, 0x74, 0x9e, 0x20, 0xbe, 0xd4, 0x27, 0x84, 0xe1, 0x2a, 0xb8, 0xec, 0x06, 0xec, 0x23, 0x79, - 0xbd, 0x92, 0xed, 0x85, 0x6f, 0x53, 0x73, 0x1b, 0x6c, 0x39, 0x41, 0x46, 0xdb, 0x08, 0x54, 0x34, - 0x06, 0xcd, 0x8c, 0x01, 0xe6, 0xcb, 0x2e, 0xa2, 0xc2, 0x91, 0x2b, 0x6c, 0x7f, 0xc0, 0x9f, 0x13, - 0x81, 0x65, 0xea, 0xd0, 0xeb, 0x70, 0x2e, 0xc5, 0xcb, 0x93, 0x86, 0x49, 0xf2, 0xc1, 0x46, 0x3e, - 0xe2, 0x4c, 0x36, 0x15, 0x16, 0xe6, 0x6b, 0x8a, 0xae, 0xbe, 0x4d, 0x03, 0x0a, 0x96, 0x87, 0x66, - 0xfd, 0xac, 0xe9, 0xf6, 0x70, 0x09, 0xa6, 0x07, 0x68, 0x72, 0x05, 0x96, 0xc6, 0xb5, 0x36, 0xeb, - 0x0f, 0x15, 0x8b, 0xc2, 0x17, 0x02, 0xaf, 0x26, 0x5f, 0x22, 0x97, 0x3f, 0x06, 0x9b, 0x34, 0x2b, - 0x54, 0x51, 0xb6, 0x8d, 0xe8, 0x60, 0x31, 0x90, 0x47, 0xaa, 0xa4, 0xa9, 0xbf, 0xed, 0xda, 0x43, - 0xc7, 0xa3, 0xb3, 0x6a, 0x90, 0x64, 0x93, 0x77, 0x42, 0x17, 0x93, 0x94, 0x21, 0x0d, 0xae, 0x04, - 0x72, 0x5f, 0x4c, 0x82, 0xe6, 0x26, 0x55, 0x77, 0xa4, 0xb8, 0x74, 0x26, 0x3b, 0x6d, 0xb6, 0x9b, - 0xbc, 0x41, 0xcc, 0x52, 0xef, 0xdd, 0x91, 0xfa, 0x08, 0x34, 0xa6, 0x18, 0xb9, 0x26, 0xbd, 0x6e, - 0x21, 0x88, 0x23, 0xd3, 0x2b, 0x3c, 0x06, 0x04, 0x26, 0x4c, 0x43, 0x49, 0x51, 0xb3, 0x81, 0xd7, - 0x67, 0x81, 0x28, 0x1d, 0x3e, 0xc4, 0x58, 0x3f, 0x35, 0xa5, 0xd1, 0x8a, 0x7f, 0x4e, 0x8a, 0x93, - 0x77, 0xc1, 0xbb, 0x51, 0x3a, 0x72, 0x6c, 0xe5, 0x14, 0x3f, 0x05, 0x7a, 0xf9, 0x47, 0xff, 0x47, - 0x34, 0x14, 0x59, 0x06, 0x56, 0x81, 0xd7, 0xa0, 0x18, 0x49, 0x63, 0xd7, 0xc0, 0x84, 0x52, 0xcb, - 0x2f, 0x3c, 0x2f, 0x96, 0x1a, 0x24, 0x8a, 0x3f, 0x45, 0xcb, 0xc7, 0x95, 0x19, 0x60, 0x1e, 0x90, - 0xef, 0x19, 0xc3, 0x80, 0x7c, 0xa6, 0xfb, 0x0c, 0xee, 0x83, 0x5b, 0xe0, 0x0c, 0xdf, 0x28, 0x9e, - 0x33, 0x66, 0x94, 0xad, 0x40, 0xb6, 0x02, 0xd9, 0x0a, 0x64, 0x2b, 0x90, 0xea, 0x0a, 0xfc, 0x06, - 0x2b, 0x3f, 0x89, 0x0a, 0x68, 0xdb, 0xdf, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXSelectIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x33, 0x17, 0x79, - 0x08, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd7, 0xce, 0x93, 0x00, 0x00, - 0x04, 0x7e, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x99, 0x5b, 0x88, 0x0e, 0x61, 0x18, 0xc7, - 0x7d, 0xd6, 0x3a, 0x6c, 0x12, 0x42, 0x24, 0x17, 0x48, 0xb1, 0x21, 0x09, 0x37, 0x5c, 0x2d, 0xe5, - 0x74, 0x23, 0x11, 0x39, 0xad, 0xc3, 0x86, 0x12, 0x17, 0x8b, 0x52, 0xd2, 0xda, 0xa4, 0xb4, 0x29, - 0xa7, 0x24, 0xe4, 0xc2, 0x31, 0x57, 0x12, 0x52, 0x88, 0x1b, 0x09, 0xed, 0x0d, 0xc9, 0x46, 0x88, - 0x9c, 0x6e, 0x24, 0xe7, 0x8d, 0x65, 0xf7, 0xf3, 0x7b, 0x3e, 0x33, 0xdb, 0xe3, 0x6d, 0x66, 0xbe, - 0x99, 0xf9, 0xde, 0xd9, 0xa1, 0xe6, 0xa9, 0xff, 0xf7, 0x3e, 0xef, 0x73, 0x7e, 0xde, 0x99, 0xf9, - 0x66, 0xe6, 0x9d, 0x4e, 0x9d, 0x32, 0xca, 0x56, 0x20, 0x5b, 0x81, 0x6c, 0x05, 0xb2, 0x15, 0xc8, - 0x56, 0x20, 0xd9, 0x15, 0xc8, 0xe7, 0xf3, 0xd3, 0xc1, 0x33, 0xb0, 0x3d, 0xd9, 0x4c, 0x29, 0x45, - 0xa7, 0xb1, 0x8b, 0x40, 0xe8, 0x07, 0x28, 0x4b, 0xa9, 0x0c, 0xcf, 0xb4, 0x9d, 0x3d, 0xa5, 0xd1, - 0x85, 0xdd, 0x1d, 0x97, 0xae, 0x8c, 0xb6, 0x62, 0x46, 0xaf, 0xc2, 0xc3, 0xe3, 0x9f, 0x2a, 0xc6, - 0xa3, 0xbe, 0x92, 0x45, 0xbe, 0x0d, 0x72, 0xaa, 0x55, 0x80, 0x31, 0x25, 0x67, 0xf0, 0x08, 0x40, - 0xdc, 0xc1, 0x60, 0x88, 0x87, 0xaa, 0x63, 0x44, 0x24, 0xcf, 0x81, 0xc7, 0x40, 0xe8, 0x04, 0x08, - 0xbc, 0xae, 0xd0, 0x5f, 0x13, 0x43, 0x87, 0xca, 0x83, 0xaa, 0xc4, 0xa6, 0x1a, 0xfc, 0x04, 0xbf, - 0xc0, 0xc8, 0x20, 0xdb, 0xc4, 0x74, 0x24, 0xee, 0x02, 0xde, 0x02, 0x97, 0x4e, 0xc3, 0xf8, 0x36, - 0x89, 0xae, 0xce, 0x31, 0xbc, 0x1b, 0x54, 0x14, 0x36, 0xcb, 0x41, 0xab, 0x63, 0x2b, 0xc3, 0xc4, - 0x20, 0xfb, 0x44, 0x75, 0x24, 0x9f, 0x06, 0x9a, 0xa5, 0x0a, 0x87, 0xce, 0x30, 0x7a, 0x36, 0x89, - 0x5c, 0x8e, 0xf8, 0x44, 0xd0, 0xc3, 0xaf, 0x28, 0x74, 0x2b, 0x41, 0x1b, 0x70, 0x69, 0xa7, 0x9f, - 0x6d, 0x87, 0xc9, 0xa9, 0x64, 0x2a, 0xd0, 0x4d, 0x36, 0xc4, 0x49, 0x4e, 0x8c, 0x2a, 0xa0, 0x9b, - 0xdb, 0x11, 0x27, 0x4e, 0x22, 0x3e, 0x4e, 0x71, 0xdf, 0x18, 0x85, 0x6e, 0xc7, 0x49, 0x82, 0xdf, - 0xb6, 0x82, 0xf7, 0x9f, 0x9f, 0xfa, 0x38, 0x31, 0x12, 0xf5, 0xa1, 0xae, 0xf1, 0x60, 0x8f, 0x8c, - 0x71, 0x12, 0xe1, 0xd7, 0x0f, 0xec, 0x02, 0x0b, 0xe2, 0xf8, 0x67, 0x3e, 0xd9, 0x0a, 0x64, 0x2b, - 0xf0, 0xff, 0xae, 0x40, 0x4e, 0x97, 0xce, 0x9f, 0xc0, 0x5f, 0xf3, 0x5c, 0x2e, 0x97, 0xd7, 0x7a, - 0x3f, 0xde, 0xf1, 0x9b, 0x89, 0xbe, 0x15, 0x9f, 0x2b, 0x7e, 0x76, 0x5a, 0x6e, 0xe6, 0x12, 0x5d, - 0xd8, 0x7c, 0x3a, 0x4e, 0x28, 0x9e, 0x64, 0x4b, 0xc0, 0x47, 0x60, 0x92, 0xbc, 0xe3, 0x55, 0x16, - 0x0b, 0x82, 0xcd, 0x71, 0xe5, 0x78, 0x28, 0xc8, 0x1e, 0xbb, 0x32, 0x70, 0x55, 0xd9, 0xbb, 0xac, - 0x3c, 0xba, 0x1d, 0x0e, 0xf2, 0x8d, 0xad, 0x23, 0xf0, 0x05, 0x37, 0x8b, 0xc7, 0xb8, 0xbe, 0x58, - 0x60, 0x7c, 0xe4, 0x3d, 0x50, 0xd3, 0x58, 0x3f, 0x1f, 0x8c, 0x86, 0x6b, 0x43, 0x83, 0x97, 0x87, - 0x0a, 0x79, 0xe5, 0xb2, 0x46, 0x5d, 0x9c, 0x48, 0x75, 0x8c, 0xdf, 0x41, 0x6f, 0x23, 0xf2, 0x53, - 0xe6, 0xa7, 0x0d, 0x99, 0xd7, 0xb4, 0x09, 0xe1, 0x38, 0xa5, 0xa8, 0x85, 0x5f, 0xae, 0xe6, 0xed, - 0x2c, 0xa7, 0xa1, 0x9c, 0x15, 0x9b, 0x10, 0x4c, 0x6f, 0x17, 0xfe, 0x61, 0x5a, 0x19, 0x4e, 0xa2, - 0x6f, 0x31, 0xe4, 0xe9, 0x4f, 0x29, 0x78, 0xb5, 0x71, 0x24, 0xe4, 0x88, 0x0e, 0x4a, 0xbf, 0x32, - 0x4b, 0x15, 0xd0, 0x4c, 0x77, 0xf0, 0xce, 0x68, 0x32, 0xfd, 0x87, 0x69, 0x4b, 0xfd, 0x15, 0xc2, - 0xd0, 0xdc, 0x76, 0xa3, 0xc1, 0xf7, 0xcc, 0x2b, 0x6c, 0xe6, 0x48, 0x35, 0x16, 0xcd, 0x0c, 0x00, - 0xdf, 0x8d, 0x26, 0xd7, 0x15, 0x2b, 0x0a, 0xfb, 0x51, 0x60, 0x26, 0xe8, 0xeb, 0xda, 0xc2, 0xcb, - 0xdb, 0xc7, 0x26, 0x90, 0xde, 0xfb, 0xa2, 0x5b, 0x8c, 0x1e, 0x29, 0xe8, 0x28, 0xd0, 0xf4, 0x84, - 0x49, 0x67, 0x50, 0x0e, 0xe4, 0x56, 0xf2, 0x09, 0x3c, 0x00, 0x53, 0xc4, 0x8f, 0x71, 0x3e, 0x70, - 0x49, 0x8e, 0xb8, 0x2b, 0x77, 0x77, 0x13, 0x44, 0x77, 0x04, 0xf8, 0x6e, 0xad, 0xe8, 0xfc, 0xb1, - 0x79, 0x12, 0x6c, 0x00, 0x4d, 0x60, 0x45, 0x50, 0x10, 0xf4, 0x95, 0x40, 0xbf, 0xf7, 0x31, 0xcd, - 0xcf, 0x01, 0x3d, 0x81, 0xdc, 0xe7, 0x5c, 0xfa, 0x00, 0x33, 0x10, 0xc8, 0x91, 0xd3, 0xf4, 0x82, - 0x89, 0x5c, 0xcf, 0x9b, 0xb5, 0x10, 0x7e, 0x77, 0x50, 0xde, 0x92, 0x74, 0x04, 0xaf, 0x53, 0xc9, - 0x1a, 0x8b, 0x05, 0xc3, 0xf6, 0xb2, 0xb2, 0x17, 0xf6, 0xa6, 0xf8, 0x30, 0x9e, 0x35, 0xe4, 0xfb, - 0x99, 0xcb, 0x4e, 0xc0, 0x23, 0x43, 0xbe, 0x91, 0xb9, 0x9c, 0xa2, 0x9a, 0x7e, 0x32, 0xb1, 0xbf, - 0x01, 0x46, 0xd0, 0x7a, 0x95, 0x45, 0x8e, 0xcc, 0xa2, 0x10, 0x0d, 0xca, 0x2e, 0x80, 0x49, 0xb2, - 0x9d, 0x31, 0xc9, 0x10, 0x7e, 0x61, 0x2e, 0xd7, 0x6d, 0x83, 0x21, 0x97, 0x3d, 0x1b, 0xf3, 0x5a, - 0x16, 0x93, 0xf3, 0xc5, 0x72, 0x47, 0xd2, 0x13, 0x70, 0xab, 0x44, 0x75, 0x48, 0x9a, 0xab, 0x09, - 0x1b, 0x00, 0xdb, 0x7b, 0xae, 0xa3, 0x33, 0x9e, 0x15, 0x5f, 0xf8, 0x9b, 0x86, 0xfc, 0x29, 0x73, - 0xf3, 0xf6, 0x62, 0x98, 0xb4, 0x4f, 0xa5, 0xf1, 0x11, 0x61, 0x6b, 0x08, 0xb4, 0x23, 0x50, 0x57, - 0xd0, 0xec, 0x84, 0x96, 0xe6, 0x56, 0x05, 0x3a, 0x18, 0x4a, 0xec, 0x97, 0x39, 0xbe, 0xee, 0x20, - 0xd7, 0xdf, 0x50, 0xb0, 0xc6, 0x15, 0xc4, 0x1c, 0x0f, 0x1a, 0xa9, 0xe2, 0x4f, 0x29, 0xe0, 0x18, - 0x90, 0xad, 0xc3, 0xa5, 0x51, 0xa3, 0xe0, 0x23, 0xff, 0x9a, 0x6f, 0x80, 0x26, 0xf9, 0xf7, 0x6c, - 0xd4, 0x82, 0x18, 0xfc, 0x57, 0x7c, 0x7a, 0x46, 0xad, 0x27, 0x11, 0x7b, 0x0a, 0xd9, 0x12, 0xa3, - 0x81, 0x30, 0x2e, 0xd5, 0x89, 0x14, 0xec, 0x15, 0x94, 0x6a, 0xe4, 0x1e, 0x57, 0x0b, 0xe4, 0x1e, - 0x57, 0xa5, 0x6d, 0x98, 0xf7, 0x01, 0xb2, 0xe2, 0xb6, 0xe9, 0xba, 0xce, 0x93, 0x28, 0x4f, 0xe5, - 0x35, 0xaa, 0x7a, 0xb9, 0x56, 0x37, 0xe8, 0x84, 0xcc, 0x0f, 0x28, 0xbd, 0x2d, 0xb6, 0x85, 0x40, - 0xdd, 0x74, 0x9e, 0x20, 0xbe, 0xd4, 0x27, 0x84, 0xe1, 0x2a, 0xb8, 0xec, 0x06, 0xec, 0x23, 0x79, - 0xbd, 0x92, 0xed, 0x85, 0x6f, 0x53, 0x73, 0x1b, 0x6c, 0x39, 0x41, 0x46, 0xdb, 0x08, 0x54, 0x34, - 0x06, 0xcd, 0x8c, 0x01, 0xe6, 0xcb, 0x2e, 0xa2, 0xc2, 0x91, 0x2b, 0x6c, 0x7f, 0xc0, 0x9f, 0x13, - 0x81, 0x65, 0xea, 0xd0, 0xeb, 0x70, 0x2e, 0xc5, 0xcb, 0x93, 0x86, 0x49, 0xf2, 0xc1, 0x46, 0x3e, - 0xe2, 0x4c, 0x36, 0x15, 0x16, 0xe6, 0x6b, 0x8a, 0xae, 0xbe, 0x4d, 0x03, 0x0a, 0x96, 0x87, 0x66, - 0xfd, 0xac, 0xe9, 0xf6, 0x70, 0x09, 0xa6, 0x07, 0x68, 0x72, 0x05, 0x96, 0xc6, 0xb5, 0x36, 0xeb, - 0x0f, 0x15, 0x8b, 0xc2, 0x17, 0x02, 0xaf, 0x26, 0x5f, 0x22, 0x97, 0x3f, 0x06, 0x9b, 0x34, 0x2b, - 0x54, 0x51, 0xb6, 0x8d, 0xe8, 0x60, 0x31, 0x90, 0x47, 0xaa, 0xa4, 0xa9, 0xbf, 0xed, 0xda, 0x43, - 0xc7, 0xa3, 0xb3, 0x6a, 0x90, 0x64, 0x93, 0x77, 0x42, 0x17, 0x93, 0x94, 0x21, 0x0d, 0xae, 0x04, - 0x72, 0x5f, 0x4c, 0x82, 0xe6, 0x26, 0x55, 0x77, 0xa4, 0xb8, 0x74, 0x26, 0x3b, 0x6d, 0xb6, 0x9b, - 0xbc, 0x41, 0xcc, 0x52, 0xef, 0xdd, 0x91, 0xfa, 0x08, 0x34, 0xa6, 0x18, 0xb9, 0x26, 0xbd, 0x6e, - 0x21, 0x88, 0x23, 0xd3, 0x2b, 0x3c, 0x06, 0x04, 0x26, 0x4c, 0x43, 0x49, 0x51, 0xb3, 0x81, 0xd7, - 0x67, 0x81, 0x28, 0x1d, 0x3e, 0xc4, 0x58, 0x3f, 0x35, 0xa5, 0xd1, 0x8a, 0x7f, 0x4e, 0x8a, 0x93, - 0x77, 0xc1, 0xbb, 0x51, 0x3a, 0x72, 0x6c, 0xe5, 0x14, 0x3f, 0x05, 0x7a, 0xf9, 0x47, 0xff, 0x47, - 0x34, 0x14, 0x59, 0x06, 0x56, 0x81, 0xd7, 0xa0, 0x18, 0x49, 0x63, 0xd7, 0xc0, 0x84, 0x52, 0xcb, - 0x2f, 0x3c, 0x2f, 0x96, 0x1a, 0x24, 0x8a, 0x3f, 0x45, 0xcb, 0xc7, 0x95, 0x19, 0x60, 0x1e, 0x90, - 0xef, 0x19, 0xc3, 0x80, 0x7c, 0xa6, 0xfb, 0x0c, 0xee, 0x83, 0x5b, 0xe0, 0x0c, 0xdf, 0x28, 0x9e, - 0x33, 0x66, 0x94, 0xad, 0x40, 0xb6, 0x02, 0xd9, 0x0a, 0x64, 0x2b, 0x90, 0xea, 0x0a, 0xfc, 0x06, - 0x2b, 0x3f, 0x89, 0x0a, 0x68, 0xdb, 0xdf, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXSelectIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x5a, 0x08, 0x06, 0x00, 0x00, 0x00, 0x26, 0x61, 0x71, - 0xb1, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x54, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x08, 0x58, 0x73, 0x21, 0x00, 0x00, - 0x07, 0x8e, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, 0x9c, 0x6b, 0xa8, 0x55, 0x45, 0x14, 0xc7, - 0xbd, 0xbe, 0x25, 0x95, 0xac, 0x30, 0x0d, 0xba, 0xbe, 0xa2, 0xf2, 0x55, 0x64, 0xd0, 0x4b, 0x0a, - 0xa2, 0xd0, 0xa2, 0x07, 0x81, 0x2f, 0x34, 0x84, 0x08, 0xb5, 0x8c, 0x88, 0x50, 0xa8, 0x88, 0xca, - 0x0f, 0x41, 0x51, 0x91, 0x19, 0x29, 0x96, 0x50, 0xe0, 0x87, 0x50, 0x22, 0xf1, 0x59, 0x4a, 0x85, - 0xa9, 0x65, 0x65, 0x24, 0xa6, 0xe0, 0x07, 0x2b, 0xbc, 0x5a, 0x99, 0xa8, 0x44, 0xa5, 0x99, 0xe5, - 0xeb, 0xf6, 0xfb, 0x5f, 0xce, 0x3e, 0xcc, 0x9d, 0x3b, 0xfb, 0x38, 0xfb, 0x9c, 0xfd, 0xb8, 0xf7, - 0x38, 0x0b, 0xfe, 0xcc, 0xcc, 0x9a, 0x35, 0x6b, 0xd6, 0xfa, 0x9f, 0x73, 0xe6, 0xce, 0x9e, 0xbd, - 0xf7, 0xed, 0xd4, 0x29, 0x48, 0x60, 0x20, 0x30, 0x10, 0x18, 0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, - 0x81, 0x81, 0xc0, 0x40, 0x60, 0x20, 0x30, 0x10, 0x18, 0x08, 0x0c, 0xb4, 0x66, 0xa0, 0xa1, 0x75, - 0x33, 0xbb, 0x56, 0x73, 0x73, 0x73, 0x0f, 0xbc, 0x4f, 0x06, 0xa7, 0xc0, 0x87, 0x0d, 0x0d, 0x0d, - 0xa7, 0xb3, 0x9b, 0xed, 0x3c, 0xf0, 0x0c, 0xa1, 0x1b, 0x40, 0x24, 0xcb, 0xce, 0x83, 0x94, 0xb3, - 0x4b, 0x11, 0x16, 0x2f, 0x8c, 0x98, 0x2c, 0x95, 0xa7, 0x28, 0xbb, 0x66, 0x37, 0x63, 0x71, 0x9e, - 0x3b, 0xe7, 0x34, 0x75, 0x2f, 0x6b, 0x1e, 0x91, 0x19, 0x08, 0xb5, 0x48, 0x09, 0x4d, 0x07, 0x03, - 0x79, 0x7d, 0x43, 0x1d, 0x53, 0xd7, 0xa7, 0x2a, 0x10, 0x9a, 0xf2, 0xe7, 0xea, 0xb5, 0x8e, 0xf1, - 0x07, 0xa4, 0x27, 0xf3, 0x4e, 0x02, 0xc7, 0xc0, 0x6a, 0xb6, 0x3c, 0xcd, 0x29, 0xc7, 0xe1, 0xe5, - 0x8e, 0x38, 0xba, 0x60, 0x38, 0x01, 0xa8, 0xd4, 0xd6, 0x4b, 0x5b, 0xb0, 0x8e, 0x27, 0x24, 0xb2, - 0x05, 0x44, 0xb2, 0x9a, 0x4a, 0xf7, 0x24, 0x59, 0x60, 0x3f, 0x30, 0x1a, 0x6c, 0x94, 0xfa, 0x90, - 0xbc, 0x85, 0x71, 0x17, 0x80, 0x8d, 0xc6, 0xf8, 0x35, 0xde, 0x83, 0xdb, 0x93, 0x21, 0x09, 0xb8, - 0xc8, 0x58, 0x87, 0x5e, 0x1b, 0x75, 0x2f, 0xc1, 0xb6, 0x9f, 0x41, 0x84, 0xaa, 0x89, 0xb6, 0x4d, - 0xd8, 0x8b, 0xcc, 0xcd, 0x1a, 0x68, 0x89, 0xbd, 0x7b, 0xf0, 0x8a, 0xa7, 0x50, 0x23, 0x12, 0xe8, - 0x02, 0xf6, 0x5a, 0x89, 0xa8, 0xf9, 0x31, 0x48, 0x42, 0xea, 0xa7, 0x86, 0x8f, 0x0f, 0x7c, 0x93, - 0x62, 0x4c, 0x6f, 0x60, 0xfe, 0x42, 0x22, 0x37, 0x3b, 0x7d, 0x7d, 0xb4, 0x3b, 0x3b, 0x32, 0xb8, - 0x06, 0x1c, 0x89, 0x32, 0x31, 0xca, 0xf5, 0xd4, 0xbd, 0x48, 0xc5, 0xae, 0x27, 0x78, 0x18, 0x4c, - 0x07, 0xdd, 0x7c, 0x92, 0xc4, 0x4e, 0x64, 0x7e, 0x01, 0x6c, 0xf9, 0x05, 0xc5, 0x15, 0x3e, 0x3e, - 0xda, 0xad, 0x0d, 0x09, 0x8c, 0x06, 0x87, 0xed, 0xcc, 0x68, 0xeb, 0x92, 0x32, 0xd1, 0x7a, 0xe8, - 0x93, 0x24, 0x3e, 0xfb, 0x80, 0x2f, 0x81, 0x2d, 0x22, 0x73, 0x98, 0x8f, 0x8f, 0x76, 0x6f, 0x43, - 0x22, 0xa3, 0xc0, 0x21, 0x3b, 0x43, 0xda, 0x0b, 0xd2, 0x0e, 0x1e, 0x9f, 0x4b, 0x1d, 0xf3, 0xfc, - 0x8c, 0x6e, 0x68, 0xda, 0x73, 0x15, 0xea, 0x8f, 0x84, 0x46, 0x02, 0x9b, 0xd4, 0xed, 0x69, 0x07, - 0xc5, 0x1c, 0xf6, 0xba, 0xbd, 0x1f, 0xdd, 0x90, 0xb4, 0xe7, 0x69, 0x17, 0xfe, 0x48, 0x6c, 0x04, - 0x38, 0x08, 0x22, 0x99, 0x97, 0x76, 0x60, 0x38, 0x5e, 0x10, 0x39, 0xa7, 0x6c, 0x02, 0xf5, 0x49, - 0x66, 0x44, 0x1c, 0x09, 0xf6, 0x07, 0x4f, 0x80, 0x07, 0x22, 0x5d, 0x9a, 0x25, 0x7e, 0x3b, 0x83, - 0x29, 0xe0, 0x71, 0xd0, 0x2f, 0x4d, 0xdf, 0xc1, 0x57, 0x60, 0x20, 0x30, 0x10, 0x18, 0x08, 0x0c, - 0x04, 0x06, 0x02, 0x03, 0x81, 0x81, 0x0e, 0xc0, 0x00, 0x5b, 0xa0, 0x3e, 0x1d, 0x20, 0xcc, 0xaa, - 0x43, 0x2c, 0xdf, 0x97, 0x27, 0xd1, 0x8b, 0xf1, 0x32, 0x1d, 0x5c, 0x14, 0xe3, 0x4d, 0x87, 0xca, - 0x3b, 0x38, 0xd4, 0x5d, 0x15, 0xd3, 0x5f, 0x51, 0x8d, 0xff, 0x7b, 0x31, 0x58, 0x08, 0x06, 0x81, - 0x9f, 0xc0, 0x4c, 0x7c, 0x6d, 0xa2, 0xf4, 0x16, 0x7c, 0x28, 0x5e, 0xdd, 0xdb, 0x1f, 0x59, 0x61, - 0xd0, 0x11, 0xfa, 0x96, 0xe2, 0xfb, 0x68, 0x05, 0x9b, 0x6c, 0xbb, 0x08, 0xb4, 0x1b, 0xd8, 0x03, - 0x7c, 0xe4, 0xe9, 0xa4, 0xd1, 0xe0, 0xf4, 0x6a, 0x70, 0xd2, 0x72, 0xfe, 0x37, 0xed, 0x44, 0x57, - 0x3f, 0xd8, 0xbf, 0x6c, 0xf9, 0x88, 0x6b, 0x6e, 0xa7, 0xa3, 0xfc, 0x65, 0x49, 0x1a, 0x6f, 0xcd, - 0xf6, 0x4c, 0xae, 0x4b, 0x49, 0x5f, 0xd9, 0x92, 0x74, 0x42, 0x1c, 0xcf, 0x89, 0x71, 0xbe, 0x2c, - 0x89, 0x2f, 0x7c, 0xec, 0x8a, 0xf1, 0xe3, 0x52, 0x0f, 0x4c, 0xe2, 0x3b, 0x2d, 0xdb, 0xe8, 0x26, - 0xdd, 0x5e, 0x1c, 0xfe, 0xea, 0xe9, 0x74, 0xb3, 0xa7, 0x9d, 0x69, 0x76, 0xd2, 0x6c, 0x18, 0xf5, - 0x89, 0x30, 0xd1, 0x68, 0xb4, 0xcf, 0x55, 0xf5, 0xfd, 0x30, 0xf7, 0xe0, 0xe8, 0xd0, 0xb9, 0x9c, - 0x65, 0xd1, 0x5f, 0xfe, 0x59, 0x90, 0x98, 0xd6, 0xb6, 0x47, 0x40, 0xdc, 0x1a, 0x7a, 0x96, 0xbe, - 0x1d, 0xe0, 0x3d, 0xd6, 0xa7, 0x33, 0x94, 0xde, 0x82, 0x6f, 0x1d, 0x06, 0xff, 0x00, 0xca, 0xf3, - 0x19, 0x83, 0xe7, 0xe3, 0x6f, 0xae, 0xd1, 0x8e, 0xad, 0xe2, 0x47, 0xf7, 0xb2, 0x66, 0x01, 0xad, - 0xa1, 0x2e, 0x5f, 0x1a, 0x7b, 0x18, 0x2c, 0xc6, 0xe7, 0x41, 0x35, 0xea, 0x56, 0x20, 0x43, 0xb7, - 0x4c, 0x5c, 0xf2, 0x17, 0xca, 0xbe, 0x75, 0x9b, 0x78, 0x56, 0x89, 0x41, 0xda, 0x1d, 0x2e, 0x36, - 0x4b, 0xba, 0x39, 0x59, 0xcd, 0x5b, 0xd7, 0x7e, 0x21, 0xef, 0xfb, 0x18, 0x52, 0xf7, 0xa1, 0xd7, - 0xbd, 0xf6, 0x20, 0x49, 0x18, 0x80, 0x34, 0xdd, 0xa0, 0x8b, 0x93, 0x29, 0x49, 0x7c, 0x05, 0x5b, - 0x18, 0x80, 0xc9, 0xee, 0xe0, 0x40, 0x0c, 0xa3, 0xdf, 0x06, 0x92, 0xaa, 0x60, 0x00, 0x32, 0x9f, - 0x89, 0x21, 0x54, 0xea, 0x5b, 0x93, 0xba, 0x64, 0xcc, 0xb5, 0x40, 0xa7, 0xfa, 0xb3, 0xc1, 0x70, - 0x73, 0x3c, 0xed, 0xbe, 0x60, 0x21, 0xd0, 0x7d, 0xfd, 0x65, 0xe0, 0x1e, 0xb3, 0xbf, 0x2e, 0xea, - 0x24, 0xa5, 0xa7, 0x48, 0x74, 0x95, 0xe4, 0x92, 0x95, 0x66, 0x92, 0x18, 0xe8, 0x3e, 0xbe, 0x6e, - 0x25, 0xcb, 0x7e, 0x27, 0x98, 0x61, 0xf5, 0xcf, 0x43, 0x67, 0xca, 0x69, 0x1a, 0x2f, 0x46, 0x36, - 0xd4, 0x75, 0x0b, 0xc5, 0x96, 0x95, 0x28, 0xda, 0xdf, 0x79, 0x02, 0x41, 0xe9, 0x21, 0x84, 0xa9, - 0x60, 0x6c, 0x94, 0x80, 0x6f, 0xc9, 0x98, 0xb7, 0x80, 0x4b, 0xce, 0xa0, 0x6c, 0x79, 0x80, 0x81, - 0x32, 0xee, 0xea, 0xed, 0x95, 0x68, 0x1e, 0x6c, 0xd6, 0xb9, 0x9c, 0xa0, 0x9b, 0x29, 0x1b, 0x4a, - 0x3d, 0x39, 0x7d, 0xcc, 0x61, 0xb3, 0x09, 0x5d, 0x8f, 0xc8, 0x4f, 0xe1, 0x25, 0xc1, 0x34, 0x82, - 0x1f, 0x8d, 0x40, 0x9f, 0x4c, 0x12, 0x14, 0xe3, 0x86, 0x01, 0x91, 0xe7, 0x92, 0x45, 0xf2, 0x45, - 0x87, 0xc8, 0x38, 0xe1, 0x30, 0xd0, 0xb8, 0x1b, 0x4b, 0x36, 0x93, 0x1d, 0xfd, 0x52, 0x69, 0x6f, - 0xab, 0xc3, 0x1e, 0xf9, 0x89, 0xfb, 0xf0, 0x5e, 0x50, 0x7f, 0xe1, 0x42, 0x80, 0x83, 0x40, 0x13, - 0x30, 0xe5, 0xbb, 0xa4, 0x81, 0x31, 0x78, 0x85, 0xe9, 0xc0, 0xa8, 0x1f, 0xa7, 0xde, 0x72, 0xb5, - 0x46, 0xf9, 0x8e, 0xa1, 0x37, 0xab, 0x1b, 0x35, 0x1f, 0x8a, 0x2e, 0xa0, 0xc9, 0xec, 0x30, 0xea, - 0xcf, 0x97, 0x6c, 0x26, 0x1a, 0x3a, 0xb3, 0xfa, 0x0f, 0x8d, 0x21, 0x49, 0xe3, 0x4e, 0xd5, 0x9e, - 0x00, 0x06, 0x83, 0x26, 0x60, 0xcb, 0x92, 0xa4, 0x13, 0xe1, 0x60, 0xac, 0xed, 0xc4, 0x68, 0x3f, - 0x5b, 0x22, 0x43, 0xa7, 0x54, 0x67, 0x0d, 0xbd, 0x59, 0xbd, 0xae, 0x64, 0xf3, 0x94, 0xa9, 0x34, - 0xea, 0x5a, 0x77, 0xe7, 0x82, 0xcf, 0x0c, 0x9d, 0x5d, 0x5d, 0x91, 0x34, 0xee, 0xd4, 0xec, 0x89, - 0x64, 0x08, 0xd8, 0x67, 0x47, 0x44, 0xfb, 0x6b, 0x50, 0xd5, 0xa5, 0x23, 0xe3, 0xbe, 0x71, 0xf8, - 0x93, 0xea, 0x37, 0xd0, 0xf2, 0x0c, 0x2a, 0x65, 0xdc, 0x3a, 0xd9, 0x72, 0x2e, 0x4b, 0xff, 0x38, - 0x50, 0xad, 0xe8, 0xc3, 0xba, 0x2a, 0x35, 0x92, 0x7c, 0x1d, 0x31, 0xe9, 0x50, 0xa0, 0x47, 0x61, - 0x6c, 0xf9, 0x0a, 0x45, 0x55, 0x64, 0x6a, 0x6e, 0xc6, 0x4e, 0xb2, 0x1d, 0x1a, 0xed, 0x87, 0x4a, - 0x36, 0xb7, 0x1b, 0x3a, 0xbb, 0xba, 0x0a, 0x45, 0x92, 0x23, 0x3d, 0x7b, 0xbc, 0xda, 0x6f, 0x6b, - 0x9e, 0xdc, 0x84, 0x09, 0xf5, 0x04, 0xc7, 0x6e, 0xcd, 0x6c, 0xc9, 0x56, 0xda, 0x35, 0x6d, 0x3f, - 0x18, 0x5f, 0x69, 0x0d, 0xdc, 0x15, 0x25, 0x89, 0xdd, 0x0e, 0x6b, 0xee, 0x34, 0x9b, 0x5a, 0x4b, - 0x2f, 0x89, 0xe6, 0xaa, 0xb5, 0x8c, 0xce, 0x43, 0x2b, 0xf9, 0x19, 0x40, 0xe7, 0x08, 0xcb, 0x60, - 0x2b, 0xed, 0xbb, 0x38, 0x22, 0x3b, 0x66, 0xe9, 0x13, 0x35, 0x4b, 0xc7, 0x80, 0x6f, 0xc6, 0x0c, - 0xd2, 0xe3, 0x93, 0x77, 0x97, 0xfa, 0x3e, 0x8f, 0xb1, 0x49, 0x43, 0xdd, 0x0b, 0x27, 0xb3, 0xd3, - 0x70, 0xe4, 0xe5, 0x83, 0xa4, 0x1a, 0x80, 0x79, 0xa8, 0xa1, 0xab, 0x8e, 0xde, 0x5e, 0x83, 0x3d, - 0x8c, 0xf0, 0xa5, 0xe7, 0x40, 0xff, 0x04, 0x2e, 0xd1, 0x03, 0x69, 0x33, 0x80, 0xef, 0xed, 0x19, - 0x97, 0x0f, 0x1f, 0x9d, 0xd6, 0xec, 0xfc, 0x0e, 0x67, 0x98, 0x4c, 0x7b, 0x42, 0xdd, 0xc6, 0x98, - 0x05, 0x12, 0xbd, 0xb0, 0xe0, 0xc1, 0xa9, 0xd6, 0xd2, 0xd7, 0x40, 0xd1, 0x12, 0xfd, 0x1a, 0x7c, - 0x42, 0x8e, 0xb5, 0x89, 0x3b, 0xf5, 0x8e, 0x1d, 0x90, 0x45, 0x07, 0x4c, 0x5e, 0x8e, 0xdf, 0xbd, - 0xa0, 0x6b, 0x16, 0xfe, 0x3d, 0x7d, 0x2e, 0x67, 0x09, 0x9a, 0xea, 0x69, 0x1b, 0x6b, 0x96, 0x39, - 0xa1, 0x90, 0xd5, 0xc8, 0xec, 0x13, 0x80, 0xde, 0x29, 0x5a, 0x49, 0xd0, 0x07, 0x5c, 0xd1, 0x60, - 0xf7, 0x3e, 0xfa, 0x69, 0xae, 0xbe, 0x9c, 0x74, 0x27, 0x98, 0x67, 0x00, 0xf1, 0x1d, 0xcd, 0x69, - 0xbe, 0xe4, 0xd3, 0x40, 0xd2, 0x18, 0xa0, 0xcb, 0xc0, 0x48, 0x54, 0xd7, 0x7d, 0xf5, 0x36, 0x82, - 0xfe, 0xfa, 0xc8, 0xa8, 0xc0, 0xb2, 0xc8, 0x0f, 0xb4, 0x0d, 0x27, 0x6d, 0x14, 0x10, 0xf3, 0x91, - 0x83, 0x1c, 0x5d, 0x8b, 0x3f, 0xd6, 0xc6, 0x18, 0x05, 0xfa, 0x4d, 0x0e, 0xfb, 0x3c, 0x55, 0xf3, - 0x5d, 0x71, 0x25, 0xd1, 0xf9, 0x6c, 0x9b, 0x92, 0xf8, 0xb3, 0x6d, 0x5d, 0xd7, 0xca, 0x9a, 0x73, - 0x11, 0x2c, 0x3d, 0x67, 0x1b, 0xd3, 0x7e, 0xdd, 0xa1, 0xcb, 0x53, 0x35, 0x26, 0xcf, 0xc9, 0x12, - 0xcf, 0x05, 0x69, 0x4b, 0xcf, 0xf1, 0xf5, 0x7a, 0x83, 0xfe, 0xf2, 0x3a, 0xae, 0x3a, 0xc8, 0x7a, - 0x8b, 0x54, 0x29, 0x24, 0x2d, 0x49, 0xe5, 0x78, 0x12, 0x27, 0x9c, 0xf5, 0x00, 0x82, 0x6b, 0x04, - 0x71, 0x7b, 0xcc, 0x28, 0x31, 0x91, 0x5e, 0xfe, 0xeb, 0x4e, 0xfd, 0xd1, 0xa8, 0xa3, 0xa0, 0xf2, - 0xd2, 0xac, 0x79, 0xa9, 0xc9, 0x3f, 0xa4, 0xdc, 0x06, 0x74, 0xf2, 0x53, 0x49, 0x56, 0xd3, 0xd9, - 0xf2, 0xf2, 0x18, 0x65, 0x2f, 0xe0, 0x7a, 0x6b, 0xaf, 0xd2, 0xf8, 0x34, 0xfb, 0x2e, 0xab, 0x25, - 0xe1, 0xac, 0xd7, 0xd0, 0x4e, 0x6c, 0x43, 0xb6, 0x10, 0xe0, 0x7d, 0x40, 0xdb, 0x92, 0x38, 0xb9, - 0x9f, 0x0e, 0xbd, 0x91, 0xd7, 0x17, 0x7b, 0xd9, 0x2d, 0x8e, 0x33, 0xcc, 0x41, 0x9f, 0x39, 0x27, - 0xa9, 0xe4, 0x00, 0x59, 0x77, 0x02, 0xd7, 0x09, 0xbc, 0xf9, 0xed, 0xd2, 0x53, 0x73, 0xfd, 0x81, - 0xde, 0x2d, 0x2d, 0x4a, 0x74, 0x91, 0x51, 0xb5, 0xe4, 0xba, 0x00, 0xc3, 0xd0, 0x38, 0x22, 0x5d, - 0x03, 0x2a, 0xdd, 0xcf, 0x39, 0x44, 0xff, 0x7e, 0x70, 0x03, 0xc8, 0x5b, 0xfe, 0x65, 0x42, 0xfd, - 0x4a, 0xaa, 0xfe, 0xc7, 0x06, 0xb9, 0x12, 0x2a, 0x76, 0x20, 0x55, 0xd7, 0xcc, 0x3a, 0x1c, 0x4e, - 0xfd, 0x4c, 0x40, 0xfe, 0x6b, 0x94, 0x6d, 0x90, 0x79, 0x53, 0x2d, 0x3e, 0x72, 0x5f, 0x2f, 0x08, - 0x78, 0x3d, 0x01, 0x4f, 0x04, 0x27, 0x6b, 0x09, 0x3c, 0xa3, 0xb1, 0x35, 0x3f, 0x6c, 0x91, 0x3b, - 0xa1, 0x22, 0x02, 0x52, 0xd7, 0x52, 0x4c, 0x01, 0x55, 0xff, 0xb4, 0xe4, 0x27, 0x03, 0xd9, 0x50, - 0xab, 0xcf, 0xdc, 0x7f, 0xf2, 0x66, 0xc0, 0xfc, 0xfc, 0x75, 0x68, 0xb2, 0x1c, 0x94, 0xf7, 0xa1, - 0x66, 0x7f, 0xce, 0xf5, 0xdd, 0xcc, 0x37, 0x9a, 0x0f, 0x5b, 0xef, 0x12, 0x54, 0x2d, 0x85, 0x7c, - 0x43, 0xa3, 0x68, 0x09, 0x5e, 0x77, 0x1d, 0x1f, 0x04, 0x67, 0x22, 0x5d, 0x81, 0xe5, 0xab, 0xb5, - 0x92, 0x59, 0x60, 0xec, 0xad, 0xa7, 0xe6, 0x9b, 0x3a, 0x0d, 0xe8, 0x31, 0x9a, 0xa2, 0x44, 0xdb, - 0xb5, 0x6e, 0xad, 0xa3, 0xea, 0xe0, 0x2d, 0x12, 0x9a, 0x0c, 0xec, 0x37, 0x45, 0xf2, 0x20, 0xf8, - 0x77, 0x26, 0x19, 0xdc, 0xc1, 0xe9, 0x73, 0x87, 0x4f, 0x62, 0xe3, 0xc1, 0xf1, 0x3c, 0x58, 0x2c, - 0xcd, 0xa1, 0xa3, 0xc4, 0xf1, 0xee, 0x68, 0xea, 0x44, 0x4b, 0x82, 0xb7, 0x00, 0x7d, 0x6b, 0xb2, - 0x16, 0x3d, 0x44, 0xa6, 0x4b, 0xde, 0xfa, 0x17, 0x12, 0xd5, 0x29, 0x95, 0xee, 0xfb, 0x67, 0x25, - 0x4d, 0x38, 0x1e, 0x5d, 0xff, 0x4c, 0x1a, 0x19, 0x92, 0x70, 0x57, 0xf0, 0x12, 0x88, 0x7b, 0x4a, - 0x8f, 0xae, 0xc4, 0x22, 0x5f, 0xef, 0x82, 0xd4, 0x1e, 0x6c, 0x30, 0x42, 0xee, 0x18, 0x55, 0x92, - 0xd7, 0x13, 0xca, 0x3a, 0x89, 0xaa, 0x55, 0x74, 0x3b, 0x66, 0x54, 0xc7, 0xc8, 0x3a, 0x87, 0x28, - 0x21, 0x43, 0xaf, 0xe5, 0xac, 0x01, 0x49, 0x76, 0x02, 0x7f, 0x60, 0xbf, 0x04, 0xdc, 0x9c, 0x43, - 0x88, 0x2d, 0x53, 0x14, 0x7a, 0xa5, 0x54, 0x4d, 0x92, 0x90, 0xa3, 0xff, 0x90, 0xa3, 0x2b, 0x2c, - 0x91, 0x34, 0x1c, 0x5c, 0x09, 0x74, 0xd0, 0xf2, 0x1f, 0xd0, 0x59, 0xaa, 0xae, 0x78, 0xb6, 0x83, - 0x6d, 0xe0, 0x13, 0x36, 0xeb, 0xd2, 0x07, 0x09, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x81, 0x81, 0xc0, - 0x40, 0x60, 0x20, 0x30, 0x10, 0x18, 0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0xfe, 0x0c, 0xfc, 0x0f, - 0x72, 0x11, 0x0f, 0x81, 0x42, 0xe0, 0xea, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82 -}; - - -#pragma mark - Toolbar Icons - -static const u_int8_t FLEXBookmarksIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x79, 0x47, 0xd8, - 0x15, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x6e, 0xd2, 0xbe, 0x00, 0x00, - 0x03, 0x25, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x99, 0xdb, 0x8b, 0x4d, 0x71, 0x14, 0xc7, - 0xcf, 0x76, 0xab, 0x51, 0x4a, 0x52, 0x2e, 0x45, 0xa9, 0xe3, 0xf2, 0x40, 0x8a, 0x29, 0x3c, 0x32, - 0x63, 0xf2, 0x36, 0x4a, 0x22, 0x49, 0x4a, 0x4a, 0x09, 0x85, 0x47, 0x5e, 0xa6, 0x3c, 0x69, 0x22, - 0xb9, 0x65, 0x5c, 0x1a, 0xe1, 0xd1, 0xcb, 0x78, 0x51, 0xfe, 0x01, 0xf7, 0x4b, 0x29, 0x22, 0x79, - 0xa3, 0x63, 0xcc, 0x18, 0x42, 0x53, 0x72, 0x7c, 0xd6, 0x99, 0xdf, 0xda, 0x2d, 0xbf, 0xdf, 0xde, - 0x67, 0x66, 0xef, 0x39, 0x73, 0x92, 0xf6, 0xaa, 0xef, 0xac, 0xcb, 0x5e, 0xbf, 0xb5, 0xbe, 0x7b, - 0xfd, 0x7e, 0xe7, 0x9c, 0xf6, 0x9e, 0x52, 0xe9, 0x1f, 0x93, 0x28, 0x89, 0x4f, 0xb5, 0x5a, 0x5d, - 0x42, 0x7c, 0x19, 0x58, 0x0c, 0xe6, 0x80, 0xc4, 0x3c, 0xe2, 0x79, 0xa4, 0xca, 0xa2, 0x0a, 0x78, - 0x03, 0x5e, 0x47, 0x51, 0xf4, 0x2a, 0xb5, 0x08, 0x44, 0x16, 0x82, 0xdb, 0xa0, 0x99, 0xd2, 0x47, - 0xb3, 0x45, 0x4a, 0x2a, 0xbe, 0x73, 0x82, 0x0b, 0x08, 0xbe, 0x04, 0x33, 0xf4, 0x62, 0x13, 0xf5, - 0x0f, 0x7a, 0xad, 0x60, 0x5a, 0xef, 0xa6, 0x98, 0xa6, 0xdd, 0xd8, 0x3e, 0x19, 0x19, 0xef, 0x00, - 0xf8, 0x6d, 0xf2, 0xc6, 0x6b, 0x4e, 0xa2, 0xc0, 0x2c, 0x10, 0x0f, 0x03, 0x7b, 0x3a, 0x38, 0x05, - 0x3a, 0x41, 0xa9, 0x24, 0x23, 0xf3, 0xf6, 0xa8, 0x1f, 0x7f, 0x3b, 0x90, 0xc4, 0x86, 0x0b, 0x75, - 0x5b, 0xc0, 0x56, 0x50, 0x01, 0x56, 0xe4, 0xdc, 0xd6, 0x08, 0x6d, 0xb2, 0x51, 0xec, 0x1d, 0x0d, - 0x67, 0x91, 0x50, 0x90, 0x3e, 0x5b, 0xbc, 0xbe, 0x9b, 0x65, 0x7c, 0x22, 0xe5, 0x11, 0x15, 0xff, - 0xed, 0x8b, 0xad, 0x89, 0x35, 0xee, 0x50, 0xde, 0x1e, 0x87, 0xb2, 0x12, 0x9a, 0x67, 0xfa, 0x7e, - 0xe5, 0x70, 0x7d, 0x33, 0xfe, 0x84, 0x99, 0xf4, 0x19, 0xa6, 0x78, 0xbf, 0x69, 0x30, 0x57, 0x09, - 0x99, 0x58, 0x49, 0x0e, 0x72, 0x33, 0xc5, 0xf6, 0x8b, 0x92, 0x08, 0x35, 0x93, 0x4c, 0xd0, 0xab, - 0x20, 0x14, 0x8c, 0xc4, 0x0b, 0x14, 0x13, 0xf2, 0x06, 0x12, 0xb8, 0xc5, 0x84, 0x82, 0x91, 0x78, - 0x81, 0x62, 0x42, 0xde, 0x40, 0x02, 0xb7, 0x98, 0x50, 0x30, 0x12, 0x2f, 0x50, 0x4c, 0xc8, 0x1b, - 0x48, 0xe0, 0x16, 0x13, 0x0a, 0x46, 0xe2, 0x05, 0x8a, 0x09, 0x79, 0x03, 0x09, 0xdc, 0x62, 0x42, - 0xc1, 0x48, 0xbc, 0xc0, 0xff, 0x39, 0x21, 0x9e, 0xad, 0x8e, 0x81, 0x4f, 0xa0, 0xcb, 0xbb, 0xe1, - 0xcc, 0xae, 0x7d, 0x94, 0xce, 0xbc, 0x58, 0x16, 0x40, 0xe2, 0x24, 0xea, 0xa8, 0x5b, 0x7c, 0x1c, - 0x7f, 0x26, 0x8f, 0x37, 0x07, 0x9d, 0x9f, 0x59, 0x8d, 0x6b, 0xcb, 0x68, 0x2e, 0xef, 0x03, 0x94, - 0x8c, 0x36, 0x3f, 0x40, 0xfc, 0x2c, 0xb0, 0xcf, 0xee, 0x7a, 0x6d, 0x54, 0x9d, 0x9b, 0x10, 0x0d, - 0x4f, 0x53, 0xfd, 0x70, 0x4a, 0x87, 0xfd, 0xc4, 0xcf, 0xe7, 0x21, 0x95, 0x8b, 0x10, 0x8d, 0xce, - 0xd0, 0xf0, 0x90, 0x21, 0x23, 0x4f, 0xba, 0x47, 0xc0, 0x17, 0x13, 0xdb, 0x87, 0x7d, 0x31, 0x0f, - 0x29, 0x39, 0x07, 0x27, 0x80, 0x8a, 0x2d, 0x6a, 0xea, 0xd7, 0xce, 0x4b, 0x44, 0xd2, 0x39, 0x4d, - 0x74, 0x7a, 0x08, 0xbd, 0x4e, 0x12, 0xd1, 0xad, 0x60, 0xc0, 0xc5, 0x55, 0x5d, 0xc6, 0x48, 0xdd, - 0x3e, 0xae, 0x7d, 0xd4, 0x44, 0xb4, 0x1c, 0x81, 0x5a, 0xa1, 0x51, 0x09, 0x49, 0x51, 0x70, 0xc1, - 0x2c, 0x16, 0x53, 0xc8, 0xac, 0xad, 0x15, 0x71, 0x7f, 0xf0, 0x57, 0x03, 0x9f, 0xd4, 0x55, 0x62, - 0x89, 0xbb, 0x41, 0x3c, 0x3b, 0x21, 0x16, 0x09, 0x99, 0x4b, 0xc0, 0x8a, 0x90, 0x59, 0x63, 0xc9, - 0xa8, 0x4d, 0x7c, 0x15, 0xf0, 0x49, 0xf5, 0x12, 0x0b, 0x48, 0x11, 0xfb, 0x8b, 0x50, 0x90, 0xa0, - 0x45, 0x55, 0xbb, 0x22, 0x3d, 0xf8, 0x7b, 0x35, 0x86, 0x1e, 0x02, 0x1d, 0x7c, 0xbc, 0xef, 0x9b, - 0x58, 0x6c, 0x12, 0x7f, 0x82, 0xd3, 0x0e, 0xe4, 0xed, 0x9b, 0xca, 0x2e, 0x0c, 0x21, 0x35, 0x59, - 0x03, 0x49, 0xba, 0x2e, 0x21, 0x47, 0xe6, 0x0a, 0x0b, 0xf7, 0x98, 0xc5, 0x75, 0xc9, 0x68, 0x5e, - 0x0a, 0xa9, 0x9d, 0x5c, 0xbf, 0x5e, 0x8f, 0x54, 0x2a, 0x21, 0x47, 0xe6, 0x1a, 0x05, 0x76, 0x6b, - 0x13, 0xb4, 0x1c, 0xf8, 0x8d, 0x34, 0x7b, 0x60, 0x62, 0xa9, 0x26, 0x79, 0x4f, 0xb9, 0xd8, 0x06, - 0x3e, 0x9b, 0x24, 0x79, 0x3b, 0x77, 0x93, 0xfa, 0x89, 0x5f, 0xca, 0x89, 0x84, 0xdc, 0x1d, 0xf4, - 0xb2, 0x50, 0xc6, 0xac, 0xa2, 0x64, 0x1e, 0x6a, 0x60, 0x2c, 0x1a, 0x52, 0xcf, 0xc8, 0x93, 0xed, - 0xb3, 0xa4, 0xb6, 0xe1, 0xdf, 0x4a, 0x23, 0xe5, 0x7f, 0xec, 0x7f, 0x91, 0x78, 0x17, 0x58, 0x19, - 0xc4, 0x69, 0x1d, 0x0b, 0x81, 0xb4, 0x1c, 0xd6, 0xaf, 0x04, 0xf2, 0x32, 0xd5, 0xca, 0x3d, 0x9c, - 0x61, 0x13, 0xe8, 0x4e, 0x9a, 0x90, 0x1c, 0xba, 0x0e, 0x53, 0x78, 0x10, 0xbb, 0x9d, 0x3b, 0x7d, - 0x64, 0x62, 0x99, 0x4d, 0xd6, 0x3f, 0x67, 0xd1, 0x06, 0x60, 0x5f, 0xe1, 0xc9, 0x76, 0x4e, 0xb3, - 0xc5, 0x94, 0x90, 0x7d, 0xad, 0x66, 0xaf, 0x2b, 0x99, 0xc7, 0x36, 0x98, 0xd7, 0x86, 0xd4, 0x0b, - 0xd6, 0x0a, 0x09, 0x4b, 0xca, 0x96, 0x8b, 0xbf, 0x17, 0x3e, 0xd8, 0xa8, 0xb3, 0x65, 0xcf, 0xdb, - 0x28, 0x22, 0x1f, 0xe1, 0x86, 0x89, 0x23, 0xb5, 0x9e, 0x82, 0xf2, 0xff, 0x0e, 0x5f, 0x46, 0x78, - 0xb0, 0x87, 0xf2, 0x3f, 0x8e, 0xef, 0x66, 0x2f, 0xdf, 0x63, 0x2f, 0xf7, 0xb3, 0x1b, 0xe9, 0x53, - 0x7f, 0x29, 0x78, 0x6b, 0x7a, 0xfe, 0xc4, 0x2e, 0xc7, 0xbf, 0x31, 0x38, 0xb3, 0x69, 0x28, 0xdf, - 0x13, 0x53, 0x41, 0x0f, 0x77, 0x92, 0xfa, 0x9b, 0xd6, 0x28, 0x62, 0xf4, 0x6c, 0xa1, 0x56, 0x27, - 0x98, 0x0f, 0x6e, 0xd0, 0xb3, 0xf2, 0x07, 0x6f, 0x8f, 0xd6, 0x17, 0xd8, 0x01, 0xed, 0x4d, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXBookmarksIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x48, 0x08, 0x06, 0x00, 0x00, 0x00, 0xbd, 0x6d, 0x06, - 0x6c, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xa1, 0x70, 0x0a, 0x00, 0x00, - 0x04, 0xb4, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x9b, 0x7b, 0x48, 0x64, 0x55, 0x1c, 0xc7, - 0x1d, 0xd3, 0xde, 0x9b, 0xab, 0x59, 0xd0, 0x03, 0x42, 0xd6, 0x30, 0xf6, 0x8f, 0x36, 0x42, 0x7a, - 0x10, 0x25, 0x15, 0x12, 0x11, 0x49, 0x84, 0x2c, 0x44, 0xd4, 0x2e, 0x19, 0x44, 0xd0, 0x2e, 0x58, - 0x4a, 0xd9, 0x53, 0x2b, 0xcb, 0xa0, 0xa4, 0x88, 0x10, 0xa2, 0xa2, 0x07, 0x14, 0xc5, 0xe2, 0xb2, - 0x1a, 0xed, 0x56, 0xbb, 0x20, 0xd5, 0x1f, 0x51, 0x54, 0x94, 0xb4, 0x3d, 0x76, 0x33, 0x22, 0x7a, - 0x48, 0x41, 0x14, 0xd1, 0xc3, 0x34, 0xfb, 0xfc, 0xe4, 0xce, 0xcc, 0x99, 0xd3, 0x39, 0x73, 0xef, - 0x3d, 0x33, 0xe3, 0xb9, 0xc2, 0x39, 0xf0, 0x65, 0xce, 0xf9, 0x3d, 0xbf, 0xdf, 0x73, 0xee, 0x0c, - 0x83, 0x73, 0xac, 0xab, 0x0b, 0x63, 0x6d, 0xed, 0x40, 0xae, 0x1c, 0xdd, 0xe5, 0xe5, 0xe5, 0x26, - 0xfc, 0xe7, 0x80, 0x53, 0x15, 0x9c, 0xc0, 0xbc, 0x6c, 0x1e, 0xfe, 0x5a, 0x8d, 0xbf, 0x28, 0xfc, - 0x15, 0x38, 0x10, 0x61, 0x7f, 0x2e, 0x97, 0xfb, 0x28, 0x71, 0x33, 0x04, 0xe5, 0xc0, 0x16, 0x30, - 0x0f, 0xb2, 0x3e, 0x5e, 0x85, 0x60, 0x5b, 0xac, 0x38, 0x09, 0x02, 0x6f, 0x65, 0x5d, 0x8d, 0xc6, - 0xef, 0x0f, 0xd6, 0x43, 0xaa, 0xb8, 0xff, 0x3d, 0x52, 0x04, 0xcc, 0x10, 0xd0, 0xa5, 0x06, 0xad, - 0xa1, 0x79, 0x0f, 0x8f, 0xe6, 0xb4, 0xf0, 0x2d, 0x11, 0x86, 0xa8, 0xab, 0xb0, 0xbd, 0xb8, 0x86, - 0x84, 0xe8, 0x54, 0xe7, 0x30, 0x6c, 0x44, 0xdc, 0xdf, 0x05, 0x61, 0x88, 0x3a, 0x0a, 0xe3, 0x17, - 0xe0, 0x24, 0x3d, 0x9a, 0xf5, 0x22, 0x90, 0x9d, 0xd8, 0x0f, 0xbe, 0x8e, 0xd6, 0xbc, 0xac, 0xfa, - 0x58, 0x4f, 0xc7, 0x0e, 0x70, 0x21, 0x38, 0xcd, 0xd2, 0xfd, 0x4e, 0x84, 0x8d, 0x16, 0x7c, 0x08, - 0xeb, 0x02, 0xa6, 0x31, 0x8b, 0xf1, 0xf4, 0x42, 0x60, 0x06, 0x26, 0xf0, 0x69, 0x00, 0x83, 0x26, - 0xb2, 0xd8, 0xde, 0x2f, 0xa1, 0x88, 0xa1, 0xcf, 0x10, 0xb8, 0x88, 0x6d, 0x53, 0x49, 0x60, 0x86, - 0x16, 0x70, 0x7b, 0xce, 0xc0, 0xf9, 0x97, 0x12, 0x8a, 0x04, 0x8c, 0x19, 0x82, 0xa6, 0x4a, 0x82, - 0x32, 0xb6, 0x80, 0x6f, 0x87, 0x81, 0xb3, 0x98, 0x5a, 0xeb, 0x15, 0xae, 0xed, 0xca, 0x3c, 0x3f, - 0xfd, 0x2c, 0x3f, 0xc9, 0xe8, 0xeb, 0x41, 0x78, 0x2d, 0x18, 0xb8, 0xb5, 0xab, 0xc2, 0x4c, 0x1f, - 0x1a, 0xdf, 0x18, 0x92, 0x32, 0x63, 0xe2, 0x43, 0x62, 0x09, 0x32, 0xdf, 0x19, 0x08, 0x9d, 0xa8, - 0x0a, 0x2b, 0x7c, 0x42, 0x2a, 0x81, 0xff, 0x2a, 0xf3, 0xac, 0x4e, 0x4d, 0x1c, 0xeb, 0x55, 0x61, - 0x59, 0x25, 0xee, 0xc4, 0x2b, 0x08, 0x73, 0xda, 0x36, 0x8f, 0x49, 0xe1, 0xc4, 0x3c, 0x6e, 0xbe, - 0x53, 0xeb, 0x70, 0x62, 0x4e, 0xdb, 0xe6, 0x31, 0x29, 0x9c, 0x98, 0xc7, 0xcd, 0x77, 0x6a, 0x1d, - 0x4e, 0xcc, 0x69, 0xdb, 0x3c, 0x26, 0x85, 0x13, 0xf3, 0xb8, 0xf9, 0x4e, 0xad, 0xc3, 0x89, 0x39, - 0x6d, 0x9b, 0xc7, 0xa4, 0x70, 0x62, 0x1e, 0x37, 0xdf, 0xa9, 0x75, 0x38, 0x31, 0xa7, 0x6d, 0xf3, - 0x98, 0x14, 0x4e, 0xcc, 0xe3, 0xe6, 0x3b, 0xb5, 0x0e, 0x27, 0xe6, 0xb4, 0x6d, 0x1e, 0x93, 0xc2, - 0x89, 0x79, 0xdc, 0x7c, 0xa7, 0xd6, 0xe1, 0xc4, 0x9c, 0xb6, 0xcd, 0x63, 0x52, 0x38, 0x31, 0x8f, - 0x9b, 0xef, 0xd4, 0x3a, 0x9c, 0x98, 0xd3, 0xb6, 0x79, 0x4c, 0x5a, 0xb5, 0x13, 0xe3, 0xe7, 0xd3, - 0x7e, 0xf0, 0x2d, 0x98, 0x01, 0xf2, 0xcb, 0x7f, 0x4d, 0xc7, 0xaa, 0x08, 0x43, 0xc8, 0x38, 0x2a, - 0x04, 0x27, 0x03, 0xb9, 0x1c, 0xf3, 0x0e, 0xb6, 0x9a, 0xfe, 0x68, 0x5f, 0x73, 0x61, 0x08, 0x78, - 0x0c, 0x21, 0xfd, 0x40, 0x1d, 0xad, 0x2c, 0xf6, 0xe1, 0x3b, 0x43, 0x35, 0x56, 0x73, 0x5e, 0x33, - 0x61, 0x90, 0x96, 0x8b, 0x66, 0x8f, 0x43, 0x76, 0xbb, 0x85, 0xf0, 0xb1, 0xd8, 0x45, 0xdc, 0x99, - 0x16, 0x7f, 0x45, 0xe6, 0x9a, 0x08, 0x13, 0x51, 0xb0, 0x7a, 0x02, 0xdc, 0x14, 0xc3, 0xae, 0x05, - 0xff, 0x5e, 0xe2, 0x3b, 0x63, 0xe2, 0x52, 0xbb, 0xab, 0x2e, 0x2c, 0x12, 0x35, 0x01, 0x93, 0x1b, - 0x13, 0xb2, 0x69, 0x26, 0xee, 0x4d, 0xf2, 0xce, 0x4a, 0x18, 0x9f, 0x28, 0xac, 0xaa, 0xc2, 0x22, - 0x51, 0x4f, 0xd2, 0xf9, 0x06, 0x4b, 0xf7, 0x17, 0xb0, 0xcb, 0x45, 0x2e, 0x7d, 0xc8, 0x1d, 0xa9, - 0x37, 0xc8, 0x3f, 0x5b, 0x77, 0xb8, 0xae, 0xab, 0x26, 0x0c, 0x52, 0x52, 0xeb, 0x29, 0x70, 0xbd, - 0x85, 0xcc, 0x08, 0xf7, 0x32, 0xae, 0xc5, 0x77, 0x01, 0xf8, 0xd2, 0x10, 0xd3, 0x84, 0x4d, 0xc4, - 0x9d, 0x6b, 0xf0, 0xa5, 0x36, 0x55, 0x45, 0x58, 0x24, 0xea, 0x69, 0xba, 0x5f, 0x67, 0x61, 0x30, - 0x8c, 0xa8, 0x61, 0xf1, 0xf1, 0x2a, 0x17, 0x4e, 0xe4, 0xf6, 0x9a, 0x49, 0xdc, 0x31, 0xd8, 0x5f, - 0xa7, 0xde, 0x79, 0xbc, 0x56, 0x34, 0x2a, 0x16, 0x16, 0x89, 0x7a, 0x16, 0x16, 0x5b, 0x2d, 0x4c, - 0xee, 0x41, 0xcc, 0x88, 0xea, 0x63, 0xfd, 0x3d, 0x6b, 0x11, 0x27, 0xd7, 0x08, 0xf5, 0xb1, 0x0e, - 0xc3, 0x1e, 0xea, 0x9e, 0xaf, 0x3b, 0xd2, 0xac, 0x2b, 0x12, 0x46, 0xf3, 0x43, 0x68, 0xf6, 0x3c, - 0xb8, 0xc6, 0xd2, 0xf4, 0x6e, 0x44, 0xdc, 0x6b, 0xf2, 0xc5, 0x88, 0x3b, 0x9a, 0x9c, 0xdd, 0xd4, - 0x77, 0xbe, 0xe9, 0xea, 0x2c, 0x2c, 0x12, 0x25, 0x1f, 0x06, 0x57, 0x9b, 0x88, 0x63, 0xbb, 0x0b, - 0xf2, 0xf7, 0x59, 0x7c, 0x2b, 0x66, 0xfc, 0x3f, 0x30, 0x91, 0x93, 0xfb, 0xdc, 0x10, 0x27, 0x17, - 0x43, 0x5f, 0xa3, 0x8f, 0xf8, 0x53, 0x0f, 0x27, 0x61, 0x34, 0x6b, 0xa0, 0x93, 0x5c, 0xb1, 0x95, - 0xab, 0xb6, 0xa6, 0x21, 0xb7, 0x3c, 0xef, 0x37, 0x39, 0x74, 0x5b, 0x8c, 0xb8, 0x23, 0x89, 0x97, - 0x5b, 0xda, 0x17, 0xeb, 0x79, 0x71, 0xeb, 0xd4, 0xc2, 0x22, 0x51, 0x2f, 0x51, 0x78, 0xb3, 0xa5, - 0xf8, 0x1d, 0x90, 0x2d, 0x5e, 0x5d, 0xb5, 0x04, 0xa9, 0x66, 0xe2, 0x7f, 0x64, 0x2d, 0x27, 0x63, - 0xba, 0x46, 0x28, 0xe2, 0xa6, 0xe9, 0xdb, 0xad, 0xe6, 0xc4, 0xcd, 0x53, 0x09, 0xa3, 0x78, 0x23, - 0x05, 0x5f, 0x06, 0xbd, 0x96, 0xc2, 0xb7, 0x43, 0xf2, 0x01, 0x8b, 0xaf, 0xac, 0x39, 0x46, 0xdc, - 0x11, 0x24, 0x4f, 0xd1, 0xff, 0x92, 0xb2, 0x45, 0x14, 0x67, 0x62, 0x61, 0x91, 0xa8, 0x57, 0xc8, - 0xbd, 0x52, 0xc9, 0x57, 0xa7, 0x43, 0x90, 0x7b, 0x50, 0x35, 0xa4, 0x9d, 0x93, 0x3f, 0x4f, 0x8e, - 0x9c, 0x9c, 0x5c, 0xaa, 0xd6, 0xc7, 0xe1, 0x18, 0x76, 0xc1, 0xe3, 0x52, 0xdd, 0x61, 0x5a, 0x27, - 0x12, 0x46, 0xb1, 0x43, 0x49, 0xde, 0x01, 0xae, 0x30, 0x15, 0xc1, 0x76, 0x1b, 0xa4, 0xc6, 0x2c, - 0xbe, 0x54, 0xe6, 0x48, 0xdc, 0x45, 0x24, 0x7d, 0x6a, 0x48, 0x3c, 0x0c, 0xdb, 0x4e, 0xf8, 0x5c, - 0x66, 0xf0, 0x95, 0x98, 0x62, 0x85, 0x51, 0x44, 0x8a, 0x4d, 0x82, 0x9e, 0x92, 0xcc, 0xe2, 0xe2, - 0x56, 0xc8, 0x3c, 0x54, 0x5c, 0x56, 0x3e, 0x4b, 0x20, 0x6e, 0x12, 0x5e, 0x97, 0x27, 0xea, 0x44, - 0xe0, 0xbb, 0x40, 0x1f, 0xcf, 0x60, 0x90, 0x6f, 0x02, 0xb6, 0x31, 0x98, 0xa8, 0xb8, 0x63, 0x10, - 0x4d, 0x8f, 0x07, 0x72, 0x3d, 0xde, 0x34, 0x16, 0x30, 0x6e, 0x03, 0xbf, 0x1a, 0x9c, 0xc5, 0xcf, - 0x00, 0x9c, 0x26, 0x61, 0x86, 0x9c, 0x82, 0x69, 0xc0, 0x91, 0x6f, 0xaa, 0x34, 0xba, 0x1d, 0x07, - 0x6c, 0xe2, 0x0a, 0x64, 0xb4, 0x49, 0x6f, 0xec, 0xa3, 0x68, 0x61, 0x31, 0xc0, 0xe3, 0xf2, 0xb0, - 0xc5, 0x57, 0x55, 0x33, 0x7d, 0x7e, 0xa2, 0xa0, 0xbc, 0xe7, 0x66, 0xd3, 0x14, 0x76, 0x11, 0x76, - 0x0b, 0xcd, 0x1e, 0x49, 0xd3, 0xa4, 0xd2, 0x58, 0x45, 0xdc, 0x27, 0x49, 0x6b, 0xa9, 0xc2, 0x7e, - 0x4f, 0x90, 0x74, 0x33, 0x4d, 0xc6, 0x13, 0xc4, 0x55, 0x3d, 0x84, 0xbe, 0x3f, 0x53, 0x54, 0xbe, - 0x81, 0x7c, 0x9c, 0xa0, 0x78, 0x51, 0x0b, 0xcf, 0xe8, 0x84, 0xf6, 0x9c, 0xea, 0xcb, 0x6d, 0x09, - 0x0a, 0xd6, 0x3c, 0x04, 0x52, 0x2d, 0xe0, 0x03, 0x9d, 0x9c, 0xb6, 0xde, 0x50, 0x20, 0x82, 0xa3, - 0x5b, 0x73, 0xe6, 0x97, 0xff, 0x30, 0xe9, 0x2b, 0x04, 0x66, 0x60, 0x02, 0x9f, 0x66, 0x20, 0x7f, - 0x9f, 0x34, 0x8d, 0x0f, 0x31, 0xaa, 0x4f, 0x62, 0x5d, 0x1d, 0x86, 0x51, 0xb0, 0xa4, 0x44, 0xcf, - 0x31, 0x97, 0x37, 0x6e, 0xe6, 0x06, 0xbc, 0x1a, 0xc1, 0xa3, 0x40, 0x36, 0x3e, 0x3f, 0x84, 0xef, - 0xca, 0x9f, 0xf4, 0x72, 0x3a, 0x63, 0x1c, 0x6d, 0xd8, 0xc4, 0xf9, 0x1b, 0x78, 0x9b, 0x67, 0xdb, - 0xf4, 0xbf, 0x23, 0x7a, 0x9a, 0xb7, 0x35, 0x7c, 0x4f, 0xa1, 0x79, 0x27, 0x90, 0xf7, 0xe0, 0x7b, - 0xf0, 0xfd, 0x53, 0xc8, 0xfc, 0x07, 0x76, 0x76, 0x93, 0xea, 0x76, 0xb7, 0x97, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXOpenTabsIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x53, 0xf7, 0x29, - 0xba, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0xfc, 0xcb, 0x00, 0x00, - 0x03, 0x6e, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x9a, 0xcb, 0x6b, 0x53, 0x41, 0x14, 0xc6, - 0x13, 0xab, 0xf8, 0x40, 0xeb, 0x03, 0xc4, 0x17, 0x5a, 0xc5, 0xfa, 0x40, 0x4a, 0xbb, 0x71, 0x55, - 0x50, 0xa4, 0x05, 0xa1, 0x6e, 0xdd, 0xd5, 0x22, 0x2e, 0xdc, 0xb8, 0xf3, 0x0f, 0x10, 0x77, 0x5d, - 0x09, 0x2e, 0x2c, 0x28, 0xb8, 0x75, 0x21, 0xba, 0xb3, 0x08, 0x42, 0xf1, 0x01, 0xae, 0x74, 0x21, - 0x56, 0xb1, 0x52, 0xad, 0x20, 0x54, 0xad, 0xf8, 0x02, 0x4b, 0x11, 0xd4, 0xda, 0xc6, 0xdf, 0xb9, - 0xcd, 0xa4, 0x5f, 0x6f, 0xd2, 0x90, 0xcc, 0xcd, 0xcd, 0x4d, 0x4a, 0x0e, 0x7c, 0xdc, 0x73, 0x26, - 0x33, 0xdf, 0x77, 0xce, 0x9d, 0xb9, 0x93, 0xe9, 0x4d, 0x53, 0xa9, 0x25, 0x62, 0xe9, 0x70, 0x1d, - 0x99, 0x4c, 0x66, 0x0d, 0x6d, 0x7d, 0xe0, 0x20, 0x68, 0x05, 0xdb, 0x41, 0x5e, 0x3f, 0xda, 0x2a, - 0x61, 0x53, 0x90, 0xbc, 0xcb, 0x62, 0x30, 0x9d, 0x4e, 0xbf, 0xae, 0x04, 0x69, 0x8a, 0x22, 0x4e, - 0x82, 0x71, 0x90, 0x84, 0x4d, 0x23, 0x7a, 0x19, 0xac, 0x8d, 0x54, 0x0c, 0x04, 0x9d, 0x60, 0x16, - 0x24, 0x6d, 0xd7, 0x7d, 0x0a, 0x09, 0x96, 0x0c, 0x99, 0x37, 0x31, 0xf8, 0x19, 0xe8, 0x10, 0x92, - 0xdf, 0xf8, 0xcf, 0xc1, 0x07, 0x90, 0x91, 0xf6, 0x4a, 0xba, 0x1b, 0x20, 0x6b, 0x07, 0xdb, 0x84, - 0xd4, 0xb4, 0x3a, 0x59, 0x66, 0x4f, 0xa4, 0xad, 0x34, 0x97, 0x42, 0xda, 0x43, 0xd3, 0xf0, 0x82, - 0xb8, 0xa5, 0xb4, 0xd1, 0xd1, 0x7a, 0xa1, 0xb3, 0x02, 0x5c, 0x0a, 0xe9, 0x5f, 0xf1, 0x62, 0x85, - 0xc4, 0x9e, 0x0d, 0xb5, 0xa3, 0x5e, 0x44, 0x9e, 0x83, 0x10, 0x6e, 0x02, 0xa3, 0x92, 0xc0, 0xbd, - 0x72, 0xa9, 0x96, 0x65, 0x07, 0xd8, 0xee, 0xe4, 0x6c, 0x16, 0xe7, 0xa9, 0x0b, 0xaa, 0x71, 0x65, - 0x19, 0xcd, 0xa0, 0xa3, 0x4b, 0x69, 0x5f, 0xb9, 0xba, 0xae, 0x90, 0x66, 0x19, 0x38, 0x05, 0xf1, - 0x1f, 0x89, 0xab, 0xe5, 0x7e, 0x13, 0x21, 0xcd, 0x47, 0x9a, 0x17, 0x77, 0x5d, 0x21, 0x8b, 0xf7, - 0xa8, 0x93, 0x4f, 0x96, 0x4c, 0x21, 0xcb, 0xa3, 0xdc, 0x70, 0x1e, 0xce, 0x75, 0x8c, 0xef, 0x06, - 0xf6, 0x8c, 0x19, 0x36, 0x02, 0x5f, 0xd3, 0xad, 0xbf, 0x19, 0xee, 0x5b, 0x42, 0x64, 0x5b, 0xf2, - 0x57, 0x60, 0xa7, 0x80, 0xb7, 0xe0, 0x3e, 0xcb, 0xff, 0x1f, 0xd7, 0x85, 0xc6, 0xa0, 0x7e, 0xd9, - 0x31, 0x7e, 0x2e, 0xfc, 0x34, 0x3f, 0xa2, 0x6f, 0x1a, 0xf4, 0x81, 0x09, 0x19, 0x57, 0x4d, 0x77, - 0x04, 0xb1, 0x2e, 0xcd, 0xcc, 0x77, 0x69, 0x9d, 0x83, 0xe4, 0x06, 0xd0, 0x2f, 0x32, 0xe5, 0x8d, - 0xdb, 0x3f, 0x84, 0xc0, 0x03, 0x8a, 0x39, 0xe6, 0x84, 0xca, 0x5e, 0x5a, 0x0c, 0xde, 0xc2, 0xe0, - 0x7e, 0x47, 0x90, 0xbd, 0xda, 0x96, 0x6d, 0x27, 0x80, 0xef, 0xa1, 0xf6, 0x4a, 0x85, 0x76, 0x02, - 0xd9, 0x0a, 0xec, 0x00, 0xab, 0x76, 0x95, 0x7c, 0x3a, 0x58, 0x66, 0xd3, 0x41, 0x23, 0x41, 0xc9, - 0x4b, 0x8b, 0xbe, 0xe7, 0x81, 0xda, 0x10, 0xc1, 0x0e, 0x65, 0x8f, 0xcb, 0x47, 0xa7, 0x0d, 0xbc, - 0x54, 0x71, 0xfc, 0xe3, 0xa6, 0xe7, 0xb3, 0xb4, 0xf4, 0xcb, 0xca, 0x8e, 0xe1, 0xbd, 0xdc, 0x91, - 0x4f, 0x71, 0x25, 0xaf, 0xbc, 0xe8, 0xbc, 0x22, 0x3e, 0xad, 0x6d, 0xf8, 0x41, 0x3e, 0x3e, 0x85, - 0xec, 0x17, 0xa2, 0x61, 0xc8, 0xe3, 0x5a, 0x4e, 0x22, 0x33, 0xef, 0xa2, 0x37, 0x4c, 0xf4, 0x63, - 0xbe, 0x25, 0x15, 0xe4, 0xe3, 0x53, 0xc8, 0x26, 0x21, 0xf9, 0x2c, 0x7e, 0x35, 0x5d, 0xd5, 0x0d, - 0xf2, 0xf1, 0x29, 0x44, 0x13, 0x8e, 0xeb, 0x78, 0xaf, 0x1a, 0x85, 0xfc, 0x3c, 0xdd, 0xa8, 0x85, - 0x14, 0x12, 0x49, 0xa4, 0xad, 0x51, 0x48, 0x22, 0xb7, 0xbd, 0x88, 0x68, 0x63, 0x46, 0x8a, 0xdc, - 0x9c, 0x44, 0x3e, 0x6a, 0xcc, 0x48, 0x22, 0xb7, 0xbd, 0x88, 0x68, 0x63, 0x46, 0x8a, 0xdc, 0x9c, - 0x44, 0x3e, 0x5a, 0x72, 0x33, 0x32, 0x77, 0x9e, 0x9f, 0xbb, 0x97, 0xab, 0x38, 0x1a, 0xc7, 0xf5, - 0xd2, 0x3a, 0xb6, 0xd9, 0x72, 0x33, 0xf2, 0x5e, 0x14, 0x56, 0xe2, 0xef, 0x96, 0xb8, 0x2e, 0x5c, - 0x57, 0xc8, 0x58, 0x28, 0xdb, 0x8b, 0xa1, 0xb8, 0xe6, 0x43, 0xf7, 0xa7, 0xee, 0x08, 0x99, 0x4e, - 0x82, 0xf5, 0xd9, 0x8c, 0xcf, 0xb0, 0xbc, 0xf6, 0xe2, 0xdf, 0x01, 0x1f, 0x81, 0x9e, 0x36, 0xa3, - 0xbc, 0x29, 0xc9, 0xd2, 0x57, 0xfe, 0x12, 0x14, 0xc2, 0x1f, 0x2b, 0x93, 0x24, 0x7e, 0x01, 0xfa, - 0x01, 0x91, 0x38, 0x82, 0x6f, 0xa8, 0x0b, 0x73, 0x4b, 0xcb, 0x92, 0xbd, 0x06, 0x6e, 0xd6, 0x45, - 0xd6, 0x05, 0x92, 0xcc, 0x15, 0xc2, 0xac, 0xcc, 0x80, 0x5e, 0xfa, 0x74, 0x81, 0x21, 0x30, 0x0e, - 0xec, 0xed, 0x48, 0x5d, 0x98, 0x7b, 0x46, 0x72, 0xc9, 0x52, 0xcc, 0x23, 0x02, 0x83, 0xfd, 0x14, - 0x67, 0x3b, 0x98, 0xbd, 0xfe, 0xd1, 0xed, 0xf8, 0x2e, 0x71, 0x1b, 0xa8, 0x29, 0xcb, 0x2b, 0x44, - 0xb3, 0xa3, 0x28, 0x7b, 0x2b, 0x6f, 0x33, 0x93, 0x33, 0x8a, 0xfb, 0x9b, 0x0b, 0x6a, 0xc8, 0xc9, - 0x2d, 0xad, 0x1a, 0xca, 0xc9, 0x2b, 0x15, 0x9f, 0x42, 0x74, 0x2b, 0x6e, 0xf2, 0x52, 0x8d, 0x3e, - 0x48, 0x75, 0x83, 0x7c, 0x7c, 0x0a, 0xd1, 0x57, 0x31, 0x2d, 0xd1, 0x73, 0xf2, 0x62, 0xd8, 0x25, - 0xa3, 0x82, 0x7c, 0x7c, 0x0a, 0xd1, 0x53, 0x40, 0x07, 0xcf, 0xcc, 0x01, 0x21, 0x8d, 0xdd, 0x45, - 0xaf, 0x07, 0x11, 0xfd, 0x2d, 0x5e, 0xf3, 0x29, 0x5d, 0x1f, 0xa2, 0xb3, 0x40, 0xed, 0x0d, 0x41, - 0x0f, 0x70, 0xa7, 0x82, 0xd2, 0xc9, 0xca, 0xe8, 0x09, 0xff, 0x66, 0x70, 0x0a, 0x7c, 0x01, 0x6a, - 0x9d, 0x46, 0xa3, 0xdb, 0x6a, 0x49, 0xb4, 0x30, 0xac, 0xa6, 0xa3, 0x1d, 0x69, 0xf6, 0x14, 0x18, - 0x90, 0xff, 0xe3, 0x4b, 0x81, 0x4e, 0x1e, 0x4d, 0x96, 0xa7, 0x3e, 0x17, 0x8e, 0xe2, 0x21, 0x3b, - 0x6b, 0xb7, 0x05, 0x65, 0x17, 0x62, 0x83, 0x28, 0xe6, 0x04, 0x97, 0x41, 0x50, 0x88, 0xdc, 0xba, - 0x54, 0xc3, 0x7e, 0x21, 0x72, 0x98, 0x42, 0x46, 0x23, 0x89, 0x51, 0x8c, 0xfd, 0x93, 0xc1, 0x63, - 0x90, 0x84, 0xdd, 0x46, 0x74, 0xa7, 0x16, 0xe0, 0x35, 0x23, 0x4a, 0x00, 0xa1, 0x2d, 0xb1, 0xd6, - 0x2c, 0xec, 0x5f, 0x32, 0xe2, 0x32, 0xf7, 0x1b, 0xe2, 0x18, 0xb3, 0x30, 0x11, 0x16, 0xf9, 0x0f, - 0xa4, 0x99, 0x6b, 0x25, 0x92, 0x4d, 0xbc, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXOpenTabsIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x48, 0x08, 0x06, 0x00, 0x00, 0x00, 0xbe, 0xda, 0x08, - 0x44, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4b, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xab, 0x1d, 0x6b, 0x00, 0x00, - 0x05, 0x20, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, 0x9c, 0x4d, 0x68, 0x15, 0x57, 0x14, 0xc7, - 0xf3, 0xaa, 0x6d, 0xb0, 0x9f, 0xba, 0x88, 0xa8, 0xad, 0xb6, 0x09, 0x7e, 0xa1, 0x50, 0x50, 0xbb, - 0xb1, 0x10, 0x25, 0xdd, 0x14, 0xd2, 0xd2, 0x2c, 0xda, 0x2e, 0x0a, 0x0d, 0x85, 0xfa, 0x81, 0x0a, - 0xe2, 0x22, 0x94, 0xe2, 0xc2, 0x4d, 0x05, 0x45, 0xe8, 0xa2, 0x50, 0xaa, 0x60, 0x57, 0x51, 0xdc, - 0xb8, 0x71, 0x91, 0xda, 0x95, 0xe9, 0xa6, 0x1f, 0xf4, 0x0b, 0x1a, 0xda, 0xb4, 0xd0, 0x54, 0xda, - 0x2e, 0x8c, 0x69, 0xd1, 0x95, 0x28, 0x56, 0xa2, 0x8d, 0xbf, 0x23, 0x93, 0x77, 0x6f, 0xee, 0x3b, - 0xf3, 0x6e, 0xe6, 0x71, 0x27, 0x99, 0xc9, 0xdc, 0x03, 0x7f, 0xe6, 0xde, 0x33, 0xe7, 0xde, 0x73, - 0xce, 0x7f, 0xe6, 0xde, 0x99, 0xb9, 0x6f, 0xe6, 0xb5, 0xb5, 0x45, 0x99, 0x35, 0x03, 0xb5, 0x59, - 0x5b, 0x62, 0x38, 0x35, 0x35, 0xd5, 0xc1, 0xe6, 0x19, 0xf0, 0x50, 0x96, 0x76, 0x39, 0xd9, 0x4e, - 0xd1, 0xef, 0xd5, 0x5a, 0xad, 0xf6, 0x4f, 0x4e, 0xfd, 0x37, 0x74, 0xdb, 0x94, 0x2c, 0xc8, 0x79, - 0x93, 0x16, 0xaf, 0x83, 0xb5, 0x09, 0x9e, 0x6a, 0xe8, 0x61, 0xfe, 0x15, 0x37, 0x09, 0xe1, 0x72, - 0x82, 0x21, 0xb6, 0x67, 0x21, 0x50, 0x88, 0x9c, 0x1b, 0x81, 0xa4, 0x4d, 0x60, 0x18, 0x94, 0x51, - 0xbe, 0x21, 0xe8, 0xad, 0x73, 0xc2, 0x14, 0x8e, 0xde, 0x02, 0x93, 0x65, 0x64, 0xc9, 0x8a, 0xf9, - 0x1e, 0xe5, 0x7d, 0xa1, 0x09, 0x9b, 0x31, 0x0c, 0x71, 0xb0, 0x0c, 0x07, 0xbf, 0x03, 0x99, 0x9b, - 0xca, 0x2e, 0x32, 0x3c, 0x37, 0x32, 0x24, 0xc7, 0x43, 0x25, 0xb2, 0xd8, 0xe9, 0xe8, 0x18, 0x75, - 0x1f, 0x51, 0xff, 0x63, 0x33, 0x77, 0x73, 0x82, 0x13, 0xa0, 0x55, 0x95, 0x03, 0xdd, 0xec, 0x42, - 0xf3, 0x38, 0xfb, 0x3f, 0x02, 0x32, 0xef, 0x86, 0x15, 0xce, 0xaa, 0x4e, 0x20, 0xa7, 0xaf, 0x26, - 0x32, 0x0f, 0xf4, 0x82, 0x67, 0x41, 0xb3, 0x00, 0xc3, 0x06, 0xd5, 0xa4, 0x37, 0xe2, 0xa8, 0x81, - 0xd5, 0xe0, 0x65, 0xf0, 0x05, 0x48, 0x93, 0x17, 0x9a, 0x74, 0xd3, 0xda, 0x2e, 0x3c, 0xbd, 0x96, - 0xe2, 0xed, 0x14, 0xfa, 0x19, 0xc3, 0xb5, 0x35, 0x0f, 0xf9, 0xb6, 0x22, 0xc6, 0xe3, 0x29, 0xf1, - 0xef, 0x0e, 0xee, 0x19, 0x47, 0x03, 0x8a, 0xb3, 0x09, 0x74, 0x4f, 0x06, 0x77, 0x96, 0x43, 0x87, - 0xc4, 0xd9, 0x0e, 0xc6, 0x94, 0x1c, 0x4e, 0x84, 0x72, 0x67, 0x0f, 0xa9, 0x75, 0x4a, 0xa7, 0x97, - 0x98, 0x20, 0x6f, 0x28, 0xfa, 0xc2, 0xa9, 0x88, 0xf3, 0x0e, 0x41, 0x7d, 0xa6, 0x04, 0xb6, 0x5e, - 0xd1, 0xb5, 0xa4, 0xb2, 0xc9, 0x92, 0x1b, 0x4f, 0x57, 0xc6, 0x5c, 0x45, 0xc1, 0xeb, 0x72, 0x25, - 0x77, 0x45, 0x3b, 0x09, 0x5c, 0x9b, 0x59, 0xd5, 0x6d, 0xb2, 0xe4, 0xea, 0xe1, 0xca, 0x35, 0x57, - 0x51, 0xf0, 0xfa, 0xbf, 0x4a, 0x7c, 0x8f, 0x29, 0xba, 0x96, 0x54, 0x36, 0x59, 0x2d, 0x75, 0x50, - 0xa5, 0x46, 0x91, 0xac, 0x0c, 0x47, 0x3b, 0x92, 0x15, 0xc9, 0xca, 0xc0, 0x40, 0x06, 0x53, 0xf7, - 0x71, 0x27, 0x43, 0x53, 0xbf, 0x29, 0xf7, 0x3c, 0xab, 0xb1, 0xb2, 0x97, 0x78, 0xe4, 0x8a, 0xbb, - 0x06, 0x2c, 0xf2, 0xb7, 0x6e, 0xc9, 0x42, 0xbb, 0x79, 0x7e, 0x8e, 0x38, 0xee, 0xa5, 0xf4, 0x26, - 0x6b, 0x61, 0xb2, 0xbc, 0xf3, 0x47, 0xb2, 0x1d, 0xe6, 0x16, 0xe4, 0x87, 0x14, 0xdb, 0xb6, 0x5c, - 0xc8, 0x22, 0xb8, 0x76, 0x1c, 0xbe, 0x07, 0x0e, 0x83, 0x47, 0xd3, 0x9c, 0xcf, 0xa1, 0x3e, 0x6d, - 0xba, 0x59, 0x45, 0x0c, 0x82, 0x1d, 0x49, 0x2c, 0x72, 0x4f, 0x7b, 0x86, 0xf2, 0xfb, 0x90, 0xd6, - 0x70, 0x65, 0x4d, 0xeb, 0x24, 0x69, 0x9b, 0x7d, 0x83, 0xb3, 0xcd, 0xb4, 0xfa, 0x0d, 0x1c, 0x05, - 0x45, 0x20, 0x2a, 0x4b, 0x12, 0x72, 0x66, 0xbe, 0x03, 0xe4, 0x49, 0xe0, 0x0d, 0xb7, 0x61, 0x50, - 0xb2, 0x70, 0x20, 0xce, 0x4e, 0x83, 0x2e, 0xd7, 0x51, 0xc9, 0xea, 0xf2, 0x88, 0xf7, 0x29, 0xf9, - 0x2c, 0xb7, 0xe3, 0x0e, 0x4a, 0x16, 0x1d, 0xbf, 0x0b, 0x5e, 0xb4, 0x1d, 0x94, 0xb8, 0xbc, 0x94, - 0xd8, 0x3f, 0xb4, 0xe3, 0x0f, 0x36, 0x67, 0x71, 0x14, 0x64, 0xc8, 0xa5, 0x3d, 0xb4, 0xca, 0xf3, - 0xe5, 0x49, 0xf0, 0x33, 0xf8, 0x13, 0x4c, 0x82, 0xf9, 0x16, 0x19, 0x05, 0x4f, 0x83, 0x0d, 0x60, - 0x0f, 0xd0, 0x1e, 0x8b, 0xfa, 0xc9, 0xeb, 0x13, 0xe6, 0xaf, 0xef, 0xd8, 0x6f, 0x04, 0xe5, 0xb7, - 0xc0, 0x95, 0x59, 0x2f, 0xcd, 0xd2, 0x70, 0xab, 0xdb, 0x38, 0xa9, 0x7f, 0xcf, 0x76, 0xa5, 0xf1, - 0x54, 0xbc, 0x12, 0xf1, 0xc9, 0x8a, 0xc5, 0xe9, 0x24, 0x5e, 0x77, 0x33, 0x30, 0x1d, 0x71, 0xc8, - 0x61, 0xa8, 0x1d, 0x99, 0xbb, 0x38, 0xda, 0xc5, 0x91, 0x99, 0x98, 0x76, 0x58, 0xc4, 0x2d, 0xf1, - 0xc9, 0x8a, 0xc5, 0x21, 0xf0, 0x97, 0x12, 0x5f, 0x3d, 0xaf, 0xbc, 0xc9, 0xfa, 0x9a, 0x40, 0x7e, - 0x51, 0x02, 0x28, 0x9c, 0x8a, 0x38, 0x6f, 0x13, 0xd4, 0xa0, 0x12, 0x58, 0x2e, 0x64, 0x69, 0xeb, - 0x46, 0x63, 0x8a, 0xf3, 0x22, 0xab, 0xb4, 0x78, 0xeb, 0x79, 0x85, 0x3c, 0xb3, 0xe4, 0x97, 0x21, - 0x57, 0xae, 0xb8, 0x8a, 0x82, 0xd7, 0xb5, 0x78, 0xeb, 0x79, 0x85, 0x24, 0x4b, 0xe3, 0x41, 0x7e, - 0x09, 0x2a, 0x93, 0x34, 0x8d, 0x37, 0x6f, 0xb2, 0xca, 0x44, 0x94, 0x37, 0xd6, 0x48, 0x96, 0x97, - 0x22, 0x63, 0x10, 0xc9, 0x32, 0x5c, 0x78, 0x4b, 0x91, 0x2c, 0x2f, 0x45, 0xc6, 0x20, 0x92, 0x65, - 0xb8, 0xf0, 0x96, 0x22, 0x59, 0x5e, 0x8a, 0x8c, 0x41, 0x24, 0xcb, 0x70, 0xe1, 0x2d, 0x45, 0xb2, - 0xbc, 0x14, 0x19, 0x83, 0x48, 0x96, 0xe1, 0xc2, 0x5b, 0x8a, 0x64, 0x79, 0x29, 0x32, 0x06, 0x91, - 0x2c, 0xc3, 0x85, 0xb7, 0x14, 0xc9, 0xf2, 0x52, 0x64, 0x0c, 0x22, 0x59, 0x86, 0x0b, 0x6f, 0x29, - 0x92, 0xe5, 0xa5, 0xc8, 0x18, 0x44, 0xb2, 0x0c, 0x17, 0xde, 0x52, 0x24, 0xcb, 0x4b, 0x91, 0x31, - 0xb0, 0xc9, 0xd2, 0x16, 0xbe, 0x1e, 0x31, 0xa6, 0xb1, 0x64, 0x93, 0x35, 0xae, 0xd0, 0xd1, 0xa5, - 0xe8, 0x2a, 0xab, 0xb2, 0xc9, 0x92, 0x37, 0x49, 0x5c, 0x79, 0xde, 0x55, 0x54, 0xb9, 0xee, 0x23, - 0xab, 0x87, 0x5f, 0x1c, 0x5f, 0xaa, 0x32, 0x41, 0x76, 0xee, 0x3e, 0xb2, 0xc4, 0x76, 0x10, 0xc2, - 0x7a, 0xed, 0x46, 0x55, 0x2d, 0xdb, 0xef, 0x3a, 0xfc, 0x08, 0x09, 0xf2, 0x1e, 0x42, 0x97, 0x43, - 0x86, 0x7c, 0x8c, 0x79, 0x11, 0xc2, 0x7e, 0x62, 0x2b, 0xaf, 0x12, 0xfd, 0x0d, 0xb4, 0x97, 0xc3, - 0xe4, 0x9d, 0x81, 0x05, 0x2d, 0x75, 0xb2, 0xf8, 0x45, 0xf6, 0x3f, 0x08, 0x39, 0x48, 0xb6, 0x17, - 0x53, 0x32, 0xde, 0x82, 0x5e, 0x50, 0x59, 0xb1, 0x87, 0x61, 0x1b, 0x84, 0x7d, 0x0e, 0x13, 0x17, - 0x2a, 0xcb, 0x86, 0x27, 0xf1, 0x19, 0x64, 0x25, 0xb6, 0x7b, 0xd9, 0x9e, 0xf3, 0xb4, 0xab, 0xe4, - 0xee, 0x06, 0xb2, 0x38, 0xbb, 0xae, 0x83, 0xb7, 0x61, 0xa3, 0x1b, 0x8c, 0x54, 0x92, 0x95, 0x94, - 0xa4, 0xeb, 0x73, 0x96, 0xbb, 0x1f, 0xc2, 0xbe, 0x62, 0x0e, 0xdb, 0x86, 0x5e, 0x26, 0xfc, 0xb5, - 0x16, 0x64, 0xc2, 0x6f, 0x20, 0x19, 0xdd, 0x76, 0xb0, 0x02, 0x2c, 0x58, 0x49, 0x25, 0x4b, 0x32, - 0x86, 0x30, 0x79, 0x04, 0xba, 0x9c, 0x40, 0x54, 0xa9, 0x02, 0xb1, 0x43, 0xec, 0x7c, 0x35, 0xd5, - 0x60, 0x01, 0xec, 0xd0, 0xce, 0x90, 0x05, 0x90, 0x56, 0x3e, 0x29, 0x44, 0xb2, 0x32, 0xf0, 0x1a, - 0xc9, 0x8a, 0x64, 0x65, 0x60, 0x20, 0x83, 0x69, 0xc8, 0x33, 0xeb, 0x96, 0xe2, 0x77, 0xc6, 0x4b, - 0xf7, 0xca, 0xfe, 0xa2, 0xa9, 0x3a, 0x94, 0x80, 0xea, 0x79, 0x85, 0x24, 0x4b, 0xae, 0x9a, 0xae, - 0x94, 0xed, 0x79, 0x51, 0x8b, 0xb7, 0x9e, 0x57, 0x48, 0xb2, 0xb4, 0x97, 0x57, 0xb7, 0x73, 0x4b, - 0x51, 0x8a, 0x7b, 0x2f, 0xe2, 0x94, 0x8f, 0x08, 0xfa, 0xdc, 0xa3, 0x4d, 0xbd, 0x9e, 0x57, 0x48, - 0xb2, 0xb4, 0xc5, 0xc3, 0x27, 0x70, 0xf6, 0x31, 0x81, 0xe4, 0xf5, 0xc9, 0x9c, 0x92, 0x5b, 0xcb, - 0xaa, 0x03, 0xb4, 0x94, 0x1b, 0x6b, 0x57, 0xb4, 0xbc, 0x5c, 0x9b, 0x6c, 0x75, 0x08, 0x59, 0x06, - 0x64, 0xe5, 0x42, 0x93, 0x11, 0x94, 0x7d, 0x40, 0xbe, 0xfd, 0x0b, 0x79, 0x80, 0xb2, 0x05, 0xe9, - 0x58, 0x13, 0x4b, 0x07, 0xe8, 0x06, 0xe7, 0x41, 0x9a, 0xbc, 0x32, 0xdd, 0x4c, 0x4e, 0xbd, 0x60, - 0x82, 0xb7, 0x0f, 0xe8, 0xec, 0x88, 0xa7, 0x43, 0x59, 0x0b, 0xd3, 0xd6, 0xc3, 0x3c, 0xcd, 0x82, - 0xef, 0x96, 0xdc, 0x1f, 0xf6, 0xf4, 0xfa, 0x25, 0xfb, 0x77, 0xf2, 0x24, 0xf3, 0xe0, 0xbf, 0x77, - 0x42, 0x93, 0xb5, 0x84, 0xce, 0x7f, 0x05, 0x9d, 0x9e, 0x20, 0xca, 0xb0, 0xfb, 0x2e, 0x41, 0x6e, - 0x81, 0xa8, 0xd1, 0xe9, 0x60, 0x83, 0x0e, 0x09, 0x3a, 0x96, 0x4f, 0x3a, 0xf6, 0x03, 0xf9, 0x16, - 0xa6, 0xec, 0x72, 0xcc, 0x26, 0x2a, 0xb7, 0x64, 0x18, 0x8e, 0x5d, 0x60, 0x28, 0x6d, 0x12, 0x28, - 0xb8, 0x7e, 0x94, 0xf8, 0x7a, 0x34, 0x72, 0x82, 0x0e, 0x43, 0xd7, 0x01, 0x4e, 0x65, 0x72, 0xec, - 0x07, 0xf2, 0xb1, 0x90, 0x2c, 0xf3, 0x14, 0xf1, 0x4f, 0x80, 0x64, 0x14, 0xc8, 0x6f, 0x0f, 0x72, - 0xd5, 0xbb, 0x04, 0x4e, 0x71, 0x46, 0xc9, 0x10, 0x6c, 0x90, 0x5c, 0xc9, 0x72, 0xbd, 0x41, 0x9e, - 0xdc, 0x21, 0xaf, 0x01, 0x45, 0xb9, 0x95, 0x90, 0xaf, 0xef, 0xaf, 0x40, 0x8e, 0x2c, 0x45, 0x79, - 0xe5, 0x3e, 0xde, 0xb6, 0x6e, 0x62, 0xf2, 0xf1, 0x89, 0x52, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXMoreIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x20, 0x4f, 0xee, - 0x6c, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x6b, 0xda, 0xa9, 0x4c, 0x00, 0x00, - 0x01, 0xc4, 0x49, 0x44, 0x41, 0x54, 0x48, 0x0d, 0xdd, 0x95, 0x4f, 0x2b, 0x44, 0x51, 0x18, 0xc6, - 0xe7, 0xfa, 0x5b, 0x14, 0x4d, 0xc4, 0x6a, 0xec, 0xd4, 0xa4, 0xd8, 0x68, 0x90, 0x1a, 0x5f, 0x60, - 0x0a, 0x65, 0xef, 0x23, 0x8c, 0x6c, 0x94, 0xad, 0x9d, 0x95, 0x2f, 0x80, 0xa5, 0x05, 0x45, 0x29, - 0x35, 0x62, 0x41, 0x4a, 0x22, 0xa9, 0x61, 0x35, 0x8c, 0x42, 0xca, 0x9f, 0xd8, 0xa9, 0x99, 0x05, - 0xe3, 0xf7, 0x4e, 0x33, 0x67, 0xee, 0x4c, 0xf7, 0x9c, 0x79, 0x6d, 0xbd, 0xf5, 0x73, 0xcf, 0x79, - 0xdf, 0xe7, 0x79, 0x8e, 0x3b, 0xdd, 0x99, 0x1b, 0x0a, 0xf9, 0xaa, 0x50, 0x28, 0x24, 0x60, 0x07, - 0x1e, 0xe1, 0x01, 0xb6, 0x21, 0xe1, 0x93, 0xa8, 0x97, 0xf8, 0xfa, 0x61, 0x1d, 0x6e, 0xe0, 0x1d, - 0x0e, 0x61, 0x0e, 0x1a, 0xd5, 0x21, 0x25, 0x21, 0x9e, 0x4e, 0x58, 0x86, 0x53, 0xf8, 0x84, 0x73, - 0x58, 0x81, 0xae, 0xaa, 0x2c, 0x1a, 0x1e, 0xac, 0x82, 0xad, 0xd6, 0x18, 0x78, 0x55, 0x26, 0xc7, - 0x06, 0xed, 0x2c, 0x7c, 0x59, 0xc2, 0xce, 0xe8, 0x77, 0x3b, 0xec, 0x55, 0x23, 0xb4, 0x31, 0x78, - 0xb2, 0x64, 0xbd, 0xd2, 0x9f, 0x30, 0x06, 0x36, 0x49, 0x8b, 0xd0, 0xdf, 0x4e, 0x1a, 0x83, 0x63, - 0x81, 0x61, 0x00, 0x72, 0x7e, 0x63, 0xc0, 0x7a, 0xd3, 0x11, 0x61, 0x46, 0xf8, 0xda, 0x21, 0x1b, - 0xe0, 0xf7, 0xb7, 0x9e, 0xd9, 0x84, 0x43, 0xfc, 0x69, 0x01, 0xdb, 0xa7, 0xe7, 0x37, 0x88, 0xa6, - 0xd9, 0x9c, 0x62, 0x59, 0xa0, 0x91, 0x47, 0x53, 0x53, 0x31, 0x4b, 0x84, 0x69, 0x13, 0xb2, 0xa0, - 0x09, 0x42, 0xb3, 0xd4, 0x80, 0x6b, 0x08, 0xda, 0x8c, 0xdb, 0xbe, 0x10, 0xcd, 0xa0, 0x7d, 0x6c, - 0x26, 0x63, 0x66, 0xe5, 0x5e, 0x8c, 0xb8, 0xc7, 0xc5, 0xa9, 0x36, 0x6b, 0x54, 0x6e, 0xa4, 0x4f, - 0x11, 0x58, 0x96, 0x44, 0xca, 0x8b, 0xa0, 0x2b, 0x9f, 0x4c, 0x2b, 0xfd, 0x9e, 0xa0, 0x59, 0x40, - 0x4f, 0x73, 0xae, 0x46, 0x23, 0xd1, 0x11, 0xb9, 0x91, 0xeb, 0x80, 0x43, 0x6c, 0x2d, 0xa7, 0xd6, - 0xf3, 0xbc, 0x3c, 0xc6, 0x8c, 0xcd, 0x5c, 0xd3, 0x4f, 0xd7, 0xec, 0x83, 0xb6, 0x1a, 0x8d, 0xf8, - 0xd2, 0x72, 0x23, 0x77, 0x90, 0x95, 0x5d, 0x9d, 0xca, 0xf0, 0x8f, 0xde, 0xd7, 0xd1, 0xc8, 0x78, - 0x5f, 0xa1, 0xc9, 0xa1, 0x39, 0x56, 0xe8, 0x34, 0x59, 0x12, 0x93, 0x2a, 0x66, 0xf1, 0x48, 0xc4, - 0xe1, 0x1b, 0x6c, 0x25, 0xb3, 0x71, 0xc5, 0xc1, 0xf2, 0xe3, 0xd1, 0x01, 0xf2, 0x0e, 0x72, 0xd5, - 0xbc, 0x26, 0x4b, 0x34, 0x84, 0xec, 0xb9, 0x82, 0x98, 0x1d, 0x40, 0xe5, 0xd5, 0xc0, 0x66, 0x06, - 0xde, 0xa0, 0xb6, 0x5e, 0x68, 0x4c, 0x6b, 0x0f, 0x2e, 0x1d, 0x1e, 0xc5, 0x73, 0x51, 0x1b, 0xc4, - 0x3e, 0x0f, 0x8b, 0x20, 0x4f, 0x82, 0xaa, 0xd0, 0x86, 0x61, 0x03, 0x82, 0x6a, 0x8b, 0x66, 0xf1, - 0xa5, 0x58, 0xb9, 0x13, 0x62, 0x69, 0xca, 0x8b, 0x6a, 0x0a, 0x86, 0xe1, 0x07, 0x2e, 0x61, 0x97, - 0x47, 0xea, 0x83, 0xeb, 0x9f, 0x8a, 0xac, 0x26, 0x0c, 0x93, 0x20, 0xbf, 0x4e, 0xbd, 0x70, 0x05, - 0x29, 0xb2, 0xb4, 0xdf, 0x21, 0xe4, 0x95, 0x22, 0x2f, 0xce, 0x4e, 0x88, 0xc2, 0x2d, 0x9c, 0x90, - 0x75, 0xc4, 0xf5, 0x7f, 0xd5, 0x2f, 0x30, 0x5e, 0xa3, 0xc0, 0xef, 0xd7, 0xce, 0x11, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXMoreIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x12, 0x08, 0x06, 0x00, 0x00, 0x00, 0x13, 0xcf, 0x23, - 0xd5, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4b, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x08, 0xca, 0x01, 0x00, 0x00, - 0x02, 0xc6, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x98, 0x3d, 0x68, 0x15, 0x41, 0x14, 0x85, - 0xb3, 0x2f, 0xd1, 0x48, 0x10, 0x02, 0xa2, 0x21, 0x85, 0x76, 0x16, 0x16, 0x1a, 0x34, 0x2f, 0xa0, - 0xd8, 0xd8, 0x99, 0x68, 0x11, 0x14, 0xb4, 0x10, 0x24, 0xa8, 0x85, 0xd6, 0x5a, 0x06, 0xd4, 0xc6, - 0x46, 0x14, 0x0b, 0x8b, 0x34, 0x4a, 0x8a, 0xa0, 0x36, 0xa9, 0xd2, 0xaa, 0x8d, 0x8d, 0x29, 0x12, - 0x83, 0x29, 0xb4, 0x12, 0x9b, 0x88, 0x8a, 0x81, 0x60, 0x63, 0xfc, 0x21, 0xc9, 0xf3, 0xbb, 0x92, - 0x59, 0x76, 0x33, 0x33, 0x99, 0xbd, 0xf7, 0x3d, 0xbb, 0x5c, 0x38, 0xec, 0xcc, 0xfd, 0x39, 0x67, - 0x77, 0x76, 0x77, 0x66, 0x76, 0xb3, 0xb6, 0x80, 0x35, 0x1a, 0x8d, 0xfd, 0xb8, 0xcf, 0x83, 0x01, - 0x50, 0x07, 0x6b, 0xe0, 0x0d, 0x98, 0x03, 0x93, 0x59, 0x96, 0x7d, 0xe0, 0xd8, 0x52, 0x43, 0xf3, - 0x20, 0x84, 0x67, 0x81, 0x68, 0xf6, 0x83, 0x65, 0xe0, 0x34, 0x9f, 0xa2, 0xf9, 0x85, 0x7e, 0x4b, - 0x0d, 0xcd, 0xe3, 0x10, 0x9e, 0x02, 0x72, 0x8d, 0x47, 0xc0, 0x12, 0x70, 0x9a, 0x13, 0x68, 0x4a, - 0x3f, 0x6c, 0x14, 0xd7, 0xc0, 0x75, 0xb0, 0x0c, 0x62, 0x26, 0xb1, 0x1b, 0xa0, 0x16, 0x66, 0xd1, - 0x79, 0xe1, 0xe9, 0x00, 0x37, 0xc1, 0x1f, 0x10, 0xb3, 0x25, 0x02, 0x17, 0x75, 0xcc, 0xf1, 0x6c, - 0xb8, 0x76, 0x82, 0x31, 0xb0, 0x06, 0x62, 0xf6, 0x95, 0xc0, 0x99, 0x20, 0x0b, 0x81, 0x76, 0xf0, - 0x22, 0x56, 0x19, 0xf0, 0xbf, 0x94, 0x9a, 0x20, 0x59, 0x45, 0x27, 0xf5, 0x9d, 0x60, 0x3a, 0xc0, - 0x1d, 0x73, 0x3d, 0xae, 0x48, 0x1d, 0x4d, 0x83, 0xb8, 0x17, 0x7c, 0x8c, 0x09, 0x04, 0xfc, 0xf7, - 0x3d, 0x32, 0x92, 0x46, 0x03, 0x89, 0x29, 0xd7, 0xa8, 0x47, 0xa4, 0x70, 0x40, 0x7e, 0x37, 0x25, - 0x10, 0x88, 0x9f, 0x53, 0x48, 0x78, 0xa9, 0xf0, 0x4d, 0x05, 0x38, 0x53, 0xae, 0x93, 0x39, 0x11, - 0x99, 0x7d, 0xe0, 0x77, 0xaa, 0x22, 0x10, 0x97, 0x9a, 0x43, 0x39, 0x91, 0xa2, 0x41, 0xdd, 0x31, - 0xb0, 0x12, 0xe0, 0x4c, 0xb9, 0xbe, 0x91, 0xb0, 0x5b, 0x21, 0x95, 0xa7, 0x52, 0x37, 0x92, 0x22, - 0x8f, 0xc4, 0x17, 0xf0, 0x77, 0xbb, 0x79, 0xe7, 0x12, 0x8c, 0xdb, 0x73, 0xd6, 0xea, 0x0d, 0xa9, - 0x19, 0xa9, 0x9e, 0x5e, 0xca, 0xbc, 0x42, 0xcf, 0xf2, 0x1a, 0xef, 0xa1, 0x6e, 0xb8, 0xc4, 0x54, - 0xbd, 0x73, 0xb5, 0x7a, 0x6a, 0x29, 0x73, 0x2f, 0xbd, 0x41, 0x37, 0x58, 0xb2, 0x02, 0x59, 0x4d, - 0x56, 0x12, 0x8b, 0x59, 0xeb, 0x44, 0x4b, 0x5d, 0xcb, 0x93, 0x21, 0x37, 0x46, 0x56, 0x3c, 0xab, - 0xd5, 0x65, 0xf5, 0x93, 0x01, 0x6b, 0x86, 0xa4, 0x1f, 0x8e, 0x4c, 0x73, 0x06, 0xe4, 0x77, 0x92, - 0x6f, 0x7a, 0x7d, 0xd7, 0x75, 0x64, 0x6b, 0xa1, 0xb5, 0x03, 0x14, 0x74, 0x69, 0x8b, 0x0a, 0xf9, - 0x75, 0x19, 0x28, 0xb9, 0x50, 0xf7, 0x84, 0x15, 0x62, 0x95, 0x9b, 0x96, 0x5a, 0xd1, 0x54, 0x0d, - 0xf0, 0x86, 0xb3, 0xb1, 0x68, 0x5a, 0x5e, 0xf9, 0xa2, 0x6c, 0xad, 0xc6, 0xc6, 0x6b, 0x15, 0xcf, - 0xdb, 0xa2, 0x57, 0xd9, 0x9e, 0x83, 0xa3, 0xa1, 0xa9, 0x21, 0xff, 0x17, 0xf9, 0xef, 0x34, 0x35, - 0x1b, 0x72, 0x65, 0xe3, 0xa8, 0xb5, 0xf7, 0x14, 0xfc, 0xd4, 0x16, 0x15, 0xf2, 0x67, 0xdd, 0x1d, - 0x9a, 0x2d, 0x38, 0xb5, 0x4d, 0x6b, 0xad, 0xe5, 0x82, 0xdd, 0xb9, 0xa9, 0x35, 0xb9, 0x41, 0x2b, - 0x14, 0xcf, 0x3b, 0x02, 0xc3, 0x71, 0xe6, 0x5f, 0x0d, 0x73, 0xc8, 0x00, 0xb0, 0x2c, 0xe3, 0xb2, - 0xeb, 0x3e, 0x6c, 0x10, 0x6e, 0xa3, 0xee, 0x04, 0xd8, 0x6c, 0x07, 0x4d, 0x38, 0x68, 0x8b, 0x78, - 0x7b, 0x8c, 0x9a, 0xd7, 0x82, 0x8c, 0x69, 0xe7, 0x27, 0x52, 0xba, 0x73, 0x4d, 0x3a, 0x77, 0xd2, - 0x35, 0x5e, 0xc6, 0xad, 0x9c, 0xc0, 0xd0, 0x80, 0xed, 0xa1, 0xc7, 0x98, 0x76, 0xc8, 0x37, 0xab, - 0xc9, 0xa0, 0xce, 0xc0, 0xf3, 0xb4, 0x84, 0x97, 0x31, 0x54, 0x12, 0x24, 0xbc, 0x0d, 0xbc, 0xf6, - 0xd2, 0xe2, 0x8e, 0x57, 0x84, 0x3a, 0x4a, 0x24, 0xca, 0x0e, 0xf5, 0x5d, 0x60, 0x3e, 0x2e, 0xe1, - 0x45, 0xc6, 0x95, 0x12, 0x5e, 0x3a, 0x8c, 0xfb, 0xc0, 0x67, 0x8f, 0x39, 0xee, 0x78, 0xe0, 0x91, - 0x88, 0x83, 0x7c, 0x19, 0xb0, 0xdb, 0x60, 0xb3, 0x8f, 0x5a, 0xd9, 0xb5, 0xcb, 0xa7, 0x51, 0x53, - 0x03, 0xe5, 0x4e, 0x00, 0x9e, 0x1d, 0xe0, 0x1e, 0x58, 0x05, 0x31, 0xfb, 0x4e, 0xe0, 0xb2, 0xab, - 0x69, 0xf6, 0x08, 0xd7, 0x2e, 0xf0, 0x24, 0x26, 0xb6, 0xee, 0x97, 0xd7, 0xbd, 0xf4, 0x14, 0x07, - 0x97, 0x6f, 0x92, 0xfa, 0x38, 0xa1, 0x0b, 0xc0, 0xfd, 0x2e, 0x71, 0xbf, 0x68, 0x64, 0x52, 0x7e, - 0xc6, 0x64, 0xd9, 0xcc, 0x4a, 0x16, 0xbc, 0x56, 0x34, 0x8f, 0x12, 0x90, 0xef, 0x3e, 0xa7, 0xf9, - 0x83, 0xb6, 0xe8, 0xc9, 0x64, 0x3e, 0x8e, 0xe6, 0x02, 0xc7, 0x96, 0x1a, 0x9a, 0x83, 0x10, 0x9e, - 0x06, 0xb2, 0xc9, 0x95, 0xb9, 0x57, 0x7e, 0xc9, 0x88, 0x9e, 0xe0, 0x11, 0x9a, 0x8b, 0x1c, 0xb7, - 0x6c, 0x6b, 0x04, 0xfe, 0xf3, 0x08, 0xfc, 0x05, 0x85, 0x24, 0x43, 0xa4, 0x3d, 0xeb, 0x6a, 0x6e, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXGearIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x57, 0x02, 0xf9, - 0x87, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x37, 0x6c, 0x0c, 0x00, 0x00, - 0x06, 0x6a, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xd5, 0x98, 0x7b, 0x88, 0x55, 0x55, 0x14, 0x87, - 0x67, 0xd4, 0xd1, 0xc9, 0x4c, 0x2d, 0xcb, 0x34, 0x8a, 0x91, 0x1c, 0x2b, 0x31, 0xc9, 0x71, 0x8a, - 0x4c, 0x1c, 0x2a, 0xc8, 0x30, 0xc5, 0xcc, 0xc2, 0x12, 0x13, 0x24, 0xe9, 0x45, 0xd0, 0x04, 0xa6, - 0xf5, 0xc7, 0x64, 0x91, 0x14, 0x61, 0x6f, 0xb4, 0x18, 0x2a, 0x04, 0x4b, 0x7b, 0x3f, 0xa0, 0x07, - 0x21, 0xf6, 0x18, 0x32, 0x8a, 0x2c, 0x19, 0x4b, 0x53, 0x62, 0x6a, 0xd0, 0x2c, 0x1b, 0xf3, 0x91, - 0x39, 0x96, 0xe9, 0xa4, 0x4d, 0xdf, 0x6f, 0xe6, 0x9e, 0x7b, 0xd7, 0xdd, 0x77, 0xdf, 0x73, 0xcf, - 0x9e, 0x07, 0x53, 0x0b, 0xbe, 0x7b, 0xd6, 0x5a, 0x7b, 0xad, 0xb5, 0xf7, 0x3d, 0x8f, 0xbd, 0xf7, - 0x39, 0x45, 0x45, 0x5d, 0x28, 0xad, 0xad, 0xad, 0x63, 0xa0, 0xcc, 0x57, 0x12, 0x7f, 0x29, 0x54, - 0x41, 0x89, 0xaf, 0xbd, 0xc7, 0x7d, 0x0c, 0xac, 0x02, 0x24, 0xcd, 0x30, 0xc2, 0x1d, 0x10, 0xbe, - 0x57, 0xd5, 0x88, 0xd4, 0xba, 0x6d, 0xff, 0x09, 0x9b, 0x81, 0xdd, 0xde, 0x36, 0xbc, 0xf6, 0x9f, - 0xe7, 0xed, 0xa0, 0x70, 0x4d, 0x30, 0x6d, 0x5b, 0x6c, 0x5b, 0x67, 0xf5, 0x3e, 0x21, 0x05, 0x18, - 0xc4, 0x60, 0xe2, 0x1f, 0x85, 0xaf, 0x8b, 0x8b, 0x8b, 0x9f, 0x72, 0x72, 0xcb, 0x8d, 0x3d, 0x97, - 0xd8, 0xed, 0xd8, 0xbd, 0xa0, 0x05, 0x66, 0x40, 0x24, 0x67, 0xd2, 0x46, 0x7a, 0x71, 0x6b, 0xe4, - 0xc0, 0x3e, 0x0f, 0x7d, 0x11, 0xac, 0xc6, 0xbf, 0x26, 0xf2, 0x77, 0xf9, 0x91, 0x8e, 0xe6, 0x43, - 0x24, 0x2b, 0x50, 0xfa, 0xc0, 0x28, 0x58, 0x02, 0xbb, 0x21, 0xa9, 0xbc, 0x4c, 0xe0, 0x15, 0xa0, - 0xfc, 0xc9, 0xa0, 0xdb, 0x4e, 0xf2, 0x55, 0x97, 0x0f, 0xda, 0x16, 0xa4, 0x03, 0x75, 0x66, 0x65, - 0xa7, 0x35, 0x3a, 0xa0, 0xff, 0x4a, 0x4e, 0x8b, 0xc9, 0x7b, 0xcb, 0xf6, 0x97, 0x44, 0xd7, 0x25, - 0x0e, 0x91, 0x0d, 0x4e, 0xf0, 0x69, 0x8e, 0x6d, 0xcd, 0x63, 0x18, 0x4d, 0xd0, 0x6c, 0x9d, 0x8e, - 0x3e, 0x14, 0xdb, 0xce, 0x4a, 0xc1, 0x57, 0x20, 0xe8, 0x19, 0xa0, 0xb3, 0x8b, 0x41, 0x03, 0xeb, - 0x0d, 0xae, 0xd4, 0xe3, 0x78, 0x09, 0x3e, 0x83, 0x9f, 0xa1, 0x89, 0xfb, 0x59, 0xb1, 0x45, 0x9c, - 0xe1, 0xe3, 0x38, 0x0c, 0x87, 0x0b, 0x61, 0x1a, 0x4c, 0x81, 0x21, 0xe0, 0x4a, 0x25, 0xb1, 0xa5, - 0xe4, 0x1d, 0x76, 0x1b, 0x82, 0x6c, 0x8a, 0x94, 0x80, 0xa6, 0xbd, 0x35, 0x30, 0x07, 0x34, 0x87, - 0xd7, 0xc0, 0x3f, 0xe0, 0x4a, 0x03, 0x8e, 0xb3, 0x42, 0x3a, 0x20, 0xbe, 0x37, 0xcc, 0x83, 0x46, - 0x70, 0x65, 0x3d, 0x8e, 0xe1, 0x30, 0x0e, 0x6a, 0xe1, 0x0b, 0xb8, 0x28, 0xa4, 0xbe, 0xce, 0xd8, - 0x78, 0xb0, 0xf2, 0xa7, 0x35, 0x3c, 0xfa, 0xc4, 0xa0, 0x0e, 0x52, 0xc1, 0xd4, 0xd1, 0x89, 0xaa, - 0x86, 0xc3, 0x4e, 0xcd, 0x43, 0x8e, 0xfd, 0x5c, 0x50, 0x7d, 0x92, 0x7b, 0xc1, 0x97, 0x4e, 0x11, - 0x6b, 0x2e, 0xc6, 0x78, 0xdb, 0x38, 0x36, 0xa0, 0x87, 0x3e, 0x4f, 0xe9, 0x31, 0x91, 0x7b, 0x3e, - 0x6c, 0x37, 0xf5, 0xac, 0x7a, 0x0c, 0x43, 0xb7, 0x5e, 0x98, 0x90, 0xa4, 0x4b, 0xf8, 0xb7, 0xad, - 0x84, 0xae, 0x5b, 0xa8, 0x5a, 0x95, 0x38, 0x6a, 0x3e, 0xb7, 0x67, 0xee, 0xc6, 0xb0, 0x1e, 0xb2, - 0xa3, 0xa9, 0x75, 0x32, 0x6c, 0x05, 0x57, 0xdc, 0xf5, 0x26, 0x3b, 0x31, 0x9f, 0x45, 0x95, 0x41, - 0xf0, 0x9b, 0x53, 0xed, 0x26, 0x1b, 0x4f, 0xdb, 0x03, 0xa6, 0x5d, 0xeb, 0xc0, 0x20, 0xdb, 0x1e, - 0xaa, 0x93, 0x5f, 0x06, 0xbf, 0x80, 0x95, 0x9b, 0x43, 0xeb, 0xb4, 0xc5, 0x53, 0xe1, 0x11, 0x5b, - 0x05, 0xfd, 0x75, 0xb7, 0x10, 0xbe, 0xfe, 0xb0, 0xc3, 0xc4, 0x3d, 0xe1, 0xc6, 0x84, 0xda, 0xd4, - 0xd2, 0x4c, 0x64, 0xaf, 0x7c, 0x13, 0xf6, 0x80, 0x82, 0x75, 0x08, 0x3a, 0x15, 0xa6, 0xc2, 0xa5, - 0x30, 0x05, 0x8e, 0x40, 0x24, 0x7b, 0x51, 0x34, 0x67, 0xe7, 0x08, 0xfe, 0xeb, 0xa2, 0x20, 0x8e, - 0xea, 0x78, 0x74, 0x4e, 0x50, 0xa0, 0x83, 0x1a, 0x8f, 0x99, 0x9a, 0x52, 0x97, 0x41, 0x15, 0x68, - 0x5c, 0x17, 0x78, 0xcb, 0xd1, 0xb0, 0x0d, 0xf2, 0xc9, 0xf5, 0xde, 0xa4, 0x94, 0x93, 0xa4, 0x3a, - 0x93, 0xb8, 0x36, 0x2e, 0x36, 0x49, 0x1b, 0xb5, 0x4e, 0x80, 0xb8, 0x55, 0x5e, 0xeb, 0x48, 0xb6, - 0x90, 0xb0, 0xc9, 0x0c, 0xc2, 0xaa, 0x2a, 0x14, 0x3b, 0xc3, 0xd0, 0x3e, 0x16, 0x8e, 0x9a, 0xa4, - 0xab, 0xb2, 0xab, 0x87, 0x5b, 0xd4, 0x5a, 0x64, 0xea, 0x59, 0x55, 0xb3, 0xd2, 0xa4, 0x9c, 0x8a, - 0x38, 0x35, 0x0b, 0xd4, 0x81, 0x2b, 0x0f, 0xe7, 0x04, 0x7b, 0x1c, 0x24, 0x2d, 0x37, 0x89, 0x8d, - 0xe8, 0xfd, 0xc0, 0xb7, 0x62, 0x7b, 0xb2, 0x73, 0x5d, 0xe4, 0x6a, 0x31, 0xb3, 0x27, 0x05, 0xb3, - 0xf5, 0x77, 0xd0, 0x4a, 0xee, 0x17, 0x1a, 0xb5, 0x3b, 0xfc, 0x1c, 0xac, 0x8c, 0xf5, 0x47, 0x67, - 0x7b, 0x49, 0x38, 0x11, 0xf6, 0x98, 0xc4, 0xfd, 0xe8, 0x9a, 0x76, 0x77, 0xc1, 0x6b, 0x70, 0x6e, - 0x76, 0x46, 0x61, 0x8b, 0x9c, 0xf7, 0xc1, 0x4a, 0x45, 0xc1, 0x2c, 0xa2, 0xeb, 0x4d, 0xc6, 0xf7, - 0x05, 0x13, 0x4c, 0x00, 0x79, 0x0b, 0x4c, 0xae, 0xab, 0xea, 0x01, 0x9f, 0x69, 0xc2, 0x0b, 0xaa, - 0xc4, 0xdf, 0xe5, 0x14, 0xc9, 0x59, 0xf1, 0xb3, 0xee, 0x6d, 0x82, 0x75, 0xc9, 0xed, 0x2c, 0xf2, - 0x43, 0xc1, 0x5e, 0x52, 0x01, 0xe4, 0xaa, 0xd6, 0xac, 0x98, 0x78, 0x6d, 0x1c, 0xb5, 0xbf, 0x1a, - 0x13, 0x13, 0xe3, 0x36, 0x6d, 0x76, 0x1c, 0x39, 0x77, 0x43, 0xfa, 0x0f, 0x50, 0x58, 0x5b, 0xe3, - 0x05, 0x50, 0x6a, 0x92, 0x7e, 0x32, 0x7a, 0x21, 0x55, 0x8b, 0xdc, 0x84, 0x54, 0xd0, 0x21, 0x8e, - 0xf3, 0x41, 0x53, 0xaf, 0x36, 0x62, 0x1b, 0x41, 0xa2, 0xad, 0xf3, 0x83, 0xf4, 0x35, 0x20, 0x09, - 0xc4, 0x6e, 0x53, 0x92, 0x91, 0xd9, 0xe4, 0x4d, 0x84, 0xf4, 0xb8, 0xb5, 0x25, 0xd0, 0xbd, 0xbb, - 0x16, 0x7c, 0x3b, 0xcd, 0x7b, 0x4c, 0x72, 0xac, 0x4a, 0xfe, 0x9b, 0x10, 0x89, 0x5e, 0x0f, 0xd3, - 0x82, 0xf3, 0x0c, 0xd0, 0xec, 0xd1, 0x55, 0xa2, 0xd5, 0x7a, 0xba, 0x3a, 0xd0, 0x3f, 0xd1, 0x59, - 0x9b, 0x0c, 0xc5, 0xe0, 0xca, 0x5e, 0xd7, 0x11, 0x63, 0x9f, 0x6d, 0xda, 0xd6, 0x1b, 0xbd, 0x88, - 0xfd, 0xbd, 0xae, 0xe4, 0x2e, 0xeb, 0xeb, 0xa4, 0xae, 0x77, 0x8b, 0xb6, 0x6d, 0x8d, 0xfe, 0x40, - 0x1d, 0x3c, 0x0e, 0xbb, 0xc1, 0x95, 0x61, 0xae, 0x23, 0xc6, 0xfe, 0xce, 0xb4, 0x55, 0x19, 0x5d, - 0x57, 0x79, 0x24, 0xb6, 0x3a, 0x95, 0xe8, 0x65, 0x7e, 0x4f, 0x42, 0x7c, 0x27, 0xf0, 0x28, 0xb9, - 0x1f, 0xc2, 0x7d, 0x90, 0x11, 0x3a, 0xd1, 0x16, 0x5a, 0x5b, 0x09, 0x2b, 0x2b, 0x32, 0x11, 0xf1, - 0x1a, 0x49, 0x37, 0x98, 0xc4, 0xbf, 0xd0, 0x6f, 0x83, 0xd3, 0x41, 0x5b, 0x93, 0x6f, 0x21, 0x92, - 0xac, 0x4f, 0x2e, 0x71, 0x55, 0x49, 0xd0, 0x8e, 0xd7, 0xca, 0x2b, 0x18, 0x27, 0xc5, 0xe5, 0xe8, - 0x6c, 0x1d, 0x30, 0x19, 0x1f, 0xc4, 0x06, 0x9b, 0x46, 0x72, 0x8a, 0xe1, 0x63, 0x93, 0xeb, 0x53, - 0xf5, 0x62, 0xa4, 0xab, 0x91, 0x48, 0x88, 0x9d, 0xe1, 0x14, 0x99, 0xe7, 0x26, 0x66, 0x9e, 0xe6, - 0x4c, 0xcb, 0xd6, 0x8c, 0x5a, 0x74, 0x0e, 0x05, 0x7c, 0xcf, 0x86, 0x09, 0x69, 0x57, 0xb9, 0xcf, - 0x75, 0x6b, 0xac, 0xcb, 0x69, 0xc8, 0x38, 0x8e, 0xa0, 0xce, 0x24, 0xae, 0x31, 0xe3, 0x2a, 0xa8, - 0xb9, 0xd3, 0xe6, 0xa6, 0xd8, 0x0c, 0x06, 0x3b, 0x04, 0x36, 0x3b, 0xff, 0x7a, 0x52, 0x6c, 0x52, - 0xaa, 0x91, 0x9c, 0x11, 0x60, 0x5f, 0x05, 0xf5, 0xc9, 0x44, 0x8b, 0xd7, 0x8f, 0xf0, 0x02, 0x94, - 0x27, 0xa9, 0x63, 0x63, 0xc8, 0xf9, 0x14, 0xac, 0xe4, 0xdf, 0x63, 0x11, 0xa5, 0x37, 0xb0, 0xed, - 0x36, 0x3a, 0xa5, 0x3f, 0x63, 0x8b, 0xe6, 0xd3, 0x89, 0x7d, 0xc7, 0xe4, 0xea, 0x24, 0x68, 0xe1, - 0xea, 0xb0, 0x90, 0x5f, 0x6e, 0xea, 0x45, 0xaa, 0xa6, 0xe2, 0x1a, 0x6f, 0x51, 0x1a, 0xf2, 0x6d, - 0x5f, 0xf5, 0x56, 0xd6, 0xd7, 0x9b, 0x94, 0x72, 0xd2, 0xee, 0xde, 0xab, 0x59, 0xb3, 0x50, 0x5c, - 0x6e, 0xbe, 0x36, 0x6a, 0xda, 0xb7, 0x3d, 0xcc, 0x2c, 0xb9, 0x32, 0x27, 0x8f, 0x66, 0xbd, 0x98, - 0xe7, 0x93, 0xbb, 0x73, 0x12, 0x52, 0x0e, 0x12, 0xfa, 0x83, 0xbd, 0x72, 0x2b, 0xf3, 0xc5, 0x26, - 0xf5, 0x53, 0x6f, 0x18, 0xd8, 0xc9, 0x04, 0x33, 0x2d, 0xda, 0xa1, 0x46, 0x2b, 0x7e, 0xa6, 0x24, - 0x4e, 0x7d, 0xab, 0xd1, 0xb4, 0xa5, 0x37, 0x33, 0x4d, 0x7f, 0xda, 0x4d, 0x46, 0xa2, 0x69, 0xd1, - 0xfb, 0xed, 0x07, 0xff, 0x43, 0x51, 0x10, 0x47, 0x5d, 0xad, 0x53, 0x32, 0x55, 0x3b, 0xa6, 0x51, - 0x63, 0x95, 0xa9, 0x29, 0xb5, 0x1a, 0xb4, 0x63, 0x28, 0xd3, 0x31, 0x51, 0x55, 0x02, 0xef, 0x04, - 0x2b, 0xeb, 0x30, 0xb2, 0x66, 0x24, 0xec, 0xd1, 0xd0, 0x62, 0x82, 0x6e, 0x4d, 0x54, 0x3c, 0x26, - 0x88, 0x5a, 0xd3, 0x4c, 0x3d, 0xa9, 0x5b, 0x20, 0xfc, 0x79, 0x22, 0xa9, 0x2f, 0xec, 0x03, 0x2b, - 0x5a, 0xb1, 0xd3, 0x42, 0x43, 0x9d, 0x69, 0xd4, 0x17, 0x35, 0xdf, 0xb4, 0x9c, 0x8e, 0x2f, 0xa4, - 0x90, 0x5f, 0x09, 0x7f, 0x98, 0x9a, 0x52, 0x67, 0x17, 0xca, 0xf3, 0xb6, 0x93, 0x38, 0xdd, 0x29, - 0x14, 0x99, 0xb5, 0x28, 0x5a, 0xb4, 0xe6, 0x46, 0x0e, 0x8e, 0x9a, 0x1d, 0xc6, 0x7b, 0x0b, 0x25, - 0x74, 0x92, 0xaf, 0xab, 0xa9, 0x97, 0x1f, 0x57, 0xde, 0x4b, 0x58, 0x22, 0x13, 0x46, 0x85, 0x52, - 0xb0, 0x0f, 0xa6, 0x5b, 0xf4, 0x45, 0x1c, 0xb6, 0xb3, 0xe5, 0x99, 0xec, 0x70, 0x8d, 0x5a, 0xb3, - 0xa0, 0xd9, 0xed, 0xc4, 0xd8, 0x57, 0x07, 0x55, 0x25, 0xb1, 0xc2, 0x24, 0x4b, 0xfd, 0x06, 0x7c, - 0xdb, 0x6d, 0xb5, 0xe9, 0xbb, 0x4d, 0x87, 0x3e, 0x68, 0x91, 0x37, 0x14, 0x9e, 0x06, 0x57, 0x1a, - 0x70, 0x68, 0xdb, 0x11, 0xc9, 0xb3, 0xa1, 0x7f, 0x40, 0xb7, 0xc8, 0xfd, 0xf0, 0x24, 0x8c, 0x53, - 0x32, 0x47, 0xcd, 0xf5, 0x07, 0xc1, 0x95, 0x8d, 0x38, 0xd4, 0x16, 0xbb, 0x56, 0xd8, 0x01, 0x10, - 0xab, 0x69, 0x52, 0xb3, 0x97, 0x7b, 0xbf, 0xe3, 0x6a, 0x5d, 0x0d, 0xba, 0x03, 0x06, 0x83, 0x66, - 0x9f, 0x95, 0x90, 0x77, 0x15, 0xcf, 0x9a, 0x55, 0x6c, 0x27, 0x3e, 0x9d, 0x42, 0xda, 0x9b, 0xd4, - 0x83, 0x6f, 0x56, 0xd8, 0x8f, 0xff, 0x0d, 0xd0, 0xbb, 0x80, 0xf6, 0xff, 0x62, 0x27, 0x1c, 0x0f, - 0xda, 0x96, 0x0b, 0xcd, 0xdf, 0x53, 0xa1, 0x12, 0x7c, 0x7d, 0x2f, 0x63, 0xaf, 0x74, 0x07, 0x6d, - 0xdd, 0x23, 0xfc, 0x01, 0x7d, 0xea, 0xe8, 0x4e, 0x59, 0x12, 0x3a, 0xf2, 0xd0, 0x69, 0xcf, 0xfd, - 0xac, 0xf7, 0x11, 0x1d, 0x1e, 0x08, 0xed, 0x34, 0x15, 0xaf, 0xdd, 0xeb, 0x27, 0xb0, 0xcf, 0xe4, - 0xbb, 0xf5, 0x4d, 0x93, 0x5f, 0x0d, 0xfd, 0x03, 0x03, 0x53, 0x65, 0xd4, 0xf9, 0x42, 0x2e, 0xf7, - 0x65, 0x1c, 0x75, 0x6b, 0x5c, 0x0b, 0x0d, 0x90, 0x54, 0x16, 0x13, 0x58, 0x46, 0xfe, 0x25, 0x1c, - 0xb5, 0xdb, 0xdd, 0x01, 0x92, 0xa8, 0x7e, 0xbb, 0xd5, 0xd5, 0xbf, 0xdc, 0x3b, 0x25, 0xb0, 0x10, - 0x2e, 0x77, 0x6b, 0xe3, 0xb3, 0x5f, 0xb3, 0xb5, 0xad, 0xd6, 0xd4, 0x38, 0x07, 0xae, 0x81, 0x77, - 0x21, 0x92, 0x83, 0x9e, 0x5c, 0x3d, 0xd4, 0x35, 0xe0, 0xee, 0xff, 0xdd, 0xd0, 0xee, 0xb3, 0xe9, - 0xfc, 0x96, 0x68, 0x84, 0x1c, 0x97, 0xda, 0x9e, 0xb0, 0x47, 0x81, 0xde, 0x0d, 0x24, 0xd1, 0x27, - 0x16, 0x1b, 0xd2, 0xf3, 0x3a, 0x03, 0x1b, 0x09, 0x9a, 0x16, 0xb5, 0x00, 0xe6, 0x6c, 0xb8, 0xf0, - 0x2d, 0x05, 0xc9, 0xbd, 0x3d, 0x3f, 0xda, 0x3c, 0x23, 0x60, 0x70, 0x03, 0xa1, 0x5f, 0x9e, 0x66, - 0xad, 0x25, 0x9d, 0xde, 0xa9, 0xe6, 0xab, 0xfd, 0xbf, 0xf5, 0xff, 0x0b, 0x9a, 0x0a, 0x94, 0x47, - 0x1c, 0x29, 0x6a, 0x39, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXGearIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x08, 0x06, 0x00, 0x00, 0x00, 0x55, 0xed, 0xb3, - 0x47, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x90, 0x31, 0x46, 0xef, 0x00, 0x00, - 0x0a, 0x22, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, 0x9a, 0x7b, 0xf0, 0x55, 0x55, 0x15, 0xc7, - 0xf9, 0xf9, 0x00, 0xd1, 0x02, 0x05, 0x8c, 0x50, 0x12, 0x30, 0x34, 0x53, 0xb0, 0x86, 0x81, 0xc6, - 0x47, 0x45, 0x8e, 0x8a, 0xf9, 0x47, 0x93, 0x4d, 0x5a, 0x99, 0x3d, 0x06, 0x7b, 0xd1, 0x64, 0x8d, - 0x8e, 0x36, 0x9a, 0x5a, 0x43, 0x9a, 0xce, 0x68, 0x35, 0x66, 0x52, 0x3e, 0xd2, 0x8a, 0x64, 0x1c, - 0x99, 0xd2, 0x9e, 0x0a, 0x3d, 0xc8, 0x34, 0x67, 0x22, 0x29, 0x41, 0x14, 0xc9, 0xc9, 0xfa, 0xa5, - 0xf8, 0xa0, 0xa2, 0xd4, 0xd1, 0x44, 0x25, 0xa4, 0xcf, 0xf7, 0xfe, 0xee, 0xb9, 0xb3, 0x7f, 0xeb, - 0xae, 0xbd, 0xcf, 0x3e, 0xf7, 0x9c, 0x7e, 0x3c, 0x86, 0x35, 0xf3, 0xbd, 0x7b, 0xef, 0xb5, 0xd7, - 0xeb, 0xec, 0x73, 0xce, 0x7e, 0xac, 0x73, 0x87, 0x0d, 0xdb, 0x49, 0xdb, 0xce, 0x08, 0x6c, 0xd9, - 0xb2, 0x65, 0x24, 0xf8, 0x3e, 0x78, 0x04, 0x5c, 0x58, 0x16, 0x19, 0x32, 0x1f, 0x03, 0x7f, 0x01, - 0x4b, 0xc1, 0xb8, 0x32, 0xf9, 0xed, 0xbe, 0x9f, 0x8b, 0xfc, 0x28, 0x08, 0xe9, 0xed, 0xb1, 0x8b, - 0x42, 0x68, 0x3a, 0xd8, 0x1c, 0x08, 0xcf, 0x8f, 0xc9, 0xee, 0x30, 0x7c, 0x2e, 0xf6, 0xba, 0xe0, - 0x82, 0x55, 0xbd, 0x17, 0xf4, 0x79, 0x17, 0x08, 0xff, 0x27, 0x12, 0x08, 0x68, 0x89, 0x27, 0xb7, - 0xdd, 0xf0, 0xb8, 0x90, 0xdd, 0xca, 0x82, 0x45, 0xe6, 0xd7, 0xc1, 0x05, 0x17, 0xd5, 0xf7, 0x5a, - 0x3d, 0x3a, 0x8e, 0x2a, 0x3a, 0x83, 0xf2, 0xcf, 0x56, 0xce, 0xb6, 0x91, 0x1d, 0x6e, 0x79, 0xdb, - 0x44, 0x9b, 0xc0, 0x2e, 0x03, 0x1b, 0xc1, 0x0a, 0xf0, 0xfa, 0x58, 0x50, 0xf4, 0xad, 0x03, 0x96, - 0x9e, 0x84, 0xa1, 0x39, 0xe6, 0xb7, 0xe0, 0x6e, 0xf0, 0x0b, 0xf0, 0x57, 0x60, 0x69, 0x13, 0x0c, - 0xf7, 0x26, 0xc0, 0xdf, 0x1f, 0x2c, 0x03, 0x92, 0x59, 0x08, 0x76, 0x89, 0xc5, 0x30, 0xe4, 0x7c, - 0x82, 0x19, 0x0d, 0x42, 0xfa, 0x37, 0x8d, 0x37, 0x87, 0x81, 0xd0, 0xd6, 0x7c, 0x72, 0x39, 0x78, - 0x19, 0xd4, 0xa1, 0x05, 0x28, 0xcf, 0x30, 0xb6, 0x0f, 0x85, 0xf7, 0xa8, 0x31, 0x3a, 0x3d, 0x94, - 0xa9, 0x53, 0x77, 0xdf, 0xff, 0x2a, 0x06, 0x09, 0x6c, 0x34, 0xf2, 0x4f, 0x1b, 0x9d, 0x17, 0x68, - 0xcf, 0x03, 0x63, 0xc0, 0x87, 0xc0, 0x1b, 0x41, 0x93, 0xb4, 0x16, 0x63, 0x8b, 0xc0, 0x9f, 0xc0, - 0xf5, 0x60, 0x1f, 0x10, 0xd2, 0xb4, 0xbe, 0xbe, 0xbe, 0x35, 0x21, 0xa3, 0xd7, 0x7a, 0xed, 0x01, - 0x92, 0x63, 0x06, 0x49, 0xf3, 0xc3, 0xd4, 0x5e, 0x83, 0x68, 0x58, 0xef, 0x79, 0xec, 0x8d, 0x62, - 0x80, 0x36, 0x37, 0x61, 0xb7, 0xa9, 0x77, 0x75, 0x45, 0x13, 0xc1, 0x34, 0x64, 0x63, 0x65, 0x53, - 0x83, 0xa3, 0x78, 0xdc, 0x49, 0xaf, 0x87, 0x40, 0xef, 0x43, 0xe7, 0xd4, 0x0a, 0x7a, 0x7a, 0x25, - 0xfb, 0xc1, 0x63, 0x60, 0x5d, 0xbb, 0x54, 0x7d, 0x13, 0x78, 0x75, 0x80, 0x09, 0xd4, 0xdf, 0x04, - 0xf6, 0x06, 0xb9, 0xa4, 0x58, 0xb6, 0x1d, 0xe2, 0xf5, 0x3a, 0x0e, 0x68, 0x62, 0x2e, 0xa3, 0xa7, - 0x10, 0xb8, 0x01, 0x1c, 0x0b, 0x76, 0xcd, 0xbd, 0x02, 0x64, 0x77, 0x03, 0x6f, 0x05, 0x5a, 0x29, - 0xef, 0x07, 0x65, 0xa4, 0xd5, 0xb4, 0xca, 0xcd, 0xca, 0x0d, 0xc5, 0x97, 0xc3, 0xd9, 0x04, 0x70, - 0x23, 0xb8, 0x09, 0x9c, 0x02, 0x76, 0x2f, 0x24, 0xa9, 0x7f, 0x1a, 0xfc, 0x17, 0xa4, 0xe8, 0x1e, - 0x3a, 0x4f, 0x02, 0x23, 0x0a, 0xbd, 0x3a, 0x25, 0x76, 0xde, 0x00, 0x7e, 0x04, 0xca, 0xe8, 0x12, - 0x04, 0x5a, 0x73, 0x2c, 0xe5, 0x2e, 0xe0, 0x44, 0xa0, 0x2d, 0x80, 0x8e, 0x3a, 0x07, 0xd5, 0x89, - 0x61, 0x90, 0x2e, 0xc6, 0x6e, 0x03, 0x21, 0xad, 0xa7, 0x71, 0x29, 0xb8, 0x3e, 0x64, 0x26, 0xea, - 0x3a, 0x4b, 0x35, 0x32, 0x38, 0x61, 0x60, 0xd8, 0x9c, 0x09, 0x96, 0x24, 0xfc, 0xaa, 0x4b, 0x03, - 0x79, 0x3e, 0xe8, 0x07, 0x21, 0xad, 0x0e, 0x6d, 0xd5, 0xaa, 0x63, 0x75, 0x79, 0x68, 0xb9, 0xc7, - 0xfa, 0x05, 0xb5, 0x82, 0x48, 0x28, 0x13, 0xcf, 0x3b, 0x80, 0x5e, 0xdf, 0x2a, 0xf4, 0x78, 0xc2, - 0x64, 0xb5, 0x2e, 0xbc, 0x9e, 0x56, 0xc1, 0xb3, 0x76, 0xc0, 0x27, 0x83, 0xf0, 0x90, 0x29, 0xf5, - 0xe7, 0xc0, 0xc4, 0x6a, 0x9e, 0xf3, 0xa5, 0xb1, 0x7d, 0x20, 0x58, 0x09, 0x72, 0xe9, 0xbc, 0x7c, - 0xeb, 0x19, 0x92, 0x78, 0xd5, 0xf6, 0xbf, 0x8c, 0xd6, 0x20, 0xb0, 0x9f, 0xcc, 0x51, 0x5e, 0xeb, - 0x08, 0xdf, 0x94, 0xe1, 0xaa, 0x67, 0x11, 0xfc, 0x29, 0x95, 0xa2, 0x39, 0xa6, 0x8c, 0x56, 0x23, - 0xd0, 0x99, 0x47, 0x7b, 0x76, 0x18, 0x2a, 0x62, 0xf0, 0xb5, 0xe0, 0xf9, 0x84, 0xe7, 0x3f, 0xd0, - 0x37, 0xb6, 0xd0, 0xa1, 0x3e, 0x0e, 0x78, 0x2b, 0xdb, 0xa0, 0x23, 0x48, 0x21, 0xdf, 0x54, 0x89, - 0xcf, 0x3e, 0xa0, 0x05, 0x25, 0x46, 0x3a, 0xea, 0x1c, 0xd9, 0x94, 0xbf, 0x8e, 0x1d, 0x8c, 0x6a, - 0x15, 0x58, 0x1b, 0xf1, 0x7a, 0x17, 0xfc, 0x51, 0x1d, 0xe1, 0x76, 0x05, 0xde, 0x19, 0x8e, 0xbc, - 0xd2, 0x1b, 0x4d, 0x6d, 0x4e, 0xad, 0xcb, 0x56, 0x1b, 0xfb, 0xbb, 0x83, 0x5f, 0x3a, 0xbe, 0xc5, - 0xda, 0x00, 0xf6, 0x72, 0x15, 0xeb, 0x30, 0x31, 0xaa, 0xcc, 0x9e, 0x47, 0xff, 0x80, 0xe9, 0x66, - 0xfa, 0xe0, 0xef, 0x0a, 0xee, 0x73, 0x94, 0x3e, 0x51, 0x27, 0x96, 0x1c, 0x5d, 0x7c, 0x8e, 0x02, - 0xab, 0x1c, 0xdf, 0x62, 0x5d, 0x94, 0x63, 0x23, 0x5b, 0x06, 0x83, 0xaf, 0x04, 0x5a, 0xda, 0x3d, - 0x7a, 0x4f, 0xca, 0x10, 0x0a, 0xb3, 0x1d, 0xa5, 0x7f, 0xc2, 0xb3, 0x87, 0xcb, 0x94, 0x99, 0x9e, - 0xfa, 0xf0, 0x31, 0x09, 0xfc, 0x07, 0x58, 0xd2, 0x54, 0xd1, 0xdc, 0x82, 0x81, 0x31, 0xed, 0x79, - 0x3c, 0xba, 0x25, 0x27, 0x72, 0x14, 0x6f, 0x76, 0x94, 0xbf, 0x9e, 0xa3, 0x5b, 0x57, 0x06, 0xbf, - 0xda, 0x03, 0x79, 0x74, 0x63, 0x65, 0xdb, 0x58, 0xd9, 0x13, 0xfc, 0x18, 0x3c, 0x0d, 0xf4, 0xea, - 0xf4, 0x83, 0x07, 0xc0, 0x8b, 0xc0, 0xd2, 0xbf, 0x60, 0x8c, 0xcf, 0x71, 0x82, 0xdc, 0x44, 0xa0, - 0x65, 0x3e, 0x24, 0x25, 0xb6, 0xa6, 0xe5, 0xe8, 0xd7, 0x91, 0xc1, 0xc7, 0x70, 0xf0, 0x50, 0xe8, - 0xb8, 0x5d, 0xd7, 0x64, 0xad, 0x63, 0x8b, 0xb6, 0x25, 0x7f, 0x07, 0xcf, 0x80, 0x3b, 0xc0, 0xab, - 0xa2, 0xfe, 0xe8, 0x3c, 0x13, 0xe4, 0xd2, 0xdc, 0xa8, 0x21, 0xa7, 0x03, 0xa3, 0xde, 0x9d, 0x5c, - 0xe6, 0x88, 0x36, 0xce, 0xc2, 0xf7, 0x9c, 0xdc, 0x8b, 0x42, 0xee, 0xab, 0xd1, 0x00, 0xe8, 0x8c, - 0x4d, 0xc4, 0xd6, 0xbe, 0x9e, 0x9e, 0x4a, 0xb9, 0x5f, 0xe4, 0x47, 0x80, 0x87, 0xad, 0x21, 0xda, - 0xef, 0x8e, 0x06, 0xd4, 0x60, 0x07, 0x7e, 0x72, 0x4f, 0x03, 0xf3, 0xa3, 0x6e, 0x31, 0xa2, 0x3d, - 0x44, 0xce, 0x46, 0xeb, 0x9b, 0x51, 0x23, 0x89, 0x0e, 0x6c, 0xeb, 0x48, 0x60, 0xa9, 0x1f, 0xc6, - 0x1e, 0x09, 0xb5, 0x46, 0xba, 0xf0, 0x31, 0xcf, 0x3a, 0x76, 0xda, 0x3a, 0xd7, 0x95, 0x9f, 0x19, - 0x11, 0x3a, 0x1b, 0xa4, 0x4e, 0xe8, 0x3d, 0x6f, 0xb4, 0xb0, 0x7b, 0x3b, 0xb0, 0xf4, 0x05, 0x8d, - 0x02, 0xcc, 0xbd, 0xc0, 0xff, 0x65, 0x8f, 0x84, 0xdd, 0xbd, 0xc1, 0x0b, 0x20, 0x46, 0x5a, 0x88, - 0xf2, 0x7d, 0x23, 0x7c, 0x3c, 0xb0, 0xe7, 0x29, 0x19, 0x2f, 0xfd, 0xf4, 0x92, 0xba, 0xe5, 0xe8, - 0x1f, 0x0c, 0xec, 0xa4, 0xaf, 0xc0, 0xb5, 0xf4, 0x8b, 0x54, 0xd7, 0xe4, 0xf9, 0x6d, 0xf0, 0xba, - 0x94, 0xad, 0xaa, 0x7d, 0xd8, 0x5b, 0x0c, 0x3c, 0x3a, 0xad, 0xaa, 0x2d, 0xdd, 0xcd, 0x7d, 0x3d, - 0x4b, 0xf0, 0x5a, 0x77, 0xbb, 0xb2, 0xc1, 0x40, 0x01, 0x1b, 0x97, 0x45, 0x6c, 0x5b, 0xb6, 0x9e, - 0xe2, 0x6b, 0x41, 0x23, 0xe7, 0x26, 0xec, 0x9c, 0x62, 0x1d, 0xb4, 0xdb, 0xb3, 0x82, 0xf0, 0xf2, - 0xaa, 0x28, 0x1e, 0x13, 0x31, 0xd6, 0xf3, 0xeb, 0x55, 0x78, 0xc6, 0xee, 0x58, 0x90, 0x7a, 0x85, - 0xad, 0xeb, 0x1f, 0xc0, 0xa8, 0x9d, 0x1a, 0xc6, 0x86, 0x9e, 0x5e, 0x8f, 0x4e, 0x2f, 0x62, 0xf3, - 0xca, 0xd8, 0x7b, 0x77, 0x98, 0x27, 0x0c, 0xef, 0x91, 0x08, 0xbf, 0x0a, 0xfb, 0x2c, 0x84, 0xb3, - 0x53, 0xae, 0xc8, 0x6a, 0xa5, 0xbb, 0xa2, 0x8a, 0x83, 0x88, 0xec, 0xc3, 0xf0, 0x37, 0x3a, 0x7d, - 0x87, 0x3b, 0xbc, 0x34, 0x8b, 0x61, 0xbe, 0xc6, 0x19, 0xea, 0x97, 0xe0, 0xc5, 0x06, 0x34, 0x6d, - 0xb0, 0xdd, 0x8b, 0xfe, 0x0c, 0xa0, 0x4d, 0xa2, 0xa5, 0x75, 0x30, 0x16, 0x01, 0x9d, 0xc4, 0xff, - 0x66, 0x3b, 0x69, 0x4b, 0xe7, 0xe0, 0x2c, 0x27, 0x09, 0x21, 0x6c, 0x28, 0xeb, 0x60, 0x29, 0x6f, - 0x3f, 0x86, 0x96, 0x96, 0xf9, 0x23, 0x80, 0xe6, 0x08, 0x9d, 0x7a, 0x2d, 0xe9, 0x2b, 0x44, 0x2d, - 0xc2, 0xe0, 0x32, 0x6b, 0x94, 0xf6, 0xd5, 0xa0, 0xb3, 0xd4, 0x53, 0x1f, 0x0e, 0xae, 0x00, 0x96, - 0x94, 0x4b, 0x1e, 0x53, 0x13, 0xde, 0xb1, 0x47, 0x67, 0xb3, 0x05, 0xe0, 0x58, 0xd0, 0xfd, 0x2a, - 0xc3, 0xd4, 0xa9, 0xfb, 0x73, 0xe0, 0x09, 0x90, 0xa2, 0x3b, 0xeb, 0x8c, 0x0e, 0x86, 0xe5, 0xc7, - 0x1e, 0x39, 0x7e, 0x07, 0xaf, 0xeb, 0xa9, 0x84, 0xa7, 0x9b, 0x75, 0x27, 0x18, 0x6a, 0xd2, 0x26, - 0xf8, 0x72, 0x30, 0xb2, 0xb8, 0x56, 0x05, 0xa7, 0x4f, 0x24, 0x97, 0x82, 0x09, 0x05, 0x33, 0x52, - 0xea, 0xfb, 0x55, 0x1d, 0x3a, 0x04, 0x65, 0x9b, 0x8b, 0xb9, 0x99, 0x8f, 0x7c, 0x2f, 0x5b, 0xa3, - 0xf0, 0xb6, 0xc0, 0x5b, 0x6c, 0xf9, 0x43, 0xd0, 0xd6, 0xa7, 0xf2, 0xcf, 0x82, 0x33, 0x0b, 0x5f, - 0x1a, 0x20, 0x31, 0x73, 0xc8, 0x9b, 0xe0, 0x72, 0xf4, 0x0a, 0x19, 0xef, 0x20, 0xb8, 0xa1, 0xe8, - 0x74, 0xca, 0x54, 0x9f, 0x23, 0xde, 0x28, 0xab, 0x33, 0x26, 0x1a, 0xa0, 0x45, 0xe0, 0xf6, 0x0c, - 0xf3, 0xaf, 0xc9, 0x90, 0x49, 0x89, 0xac, 0x72, 0x3a, 0x8f, 0x76, 0x78, 0x05, 0xab, 0xf6, 0x96, - 0xa2, 0x30, 0x54, 0xb1, 0x5c, 0x8e, 0xfc, 0x55, 0x85, 0x4e, 0xeb, 0xc3, 0x9a, 0x1a, 0xbc, 0x77, - 0x53, 0x29, 0xde, 0x05, 0x4e, 0x02, 0x0a, 0xae, 0xd3, 0x47, 0x5d, 0xb4, 0x96, 0x47, 0xff, 0xd0, - 0x81, 0x6a, 0x6f, 0xbf, 0xf8, 0xd0, 0x4e, 0x5c, 0x7e, 0x0a, 0xda, 0x44, 0xe5, 0x68, 0xec, 0x0e, - 0xfa, 0xb6, 0x8f, 0x9c, 0x96, 0xde, 0x7b, 0x40, 0x78, 0x36, 0xd2, 0xbf, 0x35, 0xbe, 0x0c, 0xea, - 0xd0, 0x5c, 0x94, 0x67, 0x3b, 0x06, 0x56, 0xc3, 0xfb, 0x21, 0xb8, 0x95, 0x58, 0x54, 0x4f, 0x13, - 0x01, 0x6a, 0xb9, 0xb5, 0xf4, 0x6c, 0x5a, 0xab, 0xbc, 0x17, 0x83, 0x3a, 0xe7, 0x59, 0x52, 0xd6, - 0xef, 0x3c, 0x70, 0x78, 0x1b, 0xe7, 0x50, 0x3e, 0x0b, 0x2c, 0xe9, 0xc6, 0xd5, 0x22, 0x0c, 0xde, - 0x61, 0x8d, 0xd2, 0xd6, 0x13, 0x53, 0x8d, 0x50, 0x3a, 0xd7, 0x31, 0x24, 0x56, 0xad, 0x54, 0x29, - 0xfa, 0x4a, 0xfe, 0x6b, 0xe5, 0xaa, 0x4a, 0x7f, 0xac, 0x76, 0x05, 0xbe, 0x34, 0x4e, 0xbd, 0xed, - 0xcb, 0x75, 0xbe, 0xf4, 0x00, 0xb7, 0x6b, 0x89, 0x6d, 0x0b, 0x3f, 0x10, 0x51, 0x3a, 0x20, 0xc2, - 0xcf, 0x62, 0xf3, 0xf8, 0x6a, 0xc5, 0x3a, 0x1d, 0x68, 0x95, 0xca, 0x25, 0x4d, 0xd6, 0x1f, 0xc8, - 0x15, 0x8e, 0xc9, 0x31, 0x38, 0x5a, 0xa5, 0xc7, 0x3a, 0xfd, 0xc9, 0x57, 0xaa, 0xea, 0x00, 0x1d, - 0xe1, 0x38, 0xa8, 0xca, 0xd2, 0xe1, 0xd0, 0xce, 0x6f, 0x31, 0x1b, 0xcf, 0xd0, 0x31, 0x87, 0x81, - 0xd5, 0x3f, 0xca, 0xea, 0x52, 0xec, 0x6f, 0x79, 0x3d, 0x0d, 0x90, 0xee, 0x70, 0xd7, 0xfe, 0x04, - 0x5e, 0xad, 0x3b, 0xc9, 0x5d, 0xd4, 0x2b, 0x9a, 0x33, 0xd1, 0x6a, 0xf2, 0x56, 0x62, 0xee, 0x10, - 0x06, 0x67, 0x25, 0x65, 0x13, 0x74, 0x42, 0xc4, 0x88, 0x7c, 0xe5, 0x13, 0x17, 0x31, 0x1b, 0x28, - 0x91, 0xed, 0x91, 0x92, 0xdd, 0x53, 0xf2, 0xad, 0x0d, 0x96, 0x44, 0x57, 0xc7, 0x0a, 0x4b, 0x3a, - 0x7e, 0xcc, 0x05, 0xf3, 0x81, 0xf2, 0xe2, 0x27, 0x00, 0xfd, 0x89, 0xaa, 0x31, 0xc2, 0x9e, 0xfe, - 0x63, 0xb4, 0x1e, 0x78, 0xa4, 0x05, 0x41, 0x07, 0xe2, 0x72, 0x42, 0xf0, 0x0c, 0xe0, 0x1d, 0x26, - 0x43, 0xc3, 0x17, 0x96, 0x5b, 0xea, 0x96, 0xc0, 0xc0, 0x2c, 0x60, 0x93, 0x70, 0x4a, 0x90, 0x35, - 0xf7, 0x5f, 0x9d, 0x6e, 0xb7, 0x2d, 0x0e, 0x3e, 0xbc, 0x74, 0x2f, 0xec, 0x41, 0x74, 0x49, 0x44, - 0x7d, 0x80, 0x8d, 0xa8, 0xee, 0x5c, 0x0e, 0x3d, 0x94, 0x34, 0xe4, 0x74, 0x62, 0x54, 0xab, 0x97, - 0x77, 0x92, 0xfe, 0xa2, 0x23, 0xde, 0x38, 0x0b, 0xdf, 0xb7, 0xe4, 0x5c, 0x18, 0x32, 0x1f, 0x89, - 0x3a, 0xa7, 0x53, 0x7b, 0x91, 0x5c, 0xf2, 0x36, 0x5b, 0x29, 0xdb, 0x7a, 0x32, 0x2d, 0xe9, 0x2b, - 0x47, 0xe7, 0x14, 0x1f, 0x55, 0xae, 0xd9, 0x81, 0x8f, 0x03, 0x81, 0x4d, 0xf3, 0xda, 0x58, 0x8a, - 0xf6, 0xd5, 0x51, 0x77, 0x48, 0x4c, 0x01, 0xde, 0x3f, 0x32, 0x0a, 0xe5, 0xb0, 0x5c, 0x43, 0x23, - 0xeb, 0xd3, 0x0f, 0x72, 0xe3, 0x81, 0x3e, 0x46, 0x5a, 0x3a, 0x31, 0x1a, 0x4c, 0x83, 0x1d, 0x38, - 0xfd, 0x99, 0x75, 0x1c, 0x69, 0x6f, 0x84, 0x9f, 0x4e, 0xbf, 0x22, 0x30, 0x02, 0xcc, 0x04, 0xd3, - 0xc1, 0x24, 0xa0, 0xfc, 0x4b, 0x2c, 0xd9, 0x7d, 0x71, 0xce, 0x75, 0xa0, 0xaf, 0x44, 0x98, 0xa5, - 0xac, 0xcf, 0xd6, 0x39, 0xf6, 0x53, 0x32, 0x38, 0x7d, 0xa7, 0x75, 0xdc, 0x6e, 0xdf, 0x4d, 0xb9, - 0x0f, 0x38, 0x00, 0x1c, 0x06, 0x34, 0x3f, 0xbe, 0x22, 0x65, 0x2b, 0xda, 0x87, 0xe2, 0x64, 0xa0, - 0xc9, 0xd4, 0x92, 0x32, 0x8c, 0xc9, 0x74, 0x25, 0xfd, 0xc7, 0x58, 0x25, 0xda, 0xca, 0x09, 0x4d, - 0x8c, 0x3a, 0x6c, 0xa8, 0x03, 0x1f, 0x23, 0x41, 0x3f, 0xb0, 0xa4, 0x95, 0x78, 0x66, 0x43, 0x6e, - 0x06, 0xcc, 0x60, 0x50, 0x59, 0x46, 0x8f, 0x34, 0xf1, 0xba, 0xf9, 0x65, 0xf8, 0xca, 0x0c, 0xae, - 0x75, 0x94, 0xce, 0x69, 0x34, 0xb8, 0x88, 0x31, 0xfc, 0x7e, 0xc7, 0xf1, 0x2d, 0xd6, 0xc2, 0x88, - 0x4a, 0xef, 0x6c, 0x8c, 0x8e, 0x06, 0xfa, 0x43, 0x83, 0x47, 0x0b, 0x60, 0x76, 0xed, 0x8c, 0xe1, - 0x29, 0x4b, 0x69, 0xe9, 0x7e, 0x18, 0xdd, 0x69, 0xcd, 0xde, 0x43, 0x73, 0x35, 0xf1, 0x71, 0xb1, - 0x75, 0xdc, 0x6e, 0xeb, 0xe9, 0xdd, 0xdf, 0x55, 0xaa, 0xc3, 0xc4, 0xe8, 0x58, 0x50, 0x7c, 0xdc, - 0x6b, 0xfb, 0x1a, 0x54, 0x7c, 0x8b, 0x56, 0xe7, 0xd8, 0x42, 0x7d, 0x12, 0xd0, 0x29, 0xdd, 0xd2, - 0x5b, 0xea, 0xc4, 0x91, 0xa3, 0x8b, 0xc3, 0x8f, 0x5b, 0xa7, 0x41, 0x5b, 0x31, 0x4d, 0xce, 0xb1, - 0x53, 0x49, 0x06, 0xa3, 0x1a, 0x80, 0x32, 0xd2, 0x64, 0xdc, 0x7a, 0x3a, 0x28, 0xf5, 0x37, 0x1a, - 0x4b, 0xdf, 0xad, 0xe4, 0xb4, 0x07, 0x61, 0x1c, 0x7e, 0x10, 0x94, 0x7d, 0x73, 0x5b, 0xd2, 0x83, - 0xe9, 0xb8, 0x0a, 0x0e, 0x8f, 0x04, 0x9a, 0xd8, 0x72, 0xe8, 0x56, 0x84, 0x4e, 0x76, 0x04, 0xb5, - 0x7d, 0xd8, 0x37, 0xee, 0xa5, 0x5e, 0x0f, 0xb6, 0xf5, 0xbf, 0xc4, 0xab, 0x1c, 0xbf, 0x31, 0xd6, - 0xfb, 0xea, 0x79, 0x0c, 0xb4, 0xf1, 0x70, 0x5b, 0xcc, 0x4b, 0x84, 0xef, 0x0d, 0xe6, 0xbc, 0xc0, - 0x64, 0xa3, 0x55, 0x62, 0x98, 0x08, 0xaa, 0xe6, 0x98, 0x94, 0x9d, 0x6c, 0x86, 0x70, 0xbe, 0xc2, - 0x19, 0x08, 0xed, 0x23, 0xee, 0x75, 0xf8, 0x1e, 0xeb, 0xf7, 0x30, 0x3b, 0xf3, 0x53, 0x33, 0x51, - 0xb5, 0x52, 0xc4, 0x7b, 0x60, 0xf7, 0x2c, 0xb0, 0xc1, 0x73, 0xda, 0xe6, 0x69, 0xb7, 0xbe, 0x14, - 0xd8, 0x9b, 0xb6, 0xbe, 0xa9, 0x38, 0x94, 0xab, 0x9e, 0x0d, 0x9e, 0x04, 0x9a, 0xa4, 0xaf, 0x01, - 0xad, 0xbd, 0x0f, 0xa5, 0xf6, 0x19, 0x8b, 0x41, 0x19, 0x5d, 0x89, 0x80, 0x97, 0xa8, 0xea, 0x29, - 0x46, 0x6c, 0x69, 0xfb, 0xf0, 0x29, 0xf0, 0x38, 0x48, 0x91, 0xb2, 0x04, 0x63, 0xe4, 0x84, 0x72, - 0x2a, 0xf8, 0x0a, 0x90, 0xce, 0x53, 0x20, 0xef, 0xf4, 0xde, 0x53, 0x84, 0x46, 0x09, 0x67, 0x9f, - 0x07, 0xf6, 0x0e, 0xc1, 0x1a, 0x44, 0xda, 0x54, 0xfe, 0x14, 0x9c, 0x0a, 0xf6, 0x34, 0x26, 0x4a, - 0x9b, 0xe8, 0x68, 0x50, 0x8e, 0x03, 0xfa, 0xe2, 0xba, 0x0e, 0x94, 0xd1, 0x37, 0x10, 0x68, 0x64, - 0x3b, 0xd1, 0xb5, 0x7f, 0x29, 0x8d, 0xd6, 0x11, 0x20, 0x98, 0x2f, 0xc1, 0xbe, 0xc0, 0xe9, 0xf2, - 0x58, 0xcf, 0xc1, 0xfc, 0x15, 0xe8, 0x07, 0xfa, 0x18, 0xf9, 0x68, 0xbb, 0x54, 0x5d, 0xc9, 0xab, - 0xf1, 0x40, 0xf9, 0x20, 0x41, 0x69, 0xd2, 0xa3, 0xc0, 0xf1, 0x20, 0xf7, 0x28, 0xf0, 0x3d, 0x92, - 0x6c, 0x1f, 0x46, 0xbe, 0x11, 0x6a, 0x64, 0x94, 0x89, 0xa4, 0xca, 0x0a, 0xa5, 0x0b, 0xad, 0xfd, - 0x85, 0x22, 0x71, 0xf5, 0x55, 0x62, 0x49, 0x98, 0x19, 0xe8, 0x6a, 0x6a, 0xf2, 0x9c, 0x55, 0xea, - 0x69, 0xe8, 0x04, 0x1a, 0x8d, 0xa5, 0xf6, 0x00, 0xf1, 0x7a, 0x29, 0xa7, 0x33, 0xcd, 0xb9, 0xfe, - 0x1b, 0xe0, 0xe9, 0x63, 0xdc, 0x4b, 0x4e, 0x5f, 0x5d, 0xd6, 0x66, 0x0c, 0x2c, 0x05, 0x5f, 0x03, - 0xca, 0x9f, 0x87, 0x34, 0x8e, 0x98, 0x26, 0x87, 0x8c, 0xad, 0x5a, 0x27, 0x18, 0x05, 0x14, 0x92, - 0x26, 0xec, 0xb3, 0x8b, 0xa0, 0xa8, 0x2b, 0x65, 0xf2, 0x49, 0x50, 0x75, 0xaf, 0x82, 0x4a, 0x17, - 0x69, 0xcb, 0xf1, 0x19, 0xd0, 0xf9, 0xce, 0x4f, 0xfd, 0xfd, 0x40, 0x8b, 0x40, 0x48, 0x33, 0x0a, - 0xff, 0x5b, 0xbd, 0x24, 0x2a, 0xa5, 0x53, 0xef, 0x6a, 0x47, 0xa7, 0xa4, 0x53, 0xf4, 0xcb, 0x07, - 0x7d, 0xde, 0x9e, 0x45, 0x39, 0xf0, 0x30, 0x9d, 0xf2, 0x22, 0x6d, 0x7b, 0xc1, 0xb0, 0x5a, 0x2b, - 0x65, 0xe7, 0x6f, 0x29, 0xe1, 0x85, 0xd3, 0x37, 0x07, 0x14, 0x49, 0xb9, 0x07, 0xa9, 0xdb, 0x7f, - 0x91, 0x84, 0xe2, 0x43, 0x5f, 0x27, 0x20, 0xed, 0x89, 0xde, 0x06, 0xb4, 0xea, 0x44, 0x89, 0xfe, - 0xe5, 0xc0, 0xd2, 0xb9, 0x52, 0x80, 0xa9, 0xa5, 0xbc, 0x95, 0x82, 0xa5, 0xd4, 0x76, 0xc0, 0xd2, - 0x63, 0x51, 0xc3, 0x03, 0xfa, 0x4a, 0x80, 0x69, 0x2b, 0x30, 0x2a, 0x25, 0xb7, 0x4d, 0xf7, 0x11, - 0xbc, 0xfd, 0xe6, 0xff, 0x04, 0xbc, 0xae, 0xa7, 0x02, 0x5e, 0x1f, 0x58, 0x05, 0x42, 0xfa, 0xcd, - 0xd6, 0xb8, 0xb8, 0xda, 0x93, 0x74, 0xc5, 0xa0, 0x1f, 0x34, 0xf2, 0x17, 0xb1, 0x67, 0xd9, 0x68, - 0x78, 0xc3, 0xe0, 0x69, 0xe2, 0x3d, 0xdf, 0xf0, 0xad, 0xae, 0xe9, 0xde, 0x01, 0x9a, 0x3c, 0x0e, - 0xfb, 0x01, 0x3d, 0x35, 0xa2, 0x9f, 0x83, 0xe4, 0x3e, 0x8c, 0xfe, 0x85, 0x12, 0x84, 0xf4, 0xd7, - 0x38, 0x6f, 0xa5, 0xdc, 0x01, 0x46, 0xc5, 0x5c, 0x02, 0x17, 0xaa, 0xf9, 0xea, 0x20, 0xe0, 0xa6, - 0x6a, 0x43, 0x71, 0x64, 0xf4, 0xaa, 0x4d, 0x01, 0xa3, 0x43, 0xfe, 0xce, 0xfa, 0xce, 0x11, 0xd8, - 0x7e, 0x46, 0xe0, 0x7f, 0xd1, 0xc6, 0xfb, 0xa0, 0x6e, 0xf6, 0xa7, 0x73, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXCircleDownArrowIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2e, 0x08, 0x06, 0x00, 0x00, 0x00, 0x57, 0xb9, 0x2b, - 0x37, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x52, 0x92, 0x24, 0x04, 0x00, 0x00, - 0x05, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xe5, 0x99, 0x5d, 0x88, 0x55, 0x55, 0x14, 0xc7, - 0xbd, 0xe6, 0x4c, 0x90, 0xa9, 0x59, 0xca, 0x64, 0x56, 0x68, 0x18, 0x0a, 0x21, 0x44, 0x90, 0x41, - 0x06, 0xe5, 0x54, 0x50, 0xbd, 0x54, 0xcf, 0x9a, 0x45, 0x11, 0x69, 0x61, 0xd6, 0x93, 0x0f, 0x41, - 0xa4, 0x49, 0x5a, 0xa2, 0x11, 0x46, 0x14, 0xf4, 0x52, 0x50, 0x4f, 0x81, 0x31, 0x84, 0x4a, 0xa6, - 0x06, 0x95, 0x58, 0xf4, 0x01, 0x8a, 0x7d, 0x3a, 0xf6, 0x92, 0x5f, 0xf9, 0x11, 0x15, 0x36, 0x39, - 0x3a, 0x4e, 0xbf, 0xff, 0xf1, 0xae, 0x3b, 0xeb, 0xec, 0x7b, 0xce, 0xb9, 0xfb, 0x5c, 0xef, 0xcc, - 0x1d, 0x68, 0xc1, 0x9f, 0xbd, 0xbe, 0xd7, 0x3a, 0xe7, 0x9e, 0x7d, 0xce, 0xde, 0xfb, 0x56, 0xc6, - 0xb4, 0x88, 0x06, 0x07, 0x07, 0xc7, 0x92, 0x6a, 0x2a, 0xb8, 0x0a, 0x4c, 0x07, 0x57, 0x82, 0x53, - 0xe0, 0x20, 0x38, 0x24, 0x54, 0x2a, 0x95, 0x7f, 0x18, 0xdb, 0x4f, 0x34, 0x3b, 0x15, 0x3c, 0x06, - 0x3e, 0x02, 0x7d, 0xa0, 0x11, 0xfd, 0x8c, 0xc3, 0x2b, 0xe0, 0x56, 0xa0, 0x0b, 0x1d, 0x59, 0xa2, - 0xe8, 0x9d, 0x60, 0x27, 0x18, 0x00, 0xcd, 0xd2, 0x61, 0x02, 0xd7, 0x80, 0x49, 0xc3, 0xde, 0x3d, - 0x45, 0xe6, 0x82, 0x2d, 0xa0, 0x95, 0x74, 0x9c, 0x64, 0xcf, 0x80, 0xce, 0x32, 0x17, 0x50, 0x89, - 0x71, 0x26, 0x69, 0x07, 0x7e, 0x1b, 0xc0, 0x93, 0x20, 0xeb, 0x27, 0x3e, 0x87, 0x7e, 0x17, 0xf8, - 0x0a, 0x24, 0xcf, 0x33, 0xe3, 0x51, 0x30, 0x1e, 0xe8, 0x99, 0x9f, 0x06, 0xae, 0x03, 0xf7, 0x00, - 0xcd, 0x83, 0x2c, 0x3a, 0x80, 0x72, 0x21, 0xf3, 0x60, 0x77, 0x96, 0xb1, 0xb4, 0x8e, 0xa6, 0xa7, - 0x80, 0x4f, 0x41, 0x16, 0x7d, 0x82, 0xf2, 0x51, 0x90, 0xd7, 0x4c, 0xaa, 0x1e, 0x7e, 0x63, 0xc1, - 0x7c, 0xb0, 0x0e, 0x9c, 0x04, 0x21, 0xfd, 0x8b, 0xe2, 0xa1, 0x54, 0x50, 0x33, 0x02, 0x49, 0x6e, - 0x00, 0x07, 0xc2, 0xec, 0xc8, 0x5f, 0x83, 0xee, 0x66, 0x72, 0x5a, 0x0c, 0xf1, 0x93, 0x81, 0x26, - 0x6a, 0xd6, 0xa4, 0x7e, 0x19, 0x7d, 0xd6, 0x2f, 0x6b, 0xe1, 0xf9, 0x23, 0x81, 0xb3, 0xc0, 0x09, - 0xe0, 0x49, 0x45, 0x74, 0x87, 0xa3, 0x1e, 0xb1, 0xfc, 0xec, 0x43, 0x16, 0x72, 0x5d, 0x03, 0xb2, - 0x7e, 0xd1, 0xd7, 0x87, 0xbc, 0x22, 0x39, 0x12, 0x4d, 0x02, 0x3f, 0x00, 0x4f, 0x87, 0x10, 0xe6, - 0x45, 0xa6, 0x28, 0xe5, 0x46, 0xde, 0x0e, 0xf0, 0xa6, 0x2f, 0x56, 0xe5, 0x97, 0x44, 0x27, 0x22, - 0xe0, 0x22, 0xb0, 0x39, 0x48, 0xb2, 0x0f, 0x59, 0x1f, 0x95, 0x61, 0x25, 0x6a, 0xe8, 0xed, 0xe2, - 0xe9, 0x0c, 0xc2, 0x82, 0xa8, 0xa2, 0x38, 0x3e, 0xe7, 0x23, 0xe1, 0xf5, 0xba, 0xd2, 0x1b, 0x61, - 0x44, 0x88, 0x5a, 0xeb, 0x33, 0xea, 0x5f, 0x5e, 0x58, 0x9c, 0x80, 0x2e, 0xf0, 0xb7, 0x0b, 0x8c, - 0xbf, 0x62, 0x97, 0x99, 0x78, 0x4d, 0xbc, 0x65, 0x20, 0xee, 0x6e, 0xa5, 0x63, 0xf5, 0x8b, 0x6f, - 0x01, 0x9e, 0xd6, 0x3b, 0x97, 0x7a, 0x16, 0xcf, 0x37, 0xbc, 0x37, 0xfc, 0xf3, 0xf5, 0x5e, 0x8d, - 0x35, 0xc4, 0xbd, 0xe3, 0xf2, 0xcc, 0x6e, 0x1c, 0x91, 0xf6, 0x20, 0xf6, 0x32, 0xf0, 0xbb, 0xcb, - 0x71, 0x1a, 0x7e, 0x46, 0xda, 0xab, 0x2a, 0x61, 0x98, 0x0d, 0x74, 0x87, 0x8d, 0x34, 0x19, 0x2f, - 0xc9, 0x74, 0x6e, 0xa0, 0x24, 0xee, 0x27, 0x4b, 0xc2, 0xb8, 0xb8, 0x81, 0x7b, 0xa6, 0x99, 0x38, - 0xfd, 0x62, 0x9e, 0xde, 0xcf, 0x73, 0x7c, 0xcd, 0x7b, 0xc1, 0xc7, 0xcf, 0xe8, 0x20, 0x23, 0xb1, - 0x5a, 0x4c, 0x19, 0x3d, 0x1c, 0x98, 0xa3, 0x44, 0x82, 0x3b, 0x41, 0xaf, 0x25, 0x61, 0xd4, 0xba, - 0xa8, 0xcb, 0x82, 0xfd, 0x4b, 0xfe, 0x01, 0x53, 0x32, 0xea, 0xb3, 0xfd, 0xb6, 0x93, 0x47, 0x9c, - 0xe5, 0xd3, 0xdf, 0x4f, 0xd1, 0x35, 0xae, 0xb0, 0x7a, 0xbd, 0xdf, 0xe4, 0xa4, 0x71, 0xae, 0xe4, - 0x26, 0x14, 0xd7, 0x9a, 0x92, 0xb1, 0x87, 0xc0, 0xb3, 0x4e, 0x6e, 0x17, 0xfb, 0x21, 0x85, 0x07, - 0x5c, 0xf1, 0x07, 0x8d, 0xb7, 0x3b, 0x5e, 0x53, 0x54, 0x0d, 0x3d, 0xe6, 0xd0, 0xce, 0x91, 0x9b, - 0x77, 0x9c, 0xfa, 0x5f, 0xb8, 0x1e, 0xba, 0xb9, 0xc9, 0x13, 0x25, 0x5b, 0xe3, 0xf3, 0x9d, 0x51, - 0xbb, 0x96, 0x1d, 0x4e, 0x6e, 0x37, 0xeb, 0x6f, 0x62, 0x27, 0xcd, 0xdc, 0xac, 0x86, 0xac, 0x71, - 0x2d, 0x3d, 0x8d, 0x7a, 0xb9, 0xd2, 0xd3, 0x26, 0x8c, 0x82, 0x71, 0x5f, 0xd0, 0x43, 0xd2, 0xab, - 0x35, 0xee, 0x3f, 0xe7, 0x9a, 0x98, 0xa3, 0x89, 0xc2, 0x7e, 0x92, 0x5e, 0xb5, 0x3e, 0x9e, 0x40, - 0x97, 0x97, 0xba, 0x4e, 0x0f, 0x3b, 0x7e, 0x34, 0xb0, 0x61, 0xe3, 0xb5, 0x3b, 0x3e, 0x25, 0xe8, - 0xee, 0x44, 0x20, 0xb7, 0x5b, 0x3c, 0x49, 0x03, 0x83, 0xae, 0x89, 0x2b, 0xc4, 0xeb, 0x51, 0x39, - 0xe6, 0x94, 0x62, 0x13, 0x43, 0xa0, 0xab, 0x13, 0xf9, 0xa5, 0xb4, 0x18, 0xd2, 0xd2, 0xf7, 0xf1, - 0x3a, 0x63, 0x81, 0x02, 0xff, 0x69, 0xe0, 0x03, 0xf0, 0x1d, 0xb8, 0xa5, 0xc0, 0xd5, 0x4c, 0x5a, - 0x60, 0xf9, 0xf5, 0xbf, 0xde, 0x34, 0xe7, 0x89, 0x04, 0x7f, 0x01, 0xa3, 0xad, 0xa6, 0xcf, 0x1b, - 0x71, 0x54, 0x71, 0x4f, 0x2b, 0xbc, 0x2f, 0x06, 0xbf, 0x96, 0x5f, 0x64, 0x36, 0xf4, 0x5a, 0xc4, - 0x79, 0xdb, 0xbb, 0x66, 0xcb, 0x1b, 0xf1, 0x9f, 0x0b, 0x3c, 0x25, 0xb5, 0x6c, 0x72, 0xfa, 0xe7, - 0x48, 0x1b, 0xdb, 0x42, 0xe2, 0xad, 0xa3, 0x79, 0xb0, 0xd7, 0x39, 0xad, 0x25, 0xb3, 0x6f, 0xbe, - 0xcf, 0xd9, 0x12, 0x1e, 0xbb, 0xf6, 0xa5, 0xdb, 0xc1, 0x1c, 0x67, 0xdb, 0xe6, 0xf8, 0x3c, 0x36, - 0xec, 0x67, 0xa8, 0x57, 0x92, 0x6e, 0x77, 0x97, 0x74, 0x0a, 0xfe, 0xe2, 0xbc, 0x2c, 0xa6, 0xc7, - 0x47, 0x5b, 0x2e, 0xbf, 0x96, 0x50, 0x0a, 0x9d, 0x02, 0x8c, 0x61, 0xfc, 0x5c, 0x42, 0x95, 0xee, - 0x65, 0x1c, 0x0f, 0xbe, 0x35, 0x45, 0x75, 0x5c, 0x6d, 0xb9, 0x8a, 0x46, 0x7c, 0x9f, 0x0d, 0xe2, - 0xba, 0x6b, 0xfe, 0x18, 0x56, 0x06, 0xc6, 0xfb, 0x6a, 0xc6, 0x02, 0x86, 0x18, 0x35, 0xbf, 0xdf, - 0xc5, 0x6a, 0x75, 0x79, 0x17, 0xf8, 0xd8, 0xe9, 0x16, 0xc0, 0x6f, 0x72, 0xb2, 0xd8, 0xa8, 0xa6, - 0x55, 0x1a, 0xdf, 0x1d, 0x2e, 0x56, 0xcb, 0x5b, 0xbd, 0x05, 0xcf, 0x13, 0xc2, 0x8d, 0xce, 0x28, - 0xf6, 0x2d, 0xb3, 0x35, 0x1a, 0xf1, 0xbd, 0x1a, 0xf8, 0xe6, 0xff, 0x40, 0xde, 0x03, 0x8c, 0xfc, - 0x45, 0x48, 0xf7, 0x62, 0xa3, 0x9c, 0x66, 0xc7, 0x57, 0x1b, 0x12, 0xbf, 0xd4, 0xde, 0x6c, 0xb6, - 0xda, 0x88, 0xc3, 0xaf, 0xc0, 0x48, 0xc7, 0x63, 0x3a, 0x04, 0x8a, 0x22, 0x7c, 0xd5, 0xfc, 0x2f, - 0x16, 0x5c, 0x30, 0xae, 0x8a, 0x4a, 0x58, 0x75, 0x22, 0xcf, 0x23, 0x41, 0xae, 0xfa, 0x37, 0x18, - 0x0e, 0xaf, 0x06, 0x4e, 0x4f, 0x95, 0x2c, 0xd2, 0xa8, 0xf9, 0x95, 0x25, 0xf3, 0x8d, 0xa3, 0x1f, - 0xbf, 0xae, 0x1f, 0x40, 0xee, 0xaa, 0xcb, 0x81, 0x52, 0xe7, 0x28, 0xfd, 0xc0, 0xe8, 0x08, 0x8c, - 0xff, 0xa2, 0xd6, 0xc5, 0x84, 0x0a, 0xfc, 0xa7, 0x83, 0xac, 0x3b, 0x5f, 0xaa, 0x69, 0xe5, 0x25, - 0xcf, 0x52, 0xe0, 0xe9, 0xbd, 0xb0, 0x5e, 0x4d, 0xc6, 0x6b, 0xa3, 0xf7, 0x84, 0x2f, 0xf5, 0xd3, - 0x56, 0x0b, 0xaa, 0x79, 0x7f, 0xa7, 0x5e, 0xa8, 0x15, 0x88, 0x64, 0x88, 0x9f, 0x08, 0x74, 0xe3, - 0x8c, 0x74, 0x34, 0x37, 0x23, 0x37, 0x1c, 0xa3, 0xce, 0xbb, 0xff, 0x34, 0x6f, 0xc6, 0xb3, 0xe0, - 0xee, 0xdc, 0x80, 0x1c, 0x03, 0x31, 0x7a, 0xfd, 0x2d, 0x07, 0x7e, 0xb9, 0x9c, 0xe3, 0x9d, 0x56, - 0x13, 0xa3, 0xf5, 0x93, 0xce, 0xdb, 0x3d, 0x15, 0xef, 0xf2, 0x95, 0x02, 0xef, 0x15, 0x3e, 0x02, - 0x5e, 0x87, 0x93, 0xd7, 0xa7, 0xd3, 0x0f, 0x9f, 0x44, 0x2d, 0x9d, 0x1b, 0x7a, 0x3a, 0x86, 0xa0, - 0xcf, 0x7e, 0x31, 0xe1, 0xa4, 0x2b, 0xee, 0xf1, 0x91, 0xf0, 0x3f, 0x02, 0xbf, 0xb5, 0x2b, 0x4e, - 0xd2, 0xa4, 0x95, 0x1a, 0x4f, 0x07, 0x75, 0x35, 0xe7, 0xee, 0x88, 0x4e, 0x87, 0xf3, 0x04, 0xb0, - 0x37, 0x48, 0x72, 0x14, 0xb9, 0xf4, 0x4f, 0x1f, 0x53, 0x94, 0xbc, 0x7a, 0x83, 0x84, 0x67, 0x3a, - 0x2a, 0xff, 0x44, 0x4c, 0x7c, 0xca, 0x87, 0xa0, 0x99, 0x40, 0x3f, 0x93, 0x27, 0x7d, 0xb9, 0x34, - 0xdb, 0x6d, 0x8d, 0x93, 0x8a, 0x69, 0x46, 0x20, 0x97, 0xbe, 0xbe, 0x3b, 0x41, 0x48, 0x1b, 0x9b, - 0xc9, 0x97, 0xc4, 0x90, 0x49, 0x87, 0x44, 0xfe, 0x0d, 0x61, 0xc9, 0xf5, 0x65, 0x8c, 0x5a, 0x16, - 0xe4, 0x15, 0x27, 0x5e, 0x5f, 0xc5, 0x75, 0xa0, 0x0f, 0x84, 0xa4, 0xff, 0x86, 0x2e, 0xec, 0xe6, - 0x90, 0x40, 0x05, 0xb6, 0x85, 0x99, 0xab, 0xf2, 0x67, 0x8c, 0x4b, 0x40, 0xb2, 0x9d, 0xca, 0x6b, - 0xd2, 0xf4, 0xf8, 0xe9, 0x5c, 0xf0, 0x76, 0xb0, 0x01, 0x68, 0x69, 0x10, 0x92, 0x2e, 0x62, 0xa1, - 0xf9, 0x17, 0x8d, 0x7e, 0x81, 0x9e, 0xeb, 0x47, 0xb2, 0x71, 0x18, 0xd7, 0x82, 0xe5, 0x40, 0x7c, - 0x48, 0xda, 0xa1, 0x7c, 0x03, 0x76, 0x03, 0x2d, 0x3b, 0xb5, 0xec, 0x3d, 0x02, 0xf4, 0x1f, 0x90, - 0x96, 0xa5, 0xda, 0x6e, 0xcd, 0x04, 0x7a, 0xb5, 0xe6, 0x6d, 0x54, 0x7a, 0xb1, 0xe9, 0x3f, 0xa0, - 0x2f, 0x19, 0x5b, 0x4b, 0x5c, 0xc0, 0x1c, 0xb0, 0x09, 0xb4, 0x92, 0x34, 0x8f, 0x74, 0x4e, 0xd8, - 0xd1, 0xda, 0x6e, 0x33, 0xb2, 0x51, 0xe4, 0x36, 0xb0, 0x15, 0xf8, 0x25, 0x02, 0x62, 0x29, 0xfa, - 0x0d, 0xef, 0xd5, 0x20, 0x39, 0xe0, 0xc9, 0x28, 0x33, 0x7c, 0x2a, 0x8a, 0xea, 0x38, 0x78, 0x11, - 0xd0, 0x1e, 0xd2, 0x6f, 0xff, 0x10, 0xeb, 0xe8, 0x1c, 0x9a, 0xef, 0xc1, 0x4b, 0x60, 0x1e, 0x88, - 0x7a, 0x4c, 0xf3, 0xba, 0xbf, 0xa0, 0xe0, 0x30, 0x29, 0xcd, 0x4c, 0x46, 0xa7, 0xe7, 0x59, 0xd0, - 0xb3, 0xad, 0x53, 0x31, 0x3d, 0xf3, 0xc9, 0x73, 0xcf, 0xf3, 0xdb, 0x0f, 0xff, 0xff, 0xa6, 0xff, - 0x00, 0x60, 0x58, 0x79, 0x12, 0xc5, 0x84, 0x2f, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, - 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXCircleDownArrowIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x45, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x8d, 0x2b, - 0x29, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x1f, 0x21, 0x4c, 0x00, 0x00, - 0x08, 0x52, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, 0x9b, 0x79, 0xa8, 0x55, 0x55, 0x14, 0xc6, - 0x7d, 0x6a, 0x5a, 0x62, 0xe5, 0xac, 0x95, 0x60, 0x65, 0x96, 0x59, 0x96, 0x69, 0xda, 0x68, 0x96, - 0x46, 0x36, 0xa1, 0x26, 0x92, 0xd1, 0x3f, 0x15, 0x41, 0xa2, 0x66, 0x11, 0x12, 0x25, 0x28, 0x99, - 0x95, 0x15, 0x44, 0x54, 0x52, 0x50, 0x34, 0x10, 0x1a, 0x0d, 0xfa, 0x87, 0x65, 0xa5, 0x26, 0xa4, - 0xbe, 0x22, 0xad, 0x88, 0xca, 0x92, 0xb4, 0x14, 0x9b, 0x54, 0x34, 0x4d, 0x71, 0x2e, 0xa7, 0x7e, - 0xdf, 0xeb, 0xee, 0xcb, 0x79, 0xe7, 0xae, 0x7d, 0xcf, 0xf8, 0xee, 0xf3, 0x8a, 0x0b, 0x3e, 0xf7, - 0x39, 0x6b, 0xaf, 0xf5, 0xad, 0xb5, 0xd7, 0x3b, 0xc3, 0x3e, 0x7b, 0x5f, 0x9b, 0x34, 0x69, 0x64, - 0x39, 0x7c, 0xf8, 0x70, 0x4b, 0xd0, 0x15, 0xb4, 0x6e, 0xe4, 0x54, 0x8a, 0xe1, 0x6b, 0x8a, 0x47, - 0x0d, 0x78, 0xa0, 0x81, 0x43, 0x3f, 0x04, 0x5c, 0x0a, 0x4e, 0x05, 0xa7, 0x15, 0x5a, 0x1d, 0xb7, - 0x07, 0x2e, 0x8f, 0x1d, 0x1c, 0x6f, 0x28, 0x60, 0x7d, 0xa1, 0xfd, 0x91, 0xf6, 0xa3, 0x9a, 0x9a, - 0x9a, 0x6d, 0xb4, 0xd5, 0x2d, 0x14, 0xe2, 0x24, 0x70, 0x1b, 0x78, 0x17, 0xec, 0x00, 0x59, 0x64, - 0x3f, 0xce, 0x8b, 0xc0, 0x78, 0xd0, 0xb5, 0xea, 0x2a, 0x43, 0xd2, 0xc3, 0xc0, 0x7c, 0xf0, 0x0f, - 0x68, 0x08, 0x39, 0x04, 0xe9, 0x57, 0xe0, 0x5e, 0xd0, 0xe2, 0x88, 0x2e, 0x10, 0x09, 0x0e, 0x00, - 0x4b, 0x41, 0x25, 0x65, 0x2d, 0xc1, 0x46, 0x03, 0x77, 0xfb, 0x1d, 0x19, 0x35, 0x22, 0xa1, 0xee, - 0x40, 0xb7, 0x48, 0x63, 0x8a, 0xae, 0x9c, 0x41, 0x79, 0x55, 0x24, 0x75, 0x85, 0x49, 0x42, 0x97, - 0xee, 0x74, 0x30, 0x01, 0xc4, 0xbd, 0x8c, 0x0f, 0x61, 0xbb, 0x06, 0x6c, 0x04, 0x1b, 0x02, 0xed, - 0x5f, 0x1c, 0x9f, 0x0c, 0xf4, 0xe0, 0x15, 0x4e, 0x29, 0xb4, 0x67, 0xd2, 0x9e, 0x00, 0xe2, 0xca, - 0x87, 0x18, 0xde, 0xc3, 0x43, 0x59, 0xfc, 0x95, 0x15, 0x0a, 0xd2, 0x11, 0xd4, 0x82, 0x38, 0xb2, - 0x1b, 0xa3, 0xb9, 0xe0, 0x2e, 0xd0, 0x21, 0x49, 0xa6, 0xd8, 0xb7, 0x02, 0xc3, 0xc1, 0xeb, 0x60, - 0x33, 0x88, 0x23, 0x7f, 0x62, 0xd4, 0x2f, 0x49, 0x9c, 0xcc, 0xb6, 0x04, 0xec, 0x0d, 0xd6, 0x81, - 0x28, 0xf9, 0x18, 0x03, 0x3d, 0x74, 0x93, 0xfc, 0xa5, 0xbd, 0xf9, 0xc1, 0xd3, 0x14, 0x5c, 0x09, - 0x5e, 0x01, 0x7a, 0x1b, 0x95, 0x93, 0x3d, 0x74, 0x8e, 0xf6, 0x92, 0xe5, 0xd9, 0x41, 0x20, 0x0d, - 0x72, 0x67, 0xb9, 0x6c, 0xe8, 0xfb, 0x1a, 0x5c, 0x93, 0x67, 0xdc, 0x30, 0x17, 0xfc, 0x67, 0x83, - 0x39, 0x20, 0x4a, 0xa6, 0x61, 0x90, 0xfa, 0x11, 0x11, 0x8e, 0x5b, 0x72, 0x0e, 0xf9, 0xfd, 0xe0, - 0x60, 0x99, 0x2c, 0xd6, 0xd0, 0x57, 0xd1, 0x37, 0x01, 0xf1, 0x2e, 0x01, 0x51, 0x6f, 0xbc, 0xd9, - 0xd8, 0x34, 0x2f, 0x19, 0x50, 0x56, 0x05, 0xa4, 0x23, 0x81, 0xe6, 0x07, 0x3e, 0x99, 0x45, 0xc7, - 0xf1, 0x59, 0xe3, 0xa4, 0xf5, 0x27, 0xf6, 0x44, 0x50, 0xee, 0x0f, 0x36, 0x23, 0x2d, 0xb7, 0xe9, - 0x47, 0xb0, 0x0b, 0xc1, 0x2e, 0x60, 0x89, 0x0a, 0x35, 0xc9, 0x74, 0xac, 0xb0, 0x92, 0x3c, 0x6e, - 0x00, 0xdb, 0xad, 0x24, 0x0b, 0xba, 0x31, 0xb9, 0xa4, 0x04, 0x59, 0x27, 0xf0, 0x9b, 0x27, 0x90, - 0x9e, 0x2d, 0xc3, 0x73, 0x09, 0x94, 0x13, 0x09, 0xf9, 0xf4, 0x04, 0x3f, 0x7b, 0xf2, 0xfd, 0x17, - 0xfd, 0xd5, 0x99, 0x42, 0x41, 0xd0, 0x02, 0x7c, 0xee, 0x09, 0xa0, 0x6f, 0x99, 0x3e, 0x99, 0x02, - 0x34, 0x90, 0x33, 0x79, 0xb5, 0x05, 0xdf, 0x79, 0xf2, 0xde, 0x82, 0x5e, 0x73, 0x9f, 0x74, 0x82, - 0xf3, 0x0c, 0x0f, 0xb1, 0xee, 0xdd, 0x9b, 0xd3, 0xb1, 0x56, 0xc6, 0x8b, 0xfc, 0xba, 0x81, 0x4d, - 0xc0, 0x92, 0x1f, 0x50, 0x26, 0x7f, 0xf0, 0xe2, 0xd4, 0x0b, 0x1c, 0xb0, 0x18, 0xd1, 0x3d, 0x5c, - 0x99, 0xa1, 0x65, 0x8b, 0x42, 0x9e, 0x9a, 0xd3, 0xf8, 0x3e, 0x4a, 0xc7, 0x27, 0x66, 0x87, 0xec, - 0x03, 0x60, 0xc9, 0x5b, 0x89, 0xc9, 0xca, 0x38, 0x10, 0xa0, 0x39, 0xb8, 0x13, 0x2c, 0x04, 0x53, - 0x40, 0xa7, 0x32, 0xe6, 0x89, 0xbb, 0xe0, 0xbb, 0x1b, 0x58, 0xa2, 0xd9, 0xf1, 0x89, 0xb1, 0x09, - 0x31, 0xbe, 0xca, 0x62, 0x41, 0xb7, 0x0a, 0xe4, 0xfa, 0xda, 0x85, 0x4f, 0xeb, 0x2d, 0x41, 0x79, - 0x33, 0x76, 0xa2, 0x31, 0x0d, 0x21, 0x7f, 0x2d, 0x18, 0x20, 0x70, 0xfc, 0x78, 0x2c, 0x0a, 0x1c, - 0x6a, 0xc0, 0x97, 0x01, 0xc7, 0xe0, 0xe1, 0xc8, 0x58, 0x24, 0x09, 0x8c, 0x20, 0xff, 0x28, 0x18, - 0x80, 0x63, 0x4d, 0xcf, 0xb5, 0x4a, 0x97, 0x9b, 0xc0, 0xd7, 0x05, 0x58, 0x53, 0x0a, 0x7d, 0x93, - 0xe9, 0xe3, 0xb3, 0xbc, 0x60, 0x74, 0x2b, 0xb0, 0x64, 0x59, 0x79, 0xcf, 0x74, 0xbd, 0x04, 0x5a, - 0x66, 0x04, 0x3b, 0x29, 0x1d, 0x9b, 0xdf, 0x8b, 0x18, 0x9a, 0xee, 0x5b, 0xf2, 0xaa, 0xdf, 0xab, - 0xd0, 0x83, 0xd7, 0x17, 0x96, 0x27, 0xba, 0xab, 0x22, 0x9d, 0x53, 0x18, 0xc0, 0x5b, 0xa9, 0xa2, - 0x9c, 0x48, 0x2c, 0xeb, 0x2b, 0x5b, 0x1f, 0x96, 0x6d, 0xc3, 0xa9, 0x37, 0x75, 0x0a, 0x3a, 0xbb, - 0x70, 0xac, 0x85, 0xe5, 0xb0, 0x68, 0xd1, 0xb8, 0x36, 0xac, 0xac, 0xa6, 0x73, 0xf2, 0xdf, 0x49, - 0xbe, 0xd3, 0x8c, 0x9c, 0xf5, 0x6a, 0x2e, 0x99, 0x5e, 0x14, 0x8b, 0x42, 0xa7, 0x66, 0xa7, 0xd6, - 0x17, 0xe5, 0xf3, 0x06, 0x59, 0x35, 0xaa, 0x74, 0xab, 0xec, 0x36, 0x12, 0x1f, 0x11, 0xd6, 0x05, - 0x8b, 0x52, 0xd2, 0x89, 0xb1, 0xb6, 0x1c, 0x96, 0x84, 0x9d, 0xaa, 0xf1, 0x9c, 0xab, 0x65, 0x1f, - 0x79, 0x2f, 0x34, 0x72, 0xbf, 0x9e, 0xbb, 0xa4, 0xde, 0x9a, 0x4f, 0x5d, 0x51, 0x50, 0xea, 0xe1, - 0x36, 0xd8, 0x70, 0x98, 0x0f, 0xd9, 0x7e, 0x43, 0x5f, 0xad, 0xaa, 0xf7, 0x8d, 0xc4, 0x5b, 0xa1, - 0xbb, 0x2e, 0xa8, 0x77, 0x57, 0xca, 0x8d, 0x28, 0xad, 0x75, 0x56, 0x8b, 0x24, 0xe8, 0x5f, 0x6d, - 0xc7, 0x5a, 0xc3, 0x3d, 0x68, 0x24, 0x5d, 0xef, 0x2e, 0x71, 0x45, 0xb1, 0xde, 0x2e, 0x07, 0x70, - 0x9e, 0x6f, 0x10, 0x54, 0xad, 0x8a, 0xab, 0xfe, 0x6f, 0x92, 0xff, 0xcc, 0x18, 0x40, 0xbd, 0xf1, - 0xbb, 0xa2, 0x68, 0x1b, 0x33, 0x2c, 0x2b, 0x20, 0xd9, 0x1e, 0x56, 0x1e, 0x05, 0xe7, 0xb5, 0xc6, - 0x18, 0xea, 0x8d, 0xbf, 0x5c, 0x51, 0xb4, 0x05, 0x71, 0x34, 0x8a, 0xf6, 0xa8, 0xc3, 0xa2, 0x4d, - 0x7e, 0xed, 0x69, 0xd7, 0x89, 0x2b, 0x8a, 0x35, 0xdd, 0x3d, 0x5a, 0x8b, 0xe2, 0x1b, 0x57, 0xb1, - 0x06, 0xda, 0x36, 0x68, 0x46, 0x79, 0xac, 0xaf, 0xd3, 0xca, 0x6f, 0x28, 0x15, 0xfe, 0x52, 0x0d, - 0xdc, 0x44, 0x17, 0x85, 0x04, 0x3a, 0x03, 0x15, 0x26, 0x2c, 0x3e, 0xe7, 0xb0, 0x5d, 0xb5, 0x9d, - 0x5b, 0xb7, 0x8f, 0xc6, 0x50, 0x7c, 0xae, 0xe8, 0xf6, 0xd1, 0x16, 0xa5, 0x25, 0x9b, 0x2c, 0xe5, - 0x51, 0xa0, 0xd3, 0x16, 0xad, 0xb6, 0x6f, 0xc3, 0xa2, 0xcf, 0x9c, 0x3a, 0x51, 0x51, 0x76, 0x15, - 0x8e, 0xc3, 0x4d, 0xea, 0x5f, 0x16, 0x71, 0x4b, 0x9e, 0x0c, 0x6e, 0x07, 0xbd, 0xc3, 0xa4, 0x59, - 0xce, 0xe1, 0xd3, 0xa2, 0xd4, 0xcd, 0xa0, 0x7b, 0x06, 0x1e, 0xcd, 0x5e, 0xdd, 0xb3, 0x34, 0x48, - 0x53, 0xac, 0x83, 0x3a, 0x7d, 0x97, 0x93, 0xef, 0x0a, 0x0a, 0x12, 0x95, 0x1c, 0x93, 0xf0, 0x65, - 0x28, 0x75, 0xeb, 0x69, 0x95, 0x4e, 0x0b, 0xc8, 0x0f, 0x94, 0x18, 0xa5, 0x50, 0xc0, 0xa3, 0x8f, - 0xd5, 0x5f, 0xc1, 0x3c, 0xf0, 0x0b, 0xe7, 0x93, 0x69, 0xd3, 0x88, 0x6f, 0x5c, 0xc5, 0xc7, 0x45, - 0x53, 0xe6, 0x22, 0xaa, 0x90, 0xbe, 0x22, 0xc3, 0x52, 0x7c, 0x1a, 0x87, 0x3b, 0x22, 0xce, 0xc7, - 0xd1, 0xaf, 0xa9, 0xb3, 0x44, 0x45, 0x7f, 0x96, 0x01, 0x4c, 0xac, 0x3b, 0x2b, 0xfd, 0xc7, 0xba, - 0x8c, 0x4b, 0x74, 0xf8, 0xf7, 0xc7, 0x75, 0x01, 0x70, 0xf7, 0xbd, 0x3e, 0x5c, 0xb5, 0x63, 0xd9, - 0xa2, 0x94, 0x32, 0x52, 0x13, 0x5d, 0x94, 0x02, 0x45, 0xb1, 0x4a, 0x01, 0x4a, 0x9f, 0x73, 0xc0, - 0xc4, 0x3c, 0xdc, 0x6a, 0x68, 0x9f, 0xf1, 0x14, 0x66, 0xaf, 0x61, 0x5b, 0x4f, 0x87, 0x5f, 0x3f, - 0x6c, 0x3e, 0x01, 0xfa, 0xa9, 0x46, 0x50, 0xf4, 0x87, 0xdc, 0x1f, 0x54, 0xc4, 0x3c, 0xf6, 0x8d, - 0xab, 0x78, 0xc7, 0xb8, 0x7b, 0xab, 0xa8, 0x08, 0x10, 0xfb, 0x9c, 0x03, 0x26, 0xe6, 0xe1, 0xcb, - 0x68, 0xf7, 0x18, 0x3d, 0x56, 0x61, 0xc2, 0x76, 0xfb, 0xb9, 0x72, 0x8b, 0xdf, 0x26, 0x14, 0xa4, - 0x0f, 0x3c, 0x2a, 0x48, 0x1b, 0x83, 0xef, 0x39, 0x6c, 0x0f, 0x1b, 0xfa, 0x28, 0x95, 0x35, 0x2e, - 0xf1, 0xd4, 0x9f, 0x82, 0x10, 0x7c, 0x26, 0x08, 0xcb, 0x46, 0x14, 0xd6, 0xfa, 0x4a, 0x54, 0xd0, - 0x26, 0xf8, 0x0d, 0x06, 0x5a, 0x03, 0xb5, 0x64, 0xac, 0x23, 0xa0, 0xf3, 0x9d, 0x90, 0x41, 0xf1, - 0xb3, 0x02, 0x7d, 0x0f, 0xa0, 0xcd, 0x2b, 0x4b, 0x9e, 0x74, 0x1c, 0x49, 0x5b, 0xc8, 0x5e, 0x32, - 0x08, 0xf5, 0x46, 0xaa, 0x2f, 0x18, 0x4d, 0x36, 0x0c, 0xa5, 0xd2, 0xbd, 0x9c, 0x4a, 0xf0, 0xbd, - 0x06, 0x58, 0x85, 0xd1, 0x12, 0xe0, 0xb5, 0x22, 0xa5, 0x7d, 0x03, 0x04, 0xa5, 0xee, 0x36, 0x46, - 0xd1, 0x06, 0x68, 0xf7, 0xc0, 0x92, 0xe9, 0xa9, 0x12, 0x2a, 0x38, 0x41, 0xf8, 0xbb, 0x41, 0x5a, - 0xfa, 0x91, 0x88, 0xd1, 0x05, 0x86, 0xa1, 0x54, 0x8f, 0x65, 0x4c, 0xc0, 0x57, 0x98, 0x6d, 0x70, - 0xeb, 0x37, 0x26, 0x2f, 0x2a, 0x48, 0x40, 0xd6, 0x72, 0xac, 0xd7, 0xee, 0xa2, 0x80, 0x2e, 0x78, - 0xf8, 0x44, 0xc6, 0x7c, 0xfa, 0x06, 0xc9, 0x02, 0xc7, 0x0f, 0x9a, 0xbc, 0x18, 0x28, 0xa1, 0xb0, - 0xac, 0x30, 0x8d, 0x13, 0x28, 0x21, 0xbc, 0x1a, 0x58, 0x57, 0xcc, 0x6a, 0xf4, 0xaf, 0x86, 0x02, - 0x6a, 0x4b, 0x33, 0x5c, 0x28, 0x67, 0x92, 0xa9, 0x20, 0x4a, 0x19, 0xa2, 0xa9, 0x8e, 0x2c, 0xd4, - 0xf6, 0x30, 0x87, 0x84, 0x91, 0x1e, 0x84, 0x96, 0x9c, 0x61, 0x3a, 0x24, 0x50, 0x42, 0x3a, 0x08, - 0x58, 0x7b, 0x2f, 0x07, 0x42, 0x01, 0xf5, 0xcb, 0x00, 0x4b, 0xe2, 0x6d, 0x5c, 0x45, 0xe4, 0x04, - 0xf1, 0xb7, 0x06, 0xf9, 0x4a, 0xaf, 0x1b, 0xc6, 0x57, 0x1a, 0x0e, 0x52, 0x4d, 0xf2, 0x3a, 0x25, - 0xe8, 0x80, 0x67, 0x10, 0xb0, 0x0a, 0x83, 0xba, 0xac, 0x64, 0xba, 0x85, 0x5d, 0x8a, 0x44, 0xd0, - 0xcf, 0x34, 0x2c, 0xf1, 0x17, 0x1c, 0x6b, 0x7d, 0x31, 0x5b, 0x3b, 0xf5, 0x5b, 0xd1, 0x5b, 0xaf, - 0x44, 0x17, 0x2f, 0x76, 0x0b, 0x8f, 0xb6, 0x64, 0x93, 0x14, 0x26, 0x97, 0x82, 0x28, 0x41, 0xe2, - 0xce, 0x01, 0x96, 0x5c, 0x5c, 0x76, 0x00, 0x78, 0xbc, 0x60, 0x79, 0xa1, 0x7b, 0xaa, 0xac, 0x63, - 0x82, 0x4e, 0xb8, 0xe2, 0x16, 0x66, 0x5a, 0x02, 0xda, 0xb2, 0xa6, 0xc4, 0xd4, 0x6f, 0xe3, 0x2c, - 0x59, 0x5d, 0xd6, 0x51, 0x9d, 0x78, 0x69, 0xdf, 0x55, 0xbf, 0x50, 0x0a, 0x8b, 0xf6, 0x78, 0xdd, - 0x14, 0x3b, 0x92, 0x27, 0xca, 0x00, 0xae, 0x81, 0xc0, 0x8a, 0xe3, 0xe2, 0x3e, 0x1a, 0xc5, 0x91, - 0xa4, 0x1f, 0xd2, 0x25, 0x8e, 0x38, 0xd4, 0x8e, 0x8a, 0xc5, 0x83, 0xd3, 0x23, 0x21, 0x47, 0x77, - 0x1a, 0xbd, 0xef, 0x1a, 0x2b, 0xc2, 0xff, 0x46, 0x90, 0xfa, 0x0a, 0x33, 0x35, 0x01, 0x4d, 0xa4, - 0x29, 0x71, 0x6e, 0x72, 0x03, 0x08, 0xb5, 0xcb, 0x23, 0x9d, 0x9d, 0x01, 0x8e, 0xad, 0x81, 0x66, - 0xb3, 0x61, 0x39, 0x88, 0x62, 0xa8, 0xb3, 0xcb, 0xa3, 0x85, 0xef, 0x0a, 0xe0, 0x9e, 0x63, 0xe2, - 0x7f, 0x28, 0x0f, 0x5e, 0xc7, 0x01, 0x5f, 0x07, 0xb0, 0x0e, 0x58, 0x32, 0xd0, 0xd9, 0xc5, 0x6a, - 0x61, 0x18, 0x63, 0xb1, 0xa0, 0xd3, 0xa4, 0xeb, 0x9c, 0x58, 0x24, 0x31, 0x8d, 0xe0, 0x53, 0xe2, - 0xa3, 0xc0, 0xb9, 0x31, 0x5d, 0x62, 0x99, 0xc1, 0x77, 0x1c, 0x58, 0x0a, 0x2c, 0x49, 0xbe, 0x9f, - 0x05, 0x8b, 0x66, 0x95, 0x3f, 0x59, 0x6c, 0xe8, 0x34, 0xe9, 0xca, 0xe5, 0x6d, 0x14, 0x6b, 0x74, - 0x29, 0x8d, 0xc8, 0xf1, 0x15, 0x4f, 0xfe, 0x9a, 0x1b, 0xf5, 0x4c, 0x45, 0x8b, 0xe3, 0x00, 0xb0, - 0xd7, 0x43, 0xbc, 0x00, 0x7d, 0xb3, 0x54, 0xc4, 0x15, 0x70, 0x22, 0xb7, 0x09, 0x9e, 0xbc, 0xa5, - 0xce, 0x76, 0x8b, 0x42, 0xa0, 0x25, 0x45, 0x9f, 0xbc, 0x47, 0x87, 0x96, 0xf6, 0x8e, 0x28, 0x21, - 0xa7, 0xb1, 0x20, 0x3c, 0x53, 0x76, 0x63, 0x98, 0x99, 0x4b, 0xb2, 0xb0, 0x4d, 0x77, 0x8c, 0x46, - 0xfb, 0x0d, 0xba, 0xae, 0xb9, 0x04, 0xca, 0x48, 0x42, 0x1e, 0xba, 0xe5, 0xad, 0x65, 0x01, 0x97, - 0xf6, 0x72, 0x0e, 0x5a, 0x66, 0x0c, 0xf3, 0xbf, 0x3b, 0x44, 0xfa, 0x1d, 0xdc, 0x5c, 0xc7, 0x6c, - 0xb4, 0x7a, 0x53, 0x69, 0xfd, 0xb4, 0xd1, 0x84, 0xf8, 0xed, 0xc1, 0x62, 0xe0, 0x93, 0x3f, 0xe8, - 0x28, 0xae, 0xd6, 0xe7, 0x92, 0x28, 0x84, 0x7a, 0x4d, 0x7f, 0xef, 0x8b, 0x88, 0x7e, 0x1f, 0xd0, - 0x9a, 0xe9, 0x71, 0xb9, 0x04, 0x4c, 0x40, 0x42, 0xcc, 0x21, 0x60, 0x2d, 0xf0, 0x89, 0xbe, 0xd0, - 0xfb, 0x26, 0xa0, 0x8c, 0x6f, 0x0a, 0x71, 0x3b, 0xf0, 0xa9, 0x2f, 0x72, 0x41, 0xbf, 0x86, 0x76, - 0x34, 0x48, 0xb5, 0x62, 0x17, 0x3f, 0x9b, 0xba, 0xd9, 0x77, 0x1f, 0xe2, 0xe8, 0x81, 0x5f, 0x4e, - 0xd6, 0xd3, 0x99, 0x7a, 0xa1, 0x2c, 0x56, 0x3e, 0x04, 0x88, 0xba, 0x6f, 0x5d, 0x82, 0xfa, 0x8f, - 0x50, 0x83, 0x63, 0x91, 0x26, 0x34, 0x82, 0xf7, 0x74, 0x30, 0x0b, 0x1c, 0x02, 0xe5, 0x44, 0x39, - 0xa4, 0xdd, 0x91, 0x48, 0x98, 0x15, 0xe6, 0x04, 0x1b, 0x07, 0xb4, 0xac, 0x18, 0x25, 0xab, 0x30, - 0x78, 0x1a, 0x5c, 0x0e, 0xdc, 0x22, 0x79, 0xe2, 0x80, 0xf8, 0x9e, 0x05, 0x26, 0x02, 0x4d, 0xc6, - 0x7c, 0x6f, 0x16, 0xba, 0x8a, 0xf2, 0x36, 0x47, 0xa9, 0xdf, 0x8c, 0xa9, 0x2f, 0x73, 0x82, 0xea, - 0x4a, 0x98, 0x0d, 0xda, 0xc5, 0x1c, 0xe5, 0x66, 0xec, 0xe6, 0x81, 0x65, 0x40, 0x6b, 0xb1, 0x1b, - 0x0b, 0xed, 0x16, 0x56, 0xe5, 0xeb, 0xf6, 0x7a, 0xe0, 0x74, 0xff, 0xe3, 0x54, 0x2b, 0xee, 0xfa, - 0x2b, 0x9f, 0x07, 0x86, 0x81, 0x5e, 0x20, 0x8e, 0x68, 0x55, 0x7e, 0x0a, 0x7c, 0x99, 0x57, 0xe9, - 0xe2, 0x04, 0x33, 0x6d, 0x18, 0x44, 0x47, 0xa0, 0xe5, 0x06, 0xdf, 0x8a, 0x19, 0x5d, 0x91, 0xa2, - 0x2b, 0x6e, 0x03, 0xb0, 0x96, 0x2c, 0x23, 0x9d, 0x03, 0x06, 0x8b, 0x38, 0xbe, 0xc8, 0x4c, 0xb4, - 0x31, 0x94, 0x24, 0xa3, 0xcb, 0x5b, 0x93, 0xb9, 0xc6, 0x10, 0xbd, 0x15, 0x87, 0x36, 0xc6, 0xb8, - 0x63, 0xc5, 0x24, 0x39, 0x2d, 0xe6, 0xd4, 0x56, 0xa8, 0x32, 0xda, 0xaa, 0xb8, 0x03, 0xa4, 0x7e, - 0x56, 0xf9, 0x06, 0x95, 0xfa, 0x99, 0xe2, 0x23, 0x94, 0x9e, 0x44, 0xcf, 0xa7, 0xb9, 0x05, 0x8c, - 0x00, 0x79, 0xce, 0x11, 0xd6, 0xc3, 0x37, 0xb7, 0x80, 0xa5, 0x3c, 0x3b, 0xd2, 0x6c, 0x9b, 0xe2, - 0xde, 0xc8, 0x42, 0x81, 0xba, 0x81, 0xfb, 0xc0, 0x62, 0xe0, 0xfb, 0xc0, 0xa4, 0xcb, 0x14, 0xad, - 0xb1, 0xac, 0x04, 0xfa, 0xd4, 0xe8, 0x0f, 0x1a, 0xe4, 0x8f, 0x18, 0x2e, 0x51, 0x45, 0x82, 0x04, - 0x83, 0x32, 0xb0, 0xf6, 0x9c, 0xeb, 0xcd, 0xe2, 0xa0, 0x65, 0xce, 0xce, 0x60, 0x3b, 0xd0, 0x5b, - 0xc9, 0x41, 0x57, 0xc5, 0x26, 0xae, 0x86, 0xe2, 0xde, 0x32, 0xe7, 0xc7, 0xe4, 0x58, 0x05, 0x8e, - 0xa0, 0x0a, 0xfc, 0x07, 0x9a, 0x90, 0xb7, 0xcb, 0x6c, 0x98, 0xf8, 0x98, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - - -#pragma mark - Content Type Icons - -static const u_int8_t FLEXJSONIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa8, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, - 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, - 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, - 0x32, 0x32, 0x3a, 0x30, 0x32, 0x3a, 0x32, 0x33, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, - 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, - 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, - 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, - 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, - 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, - 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, - 0x61, 0x3e, 0x0a, 0x03, 0x64, 0xa2, 0xe8, 0x00, 0x00, 0x06, 0x37, 0x49, 0x44, 0x41, 0x54, 0x68, - 0x05, 0xed, 0x59, 0x7b, 0x48, 0x57, 0x57, 0x1c, 0x3f, 0xc7, 0x47, 0x3e, 0xf2, 0x31, 0xc9, 0x50, - 0xdb, 0x56, 0x13, 0x73, 0x59, 0x3e, 0x57, 0x46, 0x66, 0xe2, 0x28, 0x1b, 0x51, 0x6a, 0x2a, 0xb1, - 0xcd, 0x6a, 0x43, 0xaa, 0x8d, 0x06, 0xe5, 0xa0, 0xac, 0x86, 0x8c, 0xcd, 0xbf, 0x4c, 0xb3, 0x65, - 0x81, 0xb4, 0xd2, 0xa6, 0x11, 0xe8, 0x60, 0xb4, 0x2d, 0x96, 0x2e, 0xb6, 0x08, 0x35, 0x62, 0x15, - 0x3e, 0x96, 0xda, 0x16, 0xe1, 0x7c, 0xe2, 0x62, 0x51, 0x12, 0xe5, 0x2f, 0xcd, 0xf7, 0xdd, 0xe7, - 0xfe, 0xce, 0xe5, 0x78, 0xfb, 0xa9, 0xf7, 0xfe, 0x7e, 0xbf, 0x7b, 0xf6, 0x08, 0x7e, 0x87, 0xb8, - 0x7c, 0xcf, 0xf7, 0x7c, 0xce, 0xf7, 0x7d, 0xbe, 0xe7, 0xf4, 0x93, 0x4a, 0x92, 0x44, 0x5e, 0xe4, - 0xe1, 0xf4, 0x22, 0x1b, 0x2f, 0xdb, 0xee, 0x70, 0xe0, 0xbf, 0xce, 0xa0, 0x23, 0x03, 0x8e, 0x0c, - 0x18, 0x8c, 0x80, 0xa3, 0x84, 0x0c, 0x06, 0xd0, 0xf0, 0x76, 0x17, 0xc3, 0x12, 0x14, 0x01, 0xb5, - 0xbf, 0x93, 0xeb, 0x7f, 0x48, 0xa3, 0xe3, 0xf2, 0x34, 0x29, 0x9c, 0xbe, 0xb9, 0xd4, 0x52, 0xf0, - 0xe7, 0xdf, 0x2a, 0x37, 0x66, 0xd0, 0x4b, 0xf4, 0x9d, 0x38, 0x32, 0xcf, 0xcb, 0x12, 0x60, 0xdf, - 0x5c, 0x8c, 0x03, 0x39, 0x55, 0x52, 0x45, 0xfd, 0xd4, 0x8d, 0xee, 0xe5, 0x3e, 0x83, 0x03, 0x25, - 0x3f, 0x73, 0x80, 0xf4, 0xc5, 0x8f, 0xf4, 0xa7, 0x4f, 0x68, 0x68, 0xa0, 0x7d, 0x36, 0x3f, 0xb7, - 0x4b, 0xc0, 0x19, 0x68, 0xe8, 0x24, 0x6a, 0xeb, 0x9f, 0x13, 0x3f, 0xcb, 0xe4, 0xd1, 0x53, 0x29, - 0xf7, 0x1b, 0xee, 0xcf, 0x2c, 0x20, 0xeb, 0xd8, 0x02, 0x32, 0x00, 0x07, 0xf8, 0x28, 0xc8, 0x74, - 0x7a, 0x2b, 0x82, 0xcc, 0xf3, 0xe6, 0x8c, 0x29, 0xe2, 0xd7, 0xc3, 0x4e, 0x4f, 0x86, 0xc8, 0xc7, - 0xe7, 0xa4, 0xdb, 0x7d, 0xb2, 0xe9, 0x0d, 0x1d, 0x53, 0x4b, 0x46, 0x28, 0x01, 0x0e, 0x98, 0x9e, - 0x29, 0xb1, 0xf4, 0xf5, 0xa4, 0x1f, 0x25, 0xcd, 0x6a, 0x4c, 0xf0, 0x7c, 0x79, 0x69, 0x6b, 0x3c, - 0xbd, 0x6d, 0x8e, 0xbd, 0x69, 0x18, 0xbb, 0xe8, 0xac, 0x68, 0xab, 0x17, 0x04, 0x94, 0x10, 0xd7, - 0xe5, 0x31, 0x87, 0x93, 0xb3, 0x12, 0xee, 0xae, 0xb3, 0x2e, 0xd9, 0xb7, 0x20, 0xd2, 0x01, 0xfb, - 0x2c, 0x30, 0xb8, 0xcb, 0xe1, 0x00, 0x21, 0x8f, 0x06, 0x95, 0x20, 0xba, 0x3a, 0xeb, 0x47, 0x53, - 0x8d, 0x79, 0x3c, 0xa4, 0x8f, 0xd7, 0x45, 0x18, 0xcd, 0xc0, 0xfd, 0x27, 0xa4, 0xe6, 0x96, 0xa2, - 0x65, 0x49, 0x90, 0xae, 0x3a, 0xb2, 0x64, 0xc1, 0x14, 0xa6, 0xac, 0x76, 0x8a, 0xb6, 0x9b, 0x32, - 0xe4, 0x40, 0xf1, 0x25, 0xb2, 0xea, 0x33, 0xe9, 0xfe, 0x63, 0xb9, 0x0b, 0x79, 0xcc, 0xa1, 0x39, - 0xc9, 0xfa, 0x5d, 0x25, 0x36, 0x98, 0x6c, 0x8c, 0x56, 0x60, 0x05, 0x3f, 0x4c, 0xae, 0xcb, 0x97, - 0x7a, 0xfb, 0xed, 0x36, 0x5e, 0xde, 0x68, 0xc8, 0x81, 0xe6, 0x6e, 0x69, 0xc0, 0xdc, 0x43, 0xfd, - 0xbd, 0x69, 0xd9, 0x07, 0x34, 0x6e, 0xb1, 0xbe, 0x29, 0x94, 0x92, 0xb2, 0x0f, 0xe9, 0xa6, 0x18, - 0xc5, 0x87, 0x5b, 0x3d, 0xd2, 0xa3, 0xa7, 0xfa, 0xbb, 0x34, 0x10, 0x86, 0x1c, 0x48, 0x8f, 0xa5, - 0xe1, 0xaf, 0xc8, 0xa6, 0xf4, 0x9b, 0xa4, 0xf7, 0xbf, 0x9c, 0xfc, 0xae, 0x41, 0x43, 0x91, 0xb2, - 0x34, 0x3c, 0x46, 0x36, 0x16, 0x4a, 0x97, 0x5a, 0xe4, 0xa4, 0xb9, 0xb9, 0xd2, 0xf7, 0x12, 0xe8, - 0x02, 0x3f, 0xfd, 0x5d, 0x1a, 0x08, 0x43, 0x0e, 0xbc, 0xbd, 0x8a, 0xd4, 0x7e, 0x4a, 0x23, 0x5f, - 0x55, 0xc2, 0x79, 0xa6, 0x4e, 0xb9, 0xd1, 0x34, 0xf4, 0x5d, 0x6f, 0x27, 0xbf, 0xfd, 0xa9, 0xc0, - 0x4a, 0x77, 0xd1, 0x92, 0x2c, 0x1a, 0xe0, 0xab, 0x01, 0xd7, 0x5f, 0x32, 0xe4, 0x00, 0xc4, 0xcf, - 0x71, 0x21, 0x49, 0x11, 0x8a, 0x1a, 0x6b, 0xaa, 0x59, 0x8d, 0xd9, 0x14, 0xa3, 0x6f, 0x9f, 0x2e, - 0xc2, 0xa8, 0x03, 0xb2, 0x0f, 0x56, 0x74, 0xcf, 0x19, 0xed, 0x50, 0xb7, 0xd4, 0x19, 0x01, 0xd6, - 0x30, 0x05, 0x38, 0x60, 0x8d, 0x9a, 0x7f, 0x0e, 0xe3, 0x70, 0x40, 0x15, 0x5b, 0xd3, 0x33, 0x32, - 0xa9, 0x77, 0x8c, 0x85, 0xdc, 0xbe, 0x2a, 0x9d, 0x44, 0xc0, 0x73, 0x7a, 0xbe, 0x0f, 0xba, 0x90, - 0x6c, 0xf8, 0xe0, 0x88, 0x94, 0x7d, 0x8e, 0xac, 0x5b, 0x86, 0xde, 0x4a, 0xc2, 0x54, 0x37, 0x2e, - 0xd3, 0xf7, 0x7d, 0x23, 0x19, 0x78, 0x46, 0xca, 0x6a, 0x15, 0x17, 0xcd, 0xbb, 0xd4, 0x96, 0xd8, - 0x49, 0x0b, 0x70, 0x20, 0x71, 0x29, 0x71, 0x71, 0xa6, 0xe3, 0x13, 0xb2, 0x65, 0x5f, 0xff, 0x22, - 0xe1, 0x5f, 0x6e, 0x9a, 0xd3, 0x74, 0x07, 0x76, 0x95, 0x4d, 0xaa, 0x6d, 0x4c, 0x0a, 0x57, 0xcf, - 0xec, 0xa7, 0x05, 0x9c, 0x81, 0xd7, 0x03, 0x49, 0xd1, 0x56, 0x8a, 0x5b, 0xc9, 0x7a, 0x2b, 0xde, - 0x78, 0x8d, 0x1e, 0x7e, 0xd7, 0x06, 0xbc, 0x86, 0x64, 0x2a, 0xea, 0xe7, 0xf5, 0xbf, 0x1e, 0x93, - 0xe6, 0x6e, 0xc2, 0x7e, 0x95, 0x58, 0xf6, 0xf2, 0x0c, 0x25, 0x74, 0xa1, 0x49, 0x31, 0x03, 0x37, - 0xd7, 0xea, 0xc5, 0x04, 0x6f, 0x0a, 0x21, 0x43, 0x98, 0x03, 0x42, 0xac, 0xb1, 0x43, 0x88, 0x80, - 0x12, 0xb2, 0x43, 0xab, 0xc0, 0x2d, 0x0e, 0x07, 0x04, 0x06, 0xd3, 0x2e, 0x51, 0x8e, 0x0c, 0xd8, - 0x15, 0x36, 0x81, 0x9b, 0x6c, 0xcb, 0xc0, 0x57, 0xe6, 0x21, 0x50, 0xbd, 0x71, 0x51, 0x36, 0xb4, - 0xd1, 0x91, 0x91, 0x11, 0x4f, 0x4f, 0x4f, 0x67, 0x67, 0xe7, 0xa1, 0xa1, 0x21, 0x17, 0x17, 0x01, - 0x57, 0xb8, 0x71, 0xeb, 0x21, 0xc1, 0x36, 0x3b, 0x7c, 0x7d, 0x7d, 0x3d, 0x3c, 0x3c, 0xfe, 0x3f, - 0xd6, 0xc3, 0x01, 0x1b, 0x32, 0x00, 0xf4, 0xe4, 0xa4, 0xfc, 0x9e, 0x71, 0x72, 0xd2, 0x2f, 0x3c, - 0x20, 0xad, 0x81, 0x41, 0x9a, 0xc1, 0xa1, 0x6f, 0xca, 0xb5, 0x6b, 0xd7, 0xd6, 0xae, 0x5d, 0xbb, - 0xca, 0x3c, 0x56, 0x9b, 0xc7, 0xb1, 0x63, 0xc7, 0x2c, 0xb4, 0x56, 0x57, 0x57, 0x67, 0x65, 0x65, - 0x05, 0x04, 0x04, 0xa0, 0xc6, 0x56, 0xae, 0x5c, 0x19, 0x15, 0x15, 0xb5, 0x79, 0xf3, 0x66, 0x35, - 0xe6, 0xde, 0xbd, 0x7b, 0x3b, 0x76, 0xec, 0x08, 0x0b, 0x0b, 0xf3, 0xf2, 0xf2, 0x8a, 0x89, 0x89, - 0x39, 0x74, 0xe8, 0xd0, 0xe0, 0xa0, 0xf2, 0x7b, 0xd8, 0xd9, 0xb3, 0x67, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe2, 0xe2, 0xea, 0xeb, 0xeb, 0x33, 0x33, 0x33, 0xfd, 0xfc, 0xfc, 0x16, 0x2e, 0x5c, 0x58, 0x5a, - 0x5a, 0xaa, 0xde, 0xae, 0x45, 0xe3, 0x2d, 0xa4, 0x3d, 0xf2, 0xf3, 0xf3, 0x2d, 0xf6, 0x6f, 0xdb, - 0xb6, 0x4d, 0xbd, 0xe5, 0xca, 0x95, 0x2b, 0x0c, 0xb0, 0x61, 0xc3, 0x86, 0xf5, 0xeb, 0xd7, 0x53, - 0xf3, 0x2b, 0x07, 0xb6, 0x72, 0x4c, 0x73, 0x73, 0xb3, 0x8f, 0x8f, 0x8f, 0x85, 0x90, 0xe0, 0xe0, - 0xe0, 0xfe, 0xfe, 0x7e, 0x60, 0x52, 0x52, 0x52, 0xd8, 0x12, 0x4c, 0xe7, 0x18, 0x08, 0xb9, 0x73, - 0xe7, 0x0e, 0x97, 0xa0, 0x41, 0x10, 0x8d, 0x35, 0xb6, 0x84, 0x23, 0x7b, 0xf9, 0xf2, 0xe5, 0x0b, - 0xe6, 0xb1, 0x65, 0xcb, 0x16, 0xe8, 0xb0, 0x70, 0xe0, 0xe0, 0xc1, 0x83, 0x60, 0x86, 0x87, 0x87, - 0x33, 0x7c, 0x77, 0x77, 0xf7, 0xce, 0x9d, 0x3b, 0x91, 0x10, 0x36, 0x1d, 0x1b, 0x1b, 0x8b, 0x88, - 0x90, 0xff, 0xdb, 0x1f, 0x14, 0x14, 0x74, 0xf2, 0xe4, 0xc9, 0x8e, 0x8e, 0x8e, 0xbc, 0xbc, 0x3c, - 0x1c, 0x24, 0x2e, 0xe7, 0xc1, 0x83, 0x07, 0xc8, 0x2b, 0xa6, 0xee, 0xee, 0xee, 0xe5, 0xe5, 0xe5, - 0xc8, 0x83, 0xbf, 0xbf, 0x3f, 0xa6, 0x47, 0x8f, 0x1e, 0x65, 0x12, 0xb4, 0xbf, 0xfa, 0x0e, 0xa8, - 0xf7, 0xe7, 0xe6, 0xe6, 0x72, 0xc5, 0x9c, 0x7f, 0xfe, 0xfc, 0x79, 0x30, 0x31, 0x50, 0x39, 0xd9, - 0xd9, 0xd9, 0x15, 0x15, 0x15, 0x5d, 0x5d, 0x5d, 0x7c, 0xb5, 0xad, 0xad, 0x8d, 0xad, 0x16, 0x17, - 0x17, 0x73, 0xe6, 0xf6, 0xed, 0xdb, 0xc1, 0x84, 0xc5, 0xe3, 0xe3, 0xe3, 0x60, 0x66, 0x64, 0x64, - 0x60, 0x9a, 0x9c, 0x9c, 0xcc, 0x00, 0xa9, 0xa9, 0xa9, 0x98, 0xee, 0xdb, 0xb7, 0x8f, 0xe3, 0x35, - 0x08, 0xfd, 0x33, 0xc0, 0xd4, 0x6b, 0x7c, 0xd3, 0xd3, 0xd3, 0x13, 0x12, 0x12, 0x00, 0x80, 0xad, - 0x25, 0x25, 0x25, 0x08, 0x7f, 0x48, 0x48, 0xc8, 0x9e, 0x3d, 0x7b, 0xd8, 0x96, 0xbb, 0x77, 0xef, - 0x32, 0x22, 0x2d, 0x2d, 0x8d, 0x0b, 0x61, 0xf4, 0xf0, 0xf0, 0x70, 0x4f, 0x4f, 0x0f, 0x67, 0xae, - 0x58, 0xb1, 0x82, 0xd1, 0x8b, 0x16, 0x2d, 0x02, 0x81, 0x55, 0xbe, 0xa4, 0x41, 0x08, 0x70, 0x00, - 0x5d, 0x15, 0x35, 0xd6, 0xda, 0xda, 0x8a, 0xa3, 0x99, 0x98, 0x98, 0xe8, 0xea, 0xea, 0x8a, 0x80, - 0x9d, 0x3a, 0x75, 0x0a, 0xb5, 0x04, 0xc5, 0xa8, 0x1c, 0xa6, 0xbe, 0xb1, 0xb1, 0x91, 0xdb, 0xc1, - 0x68, 0x14, 0x7a, 0x60, 0xe0, 0xd4, 0x1f, 0xfa, 0x78, 0xd7, 0x62, 0xa7, 0x88, 0x83, 0xb5, 0x09, - 0x01, 0x0e, 0xa0, 0x36, 0xd0, 0x37, 0x70, 0x54, 0x8e, 0x1c, 0x39, 0x72, 0xf5, 0xea, 0xd5, 0xce, - 0xce, 0x4e, 0xd4, 0x06, 0x7c, 0xa8, 0xab, 0xab, 0x83, 0x6e, 0xd4, 0x95, 0xb7, 0xb7, 0xfc, 0x37, - 0x33, 0x24, 0xa7, 0xaf, 0xaf, 0x0f, 0x44, 0x4b, 0x4b, 0x4b, 0x55, 0x55, 0x15, 0x08, 0xb4, 0xa3, - 0xb9, 0x73, 0xe7, 0x82, 0x00, 0x18, 0x5f, 0xd6, 0xa3, 0x39, 0xc1, 0x98, 0x98, 0xea, 0x0c, 0xe0, - 0xac, 0x1f, 0x33, 0x9e, 0x81, 0xbd, 0x7b, 0xf7, 0x42, 0x87, 0x9b, 0x9b, 0x1b, 0xaa, 0xb6, 0xb2, - 0xb2, 0xf2, 0xc0, 0x81, 0x03, 0x98, 0x22, 0x9c, 0xa8, 0x28, 0x26, 0xf9, 0xf4, 0xe9, 0xd3, 0xcc, - 0x08, 0xe4, 0x2a, 0x3a, 0x3a, 0x9a, 0xd1, 0xb8, 0xd1, 0x6f, 0xdc, 0xb8, 0x01, 0xc0, 0xfe, 0xfd, - 0xfb, 0x39, 0x07, 0x87, 0xb8, 0xa8, 0xa8, 0x88, 0xa5, 0x02, 0x79, 0x28, 0x2c, 0x2c, 0xd4, 0xb5, - 0xcd, 0xb6, 0x9b, 0x78, 0xc6, 0xba, 0x44, 0x8b, 0x84, 0x32, 0x18, 0x77, 0xfc, 0xf8, 0x71, 0x66, - 0x0a, 0xda, 0x48, 0x41, 0x41, 0x41, 0x64, 0x64, 0x24, 0x9b, 0xee, 0xde, 0xbd, 0x1b, 0x18, 0x38, - 0xdf, 0xdb, 0xdb, 0x8b, 0x4a, 0x03, 0x13, 0xe5, 0x7e, 0xe2, 0xc4, 0x09, 0xf4, 0x7e, 0xd0, 0xf0, - 0x04, 0x63, 0x62, 0x62, 0x02, 0xb5, 0x07, 0x39, 0xb0, 0x1e, 0xa2, 0x46, 0x47, 0x47, 0xf1, 0xb5, - 0xaa, 0x96, 0x74, 0x5d, 0x54, 0x03, 0x58, 0xbb, 0xc8, 0xc9, 0xc9, 0x51, 0x33, 0x4d, 0x26, 0x13, - 0x9a, 0x23, 0xfa, 0x49, 0x7b, 0x7b, 0xfb, 0xcd, 0x9b, 0x37, 0xf1, 0xc5, 0xab, 0x49, 0x0d, 0xe0, - 0xf4, 0xc3, 0x87, 0x0f, 0x91, 0x96, 0x81, 0x81, 0x01, 0xce, 0x31, 0x4e, 0xe8, 0x67, 0xe0, 0xe2, - 0xc5, 0x8b, 0x4d, 0x4d, 0x4d, 0xb8, 0x65, 0x1b, 0x1a, 0x1a, 0x6a, 0x6a, 0x6a, 0x10, 0xb3, 0x35, - 0x6b, 0xd6, 0xb0, 0xd0, 0xb2, 0x2f, 0x2e, 0x57, 0x0c, 0xd0, 0xa1, 0xa1, 0xa1, 0x6a, 0xfe, 0x74, - 0x1a, 0x99, 0xc1, 0x98, 0xce, 0x37, 0xc4, 0xd1, 0x8d, 0x81, 0xc5, 0xa3, 0x80, 0xdf, 0x50, 0xba, - 0x1b, 0xff, 0x1d, 0x80, 0xfe, 0x63, 0x0e, 0x37, 0x25, 0xfa, 0x09, 0x1a, 0x36, 0xae, 0xfa, 0xd8, - 0xd8, 0xd8, 0xe5, 0xcb, 0x97, 0x1b, 0x0a, 0x98, 0xe8, 0xcd, 0xfa, 0x0e, 0x88, 0xd6, 0x28, 0x58, - 0x9e, 0x80, 0x7b, 0x40, 0xb0, 0x45, 0x36, 0x8a, 0x73, 0x38, 0x60, 0x63, 0xc0, 0x84, 0xc3, 0x1d, - 0x19, 0x10, 0x1e, 0x52, 0x1b, 0x05, 0x3a, 0x32, 0x60, 0x63, 0xc0, 0x84, 0xc3, 0x5f, 0xf8, 0x0c, - 0xfc, 0x0d, 0x80, 0x98, 0xbd, 0xed, 0xf7, 0x50, 0xda, 0x08, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXJSONIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0d, 0x5c, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x09, 0x8c, 0x15, 0x49, 0xf5, 0x71, 0x0c, 0x37, 0x3b, 0x80, 0x9c, 0x4b, 0x80, 0xe1, 0x0a, - 0xe0, 0x22, 0x20, 0xb7, 0x24, 0x72, 0x0c, 0x12, 0xc3, 0x21, 0x4e, 0xb2, 0x8b, 0x60, 0x88, 0x44, - 0x19, 0x96, 0x51, 0x20, 0x30, 0x84, 0x05, 0x51, 0x43, 0x42, 0x96, 0x71, 0x81, 0x44, 0x10, 0xd8, - 0x48, 0xb2, 0x86, 0x63, 0xb3, 0xdc, 0xe7, 0x42, 0x60, 0xc1, 0x15, 0x44, 0x09, 0x67, 0x04, 0x16, - 0x11, 0x59, 0x40, 0x58, 0x1c, 0x21, 0x1c, 0x0e, 0xa7, 0xb3, 0xc8, 0xb5, 0x40, 0xfb, 0x5e, 0x35, - 0x55, 0x5d, 0xdd, 0x5d, 0xfd, 0xbb, 0x7b, 0xaa, 0xff, 0xff, 0x0d, 0xf3, 0x2b, 0xf9, 0xbf, 0x5f, - 0xbd, 0xbb, 0x5e, 0x75, 0x57, 0x5f, 0xf5, 0xaa, 0x2b, 0x18, 0x58, 0x20, 0x44, 0xa9, 0x18, 0x82, - 0x97, 0xb1, 0x2a, 0x05, 0xea, 0xbc, 0x65, 0xaa, 0xe1, 0x5b, 0x9b, 0x52, 0x72, 0xc9, 0xab, 0x5c, - 0xbd, 0xed, 0xa6, 0x80, 0x13, 0x95, 0xfd, 0xa6, 0x1d, 0xe3, 0xac, 0xbb, 0x04, 0x64, 0x76, 0x95, - 0x05, 0x65, 0x1b, 0x8a, 0xd6, 0x99, 0x5e, 0xaf, 0xf8, 0xd4, 0xe6, 0x3d, 0xab, 0x54, 0x20, 0x8d, - 0x6e, 0xb4, 0x37, 0x46, 0x69, 0xc1, 0x9b, 0x1d, 0xc0, 0x26, 0x50, 0xa1, 0x42, 0x05, 0xd3, 0x2c, - 0x6e, 0x6b, 0xd5, 0xaa, 0xa5, 0x94, 0xab, 0xcc, 0xb1, 0x8f, 0x1f, 0x3f, 0xe6, 0x20, 0x05, 0x42, - 0xc0, 0x4e, 0x20, 0x74, 0x1b, 0x42, 0x0b, 0xd8, 0xda, 0xe0, 0x34, 0xaf, 0xaa, 0xbb, 0x04, 0xc6, - 0xfc, 0xc6, 0x62, 0xfb, 0xcf, 0x3d, 0x0b, 0x16, 0x90, 0xdc, 0xb3, 0x04, 0xcb, 0xbb, 0x82, 0x0c, - 0x73, 0x3e, 0x97, 0x85, 0x82, 0x21, 0x42, 0x17, 0x34, 0xac, 0x63, 0xc1, 0x1c, 0x72, 0x09, 0x7c, - 0xb0, 0x8b, 0x93, 0x00, 0x4a, 0x14, 0x2e, 0xb9, 0xa2, 0xf4, 0xe4, 0x29, 0x40, 0x15, 0xd1, 0x3b, - 0x96, 0x30, 0x87, 0x5c, 0x02, 0x9c, 0xe0, 0xb5, 0x75, 0xb9, 0xe4, 0xc5, 0xc8, 0xf1, 0x2e, 0x81, - 0x96, 0x2d, 0x5b, 0xc2, 0x90, 0x21, 0x66, 0xcb, 0x69, 0xdf, 0xe2, 0x3f, 0x2e, 0x20, 0x0e, 0xa0, - 0x71, 0xe3, 0xc6, 0xf1, 0xc8, 0x25, 0xdc, 0x86, 0x6e, 0x43, 0x68, 0x01, 0xe1, 0x5a, 0x40, 0xc0, - 0xd5, 0xe6, 0x80, 0x72, 0x81, 0xd9, 0x02, 0x19, 0x50, 0x8d, 0x7f, 0xd3, 0x97, 0x03, 0xa8, 0xf0, - 0x4e, 0xcb, 0x81, 0x0c, 0x38, 0x85, 0xa8, 0x3e, 0xff, 0x27, 0x2a, 0xac, 0x1b, 0x57, 0x66, 0x03, - 0x37, 0x14, 0xbb, 0xbd, 0x5b, 0xbd, 0x63, 0x0c, 0x53, 0x31, 0x70, 0xdc, 0xb8, 0xc5, 0x1c, 0x32, - 0xb7, 0x9d, 0x7e, 0x66, 0xaf, 0x7b, 0xd5, 0xd2, 0xb7, 0x17, 0xd5, 0xac, 0x59, 0xd3, 0xcb, 0xa9, - 0x50, 0x78, 0x65, 0x1f, 0x0c, 0x1b, 0x36, 0x0c, 0x1e, 0x3c, 0x78, 0x20, 0x14, 0xf5, 0xee, 0xdd, - 0x1b, 0x8e, 0x1f, 0x3f, 0x0e, 0x27, 0x4e, 0x9c, 0x80, 0x7b, 0xf7, 0xee, 0xb1, 0xc3, 0x75, 0xec, - 0xd8, 0xb1, 0x50, 0xbd, 0x7a, 0x75, 0xb8, 0x7f, 0xff, 0x3e, 0xab, 0x17, 0x14, 0x14, 0x40, 0xdb, - 0xb6, 0x6d, 0x85, 0x8c, 0x00, 0xbc, 0x8e, 0x5b, 0x64, 0x10, 0x24, 0x82, 0xe9, 0xb7, 0x76, 0xed, - 0x5a, 0x86, 0xe3, 0xf5, 0xdd, 0xbb, 0x77, 0x1b, 0x1b, 0x37, 0x6e, 0x64, 0xb4, 0xbc, 0xbc, 0x3c, - 0xb6, 0x15, 0x42, 0x2f, 0x80, 0xf4, 0xf5, 0x01, 0x7a, 0x19, 0x49, 0x79, 0xf9, 0x5b, 0xa0, 0xdc, - 0x8b, 0x22, 0x89, 0xcd, 0x0b, 0x25, 0xf1, 0x30, 0x40, 0xa3, 0x66, 0xbd, 0x1f, 0x58, 0xed, 0xa2, - 0x7a, 0x90, 0x91, 0x94, 0x24, 0x7c, 0x5b, 0xd0, 0xf0, 0x87, 0xa6, 0xe2, 0x3b, 0x1b, 0x2d, 0x03, - 0xf7, 0x36, 0x5b, 0xb0, 0x1f, 0xe4, 0x6b, 0xe0, 0xc9, 0x57, 0x7e, 0x2a, 0x12, 0xd3, 0x7d, 0x0d, - 0x90, 0x78, 0x8d, 0xaa, 0x6a, 0x25, 0x7b, 0x4f, 0xaa, 0xf1, 0x36, 0xac, 0xf3, 0xd0, 0x96, 0xeb, - 0x7b, 0x3e, 0xb3, 0x5f, 0x5c, 0xc9, 0x34, 0xba, 0xa4, 0x56, 0x5d, 0x6c, 0xc9, 0x3c, 0x04, 0x5b, - 0x03, 0x8e, 0x93, 0xf2, 0xa2, 0x4e, 0x4a, 0x54, 0x8a, 0x08, 0x57, 0xfa, 0xc0, 0x43, 0x48, 0x42, - 0x07, 0x0a, 0x91, 0xad, 0xc9, 0x52, 0xa5, 0x76, 0x75, 0xa9, 0xe2, 0x01, 0xfa, 0x1a, 0xf8, 0x7a, - 0x73, 0x53, 0xf2, 0xbd, 0x0d, 0x96, 0x06, 0x7e, 0x23, 0x61, 0x61, 0xbc, 0x21, 0x5f, 0x03, 0x87, - 0x17, 0x02, 0xfc, 0x62, 0xa4, 0x5b, 0xc1, 0xda, 0x9f, 0xbb, 0x71, 0x2a, 0xcc, 0x2b, 0x3a, 0xd8, - 0x6d, 0xde, 0x1c, 0xe2, 0x50, 0x55, 0xc5, 0x45, 0xc2, 0xa5, 0x3e, 0x44, 0x74, 0x32, 0xa7, 0x93, - 0xfe, 0xbc, 0x79, 0xf3, 0x98, 0x1f, 0xf2, 0xfd, 0x1e, 0x21, 0xa8, 0xbe, 0x74, 0xe9, 0x52, 0xb6, - 0xa5, 0x7a, 0xbd, 0x7a, 0xf5, 0xd8, 0x7d, 0x20, 0xe7, 0x23, 0x9c, 0xad, 0x48, 0xc7, 0x84, 0x0d, - 0x9c, 0x3b, 0x77, 0x2e, 0xab, 0x5f, 0xbf, 0x7e, 0x9d, 0x9d, 0xcc, 0x51, 0x88, 0xd5, 0xf9, 0x76, - 0xfe, 0xfc, 0xf9, 0xc6, 0x99, 0x33, 0x67, 0x8c, 0x3e, 0x7d, 0xfa, 0xd8, 0xf0, 0x36, 0x25, 0x58, - 0xf1, 0x3c, 0x92, 0xb9, 0x01, 0x52, 0xc8, 0x7f, 0x24, 0x8c, 0x97, 0x26, 0xb6, 0x3a, 0xa7, 0xd1, - 0x76, 0xf8, 0xf0, 0xe1, 0x4e, 0xfd, 0x6e, 0x03, 0x3d, 0x7a, 0xf4, 0x30, 0xaa, 0x56, 0xad, 0x6a, - 0x3c, 0x7a, 0xf4, 0xc8, 0xc5, 0x5c, 0x16, 0x44, 0xea, 0x3b, 0x19, 0x9b, 0x1a, 0x69, 0xf1, 0x1d, - 0x2a, 0x74, 0xad, 0x25, 0x3d, 0x44, 0xba, 0x0e, 0xfa, 0xc9, 0x27, 0x3d, 0x42, 0x7e, 0x0e, 0xe8, - 0xd2, 0x33, 0x0d, 0xd0, 0x8d, 0xa0, 0xae, 0x7c, 0x82, 0xe7, 0x36, 0xc1, 0x55, 0xcf, 0xc1, 0x27, - 0x89, 0x0b, 0xb6, 0x58, 0xfc, 0x15, 0xb1, 0x5f, 0xe5, 0xcb, 0x4c, 0x4e, 0x71, 0x5e, 0xcb, 0x86, - 0xb9, 0xfc, 0xe4, 0x3a, 0x9c, 0xdb, 0x48, 0x0e, 0x62, 0xd9, 0x31, 0x3f, 0xa7, 0xae, 0xde, 0x06, - 0x78, 0xa3, 0xc0, 0x74, 0xc3, 0x8f, 0xd7, 0xe9, 0xac, 0xaa, 0x9e, 0xf2, 0x63, 0xe0, 0xc5, 0xb3, - 0x56, 0x95, 0x2f, 0x65, 0xc2, 0x69, 0x35, 0xa0, 0xb8, 0x04, 0xa0, 0xd9, 0x8f, 0x2c, 0xbb, 0x1f, - 0xcf, 0xb2, 0x60, 0x2f, 0xe8, 0xf5, 0x7a, 0x74, 0xc5, 0x60, 0x52, 0xa9, 0xe7, 0xa6, 0xfe, 0xde, - 0x8b, 0x33, 0x18, 0x5e, 0xab, 0x01, 0x39, 0x0d, 0x01, 0x36, 0xfc, 0xd2, 0x32, 0xf4, 0xfe, 0x0e, - 0x0b, 0x4e, 0x04, 0xf1, 0x07, 0xd7, 0x5f, 0x7b, 0x0d, 0xe0, 0xb7, 0xe3, 0x13, 0x71, 0xfa, 0xd3, - 0xb4, 0x1a, 0x40, 0xea, 0xfb, 0x74, 0xb0, 0x8c, 0xec, 0xfb, 0x9b, 0x05, 0x7b, 0x41, 0xd7, 0xee, - 0x58, 0x94, 0x2f, 0x56, 0x58, 0x70, 0x59, 0x21, 0xed, 0x06, 0x84, 0x35, 0xfc, 0xbf, 0x47, 0x61, - 0x25, 0x12, 0xf3, 0x47, 0x32, 0x0a, 0xdd, 0xb8, 0x0b, 0xd0, 0xfe, 0x6d, 0xcb, 0x50, 0x90, 0x61, - 0x94, 0x1e, 0xe9, 0xff, 0x73, 0x99, 0x25, 0x53, 0x56, 0x28, 0x92, 0x06, 0x94, 0xd5, 0x78, 0x14, - 0x72, 0x29, 0xdf, 0x85, 0xa2, 0x70, 0x5a, 0xd6, 0x51, 0xbe, 0x1a, 0x90, 0x9f, 0x9f, 0x2f, 0xee, - 0xf6, 0xe4, 0x28, 0xa4, 0x15, 0x0e, 0x72, 0x9f, 0x85, 0x0e, 0x8a, 0x1b, 0x3d, 0x82, 0x17, 0x2f, - 0x5e, 0x6c, 0x13, 0x5b, 0xb0, 0x60, 0x81, 0x8d, 0x4e, 0x3c, 0xa7, 0x4e, 0x9d, 0x12, 0x3c, 0x25, - 0x25, 0x25, 0x46, 0xc5, 0x8a, 0x15, 0x05, 0xcf, 0xa0, 0x41, 0x83, 0x04, 0xed, 0xf4, 0xe9, 0xd3, - 0x02, 0x9f, 0x9b, 0x9b, 0x2b, 0x60, 0x7c, 0x56, 0x2e, 0x78, 0x12, 0x01, 0x9e, 0x77, 0xad, 0x5e, - 0x42, 0xe4, 0x1c, 0xbf, 0xa3, 0xe5, 0x3c, 0xbc, 0x81, 0x8d, 0x1b, 0x37, 0x36, 0xa6, 0x4e, 0x9d, - 0x6a, 0x5c, 0xbd, 0x7a, 0x95, 0x93, 0x8c, 0x6e, 0xdd, 0xba, 0x31, 0xa7, 0x9e, 0x3d, 0x7b, 0x26, - 0x70, 0xa3, 0x46, 0x8d, 0x62, 0x38, 0x7c, 0x2d, 0xcb, 0x70, 0x74, 0x6b, 0x4d, 0x3a, 0x78, 0xe1, - 0xfa, 0x78, 0x3d, 0xd1, 0x36, 0x92, 0xab, 0x51, 0x34, 0xc8, 0xde, 0x2e, 0xd0, 0xdb, 0x03, 0x2a, - 0xfc, 0x21, 0x02, 0x1a, 0x86, 0xa1, 0x43, 0x87, 0xb2, 0xb7, 0x0c, 0xb4, 0xfb, 0xad, 0x5c, 0xb9, - 0x92, 0xd1, 0xd7, 0xaf, 0x5f, 0xcf, 0xb6, 0x55, 0xaa, 0x54, 0x61, 0x5b, 0xad, 0xbf, 0x44, 0xad, - 0x73, 0xd2, 0x28, 0x8a, 0x68, 0xcc, 0x58, 0xb5, 0x6a, 0x95, 0x8d, 0x44, 0x6f, 0x25, 0xe8, 0x31, - 0xc0, 0xae, 0x5d, 0xbb, 0x8c, 0xfd, 0xfb, 0xf7, 0xdb, 0x68, 0x72, 0xe5, 0xc0, 0x81, 0x03, 0xc6, - 0x95, 0x2b, 0x57, 0x64, 0x94, 0x36, 0xec, 0x7b, 0x1e, 0x78, 0xf8, 0xf0, 0x21, 0xd4, 0xa8, 0x51, - 0x83, 0x05, 0xa9, 0x72, 0xe5, 0xca, 0x70, 0xf2, 0xe4, 0x49, 0xe8, 0xd8, 0xb1, 0xa3, 0x56, 0xd0, - 0xa2, 0x14, 0xf6, 0x6d, 0x40, 0x94, 0xc6, 0x92, 0xa1, 0xab, 0x7c, 0x9d, 0x07, 0x92, 0x11, 0x41, - 0x5d, 0x9d, 0x99, 0x5d, 0x48, 0x37, 0x82, 0xba, 0xf2, 0x99, 0x63, 0x40, 0x37, 0x82, 0xba, 0xf2, - 0x99, 0x1e, 0xd0, 0x8d, 0xa0, 0xae, 0x7c, 0xa6, 0x07, 0x74, 0x23, 0xa8, 0x2b, 0x1f, 0xc9, 0xd5, - 0xa8, 0xf3, 0xa6, 0x5e, 0xf5, 0xc8, 0x50, 0x7e, 0xfc, 0x98, 0xf7, 0x2d, 0x80, 0x0f, 0xa7, 0xe9, - 0xba, 0x6e, 0xca, 0x47, 0xb2, 0x0b, 0xc9, 0x4f, 0x24, 0x82, 0xb8, 0xb5, 0xed, 0x08, 0x80, 0xfc, - 0x76, 0x38, 0x88, 0x8c, 0x17, 0x4f, 0x24, 0x0d, 0xe0, 0xca, 0x7f, 0x3a, 0x14, 0x40, 0x15, 0x7d, - 0xa2, 0x13, 0x5e, 0xa6, 0x2d, 0xd9, 0xce, 0xa5, 0xf4, 0xb6, 0xda, 0x0d, 0x78, 0xfe, 0xdc, 0x72, - 0xa0, 0x30, 0xcf, 0x82, 0xfd, 0xa0, 0x47, 0x4f, 0xfc, 0x38, 0x82, 0xd1, 0xb5, 0x1b, 0x20, 0x9b, - 0xe1, 0x0f, 0x6d, 0x65, 0x5c, 0xb2, 0xe1, 0x48, 0x1b, 0x90, 0x6c, 0x67, 0x55, 0xfa, 0xb5, 0x1b, - 0xb0, 0x47, 0x9a, 0x1a, 0xd3, 0x30, 0x5b, 0x65, 0xc2, 0x8e, 0xab, 0xee, 0x31, 0xc5, 0xc6, 0xce, - 0x15, 0xbc, 0xa6, 0xd5, 0x00, 0x7a, 0xb6, 0x3f, 0x72, 0xae, 0x69, 0x8c, 0x9e, 0x87, 0x06, 0xd9, - 0x85, 0x56, 0xbd, 0x63, 0x39, 0xd7, 0x7c, 0x0c, 0xc0, 0xa5, 0x1b, 0x56, 0xbd, 0x2c, 0x90, 0x56, - 0x03, 0x56, 0xfe, 0xd1, 0x34, 0xd9, 0xa8, 0x2e, 0xc0, 0xe7, 0x1f, 0x04, 0x33, 0xff, 0x9d, 0x6f, - 0x02, 0x8c, 0x1f, 0x6c, 0xf2, 0x96, 0xe2, 0x34, 0xc9, 0x73, 0x57, 0x82, 0xc9, 0x79, 0x71, 0x69, - 0xdf, 0xd0, 0xb4, 0xc2, 0x19, 0xb7, 0x77, 0xbe, 0x34, 0xd5, 0xcb, 0xc3, 0xa4, 0x97, 0xc1, 0xbc, - 0x77, 0x01, 0xfe, 0xf2, 0x77, 0x93, 0xfa, 0x87, 0x22, 0x80, 0xde, 0xed, 0xbd, 0x38, 0x83, 0xe1, - 0xb5, 0x7a, 0x80, 0x4c, 0x7c, 0xf6, 0xbe, 0x65, 0x48, 0x39, 0xcf, 0xde, 0x22, 0x33, 0x88, 0x3b, - 0x4f, 0x15, 0x5d, 0xe7, 0x49, 0x87, 0x76, 0x03, 0x5e, 0x33, 0x9f, 0xb8, 0x90, 0xae, 0xb4, 0x14, - 0xed, 0x06, 0xa4, 0xc5, 0x6b, 0xc9, 0x68, 0xa4, 0x0d, 0x88, 0xfa, 0xf5, 0x91, 0xe4, 0xa7, 0x27, - 0xa8, 0xdd, 0x00, 0x1a, 0x3e, 0x79, 0xe9, 0x55, 0x08, 0xe0, 0x35, 0x6d, 0x8f, 0xf0, 0xf9, 0x8b, - 0x38, 0x27, 0xc0, 0x37, 0x72, 0x2c, 0x58, 0x07, 0xd2, 0x1e, 0x85, 0xc8, 0x78, 0x9b, 0x7c, 0x80, - 0x5b, 0xff, 0xb5, 0xdc, 0x50, 0x8d, 0x46, 0xf2, 0xe5, 0x34, 0x71, 0xd2, 0xfb, 0x31, 0x55, 0xea, - 0x8b, 0xa5, 0x25, 0x18, 0x14, 0xc9, 0xfd, 0xc0, 0x45, 0xcc, 0x8e, 0xf8, 0xe4, 0x18, 0xc0, 0xc9, - 0x8b, 0xde, 0x46, 0xdf, 0x79, 0xd3, 0xa4, 0x55, 0xc9, 0xc2, 0x97, 0xdb, 0x78, 0xd1, 0x97, 0x15, - 0x89, 0x65, 0x3c, 0x79, 0xd2, 0xe3, 0x61, 0x6f, 0xb3, 0xf1, 0xa7, 0x48, 0x7b, 0x70, 0xfc, 0x9d, - 0x55, 0x79, 0x98, 0x69, 0x80, 0x2a, 0x2a, 0xa9, 0xc4, 0x95, 0xaf, 0x1e, 0xc8, 0xce, 0xce, 0x86, - 0x2d, 0x5b, 0xa4, 0xa9, 0x59, 0xa9, 0x0c, 0xb5, 0x87, 0xad, 0x50, 0x3d, 0x50, 0x5a, 0x5a, 0x0a, - 0x87, 0x0f, 0x1f, 0xf6, 0x50, 0x95, 0x1e, 0x74, 0xa8, 0xd1, 0x38, 0x8e, 0x23, 0xae, 0x6f, 0x0f, - 0x4c, 0x99, 0x32, 0x85, 0xbd, 0x36, 0xa5, 0x57, 0xa7, 0xfc, 0xe7, 0x8c, 0x35, 0xcd, 0xd1, 0xe6, - 0x34, 0x7a, 0x11, 0xc8, 0x5f, 0xb3, 0x72, 0xbe, 0xf1, 0xe3, 0xc7, 0x0b, 0x3a, 0xd1, 0xce, 0x9e, - 0x3d, 0xcb, 0x49, 0x40, 0xd9, 0x65, 0x84, 0x3b, 0x78, 0xf0, 0xa0, 0xe0, 0xc1, 0xf7, 0xc8, 0x82, - 0xee, 0x0b, 0xf8, 0xbd, 0xe7, 0x3c, 0x74, 0xe8, 0x90, 0x81, 0xef, 0x7a, 0xd9, 0xaf, 0x4e, 0x9d, - 0x3a, 0xb6, 0x17, 0xd2, 0x24, 0x3b, 0x70, 0xe0, 0x40, 0x86, 0xe3, 0x2f, 0xb2, 0xfb, 0xf6, 0xed, - 0x6b, 0xe3, 0x69, 0xd1, 0xa2, 0x05, 0xab, 0x0f, 0x1e, 0x3c, 0xd8, 0x58, 0xbe, 0x7c, 0xb9, 0x78, - 0x63, 0xcf, 0xdf, 0xe4, 0xcf, 0x98, 0x31, 0x83, 0xd1, 0xd1, 0x51, 0x63, 0xd2, 0xa4, 0x49, 0x46, - 0xb5, 0x6a, 0xd5, 0x6c, 0xf2, 0x7e, 0xfe, 0x59, 0xaf, 0xc7, 0xfd, 0x38, 0x91, 0xde, 0xb3, 0x67, - 0x4f, 0x97, 0x72, 0x9e, 0xad, 0x46, 0x0e, 0xd0, 0x14, 0x02, 0x7c, 0x89, 0x6d, 0xd3, 0x44, 0xf8, - 0x76, 0xed, 0xda, 0xb9, 0x70, 0x59, 0x59, 0x59, 0x02, 0x47, 0x3c, 0xfd, 0xfa, 0xf5, 0x63, 0x75, - 0x3e, 0xf5, 0x40, 0x7e, 0xdb, 0x2f, 0x18, 0x15, 0x80, 0x76, 0x03, 0x48, 0xe7, 0xc4, 0x89, 0x13, - 0x45, 0x14, 0xc9, 0x19, 0xfa, 0x51, 0xe1, 0x2f, 0xc6, 0x47, 0x8c, 0x18, 0xc1, 0xea, 0xfc, 0x4f, - 0xe6, 0x21, 0x1c, 0xd5, 0x67, 0xcf, 0x9e, 0xcd, 0xc8, 0xf4, 0x22, 0x9c, 0xea, 0x97, 0x2e, 0x5d, - 0xe2, 0xec, 0x09, 0xb7, 0xbe, 0xc7, 0x00, 0x2a, 0x4b, 0x58, 0x68, 0x2a, 0x01, 0x46, 0x8d, 0x3c, - 0x66, 0xbf, 0xe9, 0xd3, 0xa7, 0x33, 0x7e, 0x4c, 0x3d, 0x00, 0x9c, 0xe0, 0xc1, 0xe0, 0x4d, 0x9b, - 0x36, 0xc1, 0x93, 0x27, 0xe6, 0xa3, 0xb8, 0x85, 0x0b, 0x31, 0xb3, 0x05, 0x0b, 0xcf, 0x4b, 0x66, - 0x15, 0x9d, 0xbf, 0x84, 0xcd, 0x73, 0x10, 0xbb, 0x77, 0xef, 0x2e, 0xa2, 0xcb, 0x49, 0xad, 0x5a, - 0xb5, 0x62, 0x38, 0xf4, 0xc1, 0xc0, 0x37, 0xfa, 0x02, 0xe6, 0xf4, 0x73, 0xe7, 0xce, 0x09, 0x1c, - 0xf1, 0xd0, 0x0f, 0x0f, 0x7a, 0x4e, 0xb6, 0xd1, 0xee, 0xde, 0xbd, 0x6b, 0xab, 0x0b, 0xa6, 0x04, - 0x80, 0xd9, 0xd7, 0x09, 0x18, 0x64, 0x12, 0x9e, 0xc8, 0x98, 0x01, 0x19, 0x47, 0x5d, 0x4e, 0xb3, - 0x4e, 0x30, 0x6d, 0x94, 0x65, 0x71, 0x7a, 0x75, 0x3d, 0x4d, 0xb9, 0xd9, 0xbb, 0x77, 0xaf, 0xf1, - 0xfc, 0xf9, 0x73, 0x59, 0x5c, 0x1b, 0xf6, 0xbd, 0x9c, 0x1e, 0x39, 0x72, 0x24, 0xd0, 0x6a, 0x05, - 0x34, 0xd4, 0x6d, 0xdb, 0xb6, 0x0d, 0xda, 0xb4, 0x69, 0x03, 0x17, 0x2e, 0x5c, 0xd0, 0xe9, 0xf4, - 0x68, 0x65, 0xfd, 0x42, 0x40, 0x23, 0x0b, 0xef, 0x7a, 0xdc, 0x6f, 0xfd, 0xd8, 0x53, 0x4e, 0xf7, - 0xed, 0x81, 0x68, 0xc3, 0x15, 0xbd, 0x36, 0xed, 0x51, 0x28, 0x7a, 0x97, 0xc2, 0x69, 0xcc, 0x34, - 0x20, 0x5c, 0xbc, 0xa2, 0xe7, 0xce, 0xf4, 0x40, 0xf4, 0x31, 0x0d, 0xa7, 0xf1, 0xa5, 0x1f, 0x85, - 0xc2, 0x35, 0x37, 0x7e, 0xdc, 0x2f, 0xfd, 0x21, 0x10, 0xbf, 0x90, 0x86, 0xf3, 0x28, 0xd3, 0x01, - 0xe1, 0xe2, 0x15, 0x39, 0x77, 0xa6, 0x03, 0x22, 0x0f, 0x69, 0x38, 0x85, 0x99, 0x0e, 0x08, 0x17, - 0xaf, 0xc8, 0xb9, 0x33, 0x1d, 0x10, 0x79, 0x48, 0xc3, 0x29, 0xcc, 0x74, 0x40, 0xb8, 0x78, 0x45, - 0xce, 0x1d, 0xea, 0xb1, 0x74, 0xe4, 0xd6, 0x3d, 0x14, 0x52, 0xb6, 0xf4, 0x99, 0x7f, 0x03, 0x7c, - 0xf5, 0xcc, 0x62, 0xa0, 0xd4, 0xdd, 0x21, 0x3d, 0xac, 0x7a, 0x22, 0x88, 0x5e, 0x95, 0xca, 0x25, - 0xab, 0x12, 0x40, 0xc7, 0x1c, 0x00, 0xca, 0x01, 0x8e, 0x5b, 0x89, 0xcd, 0x7d, 0xc0, 0x43, 0x7c, - 0xe2, 0x98, 0x3b, 0x13, 0xe0, 0xec, 0x65, 0x75, 0x88, 0xbc, 0x12, 0x4b, 0x55, 0xdc, 0xce, 0x97, - 0xe9, 0x32, 0x0f, 0x75, 0xc4, 0xde, 0xf7, 0x00, 0xaa, 0x45, 0x90, 0x38, 0x25, 0xeb, 0x2d, 0x2b, - 0x1c, 0x9b, 0x23, 0xe0, 0x7b, 0xb3, 0xd5, 0xc1, 0x6f, 0xf3, 0x3a, 0x40, 0x4e, 0x23, 0x9c, 0x0e, - 0xf4, 0x22, 0x7b, 0x3d, 0x48, 0x43, 0x69, 0x32, 0x18, 0x95, 0x7f, 0xe1, 0x2c, 0xb6, 0x2f, 0xae, - 0x9b, 0x30, 0xff, 0xff, 0x47, 0x31, 0xc0, 0xf7, 0xdf, 0x05, 0xf8, 0xb4, 0x88, 0x63, 0xd2, 0xbb, - 0x8d, 0xc5, 0x11, 0x40, 0x53, 0x66, 0xe5, 0x55, 0xd4, 0x78, 0x48, 0x68, 0x65, 0x29, 0xbe, 0x7c, - 0x15, 0xc7, 0x85, 0xdd, 0x9e, 0x2e, 0x06, 0xf8, 0xb6, 0x34, 0xbd, 0x90, 0xcb, 0xab, 0xa6, 0xa1, - 0x70, 0x5a, 0x2a, 0xb7, 0xb1, 0x3e, 0x09, 0xd3, 0x52, 0x07, 0xba, 0x25, 0x0a, 0x1d, 0xba, 0x3e, - 0x24, 0x92, 0x8f, 0x75, 0x07, 0x24, 0x72, 0xfc, 0x55, 0xa1, 0xc5, 0xa2, 0x03, 0x4a, 0x1f, 0xaa, - 0xc3, 0x19, 0x62, 0xd8, 0x57, 0x2b, 0x40, 0xac, 0x97, 0x8e, 0x2f, 0x3d, 0x6c, 0x7a, 0x2a, 0x4a, - 0x12, 0x21, 0xed, 0x1d, 0x70, 0x13, 0xa7, 0x07, 0xd2, 0xd5, 0x8f, 0xb3, 0xf4, 0x6c, 0x17, 0xcd, - 0x34, 0xc0, 0x26, 0x78, 0xe9, 0xd9, 0x4d, 0xb1, 0x10, 0x6d, 0xff, 0x19, 0x00, 0xb7, 0x4b, 0x9d, - 0x56, 0x53, 0x5f, 0x4f, 0xdb, 0x49, 0x98, 0xd6, 0xe0, 0x7c, 0xeb, 0xd7, 0xee, 0x06, 0xbf, 0xd1, - 0x02, 0xe0, 0x57, 0x38, 0xb9, 0x23, 0xe8, 0x35, 0xbf, 0x5b, 0x83, 0x1a, 0xb3, 0xf3, 0xaf, 0x98, - 0x69, 0x84, 0xb9, 0xfb, 0x9f, 0x5f, 0x76, 0xd3, 0x69, 0xb9, 0xc8, 0xa8, 0xed, 0xb9, 0xad, 0xa8, - 0x31, 0x69, 0x3b, 0x02, 0xea, 0xe3, 0x09, 0xb6, 0x43, 0x73, 0xb7, 0x53, 0x74, 0x03, 0x36, 0xe1, - 0x77, 0xfa, 0x89, 0x10, 0xb2, 0xe6, 0x8b, 0xd7, 0x00, 0x26, 0xa1, 0x4e, 0x55, 0xf0, 0xc9, 0x87, - 0x28, 0x26, 0xdc, 0xca, 0xf6, 0xc2, 0xc0, 0x69, 0x3b, 0x02, 0x64, 0x27, 0xb7, 0xe1, 0xa4, 0xb5, - 0x1f, 0x9b, 0x53, 0x3e, 0x04, 0xba, 0x16, 0xae, 0x48, 0x71, 0xe5, 0xa3, 0x60, 0x59, 0x2c, 0x42, - 0x48, 0x01, 0x3c, 0xc3, 0x4b, 0x5c, 0x5a, 0x35, 0xeb, 0x81, 0xf5, 0x25, 0x04, 0xc6, 0xf5, 0x11, - 0x4e, 0x41, 0x19, 0xde, 0x4b, 0x21, 0x90, 0x62, 0x54, 0xda, 0x8e, 0x00, 0xb9, 0x9d, 0xc3, 0x7b, - 0xcb, 0x35, 0x13, 0xbe, 0x8f, 0x27, 0xc9, 0x12, 0x69, 0xfa, 0xb8, 0x9b, 0x23, 0x18, 0x86, 0x72, - 0x48, 0x9c, 0xc1, 0x27, 0xc9, 0x38, 0x04, 0x9f, 0xfc, 0x88, 0x45, 0x07, 0x90, 0x23, 0xe5, 0xb5, - 0x64, 0x3a, 0x20, 0xcd, 0x3d, 0x1f, 0x8b, 0x0e, 0xc0, 0x79, 0x5f, 0x38, 0x17, 0xd0, 0x1d, 0x89, - 0xad, 0x87, 0xdc, 0xb8, 0xb0, 0x98, 0x2d, 0x07, 0xdd, 0x12, 0x95, 0xf0, 0xe9, 0x68, 0x5c, 0x4a, - 0x2c, 0x4e, 0xc2, 0x14, 0x8c, 0x42, 0xcc, 0xba, 0xfc, 0x70, 0x8f, 0x77, 0x58, 0xa2, 0x7a, 0x1a, - 0x4a, 0x16, 0xf2, 0xbf, 0x8b, 0x2b, 0xa1, 0xbe, 0xed, 0x6d, 0x2b, 0x95, 0x14, 0xc5, 0x7e, 0x97, - 0x4a, 0xf3, 0x96, 0xad, 0x45, 0x05, 0x00, 0x7f, 0x9a, 0x8b, 0xb9, 0x5b, 0xf8, 0xf4, 0x33, 0x59, - 0xa5, 0x6d, 0x53, 0x80, 0x3f, 0xcf, 0x8f, 0x4f, 0xf0, 0xa9, 0x9d, 0xb1, 0x39, 0x02, 0x92, 0x15, - 0xf4, 0xb8, 0xeb, 0x8d, 0xcd, 0x11, 0x10, 0xf7, 0x40, 0x25, 0xcb, 0xbf, 0x4c, 0x07, 0x24, 0x2b, - 0xb2, 0x01, 0xf5, 0x66, 0x3a, 0x20, 0x60, 0xa0, 0x92, 0xc5, 0x96, 0xe9, 0x80, 0x64, 0x45, 0x36, - 0xa0, 0xde, 0xa4, 0x76, 0x00, 0x25, 0x77, 0xe0, 0x4a, 0x9d, 0x01, 0x5d, 0x29, 0x9f, 0x6c, 0x49, - 0xeb, 0x00, 0x4a, 0x30, 0xc4, 0xbc, 0x3b, 0xf6, 0x95, 0xb8, 0x69, 0xd3, 0xa6, 0x95, 0xcf, 0xe8, - 0x06, 0x68, 0x75, 0xd2, 0x3a, 0x80, 0x32, 0xe0, 0x72, 0x72, 0x72, 0x00, 0x13, 0xc9, 0x60, 0xc0, - 0x80, 0x01, 0x01, 0x5c, 0x29, 0x9f, 0x2c, 0x91, 0xdd, 0x07, 0x50, 0x6a, 0xe1, 0xcd, 0x9b, 0x37, - 0x95, 0x51, 0xac, 0x84, 0xf7, 0xfe, 0x98, 0xf0, 0x09, 0x94, 0x8a, 0x9b, 0xa8, 0xd0, 0xf7, 0x14, - 0x71, 0x51, 0x61, 0xc0, 0xe4, 0x39, 0xf6, 0xad, 0x45, 0x4a, 0xe3, 0x25, 0x39, 0xfc, 0xfe, 0x10, - 0x6c, 0xdd, 0xba, 0x15, 0x30, 0x93, 0x0f, 0x30, 0xa3, 0x95, 0xe5, 0xac, 0x79, 0xe9, 0x21, 0x1e, - 0xcc, 0x0e, 0x84, 0xf3, 0xe7, 0xcf, 0xb3, 0xe1, 0x8f, 0xe4, 0xdb, 0xb7, 0x6f, 0x0f, 0x4d, 0x9a, - 0x34, 0xf1, 0x12, 0x61, 0x79, 0x70, 0x94, 0xfb, 0x86, 0x49, 0x78, 0xec, 0x88, 0xa5, 0x6f, 0x39, - 0x12, 0x8c, 0x5f, 0x63, 0x82, 0xa3, 0x47, 0x8f, 0x32, 0xb8, 0x4b, 0x97, 0x2e, 0xd0, 0xab, 0x57, - 0x12, 0x9e, 0x5f, 0x47, 0x91, 0x98, 0xc6, 0x53, 0x84, 0xb1, 0x85, 0x22, 0x27, 0xce, 0x09, 0x3b, - 0xd7, 0xd2, 0x96, 0xed, 0xd2, 0x2a, 0xcf, 0x32, 0x7f, 0xdd, 0xba, 0x75, 0x8d, 0xfe, 0xfd, 0xfb, - 0x1b, 0x1d, 0x3a, 0x74, 0x30, 0x30, 0x41, 0xd0, 0x46, 0xa3, 0x6c, 0x45, 0x67, 0xc1, 0x2c, 0x78, - 0x83, 0xa7, 0x32, 0xcb, 0x7a, 0x9c, 0x30, 0x65, 0xf8, 0x2e, 0x5b, 0xb6, 0xcc, 0x26, 0x4e, 0xd9, - 0xc1, 0x4e, 0xbe, 0x46, 0x8d, 0x1a, 0xb9, 0x70, 0x9c, 0x07, 0x73, 0x55, 0x6d, 0xf2, 0xba, 0x95, - 0x50, 0xa9, 0x9e, 0x61, 0x8d, 0xf1, 0xf4, 0x68, 0x72, 0x3e, 0x51, 0x07, 0xc8, 0xf9, 0xae, 0x04, - 0x53, 0xca, 0xb3, 0x5c, 0x28, 0x3d, 0x74, 0xc3, 0x86, 0x0d, 0xc6, 0xa2, 0x45, 0x8b, 0x5c, 0xa9, - 0xa2, 0x93, 0x27, 0x4f, 0xb6, 0x05, 0xab, 0xa8, 0xa8, 0x48, 0x16, 0x65, 0x30, 0x2d, 0xd7, 0x2d, - 0x77, 0x24, 0xff, 0xc6, 0x98, 0xcc, 0xc8, 0x17, 0x47, 0x27, 0x5f, 0x69, 0x15, 0xf8, 0xcb, 0x97, - 0x2f, 0x0b, 0xf2, 0x8a, 0x15, 0x2b, 0x84, 0x0d, 0x3c, 0x9a, 0x8d, 0xa7, 0x4f, 0x9f, 0x0a, 0x9a, - 0x2e, 0x10, 0x8b, 0x0e, 0xc0, 0xe1, 0xc2, 0xe0, 0x79, 0xbc, 0x7c, 0x4f, 0x73, 0x6e, 0xa9, 0xe1, - 0xa3, 0x47, 0x8f, 0x36, 0x6e, 0xdd, 0xba, 0x25, 0xda, 0x8c, 0x19, 0xd4, 0x06, 0x2e, 0xce, 0x2e, - 0x82, 0x33, 0x66, 0xcc, 0x18, 0x41, 0x73, 0x02, 0x4b, 0x96, 0x2c, 0x11, 0x7c, 0xa4, 0x9b, 0x72, - 0x83, 0xe5, 0x22, 0x77, 0xc0, 0xac, 0x59, 0xb3, 0x64, 0x12, 0xeb, 0x0c, 0xd9, 0x1f, 0xaf, 0x7c, - 0x62, 0x9b, 0x50, 0xc0, 0x4a, 0xd2, 0x4e, 0xc2, 0xe8, 0x70, 0xe0, 0x52, 0xbb, 0x76, 0x6d, 0x58, - 0xbd, 0x7a, 0x35, 0x1b, 0x6b, 0xd1, 0x6f, 0xb8, 0x76, 0xed, 0x1a, 0xe0, 0x50, 0x03, 0x73, 0xe6, - 0xcc, 0x81, 0xdc, 0xdc, 0x5c, 0xa6, 0x07, 0x73, 0xef, 0x61, 0xcd, 0x9a, 0x35, 0xd0, 0xa0, 0x41, - 0x03, 0xf6, 0xed, 0x5d, 0x42, 0xe2, 0x90, 0x02, 0x98, 0x41, 0x2e, 0xec, 0x90, 0x8c, 0xfc, 0xfd, - 0x5e, 0x41, 0x40, 0x60, 0xfb, 0xf6, 0xed, 0xa2, 0x4a, 0xeb, 0xc4, 0x77, 0xee, 0xdc, 0x59, 0xd4, - 0x9d, 0x00, 0x9d, 0xb3, 0xe4, 0x42, 0x79, 0xd2, 0x49, 0x2b, 0x01, 0x3b, 0xaa, 0x4c, 0x6c, 0x41, - 0x87, 0xa0, 0xd6, 0xad, 0x5b, 0x8b, 0xbd, 0x93, 0x60, 0x5c, 0x1f, 0xc0, 0xc0, 0x13, 0x3a, 0xb3, - 0x59, 0x5c, 0x5c, 0x2c, 0x96, 0xa5, 0xc0, 0x20, 0x18, 0x78, 0x32, 0xb5, 0xf9, 0x42, 0x5f, 0x04, - 0xc0, 0x60, 0x0a, 0x79, 0xe2, 0xc1, 0x93, 0xae, 0x51, 0x58, 0x58, 0x68, 0xcc, 0x9c, 0x39, 0x93, - 0x7d, 0xd2, 0x90, 0x70, 0xfc, 0x47, 0xa9, 0xfa, 0xf2, 0xf0, 0x42, 0x76, 0x28, 0x9f, 0x9b, 0xce, - 0x0f, 0x9c, 0x87, 0xce, 0x27, 0xb4, 0x7c, 0x05, 0x95, 0x9d, 0x3b, 0x77, 0xb2, 0x73, 0x11, 0xa7, - 0xd1, 0x96, 0x56, 0x90, 0xc0, 0x0e, 0xb5, 0xf9, 0x51, 0xd6, 0x4a, 0x52, 0x87, 0x20, 0xf9, 0xf3, - 0x8b, 0xf8, 0x91, 0x49, 0x4f, 0x1f, 0xe9, 0x84, 0x4b, 0x0d, 0xc3, 0xbd, 0xdb, 0x36, 0xa4, 0xc8, - 0x8d, 0xee, 0xd4, 0xa9, 0x13, 0xeb, 0x18, 0x2f, 0x25, 0xb4, 0xe4, 0x00, 0xd9, 0xa8, 0x5f, 0xbf, - 0xbe, 0x08, 0x24, 0x97, 0xc7, 0x85, 0x4d, 0x8c, 0x09, 0x13, 0x26, 0x18, 0xb7, 0x6f, 0xe3, 0x27, - 0x63, 0x1d, 0x05, 0x8f, 0x36, 0xa3, 0x6b, 0xd7, 0xae, 0xb6, 0x73, 0x04, 0xad, 0x1b, 0x42, 0x1f, - 0xd0, 0xa0, 0xb2, 0x6e, 0xdd, 0x3a, 0xa3, 0x69, 0xd3, 0xa6, 0x36, 0x9d, 0xb4, 0x13, 0x38, 0x3f, - 0x0f, 0xe1, 0x50, 0x1b, 0xb8, 0x9a, 0xb4, 0x0e, 0xd8, 0xb1, 0x63, 0x87, 0xcd, 0xe9, 0x63, 0xc7, - 0x8e, 0x05, 0x76, 0xaa, 0x3c, 0x31, 0x26, 0xbe, 0x30, 0xc7, 0x5d, 0xc8, 0xaf, 0x1c, 0x39, 0x72, - 0x04, 0xf0, 0x04, 0xe6, 0xc9, 0x46, 0xcb, 0x8e, 0xec, 0xdb, 0xb7, 0xcf, 0x36, 0x56, 0x7b, 0x32, - 0x97, 0x43, 0x42, 0x64, 0x37, 0x62, 0xb8, 0xa2, 0x08, 0xbb, 0x81, 0xa2, 0x8f, 0xa1, 0xe0, 0x21, - 0x0b, 0xcd, 0x9a, 0x35, 0xf3, 0xbd, 0xf1, 0x2a, 0x87, 0xf1, 0x76, 0x35, 0x39, 0xb2, 0x0e, 0x70, - 0x69, 0xce, 0x20, 0x02, 0x45, 0x20, 0x16, 0x97, 0xa1, 0x81, 0x3c, 0x7d, 0x45, 0x99, 0x32, 0x1d, - 0x90, 0xe6, 0x8e, 0xcd, 0x74, 0x40, 0xa6, 0x03, 0xd2, 0x1c, 0x81, 0x34, 0x9b, 0xcf, 0x1c, 0x01, - 0x69, 0xee, 0x80, 0xff, 0x03, 0x75, 0x4b, 0xcb, 0x8b, 0xae, 0x16, 0xbd, 0x22, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXTextPlainIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa8, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, - 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, - 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, - 0x32, 0x32, 0x3a, 0x30, 0x32, 0x3a, 0x34, 0x33, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, - 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, - 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, - 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, - 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, - 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, - 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, - 0x61, 0x3e, 0x0a, 0x04, 0xa5, 0xd6, 0xff, 0x00, 0x00, 0x05, 0x7b, 0x49, 0x44, 0x41, 0x54, 0x68, - 0x05, 0xed, 0x58, 0x5b, 0x48, 0x23, 0x57, 0x18, 0xce, 0x24, 0x31, 0xf1, 0x52, 0xad, 0x31, 0x78, - 0xdf, 0xd6, 0x2a, 0xb6, 0x52, 0xad, 0x28, 0x8a, 0xe8, 0x82, 0x62, 0xe9, 0x45, 0xa5, 0x45, 0xf0, - 0x82, 0x58, 0x41, 0xb4, 0xed, 0x83, 0x0f, 0xe2, 0x83, 0x6f, 0x8a, 0x20, 0xb8, 0x3e, 0x28, 0x05, - 0x45, 0x7d, 0x12, 0x84, 0x82, 0x8a, 0x88, 0x22, 0x0a, 0xbe, 0x54, 0xb4, 0xc2, 0x3e, 0xe9, 0x82, - 0x37, 0x50, 0x1a, 0x45, 0x2a, 0x5e, 0x8a, 0xdd, 0x20, 0x58, 0x35, 0xb1, 0x8a, 0x49, 0x4c, 0xd2, - 0x2f, 0x7b, 0xe2, 0x38, 0x3b, 0xc6, 0x89, 0x33, 0x39, 0xac, 0x2b, 0x9d, 0xf3, 0x30, 0xfc, 0xe7, - 0xfc, 0xdf, 0x7f, 0xff, 0xcf, 0x3f, 0x93, 0x30, 0x4e, 0xa7, 0x53, 0xf1, 0x94, 0x97, 0xf2, 0x29, - 0x3b, 0xef, 0xf2, 0x5d, 0x0e, 0xe0, 0xb1, 0x2b, 0x28, 0x57, 0x40, 0xae, 0x80, 0x8f, 0x19, 0x90, - 0x5b, 0xc8, 0xc7, 0x04, 0xfa, 0x2c, 0x2e, 0x57, 0xc0, 0xe7, 0x14, 0xfa, 0xa8, 0x40, 0xae, 0x80, - 0x8f, 0x09, 0xf4, 0x59, 0x5c, 0xed, 0xb3, 0x06, 0x97, 0x02, 0xa7, 0x43, 0xf1, 0x7a, 0xc3, 0x61, - 0x32, 0x3a, 0x9d, 0x0e, 0x2f, 0x9f, 0x86, 0x8c, 0x92, 0xf9, 0x30, 0x86, 0x89, 0x49, 0x55, 0x32, - 0x94, 0x6a, 0x4f, 0x27, 0x80, 0xfd, 0x57, 0xf6, 0xdf, 0x5e, 0x58, 0x1e, 0x9e, 0x8b, 0xef, 0x5e, - 0x68, 0xe3, 0x9f, 0xab, 0x1e, 0x8e, 0x17, 0x40, 0xd2, 0xc9, 0x83, 0xf9, 0xc8, 0x4b, 0xe2, 0x79, - 0x1e, 0x98, 0x8d, 0xe2, 0xf0, 0x3c, 0x71, 0xee, 0x96, 0x4e, 0x05, 0x6c, 0x57, 0x6e, 0x9d, 0xfe, - 0x21, 0x4c, 0xa0, 0x8e, 0xc1, 0xc6, 0xf2, 0xaf, 0xf3, 0xe2, 0x1f, 0xb7, 0x97, 0x41, 0x7a, 0xa5, - 0xf6, 0x03, 0x17, 0xe0, 0xf2, 0xd4, 0x79, 0x65, 0x76, 0x1d, 0x5e, 0x8b, 0xa8, 0x96, 0x4b, 0x50, - 0x60, 0xd1, 0x09, 0xc0, 0x6e, 0x71, 0xfb, 0xfa, 0xc5, 0xf7, 0xea, 0xec, 0x9f, 0xfc, 0x60, 0x6f, - 0x73, 0xc6, 0xfe, 0xb2, 0xc7, 0xed, 0x66, 0xf6, 0x8f, 0x7e, 0x9f, 0x17, 0xba, 0x1a, 0xe6, 0xd5, - 0xaf, 0xb6, 0xb5, 0x71, 0x1b, 0x88, 0xeb, 0x1b, 0xbc, 0x80, 0x67, 0x0f, 0x64, 0xd1, 0x69, 0xa1, - 0x6b, 0xab, 0xdb, 0x9c, 0x4a, 0xe3, 0x4a, 0xff, 0x7d, 0x4b, 0xe5, 0x0a, 0xcd, 0xb5, 0xec, 0x37, - 0x78, 0xb2, 0xf5, 0xe5, 0x49, 0x29, 0x80, 0x9b, 0x96, 0x60, 0x5d, 0xf4, 0xe8, 0x93, 0x5a, 0xeb, - 0x0e, 0x8f, 0x0d, 0xd8, 0x23, 0x4c, 0xd4, 0x21, 0x9d, 0x00, 0x74, 0x1f, 0xb9, 0x3d, 0x0b, 0x89, - 0x12, 0xaa, 0x80, 0x3e, 0xc1, 0x6d, 0x2e, 0xf4, 0x99, 0x10, 0x4c, 0x54, 0x00, 0x74, 0xee, 0x40, - 0xd2, 0x37, 0x6a, 0xcb, 0x85, 0x42, 0xa9, 0x52, 0x7c, 0x22, 0x38, 0x1c, 0x9f, 0xa5, 0x29, 0x9f, - 0xff, 0xac, 0xb9, 0xb6, 0x3a, 0x93, 0xbe, 0xa6, 0x63, 0x17, 0xa1, 0xd2, 0x51, 0xa4, 0x0d, 0x56, - 0x64, 0x55, 0x7b, 0x57, 0xa5, 0xd2, 0x28, 0x32, 0x7e, 0xf0, 0x0e, 0x13, 0x55, 0x01, 0x3a, 0x2d, - 0x24, 0xca, 0x24, 0x5d, 0xb0, 0x1c, 0x00, 0xdd, 0x7c, 0x8a, 0xd7, 0xf6, 0xe4, 0x2b, 0x40, 0xf9, - 0x4a, 0x59, 0xce, 0x15, 0x27, 0x7f, 0x39, 0x90, 0x47, 0xd3, 0x6b, 0xd7, 0x93, 0x2c, 0xd3, 0xdf, - 0x0e, 0xa3, 0x81, 0xc1, 0xe0, 0xd4, 0x7d, 0xac, 0xc4, 0x75, 0xa7, 0xbb, 0x18, 0x8a, 0xff, 0x8d, - 0xfe, 0xf9, 0xd2, 0xfe, 0xfb, 0x2f, 0x56, 0x81, 0x2f, 0x6a, 0x7c, 0x4b, 0x7f, 0xdb, 0xac, 0xf9, - 0xf4, 0x4b, 0x3a, 0xdf, 0xa1, 0x24, 0x11, 0x34, 0x5b, 0xc8, 0x68, 0x70, 0x08, 0x78, 0x0f, 0x7b, - 0xe0, 0x1a, 0xff, 0xb8, 0xad, 0x0c, 0x95, 0x52, 0xd0, 0x0c, 0xe0, 0xb3, 0xaf, 0x54, 0xfa, 0x78, - 0x21, 0x85, 0xe0, 0x02, 0x43, 0xc5, 0x6f, 0x56, 0x09, 0xcd, 0x16, 0x62, 0x95, 0xbe, 0x4b, 0x42, - 0x28, 0x61, 0xef, 0xd2, 0x0f, 0xc9, 0xb6, 0xe4, 0x00, 0x24, 0xa7, 0x8e, 0x92, 0xa0, 0x5c, 0x01, - 0x4a, 0x89, 0x94, 0xac, 0xe6, 0xff, 0x5d, 0x81, 0xeb, 0x37, 0xcb, 0xe1, 0x90, 0xfe, 0x6e, 0x5a, - 0x5d, 0x5d, 0x6d, 0x6f, 0x6f, 0x3f, 0x3a, 0x3a, 0x92, 0x5c, 0x01, 0x05, 0x3e, 0x25, 0x24, 0xac, - 0x9d, 0x9d, 0x9d, 0xb0, 0xb0, 0x30, 0x62, 0x35, 0x34, 0x34, 0x54, 0x82, 0x06, 0x22, 0x52, 0x55, - 0x55, 0x05, 0x25, 0xc3, 0xc3, 0xc3, 0x92, 0x35, 0x48, 0x6c, 0xa1, 0xe0, 0xe0, 0xe0, 0xa4, 0xa4, - 0xa4, 0x98, 0x98, 0x18, 0x98, 0xbf, 0xb8, 0xb8, 0x90, 0x9c, 0x3f, 0xe8, 0x51, 0xa9, 0x54, 0x91, - 0x91, 0x91, 0x92, 0x35, 0x48, 0xac, 0x00, 0x49, 0xd8, 0xca, 0xca, 0x0a, 0x0c, 0xfb, 0xf9, 0xf9, - 0x09, 0xe7, 0x0f, 0x3d, 0x26, 0x00, 0xb0, 0x5a, 0xad, 0x02, 0x5c, 0xaf, 0x2c, 0x0f, 0x15, 0x68, - 0x6d, 0x6d, 0xcd, 0xce, 0xce, 0x2e, 0x28, 0x28, 0x58, 0x5a, 0x5a, 0xca, 0xc9, 0xc9, 0x09, 0x0c, - 0x0c, 0x4c, 0x4d, 0x4d, 0xed, 0xea, 0xea, 0x12, 0xd5, 0xeb, 0x5b, 0x5b, 0x5b, 0xb5, 0xb5, 0xb5, - 0x59, 0x59, 0x59, 0xc8, 0x31, 0x34, 0xa4, 0xa7, 0xa7, 0x4f, 0x4f, 0x4f, 0x73, 0xd3, 0x3c, 0x37, - 0x37, 0x97, 0x9f, 0x9f, 0x0f, 0x43, 0xb9, 0xb9, 0xb9, 0xbd, 0xbd, 0xbd, 0x5c, 0xd6, 0xe9, 0xe9, - 0x69, 0x49, 0x49, 0x09, 0x58, 0xf5, 0xf5, 0xf5, 0x93, 0x93, 0x93, 0xb0, 0x1e, 0x14, 0x14, 0x54, - 0x54, 0x54, 0x64, 0x34, 0x1a, 0xb9, 0x30, 0x37, 0x7d, 0x37, 0xc4, 0xf8, 0xf8, 0x78, 0xc2, 0x83, - 0x18, 0x57, 0xa0, 0xba, 0xba, 0x9a, 0x07, 0x16, 0xa8, 0x00, 0x22, 0x87, 0x2c, 0xc3, 0x30, 0x88, - 0x21, 0x22, 0x22, 0x02, 0xb4, 0x56, 0xab, 0xdd, 0xdf, 0xdf, 0x67, 0x35, 0x34, 0x37, 0x37, 0xb3, - 0xca, 0x11, 0x2a, 0x7b, 0x0e, 0x82, 0xa8, 0x05, 0x17, 0xc1, 0xab, 0xd5, 0xb7, 0xbf, 0x58, 0x2a, - 0x2b, 0x2b, 0xb9, 0x30, 0x42, 0x7b, 0x68, 0xa1, 0xdd, 0xdd, 0x5d, 0xd2, 0x94, 0x3a, 0x9d, 0x6e, - 0x60, 0x60, 0x60, 0x63, 0x63, 0xa3, 0xb4, 0xb4, 0x94, 0x18, 0x9b, 0x9f, 0x9f, 0xe7, 0xaa, 0x10, - 0x08, 0x60, 0x6a, 0x6a, 0xaa, 0xbb, 0xbb, 0xfb, 0xf0, 0xf0, 0x10, 0x78, 0x8b, 0xc5, 0x42, 0x62, - 0xe0, 0x5e, 0xd6, 0xf3, 0xf3, 0xf3, 0x99, 0x99, 0x19, 0xa2, 0x99, 0x17, 0x00, 0x44, 0x46, 0x46, - 0x46, 0x88, 0xc5, 0xc2, 0xc2, 0x42, 0x58, 0xa9, 0xab, 0xab, 0xc3, 0x16, 0x09, 0xe5, 0x5a, 0x27, - 0xb4, 0x87, 0x00, 0xc0, 0x48, 0x48, 0x48, 0x80, 0x00, 0x2a, 0x48, 0x40, 0xc7, 0xc7, 0xc7, 0xb8, - 0x6a, 0x38, 0x69, 0x6a, 0x6a, 0xe2, 0xaa, 0x10, 0x08, 0x00, 0x30, 0x44, 0xdb, 0xd1, 0xd1, 0xd1, - 0xd8, 0xd8, 0xd8, 0xd6, 0xd6, 0x96, 0x96, 0x96, 0x06, 0xf1, 0xce, 0xce, 0x4e, 0xae, 0x38, 0x68, - 0x28, 0xc4, 0xf9, 0xdd, 0x00, 0xd6, 0xd7, 0xd7, 0x71, 0x8e, 0xb5, 0xbc, 0xbc, 0x0c, 0x18, 0xa6, - 0x2d, 0xd9, 0x9a, 0x4c, 0x26, 0x9e, 0x86, 0xdb, 0x02, 0x11, 0x04, 0xf7, 0x89, 0x1e, 0x25, 0x5b, - 0xbd, 0x5e, 0x9f, 0x92, 0x92, 0x82, 0x52, 0x20, 0xa3, 0x5c, 0xc0, 0x7d, 0xb4, 0xcd, 0x66, 0x2b, - 0x2e, 0x2e, 0x9e, 0x9d, 0x9d, 0x05, 0x40, 0xa3, 0xd1, 0xa0, 0x91, 0x50, 0x04, 0xd0, 0x76, 0xbb, - 0xfd, 0x3e, 0x91, 0xfb, 0xce, 0x33, 0x33, 0x33, 0xc1, 0x8a, 0x8b, 0x8b, 0x23, 0x80, 0xab, 0xab, - 0xab, 0x90, 0x90, 0x10, 0x2e, 0xd8, 0xc3, 0x25, 0x66, 0xd9, 0x0b, 0x0b, 0x0b, 0x84, 0xc6, 0xad, - 0xda, 0xdc, 0xdc, 0x04, 0xcd, 0x5e, 0x0f, 0x16, 0xe3, 0x91, 0x40, 0x03, 0x10, 0xef, 0x27, 0x26, - 0x26, 0x90, 0xb3, 0xcb, 0xcb, 0xcb, 0xb2, 0xb2, 0x32, 0x8f, 0x48, 0xaf, 0x87, 0x08, 0x1e, 0x18, - 0xf2, 0xf4, 0x08, 0x16, 0x0a, 0x60, 0x74, 0x74, 0x74, 0x6c, 0x6c, 0x6c, 0x6f, 0x6f, 0xaf, 0xa1, - 0xa1, 0x01, 0xef, 0x5c, 0xc8, 0xa3, 0x23, 0x59, 0x2d, 0x38, 0x61, 0x33, 0xca, 0xa5, 0x01, 0xc0, - 0x08, 0xc2, 0x33, 0x3c, 0x3c, 0x1c, 0x2d, 0xee, 0xef, 0xef, 0x8f, 0x41, 0x79, 0x72, 0x72, 0x82, - 0x13, 0x54, 0x9f, 0x15, 0x07, 0x0d, 0x29, 0x32, 0xd9, 0xb8, 0x34, 0x01, 0xb0, 0x48, 0x42, 0xb0, - 0x03, 0x90, 0x3d, 0x67, 0xf5, 0x08, 0xdd, 0x81, 0x5b, 0xd0, 0x1b, 0xaa, 0xa6, 0xa6, 0x06, 0xf2, - 0x58, 0x66, 0xb3, 0x39, 0x36, 0x36, 0x96, 0xc7, 0xc5, 0x16, 0x93, 0x97, 0x00, 0x06, 0x07, 0x07, - 0x09, 0x37, 0x23, 0x23, 0xa3, 0xa2, 0xa2, 0x82, 0x05, 0xe3, 0x8d, 0x31, 0x34, 0x34, 0x04, 0x0c, - 0x2a, 0x13, 0x10, 0x10, 0xc0, 0xd3, 0x80, 0x66, 0xeb, 0xef, 0xef, 0x07, 0xf7, 0xe0, 0xe0, 0x00, - 0xf3, 0x83, 0x70, 0x13, 0x13, 0x13, 0xcf, 0xce, 0xce, 0xa2, 0xa3, 0xa3, 0xc9, 0x16, 0xd3, 0x05, - 0xd6, 0x89, 0x15, 0xf2, 0x14, 0xaa, 0x40, 0x4b, 0x4b, 0x4b, 0x5e, 0x5e, 0x5e, 0x54, 0x54, 0x14, - 0x66, 0x62, 0x4f, 0x4f, 0x0f, 0xeb, 0x16, 0x74, 0x91, 0x3b, 0xcd, 0xf3, 0x80, 0x2d, 0x34, 0x06, - 0x2e, 0x8a, 0x86, 0xc9, 0xb3, 0xb6, 0xb6, 0x06, 0x5f, 0xd1, 0xc1, 0x7d, 0x7d, 0x7d, 0xe8, 0x5d, - 0x48, 0x91, 0x4a, 0x42, 0x50, 0xa9, 0xe4, 0x9b, 0x66, 0xc5, 0xc1, 0x45, 0x30, 0x44, 0x39, 0x86, - 0x2f, 0xd2, 0xcf, 0xdd, 0xc2, 0xef, 0xb7, 0xec, 0x72, 0xa3, 0x61, 0x69, 0x32, 0x85, 0x16, 0x17, - 0x17, 0xd9, 0x13, 0x09, 0x04, 0x1a, 0xcc, 0x60, 0x30, 0xdc, 0x9d, 0x1b, 0x12, 0x54, 0x09, 0x88, - 0xf0, 0xa7, 0x10, 0xec, 0xe1, 0xe5, 0x87, 0x27, 0xa2, 0x1c, 0x1f, 0x1f, 0xdf, 0xde, 0xde, 0x2e, - 0x2f, 0x2f, 0xc7, 0x0b, 0xe5, 0xad, 0xa0, 0x1f, 0xb6, 0x41, 0x8e, 0x93, 0x93, 0x93, 0x1f, 0x86, - 0xf5, 0x01, 0xc5, 0x0b, 0x0e, 0x6f, 0x2e, 0x9e, 0x32, 0x74, 0x0e, 0x0f, 0xf3, 0x5e, 0x6d, 0xf9, - 0x15, 0xc0, 0x47, 0x08, 0xbe, 0x2e, 0xf1, 0x9a, 0x24, 0x61, 0xa0, 0x71, 0x31, 0xd1, 0x79, 0x21, - 0xbd, 0x57, 0x5b, 0xf9, 0x7f, 0xa1, 0xc7, 0x2e, 0x07, 0x7f, 0x96, 0x3d, 0xb6, 0x3f, 0xa2, 0xed, - 0xcb, 0x01, 0x88, 0x4e, 0x19, 0x65, 0x01, 0xb9, 0x02, 0x94, 0x13, 0x2a, 0x5a, 0x9d, 0x5c, 0x01, - 0xd1, 0x29, 0xa3, 0x2c, 0xf0, 0x1f, 0x15, 0xdc, 0xd7, 0x70, 0xbb, 0x15, 0xe8, 0x4c, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXTextPlainIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0e, 0xc4, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x09, 0x90, 0x54, 0xc5, 0xf5, 0xcd, 0xcc, 0x9e, 0xdc, 0x57, 0x40, 0x2e, 0x5d, 0xee, 0xfb, - 0x08, 0x2b, 0x22, 0x87, 0x58, 0x12, 0xce, 0x70, 0xc7, 0x14, 0x10, 0x81, 0x18, 0x52, 0x21, 0x72, - 0x05, 0x39, 0xb6, 0x8c, 0x86, 0xaa, 0x68, 0x82, 0x40, 0x15, 0x1a, 0x20, 0x80, 0x28, 0x90, 0x18, - 0x24, 0xa6, 0x8a, 0x32, 0x51, 0x63, 0x89, 0x21, 0x01, 0x53, 0x50, 0x04, 0x10, 0xb1, 0x90, 0x02, - 0x42, 0x20, 0xc5, 0xa9, 0x72, 0x83, 0xe1, 0x5a, 0x98, 0xdd, 0xd9, 0x99, 0xfd, 0x79, 0xaf, 0x67, - 0xbb, 0xa7, 0xff, 0x39, 0xff, 0xff, 0x9d, 0xf9, 0xb3, 0x8b, 0xbf, 0xab, 0x66, 0xba, 0xfb, 0xf5, - 0xbb, 0xfa, 0xbd, 0xee, 0xfe, 0xdd, 0xff, 0x77, 0xff, 0x1f, 0x50, 0x30, 0x80, 0x83, 0x10, 0x74, - 0x80, 0xcb, 0x50, 0x53, 0x4b, 0xf0, 0xc2, 0xd0, 0x7b, 0xb0, 0x76, 0x76, 0x89, 0x4a, 0x89, 0xa4, - 0x12, 0xe6, 0xbc, 0x96, 0xa7, 0x22, 0x00, 0xaa, 0xb4, 0x1c, 0x9e, 0x1f, 0x72, 0x57, 0xa1, 0x1f, - 0x85, 0x33, 0x87, 0x63, 0x22, 0xcd, 0x71, 0x02, 0x94, 0x50, 0xb3, 0xb0, 0xce, 0x25, 0x55, 0x49, - 0x4b, 0xae, 0x23, 0x08, 0x04, 0x02, 0x5a, 0x1c, 0x55, 0x5e, 0x45, 0xf0, 0xe5, 0x97, 0x5f, 0x8a, - 0xc2, 0x8d, 0x1b, 0x37, 0xb2, 0x74, 0x61, 0x61, 0xa1, 0x80, 0xb1, 0x04, 0xaf, 0xcc, 0xec, 0xd9, - 0xb3, 0x79, 0xd2, 0x32, 0x76, 0x5c, 0x69, 0xc7, 0x04, 0xaa, 0x3a, 0xa8, 0x95, 0x35, 0xce, 0x39, - 0x26, 0xc8, 0x92, 0xf9, 0x50, 0xdb, 0xe1, 0xa1, 0x5d, 0x61, 0x08, 0x6e, 0x5d, 0x53, 0x60, 0xd2, - 0x0b, 0xb9, 0xd0, 0xb4, 0x8d, 0x64, 0x6a, 0xad, 0x49, 0x78, 0xb3, 0x20, 0xf8, 0xe5, 0xb3, 0xe5, - 0xda, 0x62, 0x45, 0xa5, 0xd2, 0x1b, 0xf3, 0x4a, 0x99, 0x80, 0x97, 0xc6, 0x85, 0x59, 0xbc, 0xea, - 0xa7, 0x61, 0x90, 0xa5, 0x12, 0xb0, 0x0a, 0x5a, 0x89, 0xd5, 0x81, 0x1a, 0xdc, 0xd2, 0xa5, 0x4b, - 0x99, 0xde, 0x4c, 0x4f, 0xcc, 0xcb, 0x8d, 0xb0, 0x7f, 0xff, 0xfe, 0x22, 0xcf, 0xea, 0x40, 0x85, - 0x68, 0x0e, 0x41, 0x60, 0x95, 0x60, 0x12, 0xec, 0x22, 0x33, 0xe9, 0x64, 0x68, 0x2b, 0x8e, 0x95, - 0x2d, 0x53, 0xf9, 0xad, 0xb2, 0xcc, 0x8c, 0xe8, 0x55, 0x4d, 0x4f, 0x8b, 0xa0, 0x6d, 0x14, 0x54, - 0xbe, 0x6c, 0x7b, 0x0d, 0x86, 0x46, 0x65, 0xf3, 0x36, 0xe4, 0x43, 0x93, 0x02, 0xa9, 0x59, 0x6a, - 0x19, 0x60, 0xde, 0xb2, 0x06, 0xfd, 0xc7, 0x67, 0x0b, 0x86, 0xc4, 0x78, 0xc4, 0x4f, 0x72, 0x18, - 0x8b, 0xf7, 0x56, 0x46, 0x58, 0xfc, 0xe1, 0xba, 0x08, 0xfc, 0xf1, 0xa5, 0x08, 0x14, 0xdf, 0x30, - 0xe0, 0xcc, 0x41, 0xe4, 0x83, 0x64, 0x41, 0xee, 0x1f, 0x1c, 0x97, 0x60, 0x5b, 0x96, 0x95, 0xb2, - 0xec, 0xe6, 0x5f, 0xc6, 0x63, 0x5e, 0x26, 0xc7, 0x8e, 0xbb, 0x02, 0x57, 0xcc, 0x6e, 0x6c, 0x69, - 0x22, 0xbb, 0x4c, 0xac, 0xf0, 0x92, 0x0a, 0xd8, 0xb9, 0x73, 0xa7, 0x15, 0x3d, 0x0c, 0x1b, 0x36, - 0xcc, 0xb2, 0x5c, 0x75, 0xa9, 0x42, 0x4c, 0xe5, 0x99, 0x67, 0x9e, 0xa1, 0x7e, 0x21, 0xcc, 0x28, - 0xa7, 0x6b, 0xd6, 0xac, 0xa9, 0x94, 0x96, 0x96, 0xaa, 0xca, 0xeb, 0xd4, 0xa9, 0x23, 0x70, 0xeb, - 0xd7, 0xaf, 0xaf, 0x10, 0x8e, 0x4c, 0x93, 0xe0, 0x84, 0x68, 0x54, 0xc0, 0x7f, 0x44, 0xc5, 0xd3, - 0x9c, 0x40, 0xce, 0xdf, 0xb8, 0x71, 0xc3, 0xb2, 0x7c, 0xcc, 0x98, 0x31, 0x4c, 0x70, 0xf5, 0x77, - 0x72, 0xf5, 0xaf, 0x41, 0xd2, 0x66, 0x8a, 0x8e, 0xad, 0x54, 0xa8, 0xfe, 0x02, 0x4c, 0x87, 0x6b, - 0xa3, 0xa1, 0x9a, 0x6c, 0x25, 0x0f, 0xd7, 0x3c, 0x6d, 0x65, 0x43, 0x4b, 0x13, 0xc9, 0x0c, 0xe4, - 0x34, 0x9f, 0xea, 0x52, 0xfc, 0xfa, 0xb3, 0xf1, 0xc9, 0x85, 0x99, 0x10, 0x53, 0x01, 0x7d, 0x46, - 0x65, 0xeb, 0x68, 0xba, 0x0c, 0x88, 0x57, 0xb8, 0xee, 0xb7, 0xe2, 0x64, 0x14, 0x37, 0x68, 0x6a, - 0x7d, 0xc1, 0x51, 0x0d, 0x15, 0xac, 0x6f, 0x6b, 0xfe, 0x68, 0xdc, 0x37, 0xbb, 0x1e, 0x68, 0x50, - 0x0d, 0xb3, 0xa6, 0x35, 0xd0, 0xa9, 0x6f, 0x02, 0x28, 0x8f, 0x81, 0xa5, 0x99, 0x2c, 0x7b, 0xb2, - 0xd6, 0xd1, 0xb2, 0x1f, 0xe4, 0xb2, 0x99, 0xbf, 0xcd, 0x83, 0x07, 0x3b, 0x19, 0xeb, 0x6a, 0x29, - 0xc0, 0x44, 0x69, 0x47, 0x60, 0x63, 0xb1, 0x8e, 0x58, 0x58, 0x23, 0xdf, 0xe7, 0x02, 0xe8, 0x7a, - 0x7c, 0xe5, 0xca, 0x15, 0x4b, 0x1b, 0x74, 0xeb, 0xd6, 0xcd, 0xb2, 0x3c, 0x69, 0x3f, 0x18, 0x3e, - 0x7c, 0xb8, 0x61, 0xfb, 0xb6, 0x0b, 0x14, 0x3e, 0x58, 0xb7, 0x6e, 0x1d, 0x9b, 0x73, 0x2f, 0x5e, - 0xbc, 0x58, 0xcc, 0xbd, 0xb5, 0xaa, 0xcd, 0x9b, 0x37, 0x0f, 0x96, 0x2f, 0x5f, 0x0e, 0x7b, 0xf6, - 0xec, 0x61, 0x45, 0x53, 0xa7, 0x4e, 0x15, 0xb8, 0xc5, 0xc5, 0xc5, 0x2c, 0x8d, 0x93, 0x06, 0x68, - 0xd7, 0xae, 0x5d, 0x82, 0x54, 0xd6, 0xe4, 0xb1, 0xc7, 0x1e, 0x63, 0x59, 0x2c, 0x15, 0x60, 0x5e, - 0x83, 0xd3, 0xa7, 0x4f, 0x2b, 0x8d, 0x1b, 0x37, 0x56, 0x56, 0xaf, 0x5e, 0xad, 0xe0, 0xe2, 0x40, - 0x94, 0xcb, 0xb8, 0x3c, 0xcd, 0x63, 0x42, 0x4a, 0x70, 0xc2, 0x4c, 0xed, 0xda, 0xb5, 0xd9, 0x4c, - 0xe1, 0xc8, 0x91, 0x23, 0x8c, 0x01, 0x21, 0xf2, 0xdf, 0xb5, 0x6b, 0xb8, 0x08, 0x93, 0xf2, 0x8c, - 0x58, 0xca, 0xbf, 0xf3, 0xce, 0x3b, 0xac, 0x7c, 0xdc, 0xb8, 0x71, 0x2c, 0x66, 0x0c, 0xf0, 0x4f, - 0x0c, 0xd7, 0x33, 0x67, 0xce, 0x84, 0x26, 0x4d, 0x9a, 0xc0, 0xed, 0xdb, 0xb7, 0x91, 0x4f, 0x3c, - 0x60, 0x39, 0x4f, 0xb2, 0xd8, 0x69, 0x9e, 0x88, 0xfc, 0x9e, 0xac, 0x32, 0xa1, 0x51, 0x26, 0xed, - 0x26, 0x32, 0x12, 0x9a, 0x4a, 0x98, 0xe8, 0x67, 0xa9, 0x64, 0xea, 0x25, 0x2f, 0xbf, 0x02, 0x5e, - 0x5a, 0xdb, 0x48, 0x96, 0x18, 0x87, 0x8c, 0x0a, 0xcd, 0x60, 0xf2, 0x6c, 0xc2, 0x0c, 0x87, 0xc3, - 0xe5, 0x59, 0x08, 0xc1, 0x38, 0xed, 0x8b, 0xef, 0xd7, 0x80, 0xbc, 0x9a, 0x1c, 0xcb, 0x7d, 0x5c, - 0xa9, 0x26, 0x34, 0x7f, 0x63, 0x3e, 0xd0, 0x4f, 0x0e, 0x46, 0x30, 0xb9, 0x9c, 0xa7, 0xe9, 0xee, - 0x5b, 0x2a, 0x82, 0x2b, 0x0f, 0x70, 0xc1, 0x8d, 0x1f, 0xd2, 0x4f, 0x79, 0x8d, 0x60, 0xa7, 0x3e, - 0x2f, 0x87, 0xdf, 0x3f, 0xaf, 0xbe, 0xed, 0x4c, 0x37, 0xf7, 0xe4, 0x90, 0x57, 0x33, 0x00, 0x2f, - 0xbe, 0xaf, 0x36, 0x86, 0x5c, 0x6e, 0x96, 0x4e, 0xc9, 0x30, 0xca, 0x9b, 0x05, 0x09, 0xd1, 0x36, - 0x19, 0xad, 0x60, 0x8e, 0x6b, 0xe7, 0x26, 0x93, 0x96, 0xd6, 0x28, 0x5f, 0xa9, 0x26, 0x64, 0xc4, - 0xd0, 0x2e, 0xac, 0xf4, 0x5e, 0x6a, 0x9a, 0x90, 0x6b, 0x0f, 0xfc, 0xf9, 0x95, 0x08, 0x7c, 0xbe, - 0x23, 0x6a, 0xaa, 0xef, 0x03, 0xad, 0x82, 0xf0, 0xec, 0x7a, 0xcd, 0xc3, 0x07, 0xc4, 0xe6, 0x1e, - 0x30, 0x23, 0x4c, 0xe6, 0x41, 0x2d, 0x9d, 0xeb, 0x0a, 0x68, 0x19, 0x39, 0xcd, 0xdf, 0xbd, 0x05, - 0xf0, 0xdf, 0x03, 0x31, 0x68, 0xd8, 0x2c, 0x00, 0x2d, 0x71, 0x4d, 0x14, 0x74, 0xd9, 0x16, 0x32, - 0x56, 0x01, 0xa7, 0x15, 0x36, 0xc3, 0x77, 0x59, 0x6f, 0x33, 0x76, 0xde, 0xc3, 0xfd, 0x0a, 0x78, - 0x6f, 0x73, 0xb5, 0x44, 0xd7, 0x1e, 0x98, 0x3f, 0x7f, 0x3e, 0x5b, 0xe5, 0xd1, 0x03, 0x99, 0x11, - 0x23, 0x46, 0xa8, 0xb9, 0x3a, 0xc8, 0x11, 0xbd, 0xfc, 0xc4, 0xc7, 0x01, 0x69, 0x1c, 0x95, 0x2f, - 0xce, 0xe4, 0xb8, 0x45, 0x8b, 0x16, 0x6c, 0xe1, 0xb6, 0x63, 0xc7, 0x0e, 0x16, 0x23, 0x26, 0x5b, - 0x10, 0x96, 0x97, 0xeb, 0x9f, 0xa5, 0x51, 0x19, 0x5f, 0x79, 0xca, 0x3c, 0x66, 0xcc, 0x98, 0x21, - 0x68, 0x09, 0xa7, 0x7b, 0xf7, 0xee, 0x72, 0x31, 0x4b, 0x13, 0x9c, 0xff, 0xe4, 0xc2, 0xa3, 0x47, - 0x8f, 0x0a, 0xf8, 0xa0, 0x41, 0x83, 0x44, 0xfa, 0xde, 0xbd, 0x7b, 0x32, 0x5a, 0x9c, 0x87, 0x0e, - 0x52, 0x01, 0x20, 0xc6, 0x6d, 0xdb, 0xb6, 0x15, 0xc5, 0xf4, 0x08, 0x95, 0x60, 0xb4, 0x7a, 0x95, - 0x03, 0xc1, 0x8c, 0x2a, 0x40, 0x37, 0xe5, 0xe7, 0xcc, 0x99, 0xa3, 0xd0, 0x52, 0x7b, 0xfa, 0xf4, - 0xe9, 0x8c, 0x76, 0xd9, 0xb2, 0x65, 0x32, 0x29, 0x4b, 0xf7, 0xea, 0xd5, 0x8b, 0x95, 0x69, 0x0b, - 0xfa, 0xf5, 0xeb, 0xa7, 0x82, 0x1b, 0x55, 0x94, 0x68, 0x54, 0xcb, 0x6e, 0x99, 0x09, 0x27, 0x38, - 0x77, 0xee, 0x9c, 0x42, 0x35, 0xe7, 0x79, 0x19, 0x87, 0x31, 0x30, 0xa8, 0x00, 0x29, 0x4e, 0xf8, - 0x67, 0xce, 0x9c, 0x61, 0xe8, 0xfc, 0xc6, 0xbf, 0x7c, 0x3f, 0x80, 0xf3, 0x49, 0x6b, 0x05, 0x70, - 0xa9, 0xcf, 0xe5, 0xb8, 0x8a, 0xb7, 0x6f, 0xdf, 0xae, 0x5c, 0xbd, 0x7a, 0xd5, 0x15, 0xad, 0x5d, - 0x22, 0xc3, 0x0b, 0x99, 0xb6, 0x53, 0x21, 0x33, 0x34, 0x68, 0xd5, 0x0c, 0x86, 0xd3, 0xe9, 0xaa, - 0xac, 0xb0, 0xd6, 0x8c, 0xae, 0x87, 0x51, 0x2d, 0xa3, 0x4c, 0xe5, 0xab, 0x7d, 0x05, 0x0c, 0xfb, - 0x40, 0xa6, 0xac, 0xe9, 0x46, 0x6e, 0xb5, 0xf7, 0x80, 0x5f, 0x01, 0x37, 0x6e, 0x4f, 0x25, 0x8d, - 0xef, 0x81, 0x54, 0x5a, 0xd3, 0x0d, 0x2f, 0xdf, 0x03, 0x6e, 0xac, 0x96, 0x4a, 0x1a, 0xcf, 0x3d, - 0x40, 0x77, 0x23, 0x52, 0x19, 0x0c, 0xe7, 0x42, 0x56, 0x02, 0xce, 0xfd, 0xbb, 0x1c, 0xd6, 0x2f, - 0x50, 0xdf, 0x26, 0x34, 0xc3, 0x1f, 0x33, 0x3b, 0x07, 0xfa, 0x8e, 0x4d, 0x88, 0xd8, 0x58, 0x54, - 0x0a, 0x67, 0x8e, 0xc4, 0xd8, 0x0a, 0x6c, 0xe9, 0x3f, 0x9c, 0xdf, 0x46, 0x34, 0x92, 0xe3, 0xd8, - 0x03, 0x27, 0x3e, 0xc5, 0x27, 0xe8, 0x36, 0xc3, 0x7f, 0xf6, 0xa9, 0x71, 0x6f, 0x56, 0xdc, 0xd0, - 0x4d, 0xe5, 0x64, 0x31, 0x61, 0x1e, 0x9b, 0x4a, 0xdd, 0xbb, 0x1d, 0x9f, 0x5a, 0x77, 0x7c, 0x24, - 0x04, 0x23, 0xa6, 0xe7, 0x40, 0xa4, 0x44, 0x81, 0xd7, 0x7e, 0x16, 0xf7, 0xc8, 0x84, 0x9f, 0xe7, - 0x42, 0xf3, 0xb6, 0x41, 0xf8, 0xec, 0xef, 0x51, 0xd8, 0xf3, 0x6e, 0x19, 0x84, 0x8b, 0xd3, 0x3f, - 0x0d, 0x77, 0x5e, 0x81, 0x3b, 0xf1, 0x9a, 0xd6, 0x6b, 0x1c, 0x04, 0xba, 0x13, 0x1d, 0x09, 0x27, - 0xee, 0x50, 0x37, 0x78, 0x20, 0xc0, 0x60, 0x8d, 0x5a, 0xc4, 0x61, 0xe1, 0xe2, 0x38, 0xee, 0x67, - 0xdb, 0x62, 0xf0, 0xe9, 0x47, 0x65, 0x70, 0xfb, 0x7a, 0xa2, 0x42, 0x7c, 0xe7, 0x08, 0x61, 0x34, - 0x6c, 0x16, 0x84, 0x1f, 0x2c, 0x8a, 0x6f, 0x00, 0x8c, 0x53, 0xd8, 0xff, 0x77, 0x5c, 0x81, 0x58, - 0x24, 0xae, 0x44, 0xae, 0xc5, 0xc3, 0x89, 0x5a, 0x75, 0xe3, 0x15, 0x88, 0xc6, 0x37, 0x23, 0xc2, - 0x7b, 0x2b, 0xf5, 0x5b, 0x5b, 0x2e, 0x9c, 0x2c, 0x17, 0x5a, 0x52, 0xda, 0xb3, 0x0a, 0x3c, 0xb9, - 0x30, 0x17, 0x36, 0x14, 0x95, 0xc0, 0x90, 0xa7, 0xf5, 0xdb, 0x66, 0xb8, 0x46, 0x5d, 0x06, 0x84, - 0x80, 0x6e, 0xee, 0x7e, 0xbf, 0x28, 0x6e, 0xd5, 0x1f, 0x2f, 0xcb, 0x83, 0xfd, 0x1f, 0x46, 0xe1, - 0xd4, 0xe7, 0x31, 0xd6, 0xe4, 0x08, 0xaf, 0x73, 0xbf, 0x84, 0xed, 0x3a, 0xf4, 0x76, 0xdc, 0x15, - 0xb9, 0xa8, 0xca, 0x3f, 0x89, 0x8e, 0xe0, 0x73, 0x8a, 0x17, 0xc7, 0xc6, 0xf7, 0x3e, 0xcf, 0x58, - 0x99, 0x07, 0x0f, 0x75, 0x31, 0x57, 0xe6, 0x95, 0xa7, 0x4b, 0xe0, 0x7f, 0x97, 0xe2, 0x96, 0x77, - 0x7a, 0x17, 0x5a, 0x68, 0xac, 0x49, 0x98, 0x4b, 0xd3, 0x20, 0x56, 0xd5, 0xac, 0xa7, 0x15, 0xc0, - 0x9b, 0x70, 0x29, 0x0f, 0x9e, 0x56, 0x20, 0xaf, 0x96, 0xb1, 0xfe, 0x74, 0xbd, 0x78, 0x69, 0x6c, - 0x18, 0x2e, 0x9e, 0x4a, 0x8c, 0x52, 0xc6, 0x98, 0x7a, 0xa8, 0xeb, 0x25, 0xa5, 0x9b, 0x27, 0x2d, - 0x7b, 0xdf, 0x8f, 0xc2, 0xd6, 0xd7, 0x2b, 0x86, 0x26, 0xbd, 0x2e, 0xd0, 0xb4, 0x75, 0x10, 0xe6, - 0xbe, 0xa1, 0x7f, 0xaa, 0x63, 0x80, 0x2a, 0x40, 0x69, 0xf3, 0x40, 0xb4, 0x4c, 0xc8, 0x10, 0x89, - 0xfe, 0xe3, 0xb3, 0xa0, 0x7e, 0x13, 0x63, 0x91, 0x4d, 0x1e, 0x72, 0xae, 0x3c, 0x31, 0x76, 0xed, - 0x01, 0xa1, 0x95, 0xcb, 0xc4, 0x17, 0xc7, 0xca, 0x71, 0x97, 0xba, 0x82, 0xa7, 0x34, 0x6c, 0xec, - 0x50, 0xb4, 0x90, 0x91, 0xb1, 0x0a, 0x58, 0xe8, 0xe4, 0xa8, 0xc8, 0xd8, 0x9f, 0x8e, 0x58, 0x64, - 0x16, 0xd9, 0xaf, 0x40, 0x66, 0xed, 0x9f, 0xe4, 0xc8, 0x48, 0xa6, 0x95, 0xb3, 0x23, 0xdf, 0x6f, - 0x42, 0x76, 0xac, 0x94, 0x4e, 0x9c, 0x6a, 0xef, 0x81, 0xc4, 0xa4, 0xdc, 0xa1, 0x99, 0xf0, 0xd9, - 0x19, 0x9c, 0x3d, 0x7b, 0x96, 0x51, 0x3d, 0xf1, 0xc4, 0x13, 0x0e, 0xa9, 0x13, 0xe8, 0xf4, 0x34, - 0x28, 0x1a, 0x8d, 0x42, 0x28, 0x14, 0x4a, 0x00, 0x1d, 0xa4, 0x5c, 0x5f, 0xc8, 0xe4, 0xc7, 0x50, - 0x6e, 0x17, 0xe9, 0xf8, 0xf0, 0x0f, 0x1a, 0x34, 0x68, 0x00, 0x17, 0x2e, 0x5c, 0x80, 0x66, 0xcd, - 0x9a, 0x39, 0x50, 0x3b, 0x81, 0xea, 0xba, 0x09, 0x91, 0xd2, 0x0b, 0x16, 0x2c, 0x48, 0x70, 0x72, - 0x91, 0xc2, 0x33, 0x50, 0xf4, 0x94, 0xd4, 0xb5, 0xf2, 0x24, 0x52, 0x57, 0x01, 0x72, 0x27, 0x59, - 0x97, 0x7e, 0x43, 0x87, 0x0e, 0x15, 0x69, 0xda, 0xbf, 0x6d, 0x37, 0xdc, 0xbd, 0x7b, 0x17, 0xb2, - 0xb3, 0xb3, 0x05, 0x2d, 0xf1, 0x3a, 0x74, 0xe8, 0x90, 0x8a, 0xfc, 0xa9, 0xa7, 0x9e, 0x12, 0xe5, - 0xeb, 0xd7, 0xaf, 0x57, 0x95, 0xe1, 0xc1, 0x2e, 0x56, 0x46, 0xfb, 0xc0, 0xb9, 0x2e, 0x93, 0x26, - 0x4d, 0x52, 0xe1, 0x88, 0x0c, 0x5a, 0x40, 0x17, 0xe8, 0x01, 0x37, 0x22, 0x28, 0xc1, 0x60, 0x50, - 0xd9, 0xbc, 0x79, 0xb3, 0x82, 0x6e, 0x66, 0xf9, 0xb7, 0xde, 0x7a, 0x4b, 0x85, 0x8b, 0x1e, 0x60, - 0x70, 0x15, 0x10, 0x33, 0x1f, 0x7f, 0xfc, 0xb1, 0xd2, 0xb2, 0x65, 0x4b, 0x16, 0xe3, 0xc6, 0x73, - 0x86, 0x43, 0xfc, 0xe4, 0x40, 0x8f, 0x60, 0x47, 0x8e, 0x1c, 0xc9, 0xca, 0x56, 0xae, 0x5c, 0x29, - 0x17, 0x29, 0xcf, 0x3d, 0xf7, 0x9c, 0xa0, 0xa1, 0x67, 0xce, 0x79, 0x79, 0x79, 0x86, 0x72, 0x88, - 0x48, 0xcd, 0xb5, 0x82, 0xcd, 0xc2, 0x85, 0x0b, 0x75, 0x04, 0xa4, 0x80, 0x56, 0x09, 0xb3, 0x0a, - 0x10, 0x9b, 0xb7, 0xdf, 0x7e, 0x5b, 0xa1, 0xbd, 0xe6, 0xf4, 0x14, 0xbf, 0xa0, 0xa0, 0x40, 0x47, - 0x5b, 0x21, 0x8a, 0xc1, 0xb5, 0x15, 0xa0, 0x32, 0x92, 0xf5, 0xf8, 0xe3, 0x8f, 0x33, 0x34, 0xbe, - 0xf5, 0x00, 0xfb, 0x0a, 0xcb, 0xcb, 0x7f, 0xba, 0x26, 0x84, 0x84, 0x95, 0x0e, 0xf5, 0xea, 0xd5, - 0x83, 0x29, 0x53, 0xa6, 0x40, 0xa3, 0x46, 0x8d, 0x00, 0xf7, 0x4c, 0xb0, 0x66, 0xe0, 0x86, 0x29, - 0x1f, 0xdd, 0x88, 0x1f, 0x05, 0xdc, 0xbe, 0xa0, 0x63, 0x63, 0x59, 0x81, 0x47, 0x1f, 0x7d, 0x94, - 0x11, 0x90, 0x12, 0x14, 0x66, 0xcd, 0x9a, 0xc5, 0xe2, 0x64, 0x7f, 0xb7, 0x6e, 0xdd, 0xc2, 0x2d, - 0x64, 0x41, 0xa0, 0x33, 0xec, 0x63, 0xc7, 0x8e, 0x85, 0xba, 0x75, 0xeb, 0x26, 0x23, 0x71, 0x5f, - 0x2e, 0xbb, 0x83, 0xa7, 0x79, 0x13, 0x42, 0xae, 0xcc, 0x95, 0x14, 0xe3, 0x71, 0x10, 0x5e, 0xac, - 0xa0, 0x42, 0x02, 0x2e, 0xe3, 0xe0, 0x01, 0x7c, 0x86, 0xd3, 0xb4, 0x69, 0x53, 0x55, 0x39, 0x6f, - 0xc3, 0x84, 0x4b, 0x61, 0xdf, 0xbe, 0x7d, 0xaa, 0x72, 0xce, 0xa3, 0x4d, 0x9b, 0x36, 0xac, 0x9c, - 0xe7, 0x29, 0xe6, 0xfb, 0x2c, 0x38, 0x8c, 0x21, 0x48, 0x7f, 0x96, 0x17, 0x32, 0xc4, 0x43, 0x3a, - 0x7d, 0xb8, 0x79, 0xf3, 0xa6, 0x1e, 0x28, 0x41, 0x2e, 0x5e, 0xbc, 0xc8, 0x2e, 0x72, 0xe7, 0xcf, - 0x9f, 0x07, 0xdc, 0xad, 0x22, 0x95, 0xc4, 0x93, 0x7d, 0xfb, 0xf6, 0x65, 0xc3, 0xa7, 0xae, 0xa0, - 0x02, 0xa0, 0x95, 0xab, 0xcd, 0xab, 0xe8, 0xa4, 0xca, 0xb0, 0x24, 0x1e, 0xce, 0x51, 0x3a, 0x76, - 0xec, 0xc8, 0x2c, 0x84, 0x43, 0x97, 0xb2, 0x77, 0xef, 0x5e, 0x2d, 0x4a, 0x95, 0xca, 0xeb, 0x46, - 0xa1, 0x21, 0x43, 0x86, 0xa8, 0xdc, 0x3b, 0x7e, 0xfc, 0xf8, 0x2a, 0xa5, 0xb0, 0x56, 0x19, 0xd7, - 0x53, 0x09, 0x95, 0x1b, 0x33, 0x98, 0xb1, 0x1c, 0x85, 0x32, 0xa8, 0x97, 0x6d, 0xd1, 0x7e, 0x05, - 0x6c, 0x9b, 0x2a, 0x4d, 0x88, 0xbe, 0x07, 0xd2, 0x64, 0x58, 0xdb, 0x6c, 0xab, 0xfd, 0x28, 0x64, - 0xbb, 0xa6, 0x55, 0x14, 0xb1, 0xda, 0x77, 0x81, 0x2a, 0x6a, 0x57, 0xdb, 0x6a, 0xf9, 0x0e, 0xb0, - 0x6d, 0xaa, 0xf4, 0x20, 0xfa, 0x0e, 0x48, 0x8f, 0x5d, 0x6d, 0x73, 0xf5, 0x1d, 0x60, 0xdb, 0x54, - 0xe9, 0x41, 0xf4, 0x1d, 0x90, 0x1e, 0xbb, 0xda, 0xe6, 0xea, 0x3b, 0xc0, 0xb6, 0xa9, 0xd2, 0x83, - 0xe8, 0x3b, 0x20, 0x3d, 0x76, 0xb5, 0xcd, 0xd5, 0xf2, 0x86, 0x96, 0x6d, 0x2e, 0x36, 0x10, 0x2f, - 0x9d, 0x56, 0xe0, 0xfa, 0x85, 0x72, 0x30, 0xda, 0x3b, 0x61, 0x83, 0x5c, 0x85, 0x12, 0xc4, 0x87, - 0x38, 0x75, 0x1b, 0x05, 0xa0, 0xa0, 0xab, 0x75, 0xfb, 0x39, 0x79, 0xb0, 0x1c, 0xfe, 0xb6, 0x21, - 0x02, 0xf8, 0x0e, 0x49, 0xa8, 0x5d, 0x3f, 0x00, 0x7d, 0x46, 0x67, 0xc3, 0x77, 0xa6, 0x78, 0x56, - 0x65, 0x95, 0xce, 0x66, 0x19, 0x4f, 0x16, 0x62, 0x7b, 0xde, 0x8d, 0xc2, 0x47, 0xeb, 0xcd, 0x77, - 0xd7, 0x98, 0x29, 0x97, 0x0c, 0xde, 0x73, 0x50, 0x16, 0x4c, 0x7c, 0xde, 0x7c, 0x93, 0xe3, 0x6f, - 0xa6, 0x95, 0x30, 0xa7, 0xcb, 0x7c, 0xe6, 0xff, 0x2e, 0x1f, 0x1a, 0x3f, 0x98, 0x86, 0x0d, 0x57, - 0xb2, 0x10, 0x07, 0x69, 0xeb, 0x26, 0xe4, 0x80, 0x91, 0x15, 0xea, 0x8d, 0x2b, 0xc6, 0xb7, 0x86, - 0xad, 0x68, 0xec, 0x94, 0x25, 0xe3, 0x5b, 0x9e, 0xd8, 0xcf, 0x29, 0xd8, 0x29, 0x06, 0x30, 0x51, - 0x98, 0x81, 0x84, 0x27, 0xfd, 0x91, 0xef, 0x51, 0xe6, 0xf5, 0x7b, 0x78, 0x58, 0x16, 0x3c, 0xb9, - 0x30, 0xd1, 0x72, 0xe5, 0xfd, 0x9a, 0x1c, 0x87, 0x62, 0xed, 0xde, 0xcd, 0x7d, 0x7f, 0x8d, 0x02, - 0xbd, 0xc7, 0x93, 0x87, 0xf0, 0x9d, 0xf4, 0x38, 0x96, 0xf3, 0xf7, 0x22, 0xf6, 0xc4, 0x01, 0x5a, - 0x43, 0xd1, 0x9b, 0x3b, 0xdc, 0x84, 0xbc, 0x1a, 0x6a, 0x3a, 0x79, 0x43, 0x79, 0x18, 0xf7, 0x71, - 0x2f, 0x99, 0x10, 0x86, 0x58, 0xcc, 0xda, 0x29, 0xda, 0xb7, 0x88, 0x68, 0xf5, 0xe8, 0xd0, 0x3b, - 0x04, 0x3f, 0x5a, 0x92, 0xab, 0x05, 0xa7, 0x2d, 0xef, 0xc9, 0x10, 0xd4, 0xe6, 0xdb, 0xea, 0xad, - 0x0f, 0xad, 0x7b, 0xba, 0x13, 0xdb, 0xac, 0x9d, 0x9a, 0xae, 0x75, 0xf7, 0x04, 0xdf, 0x2c, 0xec, - 0x50, 0xa1, 0x44, 0xa7, 0x72, 0x6d, 0x30, 0xb7, 0x8d, 0xc3, 0xad, 0x40, 0x4f, 0x2e, 0xc2, 0xc9, - 0x94, 0xb3, 0x3b, 0x04, 0x25, 0xe3, 0xa3, 0x2d, 0x97, 0xb7, 0x97, 0xf3, 0xb2, 0x54, 0xbd, 0x86, - 0x86, 0xf3, 0xab, 0x6c, 0xac, 0x6e, 0x52, 0x95, 0xe5, 0xe6, 0xd3, 0x3b, 0xb6, 0x80, 0xef, 0x00, - 0xc7, 0x26, 0x4b, 0x2d, 0xc1, 0x7d, 0xed, 0x80, 0x6c, 0x83, 0x6b, 0xc2, 0xf5, 0xf3, 0xc9, 0xe7, - 0xa1, 0x26, 0x1b, 0x2a, 0x52, 0x6b, 0xf9, 0x0a, 0x6e, 0x9e, 0xcc, 0x82, 0x64, 0xcd, 0x69, 0x25, - 0x4c, 0x1b, 0xed, 0xe9, 0x00, 0x63, 0x19, 0x7b, 0x81, 0x38, 0x40, 0xcc, 0xe4, 0xbd, 0x56, 0x9f, - 0x6e, 0x8d, 0xc2, 0xf1, 0xfd, 0xf1, 0x99, 0x0f, 0x6d, 0x61, 0x6c, 0xd1, 0x21, 0x08, 0xad, 0x7b, - 0x84, 0x20, 0x37, 0xfe, 0xfa, 0x7a, 0x99, 0xad, 0x61, 0xba, 0x51, 0xcb, 0x20, 0x5c, 0xf9, 0x42, - 0x6d, 0xf0, 0x3f, 0x2d, 0x8e, 0xc0, 0xc3, 0xc3, 0x43, 0xd0, 0xa9, 0x6f, 0x08, 0xdf, 0x6a, 0x17, - 0x80, 0x1b, 0x97, 0x15, 0x38, 0x7b, 0x34, 0x06, 0xc7, 0xf6, 0xc6, 0x40, 0x3b, 0x5b, 0xeb, 0xd4, - 0x37, 0x0b, 0x7e, 0xf8, 0x2b, 0x03, 0x2f, 0x1a, 0x4a, 0x73, 0x07, 0xf4, 0xfc, 0x22, 0xfc, 0xeb, - 0xef, 0x85, 0x2b, 0x7d, 0x1e, 0xb1, 0x68, 0x53, 0x3e, 0x7b, 0x11, 0x57, 0xb2, 0x2a, 0x97, 0xe1, - 0x6e, 0xae, 0xe5, 0x53, 0xc3, 0x50, 0x7c, 0xd3, 0x7a, 0x6a, 0x6a, 0xc4, 0x27, 0x18, 0x0c, 0xc0, - 0xa4, 0x5f, 0xe4, 0x40, 0xb7, 0x81, 0x89, 0x99, 0x96, 0x11, 0x5e, 0x65, 0x61, 0x9e, 0x3b, 0x80, - 0xde, 0xf0, 0xf7, 0xaf, 0xbf, 0x94, 0xc1, 0xd9, 0x23, 0xd8, 0x03, 0x2a, 0x8e, 0x30, 0xda, 0xa9, - 0x44, 0x30, 0x14, 0x80, 0x16, 0xed, 0x83, 0x50, 0x38, 0x2c, 0x04, 0x8f, 0x7c, 0xd7, 0x59, 0xc7, - 0x8d, 0xe0, 0xb9, 0xd4, 0xed, 0x7f, 0x28, 0x83, 0x43, 0xff, 0x8c, 0x82, 0x76, 0x51, 0xc8, 0x65, - 0xd7, 0xac, 0x13, 0x80, 0x8e, 0xd8, 0x2b, 0xba, 0xf6, 0x0f, 0x41, 0x7b, 0x5c, 0x0b, 0xd0, 0xfd, - 0x26, 0x2f, 0x82, 0xe7, 0x0e, 0xf0, 0xa2, 0x52, 0xd5, 0x49, 0xc6, 0x7d, 0x7d, 0x11, 0xae, 0x0e, - 0x8e, 0xf0, 0x1d, 0x90, 0x61, 0x2f, 0xf9, 0x0e, 0xf0, 0x1d, 0x90, 0x61, 0x0b, 0x64, 0x58, 0xbc, - 0xdf, 0x03, 0x7c, 0x07, 0x64, 0xd8, 0x02, 0x19, 0x16, 0xef, 0xf7, 0x00, 0xdf, 0x01, 0x19, 0xb6, - 0x00, 0x8a, 0x4f, 0x76, 0x6a, 0x26, 0x9d, 0x1a, 0x7a, 0xde, 0x03, 0xd6, 0xae, 0x5d, 0x2b, 0x0e, - 0x10, 0xf2, 0x83, 0x84, 0x14, 0xd3, 0x81, 0x2c, 0xaf, 0xc3, 0x9d, 0x3b, 0x77, 0x98, 0x2e, 0x74, - 0x6a, 0x93, 0x74, 0xa0, 0xe3, 0x49, 0x5e, 0x07, 0x67, 0x6b, 0xfa, 0x14, 0x68, 0x37, 0x7a, 0xf4, - 0x68, 0xa0, 0xf3, 0x57, 0xf8, 0xf1, 0x1d, 0x38, 0x7c, 0xf8, 0x30, 0x9c, 0x3c, 0x79, 0x92, 0x71, - 0x8d, 0x44, 0x12, 0xcf, 0x7a, 0x53, 0x20, 0xc6, 0x16, 0x0b, 0xfc, 0x76, 0x0f, 0xe0, 0x79, 0x48, - 0xd8, 0xbd, 0x7b, 0x37, 0xf4, 0xee, 0xdd, 0x9b, 0x7d, 0x6a, 0xc7, 0x16, 0x61, 0x0a, 0x91, 0x6c, - 0xdf, 0x8a, 0xc0, 0x77, 0x4a, 0x33, 0x63, 0xd1, 0x79, 0x45, 0x3c, 0x79, 0x07, 0xed, 0xdb, 0xb7, - 0x07, 0x82, 0x1d, 0x3b, 0x76, 0x0c, 0x0e, 0x1c, 0x38, 0x00, 0x64, 0xc0, 0xae, 0x5d, 0xbb, 0x42, - 0x8f, 0x1e, 0x3d, 0x00, 0xbf, 0x8b, 0x68, 0x4b, 0x45, 0x3c, 0x11, 0x08, 0x2b, 0x56, 0xac, 0x60, - 0xb8, 0x78, 0x28, 0x14, 0xb6, 0x6d, 0xdb, 0x66, 0x8b, 0x8e, 0x3e, 0xbd, 0x84, 0xe7, 0xd7, 0x00, - 0xdf, 0x9a, 0xcc, 0x86, 0x0f, 0x3a, 0x22, 0xdc, 0xbc, 0x79, 0x73, 0xc0, 0x93, 0x7e, 0x30, 0x70, - 0xe0, 0x40, 0x5b, 0x67, 0x33, 0xbf, 0xfa, 0xea, 0x2b, 0xa0, 0x03, 0xd7, 0x3c, 0x64, 0x65, 0x65, - 0x41, 0x87, 0x0e, 0x1d, 0x2c, 0x4f, 0x8e, 0x53, 0xdd, 0xa9, 0xc1, 0x50, 0xbd, 0xf3, 0xf3, 0xf3, - 0xd9, 0x67, 0x9f, 0xb8, 0x0d, 0xf6, 0xef, 0xdf, 0xcf, 0xe0, 0x3d, 0x7b, 0xf6, 0x84, 0x3e, 0x7d, - 0xfa, 0x70, 0xb6, 0xc9, 0x63, 0xed, 0xb9, 0x31, 0xa3, 0xfc, 0xa5, 0x4b, 0x97, 0x14, 0xec, 0xa2, - 0x74, 0x4b, 0x51, 0xfc, 0xe8, 0xe3, 0x93, 0x72, 0x5e, 0x9b, 0x9e, 0x30, 0x61, 0x82, 0x11, 0x2b, - 0x15, 0x8c, 0x9f, 0xd6, 0x25, 0x5a, 0xa3, 0x77, 0x6b, 0xab, 0x90, 0x31, 0xb3, 0x6a, 0xd5, 0x2a, - 0x9d, 0x4c, 0xfa, 0x02, 0x15, 0xff, 0xf0, 0x25, 0xd7, 0xa1, 0x4b, 0x97, 0x2e, 0x0a, 0x36, 0x08, - 0x2d, 0xb9, 0xc8, 0x77, 0xee, 0xdc, 0x59, 0xc7, 0x87, 0x68, 0x8d, 0x4e, 0xfd, 0x72, 0xa2, 0x2d, - 0x5b, 0xb6, 0xe8, 0x68, 0xf0, 0xe3, 0x54, 0x3a, 0x18, 0xd7, 0x01, 0x1b, 0x16, 0x27, 0xb5, 0x8c, - 0x75, 0x07, 0x0d, 0xad, 0xb0, 0xb5, 0x67, 0x58, 0xdf, 0x7c, 0xf3, 0x4d, 0x15, 0xfa, 0xa9, 0x53, - 0xa7, 0x94, 0x1a, 0x35, 0x6a, 0x08, 0xa5, 0xe8, 0xcc, 0xb6, 0x55, 0x70, 0xea, 0x00, 0xe2, 0x15, - 0x0e, 0x87, 0x15, 0x6c, 0x75, 0x3a, 0xb6, 0x64, 0x70, 0x3c, 0x55, 0x2c, 0x64, 0x6f, 0xda, 0xb4, - 0x49, 0x87, 0x63, 0x04, 0xe0, 0xef, 0x15, 0x4f, 0xe6, 0x00, 0x4e, 0xcb, 0x5f, 0x98, 0x4e, 0xf8, - 0x74, 0x9e, 0x9d, 0x9f, 0xcf, 0xa5, 0x72, 0xb2, 0x07, 0x77, 0x00, 0xbe, 0x83, 0x41, 0xc1, 0x9e, - 0xc9, 0xc9, 0x4c, 0x63, 0xd7, 0x17, 0x61, 0xba, 0x68, 0x4e, 0x9b, 0x36, 0x0d, 0xe5, 0x25, 0x02, - 0x0d, 0x01, 0x7c, 0x48, 0x21, 0x28, 0x75, 0x73, 0x1a, 0x2a, 0x52, 0x15, 0x76, 0xed, 0xda, 0x05, - 0xad, 0x5a, 0xb5, 0x62, 0x27, 0xa9, 0xe5, 0x0b, 0x38, 0xa5, 0x73, 0x72, 0x72, 0x54, 0xb3, 0x19, - 0x2f, 0x2e, 0xa8, 0x8b, 0x16, 0x2d, 0x02, 0x6c, 0x64, 0xa2, 0x7a, 0x83, 0x07, 0x0f, 0x16, 0xe9, - 0x58, 0x2c, 0x06, 0xf2, 0xd7, 0xcb, 0x45, 0x81, 0x26, 0xe1, 0xda, 0x01, 0xf8, 0xc6, 0x01, 0x9d, - 0x00, 0x74, 0x33, 0x3b, 0x62, 0xce, 0x65, 0xd0, 0xb5, 0x80, 0x3e, 0x6f, 0x9d, 0x8a, 0x80, 0x5f, - 0xca, 0x03, 0x3a, 0x3f, 0x7f, 0xf9, 0xf2, 0x65, 0xc6, 0xee, 0xf8, 0xf1, 0xe3, 0xec, 0xc0, 0x34, - 0xc9, 0xe4, 0x3f, 0xba, 0x8e, 0x78, 0x19, 0xb4, 0x6f, 0x1a, 0xa1, 0x86, 0xe0, 0x38, 0x98, 0xf6, - 0x0d, 0x83, 0x02, 0xed, 0x10, 0x84, 0xc2, 0x58, 0x97, 0xa3, 0x8f, 0x41, 0xe0, 0x3b, 0x2e, 0x44, - 0xf7, 0x23, 0x38, 0x5e, 0x14, 0x15, 0x3c, 0xf7, 0xaf, 0xe2, 0xb2, 0x64, 0xc9, 0x12, 0xa5, 0x53, - 0xa7, 0x4e, 0x0a, 0xe1, 0xd3, 0xaf, 0x56, 0xad, 0x5a, 0x82, 0x86, 0x8e, 0xd4, 0x73, 0x38, 0x1d, - 0x9b, 0xa7, 0xef, 0x29, 0xc8, 0x61, 0xcd, 0x9a, 0x35, 0x02, 0x97, 0xf8, 0x17, 0x16, 0x16, 0x2a, - 0xaf, 0xbe, 0xfa, 0xaa, 0x82, 0xef, 0xcb, 0x50, 0xe6, 0xce, 0x9d, 0xab, 0x1a, 0x7e, 0xa8, 0xbc, - 0x61, 0xc3, 0x86, 0x4a, 0x51, 0x51, 0x91, 0xcc, 0x82, 0x7d, 0x44, 0x99, 0xae, 0x4d, 0xd8, 0x8b, - 0x84, 0x2c, 0x59, 0x6f, 0x1a, 0xc2, 0xb8, 0x0e, 0xf4, 0x31, 0x0a, 0x7c, 0xcf, 0x87, 0xa0, 0xa7, - 0x6f, 0x42, 0xd0, 0x39, 0x70, 0x2d, 0x3e, 0xbd, 0xd2, 0x82, 0xc2, 0xd6, 0xad, 0x5b, 0x59, 0xdd, - 0xb8, 0x4d, 0x28, 0xc6, 0x8b, 0xba, 0xf2, 0xc1, 0x07, 0x1f, 0x08, 0x1e, 0x46, 0x09, 0xd7, 0xd3, - 0x50, 0xfa, 0x42, 0xe2, 0xc4, 0x89, 0x13, 0x81, 0x5e, 0x46, 0x72, 0xe2, 0xc4, 0x09, 0x36, 0x33, - 0x42, 0xa5, 0x01, 0xc7, 0x48, 0x40, 0xa5, 0x20, 0x37, 0x57, 0xbf, 0xbb, 0xec, 0xeb, 0xaf, 0xbf, - 0x66, 0x53, 0x50, 0x9a, 0x7f, 0x6b, 0x43, 0x49, 0x49, 0x09, 0x2b, 0x23, 0x38, 0x0d, 0x27, 0x78, - 0xe1, 0x57, 0xa1, 0x10, 0xcf, 0x01, 0x03, 0x06, 0xb0, 0x97, 0x3e, 0x7c, 0xf2, 0xc9, 0x27, 0x70, - 0xf0, 0xe0, 0x41, 0xf6, 0x23, 0xa4, 0x82, 0x82, 0x02, 0x78, 0xf9, 0xe5, 0x97, 0x61, 0xf2, 0xe4, - 0xc9, 0x30, 0x6a, 0xd4, 0x28, 0xc0, 0xf7, 0x21, 0x00, 0x7e, 0x8f, 0x82, 0x0d, 0x81, 0x32, 0x13, - 0x9a, 0xb1, 0xd0, 0xd0, 0x44, 0x43, 0x23, 0xcd, 0x9c, 0xb4, 0x81, 0x16, 0x64, 0x7c, 0x51, 0x46, - 0x2f, 0x4e, 0x21, 0x7d, 0x79, 0x28, 0x2b, 0x2b, 0x63, 0x79, 0x99, 0x8e, 0x74, 0xbe, 0x7e, 0xfd, - 0x3a, 0x43, 0xa1, 0x3a, 0xc9, 0x5f, 0x8b, 0x24, 0x20, 0xe5, 0xb5, 0x30, 0xce, 0x4f, 0xc4, 0x46, - 0x5e, 0x31, 0x83, 0xc9, 0x3d, 0xa0, 0xb2, 0xdf, 0xad, 0x30, 0x93, 0xf1, 0x4d, 0x83, 0xdb, 0x5a, - 0x07, 0xd0, 0x67, 0x4e, 0x71, 0x86, 0x23, 0x9c, 0xa6, 0x4d, 0x50, 0xcb, 0xa7, 0x45, 0x95, 0x1f, - 0x9c, 0x5b, 0xc0, 0x96, 0x03, 0xf8, 0x62, 0xc3, 0xa8, 0x3b, 0xd1, 0x32, 0x1e, 0xc7, 0x75, 0x5b, - 0x8b, 0x1f, 0xe7, 0xea, 0xdd, 0xff, 0x14, 0xb6, 0x1c, 0x70, 0xff, 0x9b, 0x21, 0x73, 0x35, 0x74, - 0x3d, 0x0d, 0xcd, 0x9c, 0xca, 0xf7, 0x97, 0x64, 0xdf, 0x01, 0x19, 0xf6, 0xa7, 0xef, 0x00, 0xdf, - 0x01, 0x19, 0xb6, 0x40, 0x86, 0xc5, 0xfb, 0x3d, 0x20, 0xc3, 0x0e, 0xf8, 0x3f, 0xb8, 0x3e, 0x1b, - 0x7a, 0x52, 0x1b, 0x0a, 0x83, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82 -}; - -static const u_int8_t FLEXHTMLIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa8, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, - 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, - 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x39, 0x54, - 0x32, 0x33, 0x3a, 0x30, 0x32, 0x3a, 0x39, 0x35, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, - 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, - 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, - 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, - 0x70, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, - 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, - 0x3a, 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, - 0x61, 0x3e, 0x0a, 0x3c, 0x50, 0x22, 0x3f, 0x00, 0x00, 0x05, 0xe7, 0x49, 0x44, 0x41, 0x54, 0x68, - 0x05, 0xed, 0x59, 0x6b, 0x4c, 0x5b, 0x55, 0x1c, 0xa7, 0xa5, 0xe5, 0xe5, 0x78, 0xb5, 0x94, 0xf2, - 0x4a, 0x00, 0x91, 0x47, 0xd8, 0x32, 0x51, 0x24, 0x7c, 0x70, 0x20, 0xf2, 0x34, 0x31, 0x13, 0x1f, - 0x0c, 0x30, 0x2c, 0xbc, 0x24, 0xca, 0xc6, 0x07, 0x1e, 0x09, 0x1f, 0xf8, 0x60, 0x42, 0x4c, 0xd0, - 0x84, 0x98, 0x98, 0xf1, 0xc5, 0x69, 0x54, 0x60, 0x3a, 0x82, 0x3a, 0x5d, 0x98, 0x24, 0xdb, 0x88, - 0x01, 0x24, 0x3a, 0x32, 0xca, 0x63, 0x4c, 0x26, 0x8f, 0x05, 0x48, 0x86, 0x06, 0x28, 0x14, 0x4a, - 0x5b, 0x1e, 0x85, 0xb6, 0xf8, 0x83, 0xa3, 0xd7, 0x6b, 0xcb, 0x6e, 0x6f, 0x7b, 0xe9, 0x08, 0xc9, - 0x3d, 0x69, 0x2e, 0xff, 0xf3, 0x3b, 0xff, 0xf7, 0xff, 0x7f, 0xce, 0x69, 0x2f, 0x82, 0xdd, 0xdd, - 0x5d, 0xa7, 0xe3, 0x3c, 0x84, 0xc7, 0xd9, 0xf9, 0x3d, 0xdf, 0xf9, 0x00, 0x8e, 0xba, 0x82, 0x7c, - 0x05, 0xf8, 0x0a, 0x70, 0xcc, 0x00, 0xdf, 0x42, 0x1c, 0x13, 0xc8, 0x59, 0x9c, 0xaf, 0x00, 0xe7, - 0x14, 0x72, 0x54, 0xc0, 0x57, 0x80, 0x63, 0x02, 0x39, 0x8b, 0xf3, 0x15, 0x38, 0x28, 0x85, 0xab, - 0x86, 0x15, 0x4b, 0x78, 0xdd, 0xa4, 0x33, 0x39, 0x99, 0x2c, 0x71, 0x8e, 0xc8, 0x21, 0x57, 0xe0, - 0xc1, 0xc6, 0x68, 0xed, 0xec, 0xc5, 0x94, 0xfb, 0xcf, 0x5b, 0xba, 0x35, 0xa0, 0xbd, 0x93, 0x3c, - 0xfa, 0xec, 0x67, 0x0b, 0x97, 0x34, 0x46, 0xb5, 0xe5, 0xaa, 0xdd, 0x88, 0xe0, 0x50, 0x7e, 0x0f, - 0x20, 0xb5, 0xb7, 0x57, 0x7f, 0x6a, 0x5e, 0xb8, 0xac, 0xd0, 0xf6, 0xc3, 0x15, 0x57, 0xa1, 0xdb, - 0xc4, 0x0b, 0x0b, 0x66, 0x3e, 0xf5, 0xac, 0x75, 0x95, 0x4e, 0xe6, 0x02, 0x74, 0x77, 0xf6, 0x78, - 0x53, 0x9a, 0x57, 0x1c, 0x50, 0xfe, 0x8c, 0x5b, 0xb4, 0x19, 0x8f, 0x1d, 0x53, 0x91, 0x1d, 0x32, - 0x74, 0x91, 0x35, 0xa3, 0xba, 0x7d, 0xa9, 0xf5, 0xeb, 0xc5, 0x2f, 0xfe, 0xd2, 0xcf, 0xd1, 0x71, - 0x06, 0x7a, 0xd3, 0xb8, 0x71, 0x55, 0xd9, 0x8c, 0xcf, 0x19, 0xef, 0x94, 0x12, 0xf9, 0x85, 0x54, - 0x9f, 0x2c, 0x06, 0x66, 0xab, 0x4b, 0xf6, 0x07, 0xf0, 0x70, 0x73, 0xa2, 0x65, 0xf1, 0xf2, 0x75, - 0xd5, 0x77, 0x70, 0x88, 0x6e, 0xc6, 0xdf, 0x25, 0xe0, 0x9c, 0x5f, 0x01, 0x1d, 0x21, 0x74, 0x8c, - 0xfb, 0xc9, 0x37, 0xfc, 0xf2, 0x6e, 0xae, 0xdc, 0xd8, 0x32, 0x6d, 0x12, 0xe4, 0xd7, 0xb5, 0x5e, - 0x7c, 0xc2, 0xdc, 0x9e, 0x2e, 0x94, 0xbf, 0x7b, 0x4e, 0x56, 0x70, 0x42, 0xe8, 0x69, 0x29, 0x65, - 0x15, 0xb1, 0xb9, 0x85, 0x76, 0x9d, 0x76, 0x7b, 0xd4, 0x5d, 0xcd, 0x8b, 0x9f, 0xc2, 0x36, 0x5d, - 0xbb, 0x58, 0x28, 0x4e, 0xf5, 0x79, 0x25, 0xd7, 0xef, 0x7c, 0x8a, 0x4f, 0x86, 0xf0, 0xf1, 0xbf, - 0x93, 0xb4, 0xc6, 0xb5, 0x0e, 0xd5, 0xb5, 0xf6, 0xa5, 0x2b, 0x0f, 0xd6, 0x47, 0xe9, 0xe2, 0x27, - 0x9c, 0x3d, 0x11, 0x43, 0x91, 0xfc, 0xbd, 0x50, 0xd7, 0x70, 0x3a, 0x6e, 0x95, 0xb6, 0x39, 0x80, - 0xe2, 0xa9, 0x9c, 0x5f, 0xd4, 0x3f, 0xd3, 0xf5, 0x46, 0x7b, 0xc4, 0xe6, 0xca, 0xce, 0xbf, 0x2e, - 0xcd, 0x93, 0x88, 0xa4, 0x74, 0x9c, 0x99, 0xfe, 0x63, 0xe3, 0x3e, 0xc2, 0x40, 0x30, 0x1a, 0xc3, - 0x7f, 0x7b, 0x5a, 0x20, 0x10, 0x7c, 0x14, 0x76, 0x29, 0x4f, 0x56, 0xc8, 0x2c, 0x4b, 0x5f, 0xb5, - 0xf9, 0x14, 0x5a, 0x35, 0xa8, 0x28, 0xf9, 0x2c, 0xc9, 0xd9, 0x8e, 0x93, 0x3d, 0xb7, 0x4e, 0xdd, - 0x29, 0x95, 0x5f, 0xb4, 0xc9, 0x7b, 0x68, 0x88, 0xf5, 0x38, 0xfd, 0x41, 0xe8, 0xc7, 0x03, 0xcf, - 0x4d, 0x7c, 0x12, 0xf1, 0x79, 0xb8, 0x5b, 0x04, 0xd1, 0x89, 0x13, 0x45, 0x65, 0x58, 0xa6, 0xf4, - 0xb3, 0x21, 0xec, 0xdf, 0x03, 0xd0, 0xde, 0xad, 0xbe, 0x85, 0x6e, 0x79, 0xdb, 0xbf, 0x38, 0xc9, - 0xeb, 0x65, 0x36, 0xc6, 0xcc, 0x78, 0xf4, 0xbb, 0x5b, 0x9d, 0xaa, 0xeb, 0xdf, 0x2e, 0x5d, 0x99, - 0xdd, 0x9a, 0x36, 0x5b, 0x62, 0x3f, 0xb5, 0x39, 0x80, 0x7c, 0x59, 0x91, 0x6a, 0x67, 0x99, 0x9c, - 0x39, 0x3b, 0xa6, 0x9d, 0x9b, 0x2b, 0x1d, 0xf8, 0x84, 0xb8, 0x86, 0xe6, 0xcb, 0x0a, 0xd1, 0xc4, - 0xfe, 0xe2, 0x00, 0x36, 0xb6, 0xff, 0xed, 0x9f, 0xef, 0x35, 0x86, 0x35, 0x3a, 0x7f, 0xa2, 0xd7, - 0x8b, 0x67, 0x6c, 0xcc, 0x85, 0xcd, 0x7b, 0x00, 0xf6, 0xcc, 0x4e, 0x7d, 0xca, 0x03, 0x91, 0x40, - 0x84, 0x33, 0x31, 0xdf, 0xbf, 0xe8, 0x25, 0xef, 0xf4, 0x03, 0xf7, 0xb1, 0xce, 0xa4, 0xbd, 0xa1, - 0xfa, 0xa1, 0x5d, 0xd9, 0xf2, 0xfb, 0xfa, 0x3d, 0x4a, 0x0a, 0x84, 0x8b, 0xd0, 0xe5, 0x35, 0x69, - 0x4e, 0x89, 0xbc, 0x1c, 0x7d, 0x45, 0xc7, 0xd9, 0xd0, 0xf6, 0x04, 0x40, 0xe9, 0x1d, 0xdb, 0xb8, - 0x87, 0xcb, 0xab, 0x73, 0xe5, 0xc7, 0x6d, 0xd3, 0x36, 0x05, 0x82, 0x08, 0x75, 0x0b, 0xef, 0x3d, - 0x3d, 0x42, 0x47, 0x40, 0x8f, 0xe8, 0x14, 0x05, 0x93, 0xd9, 0x66, 0x67, 0xae, 0x4c, 0xec, 0x5f, - 0x20, 0x7f, 0xa7, 0xc0, 0xbf, 0xd4, 0x4f, 0x24, 0x33, 0xe3, 0x67, 0x39, 0xe5, 0x14, 0x00, 0xb1, - 0xb1, 0xbc, 0xa3, 0xbc, 0xaa, 0xfc, 0xea, 0x1b, 0xe5, 0x97, 0xcb, 0x3b, 0x4b, 0x04, 0x61, 0xbe, - 0x89, 0x09, 0xcf, 0xa9, 0xa7, 0xe2, 0x4a, 0x02, 0xca, 0xcf, 0x4a, 0xde, 0x12, 0x0b, 0xc4, 0x2c, - 0x7d, 0x3d, 0x98, 0x0d, 0x1b, 0xff, 0x50, 0x86, 0xde, 0xa4, 0xbf, 0xb6, 0xd4, 0xf6, 0xea, 0x58, - 0x72, 0xd8, 0x5d, 0xef, 0x68, 0x85, 0xdc, 0x52, 0x67, 0xb7, 0xfa, 0x36, 0x96, 0x22, 0x06, 0x24, - 0x17, 0x1e, 0x16, 0xe2, 0x7b, 0x91, 0x25, 0x83, 0x7d, 0x88, 0x93, 0x7d, 0x62, 0x0c, 0x52, 0x77, - 0x35, 0xbf, 0x55, 0x4e, 0x97, 0x59, 0x32, 0x00, 0xff, 0xf0, 0xd1, 0xfb, 0x7f, 0xea, 0x1f, 0x59, - 0x2e, 0x71, 0x41, 0x0e, 0xa1, 0x85, 0x0e, 0xae, 0xec, 0x93, 0x42, 0x6d, 0xbe, 0xc8, 0x9e, 0x94, - 0x63, 0x6c, 0xed, 0xf0, 0x01, 0xb0, 0xcd, 0x94, 0xa3, 0xf8, 0xf8, 0x0a, 0x38, 0x2a, 0xb3, 0x6c, - 0xf5, 0xf2, 0x15, 0x60, 0x9b, 0x29, 0x47, 0xf1, 0x1d, 0xfb, 0x0a, 0xb0, 0xfa, 0x3a, 0x8d, 0x9b, - 0xd2, 0x68, 0x34, 0x0a, 0xf7, 0x87, 0xa3, 0x32, 0xb9, 0xaf, 0xd7, 0x60, 0x30, 0xe0, 0xaf, 0x4d, - 0x86, 0xac, 0x57, 0x60, 0x7c, 0x7c, 0x5c, 0x2a, 0x95, 0x8a, 0xc5, 0x62, 0x99, 0x8c, 0xe9, 0x0b, - 0x23, 0x6c, 0xf7, 0xf4, 0xf4, 0xcc, 0xcf, 0xcf, 0xdb, 0x17, 0xe1, 0xf4, 0xf4, 0x34, 0xb1, 0x02, - 0x43, 0x20, 0xd8, 0x2b, 0xb1, 0x1e, 0x80, 0x97, 0x97, 0x57, 0x48, 0x48, 0x08, 0x34, 0x6a, 0x34, - 0x1a, 0x06, 0xbd, 0x5d, 0x5d, 0x5d, 0xa9, 0xa9, 0xa9, 0x65, 0x65, 0x65, 0x0c, 0x3c, 0x0c, 0x4b, - 0x9e, 0x9e, 0x9e, 0xd1, 0xd1, 0xd1, 0x41, 0x41, 0x41, 0xe0, 0x59, 0x5f, 0x5f, 0x67, 0xe0, 0x34, - 0x5f, 0x62, 0xf3, 0x45, 0x6a, 0x68, 0x68, 0x08, 0x62, 0x22, 0x91, 0x88, 0x81, 0xb9, 0xa5, 0xa5, - 0x05, 0x3c, 0x09, 0x09, 0x09, 0x0c, 0x3c, 0x56, 0x97, 0x06, 0x07, 0x07, 0xa1, 0x04, 0x45, 0xb0, - 0xca, 0x49, 0x31, 0x58, 0xaf, 0x00, 0x34, 0x52, 0xa3, 0xad, 0xad, 0x2d, 0x32, 0x32, 0x12, 0xd9, - 0xca, 0xce, 0xce, 0x56, 0x2a, 0x95, 0x14, 0x8e, 0x36, 0x9b, 0x98, 0x98, 0xc0, 0x54, 0xab, 0xd5, - 0xf6, 0xee, 0x8f, 0x81, 0x81, 0x01, 0xd2, 0xd0, 0xd8, 0x3c, 0x39, 0x39, 0x39, 0x89, 0x89, 0x89, - 0x8d, 0x8d, 0x8d, 0xe9, 0xe9, 0xe9, 0x90, 0xad, 0xac, 0xac, 0xac, 0xad, 0xad, 0x95, 0x48, 0x24, - 0x59, 0x59, 0x59, 0xfd, 0xfd, 0x7b, 0x6f, 0xf2, 0x38, 0x0d, 0x2a, 0x14, 0x06, 0x82, 0x54, 0x00, - 0x66, 0x9c, 0x9d, 0x9d, 0x29, 0x63, 0x75, 0x75, 0x75, 0x44, 0x64, 0x78, 0x78, 0x98, 0x02, 0xe9, - 0x44, 0x43, 0x43, 0x03, 0x18, 0x96, 0x97, 0x99, 0xde, 0x32, 0x44, 0x45, 0x45, 0xd1, 0xed, 0x3a, - 0xbc, 0x02, 0x19, 0x19, 0x19, 0xc8, 0x74, 0x4d, 0x4d, 0x0d, 0x1c, 0xed, 0xec, 0xec, 0x24, 0xee, - 0x62, 0x87, 0x24, 0x25, 0x25, 0xc9, 0xe5, 0x72, 0x4c, 0x5d, 0x5d, 0x5d, 0x51, 0x22, 0x8c, 0xb8, - 0xb8, 0x38, 0xb4, 0x13, 0x10, 0xec, 0xc8, 0xf6, 0xf6, 0x76, 0x10, 0x38, 0x5b, 0xc6, 0xc6, 0xc6, - 0xd2, 0xd2, 0xd2, 0x40, 0x27, 0x27, 0x27, 0x4f, 0x4d, 0x4d, 0x01, 0xc1, 0x53, 0xaf, 0xd7, 0x03, - 0xb1, 0x7f, 0xd0, 0x13, 0xf0, 0x38, 0x9a, 0xaa, 0x00, 0x32, 0x04, 0x1e, 0x85, 0x42, 0x41, 0xec, - 0xad, 0xae, 0xae, 0x52, 0x22, 0x0c, 0x7b, 0x60, 0x64, 0x64, 0xef, 0xf7, 0x71, 0x4c, 0x4c, 0x0c, - 0x98, 0xab, 0xab, 0xab, 0x41, 0xd7, 0xd7, 0xd7, 0x83, 0x0e, 0x0c, 0x0c, 0x04, 0xbd, 0xb0, 0xb0, - 0x40, 0x29, 0x71, 0x6c, 0x05, 0xb0, 0x89, 0xe3, 0xe3, 0xe3, 0x61, 0x92, 0x1c, 0x4a, 0x20, 0xb6, - 0xb7, 0xff, 0xf7, 0x5b, 0x1e, 0x08, 0xc3, 0xf0, 0xf0, 0xf0, 0xc0, 0x2a, 0xde, 0xbd, 0xe1, 0x49, - 0xa7, 0x4d, 0x26, 0x4e, 0xff, 0x34, 0xb0, 0x6d, 0x13, 0x13, 0xff, 0x88, 0x13, 0x66, 0xbe, 0xa2, - 0x1f, 0x80, 0xe8, 0x74, 0x3a, 0x33, 0xdc, 0xd1, 0x53, 0x56, 0x01, 0xa0, 0xc4, 0x74, 0x3f, 0xa8, - 0x29, 0x45, 0x60, 0xd5, 0xdb, 0xdb, 0x1b, 0x4f, 0xf4, 0xf4, 0xec, 0xec, 0x2c, 0xda, 0xba, 0xbb, - 0xbb, 0xbb, 0xa2, 0xa2, 0xa2, 0xb5, 0xb5, 0x15, 0x20, 0x61, 0xa3, 0x33, 0xd3, 0x69, 0x4a, 0x33, - 0x4e, 0x2d, 0x1c, 0x59, 0x64, 0x4a, 0xa7, 0x29, 0x86, 0x83, 0x09, 0xe8, 0x62, 0x1e, 0x33, 0x33, - 0x33, 0xbe, 0xbe, 0xbe, 0x44, 0x38, 0x36, 0x36, 0x56, 0xad, 0x56, 0x93, 0xde, 0x05, 0x02, 0x02, - 0xb7, 0x1b, 0x11, 0x9f, 0x9c, 0x9c, 0x24, 0x3c, 0x28, 0x85, 0xbb, 0xbb, 0x3b, 0xa1, 0x33, 0x33, - 0x33, 0x37, 0x37, 0x37, 0x03, 0x02, 0xfe, 0x79, 0x5d, 0x57, 0x55, 0x55, 0x45, 0x0e, 0x00, 0xec, - 0xf5, 0xbe, 0xbe, 0x3e, 0x72, 0x6d, 0x61, 0x6f, 0x40, 0x49, 0x70, 0x70, 0x30, 0x11, 0xa1, 0x3f, - 0x21, 0xce, 0xec, 0x1b, 0x56, 0xad, 0x57, 0x00, 0x3d, 0x8a, 0xee, 0x27, 0x7a, 0xc9, 0x5d, 0x86, - 0x8b, 0x86, 0x4c, 0xc9, 0x8d, 0x43, 0x68, 0x1c, 0x88, 0x4d, 0x4d, 0x4d, 0x38, 0xe6, 0xc1, 0x8f, - 0x0a, 0xc0, 0x2d, 0xdc, 0xca, 0xcd, 0xcd, 0xcd, 0xb0, 0x41, 0xc4, 0xd1, 0x78, 0x88, 0x0d, 0xf7, - 0x3a, 0xf8, 0x81, 0x80, 0x0d, 0xcc, 0xa0, 0xc9, 0xd1, 0x4c, 0x3f, 0xa0, 0x89, 0x42, 0x3c, 0x0f, - 0xec, 0x55, 0x6a, 0x95, 0x10, 0x87, 0xfc, 0x56, 0x02, 0xee, 0xce, 0xcd, 0xcd, 0xa1, 0x62, 0xc4, - 0x39, 0x33, 0x63, 0x8e, 0x98, 0x1e, 0x72, 0x00, 0x8e, 0x70, 0x91, 0x59, 0xa7, 0xf5, 0x16, 0x62, - 0x96, 0x3f, 0xf2, 0x55, 0x3e, 0x80, 0xa3, 0x2e, 0x01, 0x5f, 0x01, 0xbe, 0x02, 0x1c, 0x33, 0xc0, - 0xb7, 0x10, 0xc7, 0x04, 0x72, 0x16, 0xe7, 0x2b, 0xc0, 0x39, 0x85, 0x1c, 0x15, 0x1c, 0xfb, 0x0a, - 0xfc, 0x0d, 0x0a, 0x08, 0x48, 0x44, 0xec, 0xf6, 0xcb, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHTMLIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0f, 0x8d, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x09, 0x54, 0x14, 0x47, 0xf6, 0x73, 0x05, 0x10, 0xd4, 0x78, 0x24, 0x28, 0x8a, 0x46, 0xc1, - 0xdd, 0x28, 0xde, 0x06, 0x41, 0x8d, 0x26, 0xae, 0xc7, 0xaa, 0xf1, 0x40, 0xa3, 0x59, 0x45, 0x4d, - 0x5c, 0x13, 0x37, 0xe6, 0x78, 0x66, 0xf1, 0x4e, 0x36, 0x51, 0xdc, 0xd5, 0x98, 0xb7, 0x3e, 0xcf, - 0x68, 0xa2, 0x79, 0x26, 0xcf, 0xac, 0x67, 0x36, 0xc7, 0x4b, 0xc4, 0xe8, 0x86, 0x55, 0x14, 0x41, - 0x41, 0xf1, 0x8a, 0x1b, 0x09, 0x04, 0x0f, 0x44, 0x14, 0x41, 0x10, 0x05, 0xe5, 0x86, 0xde, 0xfa, - 0x85, 0x5d, 0x74, 0xcf, 0x74, 0xcf, 0x74, 0x4f, 0x77, 0xcf, 0x60, 0xd2, 0xf5, 0x5e, 0x4f, 0xff, - 0xfa, 0xff, 0xd7, 0x3f, 0xea, 0x57, 0x55, 0xd7, 0x74, 0x77, 0x55, 0xbb, 0x71, 0x24, 0x81, 0x8a, - 0xe4, 0xae, 0x82, 0x97, 0xb2, 0x6a, 0x2f, 0xf0, 0x87, 0xa3, 0x61, 0x54, 0x52, 0x69, 0xcd, 0x7d, - 0x7a, 0xe6, 0xf3, 0xcc, 0x12, 0xf4, 0x81, 0x4f, 0x83, 0x13, 0x9e, 0xe2, 0x41, 0x4e, 0x0e, 0x06, - 0xc6, 0xf1, 0x00, 0xb8, 0x51, 0x96, 0x63, 0x89, 0x12, 0xe5, 0xdd, 0x30, 0xc7, 0xd4, 0x29, 0x00, - 0xb4, 0x3b, 0x2d, 0xa5, 0xc4, 0xcd, 0xcd, 0x8d, 0xa1, 0x6d, 0x6a, 0x10, 0x32, 0xf2, 0x25, 0x8c, - 0xf7, 0xc1, 0x78, 0x0d, 0x36, 0x9d, 0xe6, 0x1d, 0x15, 0x9e, 0x45, 0x05, 0x2e, 0xdd, 0xcf, 0x84, - 0xe2, 0xea, 0xbb, 0x94, 0x3e, 0x35, 0x35, 0x12, 0x46, 0x24, 0x0d, 0x10, 0xf2, 0xd6, 0xc1, 0x7c, - 0xdc, 0x47, 0x1f, 0x7b, 0x96, 0x07, 0x45, 0xe7, 0x6f, 0xae, 0x7f, 0x21, 0xca, 0x5b, 0xb5, 0x25, - 0xa4, 0xf2, 0x0d, 0x6f, 0x62, 0xca, 0x08, 0x11, 0x33, 0x66, 0x9c, 0x58, 0x4b, 0x7c, 0x33, 0x98, - 0x3b, 0x77, 0xae, 0xb5, 0xa3, 0x02, 0x8c, 0xa8, 0x96, 0xf8, 0x42, 0x48, 0x1f, 0x3d, 0x7a, 0x34, - 0xec, 0xd9, 0xb3, 0x47, 0xc0, 0x5a, 0x07, 0x1a, 0xef, 0x83, 0x6a, 0x0d, 0x56, 0x36, 0xda, 0x41, - 0x88, 0x7c, 0xb6, 0xc3, 0xeb, 0x10, 0xd9, 0x21, 0x05, 0x56, 0x43, 0x9b, 0x2d, 0xd5, 0x56, 0x4d, - 0xeb, 0x01, 0x02, 0x5b, 0xdf, 0xcb, 0xa7, 0x26, 0x5b, 0x91, 0xf9, 0x56, 0x29, 0x24, 0x20, 0x6e, - 0xf3, 0xe5, 0xf5, 0x42, 0x14, 0x83, 0x25, 0x9b, 0x36, 0x4f, 0xc5, 0x82, 0xe3, 0x93, 0x87, 0xf1, - 0x59, 0xd6, 0xe4, 0x19, 0x82, 0x00, 0xc8, 0x13, 0x93, 0xb6, 0x48, 0x88, 0x12, 0xc1, 0x36, 0x15, - 0x08, 0x39, 0x5f, 0x4c, 0x7d, 0x9e, 0xbb, 0x53, 0x59, 0x24, 0x44, 0x29, 0x82, 0x5d, 0xd3, 0x8a, - 0x0e, 0x1f, 0x3e, 0x6c, 0x2b, 0x6c, 0x92, 0x34, 0xd9, 0x32, 0x52, 0x7e, 0x12, 0x09, 0xdc, 0x96, - 0x2d, 0x5b, 0xf0, 0x8a, 0x44, 0xc9, 0x78, 0xe6, 0x8f, 0x73, 0xe7, 0xce, 0x31, 0xb8, 0x5b, 0xb7, - 0x6e, 0xac, 0x38, 0xcf, 0xcb, 0x10, 0x0f, 0x00, 0xc9, 0x18, 0x20, 0xf3, 0xfd, 0xfb, 0xf7, 0x99, - 0x82, 0xf2, 0xf2, 0x72, 0x26, 0x74, 0xda, 0xb4, 0x69, 0x0c, 0xde, 0xbd, 0x7b, 0x37, 0xe7, 0xe9, - 0xe9, 0xc9, 0xf2, 0x52, 0x4a, 0x5c, 0x13, 0x03, 0x62, 0x89, 0x6e, 0xe9, 0xe1, 0xf7, 0xc0, 0xa1, - 0xb1, 0x48, 0x4d, 0xfd, 0xfd, 0x06, 0x15, 0x5c, 0x28, 0x3e, 0x0f, 0xef, 0xa7, 0xbf, 0xa7, 0xbc, - 0x96, 0x2c, 0x7b, 0x9e, 0x30, 0x8f, 0x23, 0x25, 0x19, 0xfb, 0x85, 0x28, 0x36, 0xa2, 0x56, 0xd6, - 0x56, 0x50, 0x38, 0xf5, 0x76, 0x8a, 0x88, 0x6e, 0x99, 0x91, 0xec, 0xc9, 0x5f, 0xe6, 0xec, 0x62, - 0x82, 0x2c, 0x0b, 0x0c, 0x3d, 0x1a, 0x2e, 0x42, 0xcd, 0x3b, 0xff, 0xba, 0x2c, 0x2f, 0x32, 0x4a, - 0x2a, 0x40, 0xcb, 0xb7, 0x5e, 0xd9, 0x24, 0x12, 0x84, 0x19, 0xc4, 0x4b, 0x25, 0xc4, 0x0f, 0x4b, - 0x8c, 0x90, 0x22, 0x49, 0x2b, 0x40, 0xce, 0x0f, 0x2f, 0xae, 0xb2, 0x12, 0x68, 0xa9, 0x60, 0xfa, - 0xc9, 0x09, 0x56, 0x3c, 0x96, 0x5a, 0x24, 0x3d, 0x10, 0x32, 0x0d, 0x4f, 0xec, 0x47, 0xb3, 0x52, - 0x16, 0xa6, 0x97, 0x5c, 0x10, 0xb2, 0x4a, 0xc2, 0x76, 0x15, 0xf0, 0xa5, 0x2c, 0xad, 0xe7, 0xf1, - 0xf6, 0xce, 0xe6, 0x58, 0x64, 0xb7, 0xc3, 0x59, 0x8d, 0x45, 0x85, 0x85, 0x85, 0x50, 0x56, 0x56, - 0x66, 0xb7, 0xa0, 0x90, 0x01, 0xaf, 0xc7, 0x79, 0x79, 0x79, 0x42, 0x54, 0x3d, 0x2c, 0x15, 0xa4, - 0x95, 0x2b, 0x57, 0x8a, 0xd0, 0x84, 0x5b, 0x94, 0x97, 0xca, 0x8c, 0x18, 0x61, 0xfd, 0xf7, 0x00, - 0xf9, 0x24, 0x4b, 0xa2, 0xc0, 0x16, 0x2d, 0x5a, 0x50, 0x39, 0x08, 0xf3, 0x07, 0x2d, 0x40, 0xf2, - 0x1f, 0x7c, 0xf0, 0x01, 0x17, 0x12, 0x12, 0x42, 0xf1, 0x94, 0x89, 0xfc, 0xa8, 0x52, 0x80, 0x1e, - 0x5c, 0xbc, 0x78, 0x91, 0xbb, 0x7c, 0xf9, 0x32, 0x53, 0xc2, 0x0b, 0xe2, 0xbd, 0x39, 0x7b, 0xf6, - 0xac, 0x63, 0x0a, 0x78, 0x6b, 0xf9, 0x33, 0x0a, 0xe6, 0xe1, 0x51, 0xa3, 0x46, 0x51, 0xf8, 0xf6, - 0xed, 0xdb, 0x0c, 0x27, 0xa4, 0xf3, 0xca, 0x79, 0x63, 0xf0, 0x6c, 0xf6, 0x03, 0x52, 0x2b, 0xb6, - 0x93, 0x55, 0x3f, 0xb0, 0xcd, 0xae, 0x9e, 0x6a, 0x78, 0x0c, 0xd4, 0x9b, 0xa4, 0xae, 0x84, 0xe1, - 0x35, 0xa4, 0xce, 0x1c, 0xf5, 0xdc, 0xa6, 0x03, 0xea, 0xeb, 0x4c, 0xdf, 0x12, 0x4e, 0x8b, 0xc0, - 0xcd, 0xf2, 0x1b, 0xfa, 0x5a, 0xfe, 0x40, 0x9a, 0x66, 0x07, 0x96, 0xa7, 0xbf, 0x0b, 0xf6, 0x6e, - 0x5b, 0x90, 0xe9, 0x14, 0x44, 0x9d, 0x1c, 0x27, 0x72, 0x00, 0xcb, 0x44, 0x9f, 0x9f, 0x2d, 0xc2, - 0x39, 0x92, 0x71, 0x68, 0x14, 0x9a, 0x72, 0x72, 0x0c, 0xe4, 0x95, 0xdf, 0xa4, 0xfa, 0xde, 0x0a, - 0x59, 0x08, 0xe3, 0x02, 0x27, 0xc9, 0xea, 0x46, 0xc3, 0xb1, 0xf6, 0xbf, 0x1f, 0x90, 0x00, 0xbe, - 0x1e, 0x8d, 0x44, 0x7c, 0x49, 0x85, 0x47, 0x60, 0xc9, 0x85, 0x05, 0x14, 0xe7, 0xef, 0xd9, 0x18, - 0xf6, 0xf6, 0x8f, 0x17, 0xd1, 0x95, 0x64, 0x14, 0x3b, 0x30, 0x34, 0x31, 0x1c, 0x6a, 0xb9, 0x5a, - 0x2a, 0xf3, 0xab, 0x88, 0xff, 0x40, 0xf3, 0x47, 0x5a, 0xd8, 0x95, 0xff, 0x8f, 0xf4, 0xbf, 0xc1, - 0xe1, 0xfc, 0x38, 0xf8, 0xb0, 0xe7, 0xa7, 0x10, 0xda, 0xa4, 0xbb, 0x4d, 0xfe, 0xb2, 0x9a, 0x52, - 0x18, 0x7b, 0x7c, 0x08, 0xd4, 0x70, 0xd5, 0x94, 0x2f, 0x7e, 0x50, 0xaa, 0x4d, 0x7e, 0x46, 0x14, - 0x5e, 0x98, 0xed, 0xc1, 0x69, 0xc5, 0xff, 0xa3, 0xd3, 0x74, 0x9c, 0x00, 0xe3, 0x71, 0xf9, 0xfe, - 0x45, 0xd9, 0x22, 0x78, 0xaf, 0x15, 0x79, 0x76, 0x5f, 0xfb, 0x5c, 0x96, 0x07, 0x09, 0xb7, 0x2a, - 0xf2, 0x45, 0x32, 0x93, 0x0a, 0x8e, 0xd8, 0xe4, 0xb7, 0x24, 0x2a, 0x8e, 0x00, 0xf3, 0x58, 0x00, - 0x4c, 0x26, 0x4d, 0x29, 0xff, 0x41, 0x53, 0x5a, 0xd7, 0xe3, 0x13, 0xe8, 0xde, 0xb4, 0x17, 0xa5, - 0xfe, 0x72, 0x2f, 0x1d, 0x66, 0x9f, 0x99, 0x0e, 0xfd, 0x5b, 0x0c, 0x82, 0xe5, 0xa1, 0xab, 0x05, - 0x25, 0xea, 0xc0, 0xc2, 0xca, 0x02, 0x98, 0x94, 0x32, 0x92, 0x66, 0xfc, 0x3d, 0xfd, 0xe1, 0xdb, - 0xfe, 0x07, 0xc1, 0x1d, 0x3c, 0xac, 0xf8, 0x94, 0x20, 0x34, 0x39, 0x20, 0xa5, 0xa0, 0xa2, 0xb6, - 0x02, 0x46, 0x26, 0x3d, 0x4d, 0x9a, 0x58, 0x4b, 0xf8, 0x2a, 0xe2, 0x80, 0x14, 0x8b, 0xae, 0x38, - 0xdd, 0x1d, 0x40, 0xeb, 0x12, 0x0a, 0x0e, 0xc1, 0x33, 0x2d, 0x87, 0xe8, 0x6a, 0xa8, 0x9c, 0x30, - 0x43, 0x1c, 0x90, 0x53, 0x66, 0x04, 0x5e, 0xf3, 0x75, 0xc0, 0x08, 0xa3, 0xd4, 0xc8, 0xfc, 0x6d, - 0x38, 0x80, 0x4f, 0x67, 0xf0, 0x20, 0xff, 0xf6, 0x64, 0x2b, 0x27, 0x21, 0x21, 0x01, 0xbc, 0xbc, - 0xbc, 0x64, 0xe9, 0xf6, 0x08, 0xd1, 0xd1, 0xd1, 0x54, 0x07, 0xea, 0x19, 0x39, 0xb2, 0x6e, 0x84, - 0xb2, 0x57, 0x06, 0xe9, 0x8a, 0x22, 0x40, 0xc6, 0x5e, 0x2a, 0xab, 0xa8, 0xa8, 0x88, 0x29, 0x99, - 0x39, 0x73, 0x26, 0x93, 0x7f, 0xf0, 0xe0, 0x41, 0x58, 0xba, 0x74, 0x29, 0x54, 0x57, 0x57, 0xc3, - 0xda, 0xb5, 0x6b, 0xe9, 0x91, 0x98, 0x98, 0x48, 0xe9, 0xe8, 0x34, 0x1a, 0x35, 0x7f, 0xfe, 0x7c, - 0x7a, 0x6e, 0xd2, 0xa4, 0x09, 0x90, 0xbf, 0xc4, 0x14, 0x1e, 0x3f, 0x7e, 0x3c, 0x93, 0x81, 0xe5, - 0x78, 0x3d, 0x0c, 0xa9, 0x04, 0xb0, 0xbc, 0x30, 0xc8, 0xe5, 0x89, 0x2c, 0x6e, 0xf0, 0xe0, 0xc1, - 0x94, 0x7c, 0xe6, 0xcc, 0x19, 0xfa, 0xaf, 0xf5, 0xca, 0x95, 0x2b, 0x8c, 0x9d, 0xd4, 0x20, 0xc5, - 0x31, 0x84, 0x00, 0xc0, 0xb2, 0x43, 0x87, 0x0e, 0xa5, 0x18, 0x84, 0x53, 0x52, 0x52, 0x38, 0xbc, - 0x8f, 0x8e, 0xb0, 0x65, 0x42, 0x9c, 0xdc, 0x7f, 0x78, 0x4b, 0x5e, 0xcc, 0x2b, 0x8a, 0x00, 0x11, - 0x4a, 0xd3, 0xf0, 0xe1, 0xc3, 0xe9, 0x19, 0x6b, 0x11, 0x13, 0x29, 0x4f, 0xcf, 0xf8, 0xd3, 0xb8, - 0x71, 0x63, 0x0a, 0x5f, 0xbd, 0x7a, 0x95, 0x9e, 0x57, 0xad, 0x5a, 0x05, 0xc2, 0x28, 0x79, 0x7b, - 0x7b, 0x53, 0x3c, 0xfe, 0x08, 0x61, 0x86, 0x74, 0x10, 0xd0, 0x7d, 0x18, 0xcd, 0xcc, 0xcc, 0xa4, - 0xa6, 0x74, 0xea, 0xd4, 0xc9, 0x41, 0x93, 0xd4, 0x15, 0xd3, 0xdd, 0x01, 0x75, 0xea, 0xb5, 0x73, - 0xab, 0x6a, 0x42, 0xda, 0xd5, 0xe9, 0x2f, 0xc1, 0x74, 0x40, 0xff, 0x3a, 0x55, 0x27, 0xd1, 0xec, - 0x03, 0xea, 0xea, 0x4b, 0x7f, 0x6e, 0xb3, 0x0f, 0xe8, 0x5f, 0xa7, 0xea, 0x24, 0x9a, 0x11, 0x50, - 0x57, 0x5f, 0xfa, 0x73, 0x9b, 0x11, 0xd0, 0xbf, 0x4e, 0xd5, 0x49, 0x34, 0x23, 0xa0, 0xa4, 0xbe, - 0x32, 0xef, 0x65, 0x28, 0x61, 0x73, 0x88, 0xc7, 0x29, 0x57, 0x62, 0xfe, 0xe6, 0xaf, 0xe2, 0xdb, - 0x85, 0x2a, 0x5c, 0xd1, 0xd4, 0x84, 0x8a, 0xaa, 0x0a, 0xe9, 0x9d, 0xe9, 0x4f, 0xb3, 0x3e, 0x96, - 0x55, 0x99, 0x57, 0x91, 0x4b, 0x69, 0xdd, 0x9a, 0xf6, 0x64, 0x3c, 0x87, 0x6e, 0xfd, 0x40, 0xcb, - 0x65, 0x97, 0x65, 0x31, 0x9c, 0xa3, 0x80, 0xa7, 0xa3, 0x05, 0xdf, 0x3c, 0x37, 0x13, 0xc8, 0xbd, - 0x52, 0x5a, 0xfc, 0x4e, 0xd5, 0x6d, 0x59, 0x31, 0xaf, 0x9c, 0x8e, 0xa2, 0xb4, 0xb5, 0x3d, 0xb6, - 0x30, 0x9e, 0x6b, 0xa5, 0x75, 0xff, 0xda, 0x66, 0xa4, 0x4e, 0x82, 0x36, 0xbe, 0x41, 0xb0, 0x3d, - 0xec, 0x1b, 0x46, 0x53, 0x0b, 0xa8, 0x6e, 0x42, 0xc7, 0x6f, 0x1f, 0x85, 0x77, 0x7f, 0x9a, 0x47, - 0xf5, 0xe0, 0x2d, 0xf1, 0xef, 0xfa, 0x1f, 0x02, 0x72, 0xcf, 0x42, 0x52, 0x6f, 0x2d, 0xd4, 0x02, - 0x79, 0x0b, 0x05, 0xfc, 0xc8, 0xfd, 0xcf, 0xd8, 0xfe, 0x87, 0xad, 0x78, 0x84, 0xb7, 0xe9, 0xa3, - 0x3b, 0xbd, 0x0d, 0x63, 0x5a, 0x4f, 0xb0, 0xe2, 0xb1, 0x87, 0x50, 0xec, 0x00, 0x1a, 0x33, 0xe6, - 0xd8, 0x60, 0xc0, 0xdb, 0xe0, 0x98, 0x36, 0xf4, 0xdc, 0x0a, 0x5d, 0x9b, 0xf4, 0xb0, 0x29, 0x7f, - 0xce, 0x8f, 0xaf, 0xc0, 0x4f, 0x77, 0x7f, 0x84, 0xdd, 0xe1, 0x7b, 0x21, 0xc0, 0xbb, 0xb5, 0x24, - 0xef, 0xb5, 0xb2, 0xab, 0xf0, 0x52, 0xea, 0x44, 0x4a, 0xf3, 0x70, 0xf3, 0x84, 0xd8, 0x01, 0x87, - 0xc1, 0xc7, 0xdd, 0x47, 0x92, 0x57, 0x0a, 0xa9, 0xa8, 0x0f, 0x7c, 0x46, 0xda, 0x38, 0xd6, 0x24, - 0x1a, 0x3f, 0xe4, 0xf1, 0x3f, 0x02, 0x76, 0x46, 0x7b, 0xc6, 0xa3, 0x32, 0x34, 0x1e, 0x93, 0x9c, - 0xf1, 0x48, 0x0b, 0xf2, 0x6d, 0x4f, 0xe5, 0xbd, 0xd0, 0x76, 0x1a, 0x7d, 0x36, 0x30, 0x2a, 0x69, - 0x20, 0xc4, 0xfc, 0xbc, 0x18, 0x49, 0x8a, 0x92, 0x22, 0x07, 0x1e, 0xf3, 0x0e, 0x60, 0xc2, 0x12, - 0x0b, 0x0e, 0x43, 0x79, 0x6d, 0x39, 0xcb, 0xcb, 0x01, 0x9f, 0x5c, 0xf9, 0x90, 0x92, 0xde, 0xed, - 0xbc, 0x42, 0x8e, 0x85, 0xe1, 0x31, 0xba, 0xfb, 0x6f, 0x7e, 0xc7, 0xf2, 0x81, 0x3e, 0x6d, 0x18, - 0x6c, 0x0f, 0x50, 0xdc, 0x84, 0x50, 0xd0, 0x6b, 0x67, 0x5f, 0x82, 0x8c, 0x92, 0x34, 0x2a, 0xb3, - 0xc7, 0xa3, 0x7d, 0x60, 0x6d, 0xf7, 0xcd, 0xb2, 0xf2, 0x95, 0x0e, 0x9d, 0xf8, 0x8c, 0x2d, 0x3e, - 0xff, 0x07, 0x2a, 0xa7, 0xb5, 0x6f, 0x1b, 0xd8, 0x19, 0xf6, 0xad, 0xac, 0x4c, 0x29, 0x82, 0xa2, - 0x08, 0xf0, 0x05, 0x3f, 0xee, 0xf5, 0x39, 0x6d, 0xa3, 0x1e, 0x6e, 0x1e, 0xf0, 0xe3, 0x9d, 0xd3, - 0x74, 0x28, 0x3c, 0x70, 0x73, 0x2f, 0x4f, 0x66, 0xe7, 0x63, 0x85, 0x09, 0x14, 0x8e, 0x6c, 0xf3, - 0x02, 0xc3, 0x59, 0x02, 0x27, 0x8a, 0x8e, 0xd3, 0xf2, 0xbc, 0xf1, 0x7b, 0xc2, 0xf7, 0xa9, 0x36, - 0x1e, 0x65, 0xaa, 0x8a, 0x80, 0xd0, 0x88, 0x23, 0x05, 0x07, 0xe1, 0xef, 0x69, 0x6f, 0x53, 0x14, - 0xde, 0x3a, 0x3c, 0x34, 0xf0, 0x24, 0x23, 0xdb, 0xab, 0xfd, 0x11, 0xe4, 0x01, 0x08, 0x79, 0xf9, - 0x8e, 0xf2, 0xbf, 0x19, 0x32, 0x0f, 0x26, 0x04, 0x4e, 0x66, 0x65, 0x55, 0x03, 0x52, 0xb7, 0xeb, - 0xd4, 0xe0, 0xc8, 0x90, 0xca, 0x65, 0x97, 0x66, 0xb1, 0x22, 0xfc, 0x33, 0xaf, 0x59, 0xa7, 0xa7, - 0x32, 0x9c, 0x25, 0x70, 0xaf, 0xfa, 0x1e, 0xf7, 0xfa, 0xd9, 0x97, 0x2c, 0xd1, 0x0e, 0xe5, 0x1d, - 0x8e, 0x80, 0x5c, 0x4d, 0x45, 0x26, 0x0f, 0x85, 0xe2, 0xaa, 0xbb, 0x10, 0x37, 0x30, 0x19, 0x3c, - 0xc9, 0xb0, 0x68, 0x74, 0x52, 0xd5, 0x07, 0x94, 0x18, 0x83, 0xc6, 0x3f, 0xe2, 0xee, 0xed, 0x14, - 0xe3, 0xd1, 0x1e, 0xdd, 0x23, 0x40, 0xde, 0x33, 0x83, 0xeb, 0x65, 0xd7, 0xa0, 0xad, 0x6f, 0x3b, - 0x25, 0xfe, 0x6a, 0xe6, 0xd1, 0xdd, 0x01, 0xcd, 0x16, 0xa9, 0x14, 0xa0, 0x7b, 0x13, 0x52, 0xa9, - 0x5f, 0x33, 0xbb, 0xe9, 0x80, 0xe6, 0x2a, 0xd4, 0x28, 0xc0, 0x8c, 0x80, 0xc6, 0x0a, 0xd4, 0x5c, - 0x5c, 0xd1, 0x95, 0xe6, 0xc8, 0x91, 0x23, 0xe0, 0xe1, 0xe1, 0x01, 0x03, 0x07, 0x0e, 0xd4, 0xac, - 0x50, 0x4e, 0x40, 0x56, 0x56, 0x16, 0x90, 0x87, 0x86, 0x94, 0x4c, 0x1e, 0x26, 0xca, 0xb1, 0x59, - 0xe3, 0xed, 0x5d, 0xbf, 0x77, 0xec, 0xd8, 0x41, 0x9f, 0x26, 0x92, 0x92, 0x36, 0x59, 0x7d, 0x7c, - 0x7c, 0xb8, 0xed, 0xdb, 0xb7, 0xdb, 0xe4, 0xb1, 0x45, 0x44, 0xf9, 0xfc, 0x61, 0x8b, 0xcf, 0x92, - 0x66, 0xdb, 0xaa, 0x07, 0xdc, 0x7d, 0xfa, 0xf4, 0xa1, 0xc2, 0x2d, 0x0b, 0x0b, 0xf3, 0xa8, 0x3c, - 0x32, 0x32, 0x52, 0x88, 0x52, 0x0d, 0x93, 0xb5, 0x91, 0x76, 0xf5, 0x58, 0x0a, 0x55, 0xd5, 0x89, - 0x07, 0x0c, 0x18, 0xc0, 0x1e, 0x74, 0x57, 0x56, 0x56, 0x12, 0x9b, 0x01, 0x6a, 0x6a, 0x6a, 0x60, - 0xdd, 0xba, 0x75, 0x14, 0x26, 0xaf, 0x5c, 0xd3, 0x87, 0xdc, 0x1b, 0x36, 0x6c, 0xa0, 0x79, 0xfc, - 0xc1, 0x99, 0x2a, 0x1e, 0x2d, 0x5b, 0xb6, 0xa4, 0xe7, 0xe5, 0xcb, 0x97, 0x33, 0x1c, 0x63, 0xd2, - 0x02, 0x58, 0x7a, 0x24, 0x95, 0xe7, 0x23, 0x10, 0x1c, 0x1c, 0xcc, 0x91, 0x27, 0xf2, 0xb4, 0x96, - 0x82, 0x82, 0x82, 0x28, 0x6b, 0x5c, 0x5c, 0x1c, 0x0b, 0x3d, 0xb1, 0x83, 0xc1, 0xa7, 0x4e, 0x9d, - 0xa2, 0xf4, 0x21, 0x43, 0x86, 0x50, 0xdc, 0xec, 0xd9, 0xb3, 0x19, 0x6d, 0xdb, 0xb6, 0x6d, 0x14, - 0x8e, 0x89, 0x89, 0x11, 0xa9, 0x73, 0x24, 0x02, 0x0e, 0x35, 0x21, 0xde, 0x50, 0xa1, 0x76, 0xc4, - 0x49, 0x35, 0xa1, 0xfd, 0xfb, 0xf7, 0x53, 0x63, 0x91, 0x37, 0x34, 0x34, 0x94, 0xc1, 0xc8, 0x1f, - 0x15, 0x15, 0x25, 0x14, 0xc1, 0x39, 0xe2, 0x80, 0xaa, 0x26, 0x44, 0x94, 0x36, 0xb8, 0xa4, 0xab, - 0x03, 0x87, 0x0e, 0x1d, 0xa2, 0x0e, 0x66, 0x64, 0x64, 0x40, 0xdf, 0xbe, 0x7d, 0x9d, 0xe3, 0xac, - 0x28, 0x86, 0x12, 0x19, 0x1c, 0x1a, 0x89, 0x25, 0xf4, 0x70, 0x77, 0x77, 0xe7, 0xc6, 0x8d, 0x1b, - 0xc7, 0xf2, 0x63, 0xc7, 0x8e, 0x65, 0x25, 0xda, 0xb5, 0x6b, 0xc7, 0xf0, 0x3c, 0x7f, 0x6d, 0x6d, - 0xad, 0x08, 0xc7, 0x37, 0x21, 0xbe, 0xa9, 0x20, 0x5f, 0x55, 0x55, 0x15, 0xd7, 0xb4, 0x69, 0x53, - 0x11, 0x1f, 0x5f, 0x3e, 0x3b, 0x3b, 0x9b, 0xc9, 0x97, 0x03, 0x74, 0x9d, 0x4e, 0xe3, 0x88, 0x44, - 0xde, 0x44, 0x81, 0x5e, 0xbd, 0x7a, 0x41, 0xa3, 0x46, 0xe2, 0x97, 0x5c, 0x89, 0x51, 0x86, 0x24, - 0x5d, 0x1d, 0x30, 0xc4, 0x42, 0x3b, 0x42, 0x75, 0xed, 0x03, 0x76, 0x74, 0x19, 0x42, 0x36, 0x1d, - 0x30, 0xa4, 0x5a, 0x55, 0x08, 0x35, 0x23, 0xa0, 0xa2, 0xb2, 0x0c, 0x61, 0x35, 0x23, 0x60, 0x48, - 0xb5, 0xaa, 0x10, 0xfa, 0xd0, 0x5f, 0x07, 0x54, 0xf8, 0xda, 0x20, 0x59, 0x1f, 0xfa, 0x2e, 0xd0, - 0x20, 0x6b, 0x55, 0x85, 0x51, 0x66, 0x00, 0x54, 0x54, 0x96, 0x11, 0xac, 0x66, 0x00, 0x8c, 0xa8, - 0x55, 0x15, 0x32, 0xcd, 0x00, 0xa8, 0xa8, 0x2c, 0x23, 0x58, 0xcd, 0x00, 0x18, 0x51, 0xab, 0x2a, - 0x64, 0x9a, 0x01, 0x50, 0x51, 0x59, 0x46, 0xb0, 0x9a, 0x01, 0x30, 0xa2, 0x56, 0x55, 0xc8, 0x34, - 0x03, 0xa0, 0xa2, 0xb2, 0x8c, 0x60, 0x55, 0xf4, 0x68, 0xcc, 0x08, 0xc5, 0x46, 0xc8, 0x7c, 0xe3, - 0xdc, 0x0c, 0xf8, 0xa5, 0x24, 0x1d, 0x9e, 0x6e, 0xf9, 0x2c, 0xfc, 0xa9, 0xed, 0x74, 0x78, 0xb2, - 0x71, 0xa8, 0x11, 0x6a, 0x74, 0x95, 0xd9, 0x20, 0x7a, 0xc0, 0xa9, 0xa2, 0x13, 0xb0, 0xf8, 0xa7, - 0xb7, 0xa0, 0x8a, 0xab, 0x7b, 0x58, 0xe5, 0x88, 0x87, 0xcb, 0xc8, 0xeb, 0x81, 0x3f, 0x17, 0x5f, - 0x20, 0xaf, 0x0b, 0xd6, 0x40, 0xc2, 0x2d, 0xf2, 0x02, 0x28, 0x79, 0x98, 0x25, 0x95, 0xde, 0xcf, - 0x58, 0x02, 0x3f, 0xe4, 0xed, 0x93, 0x22, 0xb9, 0x04, 0xe7, 0x92, 0x5b, 0x11, 0xf8, 0x1e, 0x4e, - 0x6c, 0xee, 0x37, 0xb0, 0xf5, 0xca, 0x46, 0x20, 0xaf, 0x6c, 0x31, 0xc7, 0x3d, 0xdd, 0x3d, 0xe1, - 0x93, 0xde, 0x3b, 0xe0, 0x89, 0x46, 0xc1, 0x0c, 0xa7, 0x04, 0xf8, 0xf8, 0xf2, 0x5a, 0x20, 0xfb, - 0xbe, 0x31, 0xd6, 0x65, 0xa1, 0xff, 0x84, 0x81, 0x2d, 0xc4, 0x0f, 0x98, 0x4b, 0xaa, 0x8b, 0x61, - 0xc6, 0xa9, 0x49, 0x50, 0x54, 0x59, 0xff, 0x6a, 0xb1, 0x97, 0xbb, 0x17, 0x4c, 0x0e, 0x7a, 0x11, - 0xa6, 0xb5, 0x9b, 0x09, 0x5e, 0x6e, 0x8f, 0xb0, 0xf2, 0xce, 0x04, 0x9c, 0x16, 0x00, 0x7c, 0xbf, - 0x74, 0x5b, 0xd6, 0x16, 0xf8, 0xfa, 0xfa, 0x6e, 0xda, 0x4a, 0x85, 0x4e, 0xfe, 0xae, 0xf1, 0x93, - 0xf0, 0xd7, 0x90, 0xc5, 0x0e, 0x0d, 0x19, 0x5f, 0x11, 0x79, 0x1f, 0x5d, 0x5a, 0xc3, 0xc4, 0xbd, - 0x11, 0x3c, 0x17, 0x9e, 0x6f, 0x33, 0x85, 0xe5, 0x2d, 0x81, 0x1b, 0xe5, 0xd7, 0x81, 0x6c, 0x6f, - 0x07, 0x27, 0x6e, 0x1f, 0xb3, 0x24, 0xd1, 0x17, 0x79, 0x5f, 0x27, 0xe5, 0x9b, 0x79, 0x35, 0xb7, - 0xa2, 0x19, 0x85, 0x30, 0x34, 0x00, 0x05, 0x95, 0xf9, 0xb0, 0x81, 0x38, 0x4b, 0x36, 0xe8, 0x10, - 0xd9, 0x8f, 0xc3, 0xc3, 0xf0, 0x80, 0xe7, 0xe0, 0xd5, 0x0e, 0x73, 0xe0, 0x51, 0xaf, 0x66, 0x22, - 0x9a, 0x9a, 0x4c, 0x62, 0x41, 0x3c, 0x2c, 0x4d, 0x5b, 0xc4, 0x8a, 0x4c, 0x6a, 0x1b, 0x05, 0xaf, - 0x75, 0x8c, 0x66, 0x79, 0x7b, 0x00, 0x6e, 0x7b, 0xb1, 0x3d, 0x7b, 0x2b, 0xfc, 0x3b, 0x67, 0x07, - 0x54, 0xd7, 0xd6, 0xed, 0x82, 0xc2, 0x97, 0xe9, 0xd2, 0xa4, 0x1b, 0xe0, 0x3b, 0xe8, 0xc1, 0x7e, - 0xc6, 0xae, 0x24, 0xd6, 0x3d, 0x00, 0x19, 0xf7, 0xd2, 0x60, 0xcd, 0x2f, 0x2b, 0x21, 0x93, 0x6c, - 0x48, 0x22, 0x4c, 0x8d, 0x3c, 0xfd, 0x60, 0x46, 0xfb, 0x57, 0x61, 0x02, 0x79, 0x7f, 0xd7, 0xd1, - 0x8d, 0x47, 0x84, 0xf2, 0xd2, 0xc9, 0x4b, 0xcf, 0xe4, 0x6d, 0x53, 0x86, 0x1a, 0xf4, 0xd8, 0x10, - 0x88, 0xe9, 0x2c, 0xbf, 0x4d, 0x01, 0x63, 0xb4, 0x01, 0x1c, 0xb9, 0xf5, 0x5f, 0xf8, 0x88, 0x0c, - 0x67, 0x05, 0x15, 0xb7, 0x44, 0x5c, 0x01, 0x3e, 0xad, 0x60, 0x0e, 0xd9, 0xb7, 0xa7, 0x5f, 0x73, - 0xfd, 0xdf, 0xcf, 0xd1, 0x35, 0x00, 0x7f, 0x39, 0x33, 0x0d, 0x2e, 0x5a, 0xac, 0xf0, 0x79, 0xc2, - 0xaf, 0x23, 0xdd, 0x11, 0x26, 0xd0, 0xa7, 0xad, 0xc8, 0x29, 0x2d, 0x99, 0x5b, 0x15, 0x79, 0x64, - 0x87, 0xa5, 0x48, 0xb6, 0x77, 0x4f, 0xe7, 0x26, 0xa1, 0xb0, 0xa9, 0xe7, 0x36, 0x2d, 0x22, 0x45, - 0x65, 0xef, 0x56, 0xdd, 0x81, 0xf7, 0x33, 0xde, 0x03, 0xb2, 0x09, 0xa9, 0x08, 0x8f, 0xd7, 0xa8, - 0xb8, 0xa7, 0x93, 0x45, 0x38, 0xad, 0x19, 0x5d, 0x03, 0x80, 0xc6, 0x14, 0x91, 0xf5, 0x33, 0xb8, - 0x56, 0x20, 0x2e, 0xef, 0x7b, 0x7c, 0x71, 0x44, 0x64, 0x1f, 0xae, 0x3b, 0x78, 0xad, 0xe3, 0x5b, - 0xf0, 0xec, 0x63, 0xc3, 0x44, 0x78, 0x35, 0x99, 0xf2, 0xda, 0x32, 0x78, 0x21, 0xe5, 0x39, 0x72, - 0xf1, 0x2e, 0xa1, 0xc5, 0x1e, 0x27, 0xad, 0x73, 0x57, 0xdf, 0x6f, 0x35, 0xf7, 0xaa, 0xf3, 0x77, - 0xcf, 0xd0, 0xe1, 0x92, 0xec, 0x91, 0x64, 0x65, 0x4e, 0x58, 0xf3, 0x08, 0x78, 0x33, 0x78, 0x3e, - 0x5d, 0x9c, 0x61, 0x45, 0xd4, 0x88, 0xd0, 0x3d, 0x00, 0x42, 0x7b, 0x70, 0xb6, 0x83, 0xcb, 0x09, - 0xb6, 0x66, 0x6d, 0x02, 0xb2, 0xa7, 0xb7, 0x90, 0x04, 0xb8, 0xe4, 0x60, 0x5c, 0xe0, 0x44, 0xf8, - 0xf3, 0x13, 0xb3, 0xc1, 0xcf, 0xc3, 0x5f, 0x44, 0x93, 0xcb, 0xa0, 0xbc, 0x17, 0x53, 0x27, 0x90, - 0x37, 0x99, 0x73, 0x28, 0x8b, 0xaf, 0x87, 0x2f, 0x7c, 0x11, 0xfe, 0x3d, 0xe0, 0xda, 0x23, 0xb5, - 0xa9, 0x9a, 0xec, 0x7c, 0xf5, 0x65, 0xce, 0x4e, 0xd8, 0x91, 0xfd, 0x29, 0x59, 0x49, 0x53, 0x26, - 0x2a, 0xee, 0xed, 0xe1, 0x03, 0x51, 0x41, 0x33, 0xc8, 0x0c, 0x69, 0xba, 0xe1, 0xb3, 0x23, 0x43, - 0x03, 0x20, 0xf2, 0x8a, 0x64, 0xb2, 0x4a, 0x2f, 0xd1, 0x56, 0x76, 0x8e, 0xac, 0xf5, 0xb0, 0x4c, - 0xf8, 0xa7, 0x69, 0x4e, 0xc8, 0x02, 0x9b, 0x33, 0xa1, 0xe8, 0xf3, 0xaf, 0x92, 0x75, 0x22, 0x67, - 0x68, 0x51, 0xbc, 0x90, 0xff, 0x2b, 0xec, 0x6b, 0x68, 0xe3, 0x13, 0x64, 0x29, 0x4a, 0x36, 0x8f, - 0x33, 0xa0, 0x4d, 0x97, 0x56, 0x43, 0x72, 0x61, 0xdd, 0x2e, 0x2f, 0x42, 0xc6, 0x0e, 0x7e, 0xc1, - 0xb4, 0x95, 0xf7, 0x7a, 0xf4, 0x29, 0x21, 0xda, 0x70, 0xd8, 0xa9, 0x01, 0x10, 0x7a, 0x83, 0x33, - 0x90, 0x9d, 0xd9, 0x9f, 0xd1, 0x19, 0x48, 0x65, 0x6d, 0xdd, 0x1f, 0x30, 0xdc, 0x51, 0x0c, 0x77, - 0x16, 0x93, 0x4a, 0xf8, 0x07, 0xea, 0x60, 0xde, 0x01, 0x46, 0x5a, 0xd3, 0x63, 0x33, 0xf4, 0x6c, - 0xda, 0x87, 0xe5, 0x95, 0x00, 0x6b, 0x2f, 0xae, 0x84, 0xd8, 0x1b, 0x75, 0x4b, 0x04, 0x31, 0x80, - 0x23, 0x03, 0xc6, 0xc2, 0x2b, 0x1d, 0xde, 0xd0, 0x34, 0x13, 0x53, 0xa2, 0xd7, 0x16, 0x8f, 0xcb, - 0x02, 0x60, 0x69, 0x54, 0x2e, 0x69, 0x9d, 0xad, 0x65, 0xd6, 0x8a, 0xe1, 0x10, 0xb6, 0x2b, 0x7b, - 0x1b, 0x2b, 0xb2, 0xf8, 0xf7, 0x31, 0x74, 0x1a, 0xcb, 0x10, 0x2a, 0x00, 0x5c, 0x88, 0x6a, 0x6b, - 0x11, 0x9e, 0x0a, 0x51, 0xba, 0xb0, 0x36, 0x98, 0x00, 0xc8, 0x79, 0xb3, 0x37, 0xf7, 0x6b, 0x58, - 0x97, 0x59, 0x3f, 0xbd, 0xc4, 0x6b, 0xc6, 0xf4, 0x76, 0x2f, 0xcb, 0xb1, 0x3f, 0x74, 0xf8, 0x06, - 0x71, 0x2f, 0x48, 0xae, 0xd6, 0x70, 0x35, 0x25, 0x5e, 0xac, 0xf9, 0xa5, 0x43, 0xcf, 0xb5, 0x8e, - 0xfc, 0x55, 0x55, 0x3e, 0xfa, 0xdd, 0xe0, 0x7b, 0x80, 0x5c, 0x70, 0x7e, 0x2d, 0xf8, 0x06, 0xdd, - 0x03, 0x7e, 0x2d, 0x95, 0x6c, 0xcb, 0x0f, 0x33, 0x00, 0xb6, 0x6a, 0xc7, 0x09, 0x34, 0x33, 0x00, - 0x4e, 0xa8, 0x64, 0x5b, 0x2a, 0xcc, 0x00, 0xd8, 0xaa, 0x1d, 0x27, 0xd0, 0xcc, 0x00, 0x38, 0xa1, - 0x92, 0x6d, 0xa9, 0x30, 0x03, 0x60, 0xab, 0x76, 0x9c, 0x40, 0xd3, 0x25, 0x00, 0xc9, 0xc9, 0xc9, - 0x40, 0xd6, 0x30, 0xb1, 0x45, 0x84, 0xf8, 0x37, 0x7f, 0xe3, 0xc6, 0x8d, 0x0e, 0x9b, 0x5f, 0x5a, - 0x5a, 0x0a, 0x77, 0xee, 0xdc, 0x71, 0xb8, 0xbc, 0x96, 0x82, 0x68, 0x37, 0xda, 0x6f, 0x79, 0x90, - 0xf5, 0x59, 0x5a, 0xc4, 0xca, 0x96, 0xd5, 0x25, 0x00, 0xdd, 0xbb, 0x77, 0x87, 0x25, 0x4b, 0x96, - 0x40, 0xb3, 0x66, 0xf5, 0x4f, 0xb7, 0xee, 0xdd, 0xab, 0x7f, 0xd6, 0x2b, 0xab, 0x5d, 0x82, 0xf0, - 0xce, 0x3b, 0xef, 0x80, 0x9f, 0x9f, 0x1f, 0x95, 0x45, 0xd6, 0x22, 0x4a, 0x70, 0x18, 0x8b, 0x1a, - 0x33, 0x66, 0x0c, 0x2c, 0x5a, 0xb4, 0x08, 0x26, 0x4e, 0x9c, 0x08, 0xc2, 0x7d, 0x75, 0xf9, 0xd5, - 0xad, 0x7a, 0x6b, 0xd7, 0xe5, 0xb5, 0x14, 0xac, 0x30, 0xb2, 0xf2, 0x14, 0xf6, 0xed, 0xdb, 0x07, - 0xa7, 0x4f, 0xd7, 0xdf, 0xe9, 0x44, 0xa3, 0xc9, 0xaa, 0x55, 0x8a, 0xf3, 0xf7, 0xf7, 0x87, 0xde, - 0xbd, 0x7b, 0x43, 0x8f, 0x1e, 0xb6, 0x77, 0x7d, 0x22, 0x9f, 0x43, 0x64, 0x3e, 0x2a, 0xfd, 0xb0, - 0xd4, 0xf5, 0xeb, 0xd7, 0x01, 0x3f, 0x44, 0x85, 0x8b, 0xeb, 0xc8, 0x67, 0x9a, 0xe8, 0xc7, 0xa5, - 0x70, 0xaf, 0xeb, 0x92, 0x92, 0x12, 0xc0, 0x9d, 0x98, 0x3b, 0x76, 0xec, 0x08, 0xf9, 0xf9, 0xf9, - 0x10, 0x1f, 0x1f, 0x0f, 0xb9, 0xb9, 0xb9, 0x40, 0x56, 0x0c, 0xc2, 0xb0, 0x61, 0xc3, 0x24, 0xdf, - 0x9c, 0x68, 0xdf, 0xbe, 0x3d, 0xdb, 0x00, 0x7c, 0xde, 0xbc, 0x79, 0xb0, 0x66, 0x4d, 0xfd, 0xf3, - 0x66, 0x66, 0x98, 0x9e, 0x80, 0xdc, 0x12, 0x44, 0x47, 0xf0, 0xfc, 0xb2, 0x62, 0x62, 0x1f, 0x47, - 0x96, 0xd8, 0x4b, 0x2e, 0x7f, 0x44, 0x1a, 0xd9, 0x72, 0x5a, 0x24, 0xfe, 0xc0, 0x81, 0x03, 0xb2, - 0xbc, 0xc8, 0x6f, 0x79, 0x9c, 0x38, 0x71, 0x82, 0x95, 0x9f, 0x3a, 0x75, 0xaa, 0x15, 0xdd, 0x92, - 0x5f, 0x2e, 0x4f, 0xb6, 0x02, 0x60, 0x72, 0xa4, 0x00, 0xe1, 0x92, 0x4e, 0x35, 0x7b, 0x75, 0x4b, - 0xc9, 0x92, 0xc3, 0xe9, 0x32, 0x04, 0x11, 0x07, 0xad, 0x12, 0x51, 0x08, 0xd7, 0xae, 0x5d, 0xa3, - 0x4f, 0xc5, 0x10, 0x26, 0x6b, 0x5e, 0x19, 0xcf, 0xc2, 0x85, 0x0b, 0x45, 0x9f, 0x4d, 0xc3, 0x56, - 0x8a, 0xad, 0x13, 0x77, 0x57, 0x1f, 0x34, 0x68, 0x10, 0xe3, 0xeb, 0xda, 0xb5, 0x2b, 0x6d, 0x81, - 0xd8, 0x0a, 0xf1, 0x58, 0xbf, 0x7e, 0x3d, 0x24, 0x25, 0x25, 0x89, 0x16, 0xf2, 0x92, 0x2d, 0x09, - 0x80, 0x2c, 0xa9, 0x66, 0x65, 0x70, 0xd7, 0x76, 0xd4, 0x87, 0x07, 0xc2, 0x7c, 0xda, 0xbc, 0x79, - 0x33, 0xc5, 0xad, 0x5e, 0xbd, 0x9a, 0x47, 0x49, 0x7e, 0x80, 0x98, 0x11, 0x9d, 0x04, 0xe8, 0x32, - 0x04, 0x49, 0xd9, 0xba, 0x6c, 0xd9, 0x32, 0x68, 0xdb, 0xb6, 0xfe, 0x39, 0x70, 0xbf, 0x7e, 0xfd, - 0x18, 0x1b, 0x56, 0xce, 0xcd, 0x9b, 0x37, 0xa1, 0x43, 0x87, 0x0e, 0x14, 0x87, 0x17, 0x70, 0xdc, - 0x28, 0x02, 0x0f, 0xb2, 0x40, 0x18, 0x8e, 0x1e, 0x3d, 0x4a, 0xf1, 0x38, 0x9c, 0xe0, 0x9e, 0xfd, - 0x6a, 0x52, 0x44, 0x44, 0x04, 0x63, 0x6f, 0xd5, 0xaa, 0x15, 0x1d, 0x9a, 0x10, 0x11, 0x1e, 0x1e, - 0x4e, 0xf1, 0x81, 0x81, 0x81, 0x8c, 0x5e, 0x5c, 0x5c, 0xcc, 0x60, 0x57, 0x01, 0x86, 0xf5, 0x00, - 0xf2, 0xf9, 0x5a, 0x87, 0x7c, 0xc2, 0xdd, 0x41, 0xf8, 0xe4, 0xaa, 0x99, 0x10, 0xaf, 0xdf, 0x29, - 0x67, 0xd2, 0x1a, 0x35, 0x27, 0xd2, 0x9a, 0x39, 0x32, 0x8c, 0x70, 0xe4, 0xeb, 0x14, 0x6c, 0x3c, - 0xc6, 0x6f, 0x1a, 0x2e, 0x58, 0xb0, 0x80, 0xca, 0x8e, 0x8d, 0x8d, 0xe5, 0xba, 0x74, 0xe9, 0xc2, - 0x68, 0xc4, 0x31, 0xba, 0xfb, 0x02, 0xb9, 0x68, 0x5b, 0xe9, 0xde, 0xb9, 0x73, 0xa7, 0x88, 0x0f, - 0x97, 0xe8, 0x87, 0x85, 0x85, 0x71, 0x01, 0x01, 0x01, 0x22, 0x3c, 0xca, 0x48, 0x4b, 0x4b, 0xe3, - 0xf0, 0xfa, 0x41, 0x2e, 0xb2, 0x8c, 0xe6, 0xeb, 0xeb, 0xcb, 0x91, 0x4f, 0x1a, 0x50, 0xb9, 0xfc, - 0xf2, 0x7c, 0xe4, 0x45, 0xfd, 0xc7, 0x8f, 0x1f, 0x67, 0xdf, 0x64, 0x40, 0x1c, 0x99, 0x3c, 0xd0, - 0x5d, 0x1e, 0x78, 0x23, 0x56, 0xac, 0x58, 0xc1, 0x75, 0xee, 0xdc, 0x99, 0x23, 0x3d, 0x97, 0x1e, - 0x64, 0xe2, 0xc0, 0xe4, 0xe2, 0xae, 0x2a, 0x3c, 0x1e, 0xb7, 0xce, 0x98, 0x35, 0x6b, 0x16, 0x5f, - 0x4c, 0xd3, 0x59, 0x97, 0x1e, 0x80, 0x33, 0x17, 0xfc, 0xac, 0x25, 0x7e, 0x5d, 0x83, 0x4f, 0x38, - 0x97, 0xe7, 0x3f, 0x75, 0x89, 0x5d, 0x1d, 0xbf, 0xcc, 0x21, 0x4c, 0xe4, 0xb3, 0x8c, 0x56, 0x38, - 0xa4, 0xe3, 0xd4, 0x13, 0x67, 0x2c, 0x53, 0xa6, 0x4c, 0xa1, 0x9f, 0x1b, 0x21, 0x7b, 0x1e, 0x40, - 0x6a, 0x6a, 0x2a, 0x95, 0x85, 0x9f, 0x1f, 0xc1, 0xeb, 0xc5, 0xae, 0x5d, 0xbb, 0xe8, 0x78, 0x4e, - 0x2a, 0x0b, 0x50, 0xb6, 0x70, 0x28, 0xc1, 0x99, 0x17, 0xaf, 0x17, 0x67, 0x34, 0x7c, 0x42, 0xfd, - 0x38, 0x2b, 0x22, 0x81, 0x64, 0x9f, 0x31, 0xa9, 0xa8, 0xa8, 0xa0, 0x43, 0x21, 0xcf, 0x83, 0x33, - 0xa9, 0x9c, 0x9c, 0x1c, 0x76, 0x08, 0xa7, 0xd2, 0xe8, 0x23, 0x4f, 0xc3, 0x6b, 0x1b, 0xce, 0xa6, - 0xf4, 0x48, 0xe6, 0xf3, 0x00, 0x3d, 0x6a, 0x51, 0x83, 0x0c, 0x5d, 0x7a, 0x80, 0x06, 0xfd, 0xbf, - 0xf9, 0xa2, 0x66, 0x00, 0x5c, 0xdc, 0x04, 0xcc, 0x00, 0x98, 0x01, 0x70, 0x71, 0x0d, 0xb8, 0x58, - 0xbd, 0xd9, 0x03, 0xcc, 0x00, 0xb8, 0xb8, 0x06, 0x5c, 0xac, 0xde, 0xec, 0x01, 0x66, 0x00, 0x5c, - 0x5c, 0x03, 0x2e, 0x56, 0xff, 0x7f, 0x0f, 0x62, 0xce, 0xd5, 0xad, 0xd5, 0x92, 0x0c, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXAudioIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x32, 0x39, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xa6, - 0xa8, 0x92, 0xdf, 0x00, 0x00, 0x09, 0x77, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x99, 0x57, - 0x4c, 0x94, 0x4b, 0x14, 0xc7, 0xd9, 0xa2, 0xd2, 0x44, 0x40, 0x2c, 0x14, 0x51, 0xc0, 0xa8, 0xd8, - 0x30, 0x8a, 0x77, 0xc5, 0xcb, 0xb5, 0xbc, 0x20, 0xf6, 0x68, 0xa2, 0x89, 0x3d, 0x24, 0xbe, 0x58, - 0x5e, 0x7c, 0xd0, 0x18, 0xbd, 0x46, 0xe3, 0x8b, 0x4f, 0x1a, 0x8d, 0x31, 0xea, 0x83, 0x35, 0x6a, - 0x2c, 0xb9, 0x24, 0x46, 0x0d, 0x8a, 0x41, 0x54, 0x04, 0x0d, 0x08, 0x42, 0x58, 0x69, 0xa2, 0xec, - 0x52, 0xa4, 0x08, 0xb2, 0x74, 0x41, 0x81, 0xfb, 0x93, 0xb9, 0x99, 0x7c, 0x77, 0x29, 0xba, 0x1f, - 0x4d, 0x93, 0xfd, 0xb2, 0xd9, 0x9c, 0x99, 0x39, 0x33, 0xdf, 0xf9, 0x9f, 0x36, 0x73, 0xe6, 0xd3, - 0xb4, 0xb7, 0xb7, 0x3b, 0xfc, 0xce, 0x8f, 0xf6, 0x77, 0x16, 0xfe, 0xbb, 0xec, 0x76, 0x00, 0x83, - 0x6d, 0x41, 0xbb, 0x05, 0x6c, 0xb4, 0x40, 0x65, 0x65, 0x65, 0x7e, 0x7e, 0xfe, 0xb7, 0x6f, 0xdf, - 0x6c, 0x9c, 0xd7, 0x2d, 0xbb, 0xa6, 0x6f, 0xb3, 0x50, 0x71, 0x71, 0x71, 0xb5, 0xc5, 0xa2, 0xd7, - 0xe9, 0xbc, 0xc7, 0x7a, 0xbb, 0x7b, 0xb8, 0x2b, 0x5f, 0xcb, 0x8b, 0x34, 0x1a, 0x4d, 0x5d, 0x5d, - 0xdd, 0xf3, 0xe7, 0xcf, 0x1b, 0x1b, 0x1b, 0x97, 0x2e, 0x5d, 0xea, 0xea, 0xea, 0xaa, 0x64, 0x50, - 0x47, 0xf7, 0x25, 0x80, 0x9c, 0x9c, 0x9c, 0x4c, 0xa3, 0xd1, 0xa1, 0x5d, 0xd3, 0xdc, 0xd2, 0xac, - 0xd7, 0xeb, 0x02, 0x03, 0x02, 0xa6, 0x4f, 0x9f, 0xee, 0xec, 0xec, 0x2c, 0x24, 0x43, 0xf4, 0xf2, - 0xf2, 0x72, 0x3f, 0x3f, 0x3f, 0xad, 0x56, 0xfb, 0xf0, 0xe1, 0xc3, 0xcf, 0x9f, 0x3f, 0xaf, 0x5f, - 0xbf, 0x5e, 0x8e, 0xaa, 0x93, 0x9e, 0x59, 0xba, 0x23, 0x47, 0x8e, 0xa8, 0x9e, 0xac, 0x9c, 0xd8, - 0xd0, 0xd0, 0x90, 0x9a, 0x9a, 0x86, 0x9a, 0x1f, 0x3f, 0x8e, 0x8d, 0x7f, 0x12, 0x57, 0x55, 0x59, - 0xd9, 0xd4, 0xd8, 0x44, 0xa7, 0x97, 0xd7, 0x28, 0x27, 0x27, 0x47, 0x38, 0xf5, 0x7a, 0x3d, 0x42, - 0xbf, 0x79, 0xf3, 0xc6, 0xdb, 0xdb, 0x7b, 0xda, 0xb4, 0x69, 0xa0, 0xcd, 0xcd, 0xcd, 0x9d, 0x31, - 0x63, 0x86, 0x72, 0x11, 0x15, 0x74, 0x9f, 0x01, 0x30, 0x9b, 0xcd, 0x38, 0x46, 0x7c, 0x7c, 0x7c, - 0x74, 0xf4, 0x3f, 0xc8, 0xf1, 0xb9, 0xba, 0xda, 0x64, 0x36, 0xe1, 0xeb, 0xad, 0xad, 0xad, 0x63, - 0xc6, 0x8c, 0x71, 0x72, 0x72, 0x42, 0xfd, 0x82, 0x78, 0xf5, 0xea, 0xd5, 0xf8, 0xf1, 0xe3, 0x27, - 0x4c, 0x98, 0xf0, 0xe2, 0xc5, 0x8b, 0xa1, 0x43, 0x87, 0xfa, 0xf8, 0xf8, 0xa8, 0x90, 0x5b, 0x4e, - 0xe9, 0x33, 0x00, 0x65, 0x65, 0x65, 0xb5, 0xb5, 0x75, 0x0f, 0x1e, 0xdc, 0xd7, 0x68, 0x1c, 0xc6, - 0x8e, 0x1d, 0xeb, 0xe2, 0xe2, 0x82, 0xca, 0x09, 0x09, 0x8b, 0xa5, 0x1a, 0x0c, 0xe3, 0xc6, 0x8d, - 0x1b, 0x36, 0x6c, 0x98, 0xd1, 0x68, 0x0c, 0x08, 0x08, 0xc0, 0x85, 0xc0, 0x30, 0x67, 0xce, 0x1c, - 0x7a, 0x9e, 0x3d, 0x7b, 0x36, 0x75, 0xea, 0x54, 0x47, 0xc7, 0xef, 0x26, 0x52, 0xf7, 0xf4, 0x59, - 0x1a, 0x45, 0x2c, 0x44, 0x47, 0x14, 0x6f, 0x6f, 0x1f, 0x4f, 0x4f, 0x4f, 0x0f, 0x0f, 0x8f, 0x11, - 0x23, 0x46, 0xb8, 0xbb, 0xbb, 0x17, 0x14, 0x14, 0x20, 0x6e, 0x42, 0x42, 0x02, 0xee, 0x0e, 0x0c, - 0x5c, 0x28, 0x38, 0x38, 0x18, 0x6c, 0xa9, 0xa9, 0xa9, 0xb3, 0x66, 0xcd, 0xa2, 0x93, 0x51, 0x75, - 0xa2, 0x8b, 0x59, 0x7d, 0x03, 0xa0, 0xa9, 0xa9, 0x29, 0x3b, 0x3b, 0x1b, 0xe9, 0x3d, 0x3c, 0xdc, - 0xbd, 0xbc, 0xbc, 0x46, 0x8e, 0x1c, 0x29, 0x31, 0xd0, 0x24, 0x6f, 0x26, 0x25, 0x25, 0xbe, 0x7e, - 0xfd, 0x1a, 0x6f, 0x01, 0xd5, 0xbb, 0x77, 0xef, 0x16, 0x2e, 0x5c, 0x98, 0x96, 0x96, 0x56, 0x5f, - 0x5f, 0x3f, 0x7f, 0xfe, 0xfc, 0xcc, 0xcc, 0x4c, 0xe2, 0x5b, 0x35, 0x86, 0xbe, 0x01, 0x40, 0x76, - 0x7f, 0xff, 0xfe, 0xbd, 0x4e, 0xa7, 0x77, 0x77, 0xf7, 0x70, 0x73, 0x73, 0x43, 0xf1, 0xc2, 0x02, - 0xd0, 0xc3, 0x87, 0x0f, 0x87, 0xce, 0xcb, 0x7b, 0xf7, 0xf2, 0xe5, 0x4b, 0xc2, 0x60, 0xf2, 0xe4, - 0xc9, 0x26, 0x93, 0x89, 0x90, 0x20, 0x0c, 0x92, 0x92, 0x92, 0xa6, 0x4c, 0x99, 0x82, 0x11, 0x80, - 0x34, 0xc8, 0x00, 0x4a, 0x4a, 0x3e, 0xf2, 0x23, 0x64, 0x51, 0x3c, 0xd9, 0x1d, 0xb9, 0x79, 0x80, - 0x21, 0x09, 0x9d, 0x4e, 0x47, 0xda, 0x49, 0x4c, 0x4c, 0x1c, 0x32, 0x64, 0x08, 0x59, 0x08, 0xad, - 0x13, 0x03, 0x44, 0xc8, 0xd7, 0xaf, 0x5f, 0xf1, 0xa8, 0xbc, 0xbc, 0x3c, 0xe2, 0x44, 0x1d, 0x86, - 0x3e, 0xb0, 0x00, 0xef, 0x36, 0x99, 0x0a, 0xb0, 0x40, 0x5d, 0x5d, 0x2d, 0x79, 0x86, 0x26, 0x18, - 0x04, 0x0c, 0x30, 0xe0, 0x33, 0x18, 0x61, 0xd4, 0xa8, 0x51, 0x44, 0x79, 0x46, 0x46, 0x06, 0xa2, - 0xa3, 0xf5, 0xaa, 0xaa, 0x2a, 0x8c, 0x80, 0x77, 0x7d, 0xf8, 0xf0, 0x81, 0x20, 0xa6, 0x59, 0x5b, - 0x5b, 0x3b, 0x38, 0x00, 0x2c, 0x16, 0x4b, 0x4c, 0xcc, 0xc3, 0x94, 0x94, 0x94, 0xaa, 0xaa, 0x4a, - 0x93, 0xc9, 0x4c, 0x98, 0xea, 0xf5, 0x43, 0xd8, 0x71, 0x9b, 0x9b, 0x9b, 0x09, 0x6b, 0x81, 0x44, - 0xfc, 0xe3, 0x48, 0xa4, 0x5a, 0xbc, 0x85, 0x7e, 0x68, 0xbc, 0x2e, 0x28, 0x28, 0xa8, 0xb0, 0xb0, - 0x10, 0x84, 0xc4, 0x34, 0xf0, 0x06, 0x01, 0x00, 0x81, 0x6b, 0x36, 0x97, 0x14, 0x14, 0x98, 0xd8, - 0xb0, 0xf0, 0x9f, 0x8c, 0x8c, 0x74, 0x12, 0x28, 0xe2, 0xd2, 0x24, 0xcd, 0xe3, 0xdc, 0x6d, 0x6d, - 0x6d, 0x68, 0x9a, 0x07, 0x1a, 0x77, 0xa2, 0x1f, 0xa8, 0x9f, 0x3e, 0x7d, 0x22, 0x9a, 0x2b, 0x2a, - 0x2a, 0x60, 0x26, 0x7c, 0xd9, 0xfb, 0xb0, 0x5b, 0x69, 0x69, 0xe9, 0x40, 0x03, 0xa8, 0xa9, 0xa9, - 0x49, 0x4f, 0x37, 0x56, 0x56, 0x56, 0x39, 0x38, 0x68, 0x5a, 0x5b, 0xbf, 0x7b, 0xff, 0xdb, 0xb7, - 0x6f, 0x11, 0xc8, 0xc7, 0xc7, 0x1b, 0x47, 0x9f, 0x39, 0x73, 0x66, 0x64, 0x64, 0x24, 0xbb, 0x01, - 0x62, 0xb1, 0x5b, 0x91, 0xf2, 0xc9, 0x51, 0x10, 0xd5, 0xd5, 0xd5, 0x64, 0x52, 0xd2, 0x14, 0xbb, - 0x1e, 0xa3, 0x3c, 0x98, 0x8b, 0xa8, 0x50, 0x9d, 0x88, 0xd4, 0xc7, 0x00, 0xdb, 0x56, 0x43, 0x43, - 0x3d, 0xa2, 0x18, 0x0c, 0x86, 0xc6, 0xc6, 0x26, 0xd2, 0x0b, 0x61, 0x90, 0x9c, 0x9c, 0x82, 0x63, - 0xb4, 0xb4, 0xb4, 0x20, 0x37, 0x7e, 0x42, 0xaa, 0xc1, 0x97, 0x90, 0x1b, 0x48, 0xf8, 0x09, 0xc6, - 0xe1, 0x34, 0x61, 0x36, 0x17, 0x62, 0x2e, 0x3c, 0x07, 0x5f, 0x42, 0x74, 0x2c, 0xc0, 0x22, 0x8c, - 0xaa, 0xb3, 0x80, 0xca, 0x69, 0xbc, 0xcc, 0xd5, 0xd5, 0x05, 0xd3, 0x07, 0x05, 0x05, 0xea, 0x74, - 0xd0, 0xae, 0x44, 0x2a, 0xe1, 0x88, 0x7c, 0x48, 0x8c, 0xe8, 0x29, 0x29, 0xaf, 0xbf, 0x7c, 0xf9, - 0xc2, 0xfe, 0x80, 0xac, 0xe8, 0x1e, 0x35, 0xf3, 0x20, 0x25, 0xcd, 0xb2, 0xf2, 0x52, 0xa0, 0x8a, - 0x70, 0x1f, 0x3d, 0x7a, 0x34, 0xd8, 0xf0, 0x31, 0xa6, 0x0c, 0x34, 0x00, 0x5e, 0x89, 0xe8, 0x1a, - 0x4d, 0x9b, 0xb3, 0xb3, 0xcb, 0x82, 0x05, 0x0b, 0xee, 0xdd, 0xbb, 0xb7, 0x6b, 0xd7, 0xae, 0xe6, - 0xe6, 0x96, 0xec, 0xec, 0x9c, 0xe0, 0xe0, 0x29, 0xf1, 0xf1, 0x4f, 0xb0, 0x8f, 0x88, 0x0d, 0x24, - 0x43, 0xcd, 0x3c, 0x10, 0x88, 0x5b, 0x5e, 0x56, 0x86, 0xfb, 0xe1, 0x63, 0x44, 0x08, 0x61, 0x00, - 0x2a, 0x10, 0x62, 0x2b, 0x75, 0x00, 0xd4, 0xbb, 0x10, 0xef, 0x43, 0xf1, 0x45, 0x45, 0x85, 0xc8, - 0xf5, 0xe7, 0x9f, 0xe1, 0xf8, 0x74, 0x71, 0xf1, 0x47, 0xb2, 0x26, 0x82, 0x92, 0x16, 0x03, 0x02, - 0x82, 0xb2, 0xb2, 0xb2, 0xf1, 0x6c, 0xfc, 0x07, 0xad, 0x23, 0x6b, 0x07, 0x84, 0x76, 0xdc, 0x06, - 0x7f, 0x03, 0x1a, 0x04, 0xa2, 0x33, 0xca, 0x3a, 0xc4, 0x37, 0x48, 0x06, 0x01, 0xc0, 0xa4, 0x49, - 0x93, 0xd2, 0xde, 0xa4, 0x7f, 0x2c, 0xa9, 0x68, 0x6b, 0xd3, 0x86, 0x86, 0xce, 0x4d, 0x4c, 0x4c, - 0x40, 0xe7, 0x1d, 0x19, 0xe6, 0x93, 0x9f, 0x9f, 0x2f, 0x25, 0x01, 0xc9, 0x91, 0x2d, 0x8c, 0xdd, - 0x4a, 0x60, 0x60, 0x8b, 0x00, 0x09, 0x7e, 0x65, 0xa9, 0xb1, 0x60, 0x04, 0x29, 0x31, 0x66, 0x81, - 0x4d, 0x36, 0x6d, 0x22, 0x7a, 0x65, 0x01, 0xd4, 0xe6, 0xe4, 0xe8, 0x94, 0x90, 0xf0, 0x9c, 0xfd, - 0x28, 0x34, 0xd4, 0x80, 0x7c, 0x89, 0x89, 0x2f, 0xc8, 0x8f, 0x15, 0x15, 0xe5, 0x9c, 0xe1, 0xfe, - 0x30, 0x18, 0xd8, 0x9e, 0xc0, 0x40, 0x30, 0xf0, 0x10, 0x1b, 0x04, 0x37, 0x0f, 0x04, 0xa7, 0x20, - 0xbc, 0xcb, 0x26, 0x41, 0xbb, 0x63, 0xee, 0x15, 0x00, 0x16, 0x0d, 0x0b, 0x33, 0x64, 0x65, 0x19, - 0x39, 0x48, 0xa0, 0xd7, 0xad, 0x5b, 0xa3, 0x38, 0x2f, 0xc4, 0xc6, 0x3e, 0x4a, 0x4e, 0x4e, 0xbe, - 0x7f, 0xff, 0x7e, 0x6d, 0x4d, 0x4d, 0x44, 0xc4, 0x12, 0xdc, 0x89, 0x1c, 0x8f, 0xc4, 0xf8, 0x18, - 0x0f, 0x6c, 0x18, 0x41, 0xab, 0xd5, 0xf1, 0xdf, 0x9d, 0x4c, 0x36, 0xf5, 0xf7, 0x0a, 0x00, 0x6e, - 0x4d, 0x1e, 0x5c, 0xbe, 0x2c, 0x32, 0x37, 0x2f, 0x27, 0x24, 0x64, 0xc6, 0xaa, 0x55, 0xcb, 0x0f, - 0x1e, 0xfc, 0xdb, 0xd1, 0xd1, 0xc9, 0xd7, 0xd7, 0xd7, 0xc7, 0xc7, 0x97, 0xda, 0x17, 0x7d, 0x87, - 0x87, 0xff, 0x85, 0xfa, 0x39, 0xc0, 0x61, 0x17, 0x72, 0x14, 0xff, 0x6c, 0x6a, 0xe4, 0x4d, 0xdc, - 0xc6, 0x26, 0x41, 0xbb, 0x63, 0x56, 0x5f, 0xd0, 0x20, 0x3d, 0x5a, 0x44, 0x44, 0x7f, 0x7f, 0x7f, - 0x9d, 0x4e, 0x63, 0x34, 0x66, 0xb2, 0x5f, 0x79, 0x7a, 0x8e, 0x1c, 0xee, 0xe6, 0xa6, 0xd5, 0x68, - 0xe7, 0xcd, 0x33, 0x40, 0x37, 0x35, 0x35, 0xe2, 0xdc, 0x41, 0x41, 0x13, 0x21, 0x38, 0xb1, 0x71, - 0x1a, 0x25, 0x76, 0x57, 0xad, 0x5c, 0xe5, 0xef, 0x3f, 0x8e, 0x13, 0x91, 0x6a, 0xbf, 0x57, 0x82, - 0x51, 0x59, 0xd4, 0x23, 0x3d, 0xab, 0xe0, 0xf4, 0x00, 0xc0, 0x2b, 0x68, 0xb2, 0x0d, 0xf3, 0x20, - 0x13, 0xea, 0x9f, 0x38, 0x71, 0x22, 0x99, 0x91, 0x14, 0x44, 0x0c, 0xe0, 0x36, 0xf8, 0x4f, 0x6b, - 0x6b, 0x3b, 0x2d, 0x0e, 0x11, 0x1c, 0xef, 0x28, 0x16, 0x28, 0x7a, 0xc2, 0xc2, 0xe6, 0x75, 0xf8, - 0x12, 0x65, 0x90, 0x46, 0x29, 0x90, 0xad, 0x74, 0xaf, 0x00, 0x20, 0x01, 0xe9, 0x05, 0x00, 0x88, - 0x08, 0x01, 0x18, 0x12, 0x0e, 0x18, 0xc0, 0x43, 0x7e, 0xe4, 0xf8, 0x80, 0x9f, 0xd0, 0x0f, 0x8c, - 0xfc, 0xfc, 0xf7, 0xf5, 0x0d, 0xf5, 0xe4, 0x4d, 0xac, 0x86, 0x11, 0x42, 0x43, 0x43, 0x39, 0x9f, - 0x02, 0x12, 0x7a, 0x70, 0x00, 0x08, 0x3d, 0x21, 0x28, 0x0f, 0x30, 0x04, 0x12, 0xfe, 0x69, 0x22, - 0x90, 0xc8, 0xf1, 0x82, 0x87, 0x4e, 0x80, 0x61, 0x2b, 0x40, 0x82, 0x04, 0x0c, 0x88, 0x2e, 0x8e, - 0x46, 0xbd, 0x97, 0x9e, 0x57, 0xa8, 0xb4, 0x80, 0xad, 0x86, 0xee, 0x3f, 0xfe, 0x5e, 0x65, 0xa1, - 0xfe, 0x13, 0xeb, 0xe7, 0x57, 0xb6, 0x03, 0xf8, 0x79, 0x5d, 0xf5, 0x0f, 0xa7, 0xdd, 0x02, 0xfd, - 0xa3, 0xd7, 0x9f, 0x5f, 0xd5, 0x6e, 0x81, 0x1f, 0xe9, 0x4a, 0x6c, 0x11, 0x6c, 0x67, 0x9d, 0x19, - 0xb9, 0x5d, 0x3c, 0x7a, 0xf4, 0x28, 0xe7, 0x8b, 0xce, 0x43, 0x36, 0xf4, 0x74, 0xec, 0x45, 0xfd, - 0xf5, 0x77, 0xe0, 0xc0, 0x01, 0x79, 0xe0, 0xd9, 0xb1, 0x63, 0x87, 0xd5, 0x6b, 0x36, 0x6c, 0xd8, - 0x80, 0xa0, 0x57, 0xaf, 0x5e, 0xb5, 0xea, 0xb7, 0xa9, 0xd9, 0xbf, 0x2e, 0x44, 0xa1, 0x48, 0x8d, - 0xcf, 0x85, 0x05, 0x82, 0xb2, 0x0d, 0x5b, 0xe9, 0x95, 0x32, 0x1a, 0x78, 0x14, 0xc7, 0x56, 0xfd, - 0xb6, 0x35, 0x7b, 0x86, 0x2b, 0x4e, 0x07, 0x3d, 0xf3, 0xfc, 0x70, 0xf4, 0xc4, 0x89, 0x13, 0xc8, - 0xb4, 0x79, 0xf3, 0xe6, 0xce, 0x9c, 0x9c, 0x32, 0x3a, 0x77, 0xda, 0xd4, 0xd3, 0x85, 0x05, 0xb8, - 0xae, 0xda, 0xb6, 0x6d, 0xdb, 0xdc, 0xb9, 0x73, 0xd1, 0x10, 0x67, 0x77, 0x2e, 0xc1, 0xef, 0xde, - 0xbd, 0x2b, 0xb5, 0x72, 0xec, 0xd8, 0xb1, 0x79, 0x1d, 0x0f, 0x55, 0x0b, 0x9d, 0xe7, 0xcf, 0x9f, - 0x0f, 0xa3, 0xa8, 0x31, 0x18, 0xa8, 0x60, 0x24, 0x0f, 0xc4, 0xad, 0x5b, 0xb7, 0xb6, 0x6c, 0xd9, - 0x12, 0x11, 0x11, 0xc1, 0x17, 0xa0, 0xce, 0xba, 0x8f, 0x8d, 0x8d, 0xe5, 0x82, 0x9a, 0x59, 0xe1, - 0xe1, 0xe1, 0x27, 0x4f, 0x9e, 0x54, 0x4e, 0x14, 0x74, 0x49, 0x49, 0x49, 0x54, 0x54, 0x14, 0x47, - 0x6e, 0xca, 0x6e, 0x04, 0xd8, 0xb7, 0x6f, 0x5f, 0xb7, 0x15, 0x5c, 0x67, 0xb8, 0x88, 0xc7, 0x2a, - 0x9c, 0xc9, 0xc0, 0xc0, 0xb5, 0x07, 0x34, 0x67, 0x2f, 0x2a, 0x12, 0xc1, 0x29, 0x3f, 0x0a, 0xdd, - 0xbe, 0x7d, 0x9b, 0x9e, 0x25, 0x4b, 0x96, 0x88, 0x57, 0x1e, 0x3f, 0x7e, 0x5c, 0x2e, 0xb5, 0x7d, - 0xfb, 0x76, 0xd1, 0x29, 0xfe, 0xc5, 0x79, 0x53, 0x69, 0x81, 0xfd, 0xfb, 0xf7, 0x4b, 0x06, 0x94, - 0x25, 0x27, 0x0a, 0x82, 0xe0, 0xa6, 0xcc, 0x97, 0x0c, 0x82, 0xe0, 0xcb, 0x08, 0xb7, 0x91, 0x56, - 0x9c, 0x34, 0xff, 0xbb, 0xf0, 0x50, 0x0e, 0x44, 0x47, 0x47, 0x23, 0x0d, 0x57, 0xc7, 0x74, 0x52, - 0xbf, 0x0a, 0x0c, 0x32, 0xd4, 0xb8, 0xcd, 0x0c, 0x0c, 0x0c, 0x64, 0x51, 0x01, 0x80, 0x1c, 0x32, - 0x7b, 0xf6, 0x6c, 0x9a, 0x12, 0x80, 0x34, 0x17, 0xda, 0xbd, 0x78, 0xf1, 0xe2, 0xe2, 0xc5, 0x8b, - 0x85, 0x04, 0x9b, 0x36, 0x6d, 0x92, 0x6f, 0xa1, 0x54, 0x88, 0x89, 0x89, 0x59, 0xb3, 0x66, 0x0d, - 0x43, 0x56, 0x00, 0x38, 0x90, 0xf3, 0x69, 0x90, 0x7e, 0x6a, 0xbd, 0x33, 0x67, 0xce, 0xf0, 0x6d, - 0xe1, 0xf0, 0xe1, 0xc3, 0x5c, 0x1c, 0xd1, 0xb3, 0x71, 0xe3, 0x46, 0xb9, 0x82, 0x24, 0xba, 0xb8, - 0xd8, 0x62, 0xdd, 0xb8, 0xb8, 0x38, 0x24, 0xa6, 0xfc, 0xa3, 0xfe, 0x60, 0x21, 0x08, 0x6c, 0x2a, - 0xe4, 0xe0, 0xfa, 0x96, 0x4e, 0x68, 0xa1, 0x57, 0xe0, 0x59, 0x45, 0xe1, 0xa5, 0x4b, 0x97, 0x18, - 0xa5, 0x9f, 0xcf, 0x47, 0x1c, 0x98, 0xf1, 0x04, 0xee, 0x49, 0xb9, 0xd6, 0x15, 0xd3, 0xc5, 0x3f, - 0x8e, 0xc1, 0xc5, 0xe3, 0xd3, 0xa7, 0x4f, 0x95, 0x9d, 0x82, 0xc6, 0x81, 0xf9, 0x12, 0x05, 0xbd, - 0x77, 0xef, 0xde, 0x9d, 0x3b, 0x77, 0x42, 0xe0, 0x84, 0xc0, 0xb8, 0x7e, 0xfd, 0x3a, 0x9a, 0xe5, - 0x58, 0x2e, 0xd3, 0x9a, 0xe0, 0xb7, 0x06, 0x80, 0x02, 0x56, 0xae, 0x5c, 0xf9, 0xe8, 0xd1, 0x23, - 0x86, 0x29, 0x4a, 0x90, 0x12, 0x23, 0x40, 0x33, 0x53, 0x4c, 0xf8, 0xe1, 0x3f, 0x75, 0x3d, 0x3c, - 0xcb, 0x96, 0x2d, 0x43, 0x7a, 0xc1, 0xbc, 0x62, 0xc5, 0x0a, 0x74, 0xf9, 0xc3, 0x89, 0x82, 0x41, - 0x4c, 0x87, 0x5e, 0xbd, 0x7a, 0xb5, 0x9c, 0x02, 0x0d, 0x00, 0x51, 0x5b, 0x93, 0xd6, 0x64, 0x3f, - 0x84, 0x75, 0x10, 0x5f, 0xbb, 0x76, 0x4d, 0x48, 0x7f, 0xe7, 0xce, 0x1d, 0xae, 0x6e, 0x28, 0x08, - 0xd7, 0xae, 0x5d, 0xab, 0x9c, 0x00, 0x2d, 0x74, 0xc0, 0x75, 0x83, 0xe8, 0x27, 0x3c, 0x94, 0x0c, - 0x68, 0x97, 0x26, 0xd7, 0x2a, 0xb2, 0x53, 0x49, 0xcb, 0xce, 0xee, 0x08, 0x0c, 0x2e, 0x86, 0xb8, - 0xc7, 0x96, 0x3c, 0x82, 0x46, 0x9b, 0x9d, 0xef, 0xbf, 0xac, 0x01, 0x60, 0x41, 0xa6, 0x51, 0x34, - 0xe1, 0x48, 0x94, 0x7c, 0xa4, 0x39, 0xae, 0x12, 0xe8, 0xc1, 0xe7, 0xe4, 0x72, 0x22, 0x2a, 0xf8, - 0x48, 0x4a, 0x27, 0x6e, 0x20, 0xa6, 0x48, 0x06, 0x3e, 0xbd, 0xc0, 0xc9, 0x28, 0xdf, 0x63, 0x20, - 0x78, 0x37, 0x0e, 0x29, 0xe7, 0x0a, 0x02, 0x66, 0xf6, 0x66, 0x72, 0x34, 0x4d, 0x25, 0x4d, 0x93, - 0x2b, 0x47, 0xb2, 0x1f, 0xc4, 0xe9, 0xd3, 0xa7, 0x8b, 0x8a, 0x8a, 0x20, 0xd2, 0xd3, 0xd3, 0x51, - 0x3f, 0x04, 0xe9, 0x88, 0xdb, 0x6c, 0x88, 0xff, 0x3d, 0xcc, 0x57, 0x3e, 0x97, 0x2f, 0x5f, 0x16, - 0xc3, 0x84, 0xe6, 0xba, 0x75, 0xeb, 0xa8, 0xd0, 0x45, 0x93, 0xea, 0xf6, 0xca, 0x95, 0x2b, 0x82, - 0x93, 0xfd, 0x5f, 0x74, 0xf2, 0xd9, 0x5d, 0x10, 0xfc, 0xe3, 0x6f, 0x37, 0x6f, 0xde, 0x84, 0x81, - 0x28, 0x97, 0xaf, 0x21, 0x0f, 0x4a, 0x06, 0xf4, 0x77, 0xe8, 0xd0, 0x21, 0x18, 0xb0, 0xad, 0x08, - 0x4a, 0x39, 0x24, 0xa6, 0x9f, 0x3d, 0x7b, 0x56, 0xac, 0x7f, 0xee, 0xdc, 0x39, 0x31, 0x44, 0xfd, - 0x19, 0x12, 0x12, 0x22, 0x68, 0xcc, 0xce, 0x57, 0x36, 0xc1, 0xa0, 0xfc, 0xb7, 0xce, 0x42, 0x28, - 0x66, 0xf7, 0xee, 0xdd, 0x42, 0xc7, 0xcc, 0xe4, 0x2b, 0xe2, 0xa9, 0x53, 0xa7, 0x48, 0x6a, 0x58, - 0xe3, 0xc2, 0x85, 0x0b, 0x62, 0x26, 0xce, 0x43, 0x0a, 0x17, 0xeb, 0x2e, 0x5a, 0xb4, 0x68, 0xcf, - 0x9e, 0x3d, 0xd0, 0xec, 0x18, 0xe8, 0x49, 0x30, 0xf0, 0x26, 0xbe, 0x7c, 0x09, 0x06, 0x5c, 0x82, - 0x4c, 0x2f, 0xaa, 0x64, 0x09, 0x40, 0x22, 0x14, 0x3c, 0xfc, 0x93, 0xa9, 0x25, 0x00, 0x16, 0xb9, - 0x71, 0xe3, 0x86, 0xf2, 0xba, 0x17, 0xab, 0xf2, 0xa1, 0x56, 0x29, 0xb7, 0xa4, 0xbb, 0xae, 0x89, - 0x31, 0x2e, 0xc1, 0x84, 0x82, 0x3b, 0xe7, 0x63, 0xf9, 0x4a, 0x34, 0x0d, 0x2a, 0x09, 0x55, 0xf6, - 0x4b, 0x82, 0x0b, 0x39, 0x76, 0x1f, 0x62, 0x4e, 0xe4, 0x2b, 0xd9, 0xff, 0xf3, 0x04, 0x89, 0x9f, - 0x45, 0x48, 0x62, 0xc2, 0xa9, 0xba, 0x9c, 0xd8, 0x35, 0x80, 0x2e, 0x59, 0x7f, 0xcd, 0x4e, 0xeb, - 0x20, 0xfe, 0x35, 0xa5, 0xec, 0x41, 0x2a, 0x3b, 0x80, 0x1e, 0x94, 0x33, 0x20, 0x43, 0x76, 0x0b, - 0x0c, 0x88, 0x9a, 0x7b, 0x78, 0x89, 0xdd, 0x02, 0x3d, 0x28, 0x67, 0x40, 0x86, 0xec, 0x16, 0x18, - 0x10, 0x35, 0xf7, 0xf0, 0x12, 0xbb, 0x05, 0x7a, 0x50, 0xce, 0x80, 0x0c, 0xfd, 0x0b, 0xbe, 0x35, - 0x47, 0x3f, 0x08, 0xc9, 0x3b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, - 0x60, 0x82 -}; - -static const u_int8_t FLEXAudioIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x1e, 0x78, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x5d, 0x09, 0x7c, 0x94, 0xd5, 0xb5, 0xff, 0x27, 0x93, 0x4c, 0x32, 0xd9, 0xc9, 0x46, 0xc8, 0x06, - 0x04, 0x12, 0x08, 0x09, 0x24, 0x40, 0x58, 0x02, 0x28, 0x9b, 0x40, 0x15, 0xaa, 0xaf, 0x08, 0x42, - 0x9f, 0xd6, 0xa5, 0x82, 0x88, 0x3f, 0xea, 0xd3, 0xb6, 0x56, 0x5b, 0x5f, 0x4b, 0x5d, 0xb0, 0x5a, - 0xab, 0x3e, 0xad, 0xc2, 0xd3, 0xa7, 0xa8, 0x45, 0x7c, 0xe2, 0x82, 0xa2, 0x65, 0x91, 0x45, 0xd9, - 0x21, 0x80, 0x81, 0x40, 0x08, 0xbb, 0x40, 0x12, 0x92, 0x90, 0x7d, 0x5f, 0x67, 0xf2, 0xbd, 0xff, - 0xf9, 0xe0, 0x1b, 0x26, 0x99, 0x49, 0x26, 0xcb, 0x84, 0xa5, 0x2f, 0xf7, 0xf7, 0x9b, 0xf9, 0xee, - 0x77, 0xef, 0xb9, 0xdb, 0x39, 0xf7, 0x9e, 0xbb, 0x9d, 0x73, 0x3e, 0x27, 0x85, 0x0e, 0xed, 0x70, - 0xce, 0xad, 0xc1, 0x7e, 0x56, 0x59, 0x6f, 0x15, 0x6d, 0x33, 0x81, 0xab, 0xab, 0x0e, 0x5e, 0x5e, - 0x5e, 0x48, 0xd6, 0x11, 0xbe, 0x59, 0x05, 0x6c, 0x26, 0xc8, 0x2d, 0xae, 0x82, 0xab, 0xab, 0x2b, - 0xe6, 0x4d, 0x9f, 0x8e, 0x06, 0xa6, 0x59, 0x5d, 0x66, 0x34, 0x97, 0xe4, 0xd4, 0xbc, 0x0d, 0x46, - 0xa3, 0x11, 0xbf, 0xfe, 0xed, 0xef, 0xd0, 0x6f, 0xc8, 0x18, 0xe4, 0x64, 0x9d, 0x06, 0x0b, 0xc3, - 0x93, 0x4f, 0xfe, 0x16, 0xde, 0xae, 0x2e, 0x97, 0x12, 0x49, 0x02, 0x4b, 0xf7, 0xe9, 0x67, 0x9f, - 0x29, 0x09, 0xc3, 0x47, 0x2a, 0xb7, 0x4d, 0x9f, 0xae, 0x2c, 0xff, 0xf4, 0x5b, 0x25, 0x36, 0x7e, - 0x88, 0x65, 0xb4, 0xc2, 0x2a, 0x5a, 0xbb, 0xe4, 0xd1, 0xa3, 0x95, 0x99, 0x3f, 0xff, 0x85, 0x75, - 0x04, 0x43, 0xac, 0xaa, 0x64, 0xae, 0x6c, 0x0b, 0x1e, 0x9b, 0x8d, 0x6e, 0x01, 0x56, 0x0d, 0x36, - 0x27, 0x58, 0xb9, 0x72, 0xa5, 0x19, 0xee, 0x77, 0xbf, 0xfb, 0x9d, 0xd9, 0xef, 0xe4, 0xe4, 0x84, - 0xc6, 0xc6, 0xc6, 0x2b, 0xef, 0x52, 0x51, 0xf3, 0x5b, 0x1b, 0x3c, 0xe6, 0x12, 0xda, 0x00, 0xab, - 0x82, 0x38, 0xae, 0xd1, 0x2b, 0x72, 0xab, 0x6d, 0x16, 0x6a, 0x55, 0xa5, 0xf7, 0x56, 0x7e, 0x01, - 0x5f, 0xbf, 0x1e, 0x38, 0xb6, 0xf4, 0x35, 0x35, 0x41, 0x63, 0xf3, 0x26, 0xda, 0xa2, 0x8e, 0xbb, - 0xbb, 0xbb, 0x12, 0x17, 0x3f, 0x58, 0x79, 0xe5, 0x1f, 0x9f, 0x5b, 0x45, 0x5f, 0xee, 0x20, 0x57, - 0x4a, 0x1f, 0x38, 0x28, 0x1e, 0x5f, 0xad, 0xf9, 0x0a, 0xe9, 0x67, 0x4b, 0x71, 0xb6, 0xb4, 0x0c, - 0x59, 0x65, 0x95, 0x88, 0xf0, 0xf5, 0x32, 0x03, 0x58, 0x35, 0x7a, 0xce, 0x3d, 0x0f, 0xa0, 0x24, - 0x2f, 0x1b, 0xd5, 0xd5, 0xd5, 0x48, 0x3f, 0x76, 0x14, 0xd1, 0x31, 0x71, 0xd8, 0x9f, 0xb2, 0xcb, - 0x9c, 0xc0, 0xaa, 0x2f, 0x99, 0x4c, 0x26, 0xe5, 0x96, 0x5b, 0x6f, 0xb7, 0xaa, 0x8a, 0x16, 0x60, - 0x55, 0xc2, 0x95, 0xac, 0x6c, 0xfb, 0xac, 0xb0, 0xa4, 0x81, 0x49, 0x97, 0xb0, 0xe5, 0xd4, 0x04, - 0x12, 0xe9, 0xe6, 0xe6, 0x06, 0x79, 0x06, 0x05, 0x05, 0x21, 0x27, 0x27, 0xa7, 0x09, 0xec, 0x5d, - 0x77, 0xdd, 0xa5, 0xc6, 0x49, 0xa0, 0xe3, 0xaa, 0xd4, 0xa4, 0x08, 0x8b, 0x97, 0x76, 0x97, 0x60, - 0x91, 0xb6, 0x4d, 0xde, 0x16, 0x91, 0xd4, 0x3c, 0xf5, 0xfb, 0x9f, 0x6d, 0xc4, 0xdf, 0xff, 0x67, - 0x25, 0x64, 0xec, 0x6c, 0x4e, 0x3f, 0xa5, 0x46, 0x37, 0xc8, 0x4b, 0xf3, 0xae, 0xd6, 0x3c, 0xa1, - 0x46, 0xbf, 0xd6, 0x9e, 0x3b, 0xf6, 0xec, 0x53, 0xa6, 0xfd, 0xf4, 0x4e, 0xc5, 0xdb, 0xc7, 0x47, - 0x09, 0x09, 0xef, 0xad, 0x3c, 0xfe, 0xbf, 0xff, 0x54, 0x16, 0xbf, 0xb6, 0xec, 0x52, 0x12, 0xf6, - 0x0b, 0xa5, 0x91, 0x3d, 0xba, 0x05, 0xd7, 0x26, 0x14, 0x09, 0x2b, 0x4c, 0xd9, 0x77, 0x00, 0x67, - 0x0b, 0x6a, 0x90, 0x90, 0x94, 0x80, 0xb4, 0xb4, 0x0c, 0x2c, 0x7d, 0x69, 0x31, 0x22, 0x07, 0xc4, - 0x62, 0xea, 0xf4, 0xdb, 0x11, 0x37, 0x65, 0x32, 0x46, 0x79, 0x08, 0x17, 0xb6, 0x76, 0x76, 0x51, - 0xf4, 0xb3, 0x59, 0x73, 0xf0, 0xe0, 0xc2, 0x47, 0xa5, 0x3f, 0x60, 0xcd, 0x47, 0xcb, 0xb0, 0x6c, - 0xc9, 0xd3, 0x28, 0xcc, 0xb9, 0x80, 0xda, 0xaa, 0x72, 0xe4, 0x5f, 0xc8, 0xc2, 0xea, 0x0f, 0x97, - 0xe3, 0xe3, 0xe7, 0x5e, 0xb0, 0xce, 0xf9, 0x72, 0x48, 0x9b, 0x5a, 0xf0, 0xcb, 0x79, 0xf3, 0xf0, - 0xf9, 0xe7, 0x5f, 0xc0, 0xd8, 0x60, 0xc4, 0xc8, 0xa4, 0xe1, 0x44, 0xbb, 0x11, 0x6f, 0xbf, 0xf3, - 0x2e, 0x76, 0x6c, 0xdf, 0x06, 0x45, 0xef, 0x03, 0x93, 0xb1, 0x1e, 0x0b, 0xe7, 0xdd, 0x67, 0xb3, - 0x90, 0x36, 0x15, 0x60, 0x33, 0x65, 0x1b, 0x03, 0xed, 0xa2, 0xa8, 0x79, 0x3e, 0xdb, 0xb7, 0x6f, - 0xc7, 0xfe, 0xfd, 0xfb, 0xcd, 0xc1, 0x06, 0x83, 0xc1, 0xec, 0xb7, 0xe9, 0xb1, 0x24, 0xfe, 0x94, - 0x29, 0x53, 0x94, 0xb4, 0xb4, 0x34, 0x65, 0xf2, 0xe4, 0xc9, 0xca, 0xf9, 0xf3, 0xe7, 0xd5, 0x4e, - 0xb8, 0x6e, 0xdd, 0x3a, 0x25, 0x30, 0x30, 0x50, 0x05, 0x63, 0x06, 0x8a, 0x87, 0x87, 0xc7, 0xa5, - 0xce, 0xc9, 0x90, 0xa7, 0x9f, 0x7e, 0xda, 0xec, 0x17, 0x00, 0x89, 0x7f, 0xef, 0xbd, 0xf7, 0x9a, - 0x86, 0xa9, 0x29, 0x2f, 0xff, 0x09, 0x80, 0xf6, 0xd3, 0x12, 0x74, 0xe4, 0xdd, 0xdf, 0xdf, 0xdf, - 0x9c, 0xed, 0xf5, 0x47, 0x03, 0xb6, 0xa8, 0x5d, 0xee, 0xc6, 0x6f, 0x41, 0xbb, 0xbb, 0xa9, 0x30, - 0xb7, 0x4f, 0xca, 0xeb, 0x50, 0x61, 0xba, 0xb2, 0x80, 0x68, 0x15, 0x67, 0x66, 0x72, 0xb7, 0xe2, - 0xd9, 0xb4, 0xeb, 0x90, 0xb2, 0x78, 0xc9, 0xab, 0x4a, 0xfa, 0xc9, 0xb3, 0x64, 0x6c, 0x64, 0x6e, - 0x97, 0xdd, 0x47, 0x67, 0xf3, 0x35, 0x6f, 0x8b, 0x4f, 0xab, 0x59, 0xb3, 0x39, 0xa4, 0xc9, 0x64, - 0x54, 0x3e, 0xdb, 0xb0, 0x57, 0xf1, 0xf6, 0xf6, 0x56, 0x7a, 0xf4, 0xf0, 0x57, 0xe6, 0xbd, 0xf1, - 0x9e, 0xb2, 0xed, 0x87, 0x23, 0xca, 0x9b, 0x27, 0x72, 0x54, 0xd0, 0x2d, 0x25, 0xb5, 0xcd, 0x93, - 0x34, 0x79, 0xb7, 0x8b, 0x22, 0x67, 0x67, 0x1d, 0x42, 0x7b, 0xf6, 0x40, 0x43, 0x43, 0x03, 0x64, - 0x99, 0x71, 0x96, 0x6b, 0xdd, 0xa7, 0x52, 0xd2, 0x70, 0x87, 0x97, 0x13, 0x3e, 0xce, 0xab, 0xc4, - 0x24, 0x3f, 0x37, 0xec, 0xaa, 0x35, 0xb5, 0x88, 0x25, 0xbb, 0x05, 0x48, 0xca, 0x5e, 0x3d, 0x3c, - 0xf1, 0x93, 0x3b, 0xe6, 0xa2, 0xae, 0xb6, 0x06, 0x91, 0x55, 0xc5, 0xb8, 0xcb, 0xcb, 0x80, 0x67, - 0x8f, 0x9c, 0xc1, 0x64, 0x5d, 0x1d, 0xbe, 0xad, 0x34, 0x62, 0xac, 0xbb, 0x0e, 0x2d, 0x51, 0xa4, - 0x4d, 0x05, 0xfc, 0x65, 0xc9, 0x33, 0x58, 0xf6, 0xf7, 0x97, 0xf1, 0xfc, 0x5f, 0xfe, 0x86, 0xc7, - 0x7e, 0xf9, 0x00, 0x6a, 0xca, 0x4b, 0x11, 0x93, 0x93, 0x8d, 0xc7, 0xd6, 0x6c, 0x82, 0xdf, 0xc9, - 0xa3, 0x6a, 0xed, 0x57, 0x56, 0xd9, 0x2e, 0xc2, 0x6e, 0x01, 0xfe, 0x81, 0x81, 0x88, 0x4d, 0x48, - 0xc2, 0x6f, 0x1f, 0x7f, 0x1c, 0x33, 0x6e, 0x9f, 0x81, 0x83, 0x07, 0xd3, 0x98, 0xa1, 0x0b, 0xb2, - 0xf3, 0xf2, 0xe0, 0x1e, 0xdc, 0x1b, 0x9f, 0xa7, 0x5e, 0x2a, 0xe0, 0x17, 0x9e, 0xb6, 0xb3, 0xb2, - 0x3b, 0xd0, 0x66, 0xfd, 0xfb, 0xbd, 0xc8, 0xc9, 0xce, 0x42, 0x6c, 0x4c, 0x7f, 0xd4, 0x70, 0x7d, - 0x35, 0xe3, 0xce, 0x39, 0xd8, 0xfd, 0xfd, 0x06, 0xae, 0xb3, 0xce, 0xc0, 0xcb, 0xc7, 0x07, 0x20, - 0x8d, 0x3e, 0x59, 0xf1, 0x01, 0xbc, 0x3c, 0xdc, 0xd5, 0x96, 0x34, 0xff, 0xb3, 0x5d, 0xac, 0x05, - 0x94, 0x8b, 0x8b, 0x1e, 0x3e, 0xbe, 0x7e, 0x38, 0x75, 0xea, 0x14, 0x8a, 0x4b, 0x8a, 0xb1, 0x72, - 0xf9, 0x7f, 0x23, 0x2f, 0x27, 0x1f, 0x81, 0x3d, 0x7b, 0xe1, 0x70, 0xea, 0x01, 0x64, 0x9d, 0xff, - 0x11, 0x9b, 0xb6, 0xa5, 0x58, 0xa4, 0x68, 0xea, 0xb5, 0x5a, 0x3e, 0x36, 0x8d, 0x06, 0xc6, 0x8f, - 0x49, 0xc2, 0x8b, 0x2f, 0xbd, 0x8c, 0x0b, 0xd9, 0x99, 0xe8, 0x1f, 0x3d, 0x10, 0xf7, 0xdd, 0x33, - 0x17, 0xf3, 0x1f, 0x5a, 0x80, 0x95, 0x1f, 0xad, 0xc0, 0x6d, 0x53, 0x26, 0x00, 0x7a, 0x5f, 0xdc, - 0x3c, 0x32, 0xae, 0x79, 0xb2, 0x2b, 0xef, 0x4d, 0x3a, 0x6d, 0x0b, 0x2f, 0xf3, 0xe6, 0xcf, 0x53, - 0x12, 0x93, 0x46, 0x2a, 0x3f, 0xbf, 0xf7, 0x41, 0x25, 0xfd, 0xe8, 0xd1, 0x16, 0xa0, 0x6c, 0x07, - 0xdb, 0xa5, 0xc1, 0x95, 0xaa, 0x74, 0xcc, 0x67, 0x97, 0x06, 0x1d, 0xcb, 0xf6, 0x4a, 0xaa, 0x76, - 0x17, 0xf0, 0xfd, 0xf7, 0xdf, 0x9b, 0x53, 0x73, 0x3a, 0x35, 0xfb, 0x5b, 0xf2, 0xb4, 0x1b, 0x45, - 0x3d, 0x7b, 0xf6, 0xc4, 0xc5, 0x8b, 0x17, 0x5b, 0xca, 0xcf, 0x3a, 0x5c, 0x23, 0xcd, 0xb4, 0x69, - 0xd3, 0xcc, 0x13, 0xbd, 0x84, 0xe9, 0x74, 0x3a, 0x35, 0x8a, 0x29, 0xcc, 0x4f, 0x59, 0x0c, 0x68, - 0xef, 0x12, 0x98, 0x94, 0x94, 0xa4, 0xc6, 0xc9, 0x5f, 0xef, 0xde, 0xbd, 0x95, 0x5b, 0x6f, 0xbd, - 0x55, 0x71, 0x76, 0x76, 0x56, 0x17, 0x0e, 0x5a, 0x84, 0x99, 0x9b, 0x4a, 0xc2, 0xc5, 0x8b, 0x17, - 0x9b, 0x33, 0xf0, 0xf4, 0xf4, 0x54, 0x61, 0xb4, 0x0c, 0xb5, 0x27, 0x37, 0x05, 0x5a, 0x5a, 0xe5, - 0xeb, 0xaf, 0xbf, 0x36, 0xfb, 0xb5, 0x78, 0x09, 0x68, 0xe2, 0xd7, 0x20, 0x24, 0x50, 0x7e, 0xdc, - 0x59, 0x28, 0x8f, 0x3d, 0xf6, 0x98, 0x5a, 0x0b, 0x2d, 0xec, 0x4f, 0x7f, 0xfa, 0x93, 0x32, 0x62, - 0xc4, 0x08, 0x35, 0xbe, 0x6f, 0xdf, 0xbe, 0x4a, 0x72, 0x72, 0xb2, 0x32, 0x75, 0xea, 0x54, 0xf5, - 0x5d, 0x60, 0x56, 0xac, 0x58, 0xa1, 0x1c, 0x3f, 0x7e, 0xdc, 0xfc, 0xae, 0xe5, 0x29, 0xcf, 0x76, - 0xd3, 0x80, 0x19, 0xb6, 0xcb, 0xb5, 0xbb, 0x17, 0xb5, 0x2b, 0x77, 0x02, 0xdf, 0xf8, 0x05, 0x74, - 0x39, 0x0d, 0xda, 0x8b, 0xd2, 0xf6, 0xc2, 0x77, 0x39, 0x09, 0x2c, 0x2b, 0x24, 0xdd, 0xd8, 0xd1, - 0xce, 0xe1, 0x0d, 0xa8, 0xad, 0xaf, 0x47, 0x5d, 0xbd, 0x1c, 0xb0, 0x5d, 0x71, 0x15, 0x46, 0x13, - 0x7e, 0x2c, 0x29, 0x87, 0x76, 0x76, 0xb0, 0xb3, 0xb8, 0x1a, 0xdb, 0x78, 0x1c, 0x07, 0xc5, 0xf6, - 0x32, 0xe1, 0x4a, 0x4a, 0xfb, 0x3e, 0x87, 0x35, 0xe0, 0xcb, 0x75, 0x9b, 0xf0, 0xe9, 0x86, 0x14, - 0x04, 0x07, 0x06, 0xc0, 0xc7, 0xdb, 0x0b, 0x3c, 0xe3, 0x81, 0x1f, 0x0f, 0x86, 0x7e, 0x36, 0xfb, - 0x6e, 0xac, 0x38, 0x78, 0x16, 0x55, 0x35, 0xf5, 0x78, 0x2f, 0xa7, 0x18, 0x07, 0xab, 0xeb, 0x31, - 0xce, 0xdf, 0x03, 0xe3, 0xfd, 0x3d, 0x59, 0x3b, 0x27, 0xfc, 0x33, 0xaf, 0x14, 0xc6, 0xc6, 0x8e, - 0xd3, 0xc6, 0x21, 0x0d, 0x20, 0x3f, 0x43, 0x75, 0x55, 0x0d, 0x7a, 0x06, 0x05, 0xc0, 0xc9, 0xd9, - 0x45, 0x3d, 0x86, 0x71, 0x63, 0x03, 0x9c, 0x9c, 0x9d, 0xb1, 0xf5, 0xbb, 0x0d, 0xd8, 0xf1, 0xc1, - 0x5b, 0x98, 0x36, 0x6e, 0x14, 0x52, 0x5e, 0x7d, 0x15, 0x21, 0xd5, 0x95, 0xe0, 0xd2, 0x19, 0x6f, - 0x1c, 0xbf, 0xa0, 0x52, 0x60, 0x46, 0x88, 0x1f, 0x5c, 0x9c, 0x9d, 0xb0, 0xa3, 0x8a, 0x54, 0xb3, - 0x38, 0xee, 0xb3, 0x8f, 0xfb, 0x4b, 0x10, 0x0e, 0x1b, 0xc4, 0xe5, 0x15, 0x95, 0x38, 0x71, 0x2e, - 0x13, 0xc5, 0xe5, 0x26, 0xcc, 0x98, 0x30, 0x94, 0x14, 0x30, 0x40, 0xe7, 0xe2, 0x02, 0x77, 0x0f, - 0x2f, 0x8c, 0xbd, 0x7b, 0x01, 0x6a, 0x4f, 0xa7, 0x43, 0xd7, 0x58, 0x8f, 0xc6, 0x39, 0x0f, 0x61, - 0x8a, 0x5e, 0xc1, 0xed, 0x23, 0x86, 0xa0, 0x4f, 0x64, 0x18, 0xbe, 0x2d, 0xab, 0xc3, 0x4f, 0x7c, - 0xdd, 0xd4, 0xda, 0xd4, 0x90, 0x12, 0x45, 0x8d, 0x4e, 0x08, 0xb7, 0xbb, 0x8e, 0xba, 0xd2, 0x3c, - 0x87, 0x50, 0x40, 0xb2, 0x93, 0x6e, 0xd3, 0x58, 0x53, 0x89, 0xe1, 0x83, 0x22, 0x70, 0x2a, 0xa7, - 0x1c, 0x3a, 0x57, 0x3d, 0x16, 0xfd, 0xc7, 0x13, 0x78, 0xe1, 0xad, 0x7f, 0x60, 0xe2, 0xb0, 0xe1, - 0x98, 0xfd, 0xe0, 0x02, 0xfc, 0x78, 0xfa, 0x0c, 0xa6, 0xa1, 0x0e, 0xeb, 0x97, 0xbd, 0x8e, 0xf7, - 0xcb, 0x6a, 0xb1, 0xe4, 0xf5, 0x77, 0x30, 0xb8, 0xae, 0x02, 0x67, 0x88, 0x7c, 0x19, 0x35, 0x06, - 0x52, 0x22, 0xdc, 0xc9, 0x84, 0x73, 0xc6, 0xb6, 0x77, 0x29, 0x87, 0x34, 0xa0, 0xa6, 0xa6, 0x06, - 0x3c, 0x44, 0xc2, 0xba, 0x4d, 0xdb, 0x71, 0xc7, 0x4f, 0x6f, 0x47, 0x61, 0xd6, 0x31, 0xa4, 0x1d, - 0x49, 0x47, 0x44, 0x74, 0x3c, 0xfa, 0x47, 0x04, 0x62, 0x78, 0x6c, 0x0c, 0x9c, 0x6b, 0x1b, 0x30, - 0xff, 0x0f, 0x7f, 0x41, 0x51, 0x51, 0x21, 0x4c, 0x9e, 0xbe, 0x28, 0x5b, 0xf5, 0x31, 0x6a, 0x43, - 0x7a, 0xe1, 0xa1, 0xf9, 0x0b, 0x51, 0x7e, 0xec, 0x04, 0xb6, 0xf0, 0x74, 0x6b, 0xdb, 0x91, 0xe3, - 0x38, 0x5a, 0x54, 0x8e, 0xbc, 0xf2, 0x9a, 0x2b, 0x28, 0xb6, 0xe3, 0xeb, 0x74, 0x17, 0xba, 0x73, - 0xd6, 0x2c, 0x14, 0x95, 0x56, 0xc2, 0xd3, 0xcb, 0x1b, 0x91, 0x11, 0xa1, 0x48, 0x1e, 0x35, 0x0a, - 0xeb, 0xd7, 0xad, 0x85, 0x9b, 0xbb, 0x1b, 0x86, 0x0d, 0x4d, 0x44, 0xd2, 0x98, 0x89, 0xd8, 0x9e, - 0x72, 0x08, 0x45, 0xb9, 0x99, 0xf0, 0xf7, 0xf3, 0xc6, 0x85, 0xac, 0x4c, 0x9c, 0x3e, 0x77, 0x1e, - 0x1e, 0x72, 0x5c, 0xc9, 0xca, 0x99, 0x74, 0x3a, 0x28, 0x75, 0x75, 0xb8, 0xff, 0xe1, 0x5f, 0xe1, - 0x67, 0x53, 0xc6, 0xda, 0xa9, 0xae, 0x75, 0x74, 0xa7, 0x1b, 0xf0, 0xe4, 0xd3, 0x8b, 0x91, 0x9b, - 0x77, 0x91, 0x95, 0x71, 0x42, 0x2d, 0x2b, 0x52, 0x54, 0x90, 0x83, 0xa9, 0xb7, 0x4c, 0x42, 0x4a, - 0xca, 0x7e, 0xee, 0x15, 0x1b, 0xd5, 0x4a, 0xd6, 0xd5, 0xd4, 0x22, 0x3e, 0x71, 0x18, 0x7a, 0xf5, - 0x4f, 0xc4, 0x2b, 0x8b, 0x1f, 0x87, 0x2b, 0x2b, 0xef, 0xd7, 0xc3, 0x1f, 0x2e, 0x6e, 0xee, 0x30, - 0xd0, 0xaf, 0xe8, 0x5c, 0xe0, 0xc5, 0x06, 0x3f, 0xff, 0xc2, 0x5f, 0x31, 0x2c, 0x3e, 0xda, 0xba, - 0x96, 0xad, 0x84, 0x74, 0xba, 0x01, 0x67, 0xce, 0x9c, 0xc1, 0xfe, 0x1f, 0x52, 0xf1, 0xf6, 0xbb, - 0x1f, 0x70, 0x63, 0x55, 0x85, 0x82, 0x8b, 0x79, 0x5c, 0xb1, 0xe6, 0xa2, 0x57, 0x48, 0x08, 0x82, - 0x03, 0x02, 0x10, 0x37, 0x38, 0x1e, 0xc5, 0x45, 0x45, 0xf8, 0x91, 0x58, 0xf7, 0xe4, 0xc0, 0xf6, - 0xf3, 0xf5, 0xc6, 0xc8, 0x71, 0x93, 0x11, 0x18, 0x1e, 0x85, 0xf5, 0x6b, 0x3e, 0xc1, 0xc1, 0xfd, - 0x29, 0x30, 0x99, 0x1a, 0x70, 0xc7, 0x5d, 0xf7, 0x61, 0xc6, 0xad, 0xd3, 0x30, 0x7d, 0xea, 0xf8, - 0x56, 0xaa, 0x6b, 0x1d, 0xd5, 0xe9, 0x06, 0x48, 0x96, 0xbc, 0xa6, 0xc1, 0x5d, 0xb3, 0xe7, 0xe0, - 0xcc, 0xe9, 0xd3, 0x38, 0x78, 0xe8, 0x20, 0xbb, 0x93, 0x17, 0x06, 0xc6, 0x0d, 0x46, 0x48, 0xaf, - 0x30, 0x62, 0x3a, 0x00, 0xf9, 0xf9, 0x79, 0xf8, 0xed, 0x63, 0x8b, 0x48, 0x99, 0x5b, 0xcc, 0x35, - 0x28, 0x2c, 0x2c, 0x44, 0x2e, 0x4f, 0xba, 0xeb, 0xea, 0x6a, 0x70, 0x31, 0x37, 0x17, 0x23, 0x46, - 0x8d, 0x46, 0x70, 0xcf, 0x10, 0x73, 0x7c, 0x5b, 0x3d, 0x0e, 0x69, 0x80, 0x65, 0x61, 0xb9, 0xb9, - 0x39, 0x38, 0x74, 0xf0, 0x20, 0x5c, 0xf5, 0xae, 0x70, 0x37, 0x78, 0x23, 0x31, 0x71, 0x08, 0xbc, - 0x3c, 0x65, 0xd2, 0xea, 0x1a, 0xe7, 0xf0, 0x06, 0x74, 0x4d, 0x35, 0x5b, 0xce, 0xd5, 0x21, 0x6c, - 0xb4, 0xe5, 0xec, 0xbb, 0x3e, 0xa6, 0x4b, 0x1b, 0xb0, 0x67, 0xcf, 0x1e, 0xf5, 0xf6, 0x46, 0x6e, - 0x77, 0xe4, 0xd7, 0xdc, 0x71, 0x6f, 0x66, 0x33, 0xbc, 0x39, 0x5c, 0xab, 0xef, 0x96, 0x1b, 0x34, - 0xcd, 0xbf, 0x79, 0xf3, 0x66, 0x99, 0x0a, 0xcd, 0x3f, 0xd9, 0x08, 0x6a, 0xee, 0xe3, 0x8f, 0x3f, - 0x36, 0x87, 0x4b, 0xd8, 0xcc, 0x99, 0x33, 0xd5, 0xf7, 0x88, 0x88, 0x08, 0x0d, 0x44, 0x7d, 0x8e, - 0x1c, 0x39, 0x52, 0x0d, 0x4f, 0x4c, 0x4c, 0x54, 0x78, 0x35, 0xa5, 0xfa, 0x2d, 0x01, 0xe4, 0x42, - 0x4f, 0x2b, 0xc3, 0x32, 0x5c, 0xf3, 0xcf, 0x9f, 0x3f, 0xdf, 0x1c, 0x2f, 0x70, 0x19, 0x19, 0x19, - 0x5a, 0x54, 0x93, 0xa7, 0x79, 0x5b, 0xdc, 0x24, 0x94, 0x2f, 0xb2, 0x53, 0x9d, 0x34, 0x69, 0x92, - 0x32, 0x6b, 0xd6, 0x2c, 0x35, 0x23, 0xcb, 0x46, 0xc8, 0x96, 0x59, 0x32, 0xd5, 0x9c, 0xf8, 0xb5, - 0x03, 0xf9, 0xaf, 0xbe, 0xfa, 0x4a, 0x8d, 0x5b, 0xbe, 0x7c, 0xb9, 0x16, 0x6d, 0xae, 0x88, 0x39, - 0xe0, 0xb2, 0x47, 0xb6, 0xd5, 0x96, 0xf9, 0x68, 0xf1, 0x12, 0x36, 0x60, 0xc0, 0x00, 0xed, 0x55, - 0x7d, 0x4a, 0x18, 0x6f, 0xc3, 0x9b, 0x84, 0xc9, 0xcb, 0x95, 0x5a, 0x5c, 0x8e, 0x22, 0x7b, 0x53, - 0x33, 0xbd, 0xff, 0xfe, 0xfb, 0xcd, 0xc0, 0x92, 0x58, 0xaf, 0xd7, 0x9b, 0xdf, 0x87, 0x0f, 0x1f, - 0xae, 0xc2, 0xf0, 0xb2, 0x58, 0xc9, 0xcd, 0xcd, 0x55, 0xfd, 0x5a, 0x03, 0xb4, 0xed, 0xf7, 0xc0, - 0x81, 0x03, 0x55, 0xf8, 0x92, 0x92, 0x12, 0x35, 0xde, 0x56, 0x45, 0x5b, 0x6b, 0x80, 0xc0, 0xd7, - 0xd5, 0xd5, 0xa9, 0x79, 0xbc, 0xf2, 0xca, 0x2b, 0x6a, 0x1e, 0xb7, 0xdd, 0x76, 0x9b, 0xb9, 0x0e, - 0x9a, 0xc7, 0xaa, 0x01, 0x5a, 0xc4, 0x81, 0x03, 0x07, 0x5a, 0x24, 0x9b, 0xc0, 0x48, 0xe6, 0x3b, - 0x77, 0xee, 0xd4, 0xc0, 0xad, 0x9e, 0x72, 0xc9, 0xba, 0x61, 0xc3, 0x06, 0xab, 0xf0, 0xf6, 0x04, - 0xe4, 0xe7, 0xe7, 0x2b, 0xd2, 0x9d, 0x05, 0x51, 0x2d, 0xb9, 0x6e, 0x36, 0x4a, 0x52, 0x5f, 0x53, - 0xd7, 0xa5, 0x6c, 0xf4, 0x6a, 0xb4, 0xec, 0x86, 0x6f, 0x40, 0xf7, 0x18, 0xb8, 0x1a, 0xdd, 0xa4, - 0xb5, 0x32, 0x6e, 0xf8, 0x2e, 0x74, 0xd5, 0x1a, 0x20, 0x47, 0x58, 0x32, 0x1b, 0x39, 0xda, 0xb5, - 0xe3, 0x00, 0xa3, 0xe3, 0x45, 0x9f, 0xab, 0x31, 0xe1, 0x50, 0xad, 0x11, 0x39, 0x44, 0xd7, 0x78, - 0x83, 0x33, 0x06, 0x71, 0xaf, 0x60, 0xbd, 0xb4, 0xeb, 0x60, 0xfe, 0x2d, 0xcd, 0x70, 0x1d, 0x09, - 0x37, 0x1a, 0x4d, 0x4a, 0x4d, 0x6d, 0x9d, 0x22, 0x4f, 0x4b, 0x97, 0x92, 0x5f, 0x66, 0x7e, 0x35, - 0x72, 0x56, 0x5d, 0x7a, 0xb6, 0x40, 0x29, 0x69, 0x30, 0x9a, 0xc3, 0x3a, 0xe3, 0x71, 0x18, 0x17, - 0x2a, 0x28, 0x2a, 0xc6, 0xe6, 0xbd, 0xc7, 0x91, 0x73, 0xee, 0x04, 0x6a, 0x79, 0xcc, 0x32, 0x68, - 0x50, 0x2c, 0x26, 0xde, 0x34, 0x0a, 0x7e, 0xde, 0x1e, 0xc8, 0x2a, 0x2a, 0x45, 0x08, 0xa5, 0xc1, - 0x5c, 0x79, 0xd0, 0xa5, 0xb9, 0x6f, 0x79, 0xa4, 0x18, 0xe5, 0xe9, 0x8e, 0x68, 0x6f, 0xdb, 0x97, - 0x90, 0x1a, 0x9c, 0xdd, 0x67, 0x67, 0x5a, 0xaf, 0xa5, 0x2d, 0x2d, 0x2b, 0x53, 0x3e, 0x5c, 0xbd, - 0x45, 0x79, 0xf0, 0xe1, 0x47, 0xd5, 0x45, 0x97, 0x9b, 0x9b, 0xbb, 0x62, 0x30, 0xb8, 0x2b, 0xfd, - 0x62, 0x06, 0x2a, 0x2f, 0xbd, 0xb5, 0x5c, 0x59, 0x7d, 0xbe, 0x54, 0xf9, 0xdb, 0x96, 0x14, 0x65, - 0x45, 0x61, 0x95, 0x62, 0x89, 0xf7, 0xfc, 0x7a, 0xa3, 0xb2, 0x31, 0xbf, 0x5c, 0xcb, 0xa6, 0x43, - 0x4f, 0x87, 0x0c, 0xe2, 0xcc, 0xec, 0x1c, 0x78, 0x7a, 0x18, 0x70, 0x2c, 0x23, 0x1d, 0x1e, 0x14, - 0x96, 0xd1, 0xbb, 0xe9, 0xf9, 0x33, 0xf0, 0x88, 0x25, 0x1f, 0xab, 0x56, 0xad, 0xc0, 0x1b, 0xbf, - 0x59, 0x84, 0x50, 0x93, 0x82, 0xd9, 0x5e, 0x2e, 0x58, 0x9d, 0x59, 0x88, 0x2c, 0x1e, 0x72, 0x89, - 0x0b, 0xa2, 0xd0, 0xe7, 0xa8, 0x00, 0x2f, 0xec, 0x28, 0xb3, 0x16, 0x49, 0xb5, 0x8b, 0xf9, 0xcb, - 0x00, 0x0e, 0x69, 0x80, 0x54, 0x5e, 0x31, 0xd5, 0x21, 0x61, 0xc4, 0x18, 0x18, 0x4d, 0x94, 0x0f, - 0x20, 0x1d, 0x64, 0x90, 0xca, 0xe1, 0x6e, 0x66, 0x5a, 0x2a, 0xc2, 0x06, 0x0d, 0xc1, 0x93, 0x73, - 0x6f, 0xc3, 0xdb, 0x6b, 0xb7, 0x60, 0x76, 0x84, 0x3f, 0x6a, 0xeb, 0x8d, 0xf8, 0xa1, 0x84, 0xc7, - 0xeb, 0x74, 0x3e, 0x3c, 0x4e, 0x1c, 0xea, 0xa3, 0x47, 0x6e, 0x5d, 0xcb, 0x72, 0x05, 0x2a, 0x60, - 0x0b, 0x7f, 0x0e, 0x69, 0x40, 0x2f, 0xde, 0x5e, 0xba, 0xb1, 0x7b, 0x4f, 0xbf, 0xfd, 0xce, 0xcb, - 0x02, 0xa5, 0x8a, 0x7a, 0xa8, 0x65, 0x6a, 0xa8, 0xc7, 0xc8, 0x3f, 0xbd, 0x0e, 0x94, 0x5c, 0x44, - 0xc2, 0xca, 0xf5, 0xf8, 0x96, 0xd7, 0xa8, 0xef, 0x7c, 0xb6, 0x16, 0xfd, 0xd9, 0xef, 0xfb, 0x52, - 0x6e, 0x21, 0xed, 0xb2, 0x30, 0x30, 0xe5, 0x23, 0x90, 0xcf, 0x0a, 0x56, 0x71, 0x7f, 0xd2, 0x5e, - 0xe7, 0x90, 0x06, 0xb0, 0xbf, 0xa3, 0x57, 0xb0, 0x3f, 0x62, 0xa3, 0xfb, 0x62, 0xdc, 0xa4, 0x69, - 0x10, 0x99, 0x38, 0x95, 0xe9, 0x73, 0x1f, 0xec, 0x55, 0x9c, 0x8b, 0xad, 0x9f, 0x7f, 0x82, 0xa4, - 0x13, 0x07, 0x51, 0x5e, 0x57, 0x8b, 0xe3, 0xbe, 0xc1, 0x78, 0x63, 0xf9, 0x2a, 0xf8, 0xbb, 0x3a, - 0x23, 0xd4, 0xe0, 0x82, 0xc2, 0x86, 0x4b, 0x97, 0x1c, 0x09, 0x6e, 0x3a, 0x6c, 0xa8, 0x60, 0x03, - 0xda, 0xdb, 0x88, 0x0e, 0x8d, 0x1c, 0x1b, 0x89, 0x2a, 0xab, 0xaa, 0x94, 0xcc, 0x9c, 0x8b, 0x4a, - 0x4a, 0x46, 0x26, 0xb7, 0x7e, 0x7a, 0x0e, 0x62, 0x83, 0x2a, 0xeb, 0xd2, 0xbb, 0x6f, 0x7f, 0x65, - 0xd1, 0xb3, 0x2f, 0x2b, 0x43, 0x86, 0x26, 0x29, 0x7f, 0xfb, 0xef, 0xf7, 0x95, 0x09, 0xb3, 0xe7, - 0x2a, 0xaf, 0xa4, 0x9d, 0x53, 0x5e, 0x7d, 0x67, 0xa5, 0x2a, 0x3d, 0xb8, 0xaf, 0xc6, 0x78, 0x45, - 0x88, 0xd0, 0x68, 0x54, 0xd2, 0x6b, 0x2d, 0x87, 0xb9, 0x8d, 0x82, 0x9a, 0x05, 0x39, 0x8c, 0x8d, - 0x72, 0x87, 0x86, 0xac, 0x0b, 0x39, 0x08, 0x08, 0xee, 0x89, 0x25, 0x2f, 0xbf, 0x89, 0xed, 0xeb, - 0xbf, 0xc0, 0xbc, 0x5f, 0x51, 0x5e, 0xd9, 0x3b, 0x10, 0x3a, 0xf6, 0xaf, 0xed, 0x9f, 0x7f, 0x88, - 0x06, 0x27, 0x17, 0xf4, 0x89, 0x8a, 0x46, 0x66, 0x55, 0x29, 0x7a, 0xc7, 0x26, 0x20, 0x86, 0x2c, - 0xf6, 0xbe, 0x19, 0x53, 0xb0, 0x9a, 0x98, 0x9f, 0xe9, 0x77, 0x89, 0xc5, 0xae, 0xae, 0x68, 0xc4, - 0xcf, 0xbc, 0x9d, 0xdb, 0x3c, 0xd1, 0x39, 0xa4, 0x0b, 0x49, 0xbf, 0x3d, 0x70, 0x60, 0x3f, 0xfe, - 0xf8, 0x9f, 0x7f, 0x44, 0x03, 0x65, 0x73, 0x9e, 0xfc, 0xf5, 0xa3, 0x1c, 0xd0, 0x63, 0x31, 0x30, - 0x76, 0x20, 0x6e, 0x4a, 0x1e, 0x8a, 0x08, 0x1f, 0x2f, 0x4c, 0xfd, 0xf7, 0xf9, 0x28, 0x2b, 0x29, - 0xe2, 0x31, 0xe2, 0x05, 0x84, 0xea, 0x0d, 0xc8, 0x0f, 0xef, 0x8f, 0x3d, 0xeb, 0xbe, 0xc1, 0xca, - 0x2d, 0x7b, 0x60, 0x28, 0xce, 0x37, 0x2f, 0x33, 0x6e, 0x31, 0x38, 0xa1, 0xba, 0x1d, 0x43, 0xc1, - 0x21, 0x14, 0xf8, 0xcd, 0x6f, 0x7e, 0x83, 0xed, 0x7b, 0xf6, 0x63, 0xca, 0xa4, 0xf1, 0x28, 0x29, - 0x2e, 0xc1, 0xa2, 0x5f, 0x3d, 0xc2, 0x53, 0x00, 0x7f, 0xec, 0xdc, 0xb5, 0x1d, 0xa3, 0xc6, 0x8e, - 0x45, 0x5e, 0x56, 0x2e, 0x4e, 0x9d, 0xcd, 0x86, 0x8b, 0xb7, 0x01, 0xbb, 0xbf, 0xdb, 0x88, 0xb2, - 0x82, 0x8b, 0x18, 0x3b, 0x75, 0x1a, 0x8e, 0x64, 0x9e, 0x47, 0x3f, 0xbd, 0x1e, 0x4f, 0xfc, 0xfa, - 0x57, 0xd8, 0x96, 0x71, 0x12, 0x21, 0xc1, 0xc1, 0xc8, 0x68, 0x70, 0xc2, 0xdd, 0xfd, 0x7a, 0x42, - 0x67, 0xe3, 0x1c, 0xc9, 0xd6, 0x00, 0xef, 0x34, 0x05, 0x5e, 0x78, 0xe1, 0x05, 0x7c, 0xb3, 0x6e, - 0x03, 0xbc, 0x3d, 0x3d, 0x10, 0x33, 0x60, 0x20, 0x32, 0x8e, 0x1d, 0xc3, 0xfe, 0x7d, 0xfb, 0x50, - 0x98, 0x7d, 0x9c, 0x42, 0x34, 0x83, 0xb0, 0x67, 0xd7, 0x2e, 0x64, 0xe6, 0xe6, 0xa1, 0x92, 0x72, - 0xa7, 0x35, 0xc4, 0xb4, 0x0b, 0x15, 0x05, 0x62, 0xc7, 0x4f, 0x44, 0x3a, 0xef, 0x30, 0x02, 0xfc, - 0x83, 0xd1, 0x18, 0x18, 0x84, 0xd7, 0xbf, 0xdb, 0x8b, 0x19, 0x49, 0x43, 0x30, 0x38, 0x3c, 0x18, - 0x3f, 0x6f, 0x47, 0xe5, 0xa5, 0x41, 0x57, 0xe6, 0x76, 0x5b, 0xcd, 0xb3, 0x13, 0x26, 0x72, 0xe0, - 0x6f, 0xbf, 0xfb, 0x3e, 0x06, 0x0f, 0x49, 0xe4, 0x49, 0x73, 0x36, 0xe2, 0xe2, 0xe3, 0x31, 0x28, - 0x36, 0x16, 0x6b, 0xd6, 0x7c, 0x83, 0xe4, 0xe4, 0x51, 0x08, 0x0b, 0x0f, 0x47, 0x78, 0x78, 0x0c, - 0xbe, 0xdf, 0xbc, 0x8e, 0x97, 0x1b, 0xfe, 0xa8, 0xe3, 0x4d, 0x65, 0x51, 0xe6, 0x19, 0xe4, 0x9e, - 0x3f, 0x8b, 0x1e, 0x1e, 0x6e, 0x38, 0x47, 0xd6, 0x4f, 0xe6, 0x03, 0x83, 0x8f, 0x3f, 0xca, 0x27, - 0x8e, 0x86, 0x0f, 0x59, 0x6b, 0x7b, 0x5d, 0xa7, 0x28, 0x20, 0x17, 0x1a, 0xd1, 0xc4, 0xba, 0x8f, - 0xaf, 0x2f, 0x62, 0x62, 0xe3, 0xb0, 0xe6, 0xcb, 0xd5, 0x18, 0x3d, 0x6a, 0xa4, 0xaa, 0x8e, 0xb1, - 0x6b, 0xd7, 0x1e, 0xec, 0xd9, 0xbd, 0x1b, 0xfb, 0xb6, 0x7e, 0x8d, 0xb1, 0xe3, 0xa7, 0xa0, 0xac, - 0x28, 0x17, 0x19, 0x69, 0x3f, 0x20, 0x9b, 0xe2, 0x4d, 0x8d, 0x75, 0xd5, 0x28, 0xe4, 0xa5, 0xa0, - 0x93, 0x91, 0x72, 0x84, 0x35, 0x75, 0x28, 0xce, 0xcb, 0xc2, 0xf6, 0xfd, 0x22, 0x11, 0xd6, 0x7e, - 0xd7, 0xa9, 0x06, 0x1c, 0x4c, 0x3d, 0x08, 0x7f, 0xff, 0x00, 0x1e, 0xa5, 0xeb, 0xa1, 0xe3, 0xac, - 0xbb, 0x6e, 0xc3, 0x46, 0x14, 0x14, 0xe6, 0xab, 0xcb, 0x0a, 0x57, 0xaa, 0x84, 0x64, 0x65, 0x65, - 0xe3, 0x58, 0xfa, 0x51, 0xfc, 0xef, 0xdb, 0x7f, 0x43, 0xf4, 0xe0, 0x11, 0x9c, 0x07, 0x9c, 0x90, - 0x9b, 0x99, 0x89, 0xdc, 0x0b, 0xd9, 0x28, 0xcc, 0xbf, 0xc8, 0x8b, 0x8f, 0x42, 0xd4, 0x56, 0x94, - 0xa1, 0xa2, 0xb2, 0x12, 0x87, 0x0e, 0x1d, 0xb9, 0x34, 0x8b, 0xb7, 0xb3, 0x0d, 0x9d, 0x6a, 0x40, - 0x5c, 0x5c, 0x2c, 0xa6, 0xf0, 0x3a, 0xa9, 0xbe, 0xae, 0x1e, 0x95, 0x95, 0x15, 0xf0, 0xf1, 0xf1, - 0xc3, 0x6b, 0xaf, 0xbf, 0x09, 0xb9, 0xf4, 0xcb, 0xcb, 0xc9, 0x95, 0x43, 0x33, 0xde, 0xda, 0xd7, - 0xa1, 0xb4, 0xb4, 0x04, 0x1f, 0xbd, 0xf9, 0x12, 0x12, 0x86, 0x24, 0xe0, 0xa9, 0x25, 0xff, 0x85, - 0x72, 0x56, 0x3a, 0xfb, 0xec, 0x29, 0x5c, 0xcc, 0xcb, 0x45, 0x71, 0x61, 0x01, 0x07, 0x7e, 0x31, - 0x2a, 0xca, 0xcb, 0x51, 0x41, 0xaa, 0xb4, 0xd7, 0x75, 0xaa, 0x01, 0x21, 0xbc, 0x65, 0xf4, 0x32, - 0xe8, 0x29, 0x31, 0xd0, 0x80, 0xb2, 0xd2, 0x52, 0x14, 0xb1, 0x32, 0x0a, 0xef, 0x7a, 0xbf, 0x59, - 0xbb, 0x96, 0x8d, 0xa8, 0x86, 0x9e, 0x03, 0x36, 0x84, 0x57, 0x4d, 0xf5, 0x94, 0xad, 0xac, 0xe5, - 0x1a, 0x69, 0xe7, 0xa6, 0xb5, 0xc8, 0xd8, 0xb3, 0x19, 0x7f, 0x7c, 0xee, 0x55, 0xfc, 0x72, 0xe1, - 0xaf, 0xc1, 0xe3, 0x4a, 0x14, 0x14, 0x70, 0x80, 0x53, 0x5a, 0x51, 0x14, 0x32, 0xb8, 0x2c, 0x6a, - 0xb7, 0xeb, 0x34, 0x1b, 0xe5, 0xd9, 0x27, 0xfe, 0xf2, 0xe2, 0x4b, 0xd8, 0xb0, 0x71, 0x13, 0xf2, - 0x79, 0x3f, 0x26, 0xd8, 0x34, 0xb2, 0xc2, 0xa1, 0xe1, 0x11, 0xf0, 0xe6, 0x55, 0xd3, 0xcd, 0xe3, - 0x92, 0x11, 0x1c, 0x14, 0x88, 0xf4, 0x8c, 0xe3, 0x78, 0xf3, 0xcd, 0x37, 0xd9, 0x55, 0x0e, 0xf1, - 0xbe, 0xf8, 0x34, 0x78, 0x40, 0x0c, 0x93, 0xb3, 0x1e, 0x8d, 0x3a, 0x37, 0x36, 0xd4, 0x0d, 0x5e, - 0xae, 0x26, 0xcc, 0x9a, 0x35, 0xf3, 0xea, 0x37, 0x40, 0x4a, 0xdc, 0x45, 0x56, 0xf9, 0x87, 0xa7, - 0xff, 0x13, 0x29, 0x7b, 0xf7, 0x10, 0xdb, 0xf5, 0x88, 0xec, 0x1d, 0x85, 0xa8, 0xfe, 0xd1, 0x08, - 0x0a, 0x0e, 0xa1, 0xf0, 0xa4, 0x4e, 0xed, 0x26, 0xeb, 0xff, 0xf9, 0x25, 0x31, 0x7c, 0x89, 0xe0, - 0xf5, 0x14, 0x08, 0xc9, 0xce, 0xca, 0x42, 0x71, 0x71, 0x11, 0x8c, 0xec, 0x62, 0x15, 0x15, 0xe5, - 0xb8, 0x65, 0xda, 0x6d, 0x1d, 0xba, 0x2b, 0xe8, 0x34, 0x05, 0x34, 0x94, 0xa5, 0x1e, 0x4c, 0xc5, - 0xbc, 0x07, 0xe7, 0x73, 0x1f, 0x20, 0xd7, 0xa6, 0x7a, 0x84, 0x86, 0x86, 0xa9, 0x77, 0xc7, 0xa2, - 0xe7, 0xb5, 0xfc, 0x9d, 0x65, 0x2d, 0x56, 0x4e, 0xc6, 0x89, 0xad, 0xcb, 0x0f, 0x2d, 0x5f, 0x7b, - 0x4f, 0x87, 0x35, 0x40, 0x0a, 0x32, 0x1a, 0x1b, 0x70, 0x80, 0x9a, 0x00, 0x85, 0x05, 0x85, 0x08, - 0xe2, 0x8d, 0xa3, 0xa7, 0x97, 0x27, 0xe2, 0xe3, 0x5a, 0x91, 0xfc, 0xb4, 0x57, 0xbb, 0x36, 0xc4, - 0x3b, 0xb4, 0x01, 0x6d, 0x28, 0xcf, 0xe1, 0x20, 0x9d, 0xe2, 0x42, 0x0e, 0xaf, 0x4d, 0x07, 0x32, - 0xec, 0x6e, 0x40, 0x07, 0x90, 0xe6, 0xd0, 0x24, 0x5d, 0x4a, 0x81, 0x8a, 0x8a, 0x0a, 0x88, 0x38, - 0xb1, 0xfc, 0x84, 0xdb, 0x34, 0x77, 0x54, 0x8c, 0xc1, 0x87, 0x1f, 0x7e, 0xd8, 0x3c, 0xb8, 0x7d, - 0xef, 0xcd, 0x76, 0x68, 0x0e, 0x7d, 0x65, 0x4d, 0xa4, 0xd6, 0xea, 0x2f, 0x25, 0x25, 0xc5, 0x2a, - 0x6f, 0x89, 0x93, 0xeb, 0xd4, 0xce, 0xb8, 0x4e, 0x2d, 0xa7, 0xed, 0xa1, 0x8a, 0x15, 0x53, 0x41, - 0x5a, 0xba, 0xe8, 0xd6, 0xe2, 0xed, 0xe5, 0xd3, 0x5a, 0xbc, 0xcd, 0x2e, 0x14, 0x13, 0x13, 0xa3, - 0x4e, 0x2e, 0x5a, 0xc1, 0x4f, 0x3c, 0xf1, 0x84, 0x39, 0x0f, 0x17, 0x1e, 0x0f, 0x4a, 0x38, 0x31, - 0xda, 0x62, 0xe5, 0xd6, 0xaf, 0x5f, 0x0f, 0x2a, 0x6f, 0x81, 0xb2, 0xda, 0xdc, 0x1b, 0xac, 0x31, - 0xa7, 0xd5, 0x3c, 0x87, 0x0f, 0x1f, 0x36, 0xe7, 0xdf, 0xab, 0x57, 0x2f, 0x2d, 0xd8, 0xfc, 0x2c, - 0x28, 0x28, 0x00, 0xe5, 0xc3, 0xcd, 0x30, 0x94, 0xa4, 0x36, 0xc7, 0x59, 0x79, 0x6c, 0x91, 0x8f, - 0x95, 0x54, 0x96, 0x2d, 0xbb, 0xa4, 0x7b, 0x18, 0x1f, 0x1f, 0xaf, 0x76, 0x01, 0x0d, 0xee, 0xe1, - 0x87, 0x1f, 0x56, 0xdf, 0xb7, 0x6e, 0xdd, 0xaa, 0x06, 0x8d, 0x1b, 0x37, 0xae, 0x49, 0xfc, 0xd2, - 0xa5, 0x4b, 0xd5, 0x77, 0xb9, 0x89, 0xb7, 0x14, 0xe1, 0xb6, 0xec, 0x42, 0x95, 0x95, 0x95, 0xca, - 0x8c, 0x19, 0x33, 0x54, 0x38, 0x5f, 0x5f, 0x5f, 0x2d, 0x6b, 0xf5, 0x69, 0x79, 0xaf, 0xfc, 0xd6, - 0x5b, 0x6f, 0x29, 0x0f, 0x3c, 0xf0, 0x80, 0x39, 0xbf, 0x26, 0x80, 0x97, 0x5f, 0x64, 0x70, 0x59, - 0xb9, 0x13, 0x27, 0x4e, 0x28, 0xf7, 0xde, 0x7b, 0xaf, 0x32, 0x61, 0xc2, 0x04, 0x65, 0xce, 0x9c, - 0x39, 0x4d, 0x2a, 0x28, 0xc0, 0xc4, 0x82, 0xa2, 0x35, 0xe0, 0x8b, 0x2f, 0xbe, 0x68, 0x12, 0x2f, - 0x71, 0xf2, 0xd3, 0xdc, 0xea, 0xd5, 0xab, 0xd5, 0x77, 0xcb, 0x06, 0x68, 0x71, 0x02, 0xd7, 0xbc, - 0x01, 0xda, 0x25, 0xba, 0xdc, 0x33, 0x6b, 0x6e, 0xee, 0xdc, 0xb9, 0x6a, 0x1e, 0xda, 0xc5, 0xb7, - 0x16, 0x2e, 0x4f, 0xab, 0x2e, 0xf4, 0xe8, 0xa3, 0x8f, 0x82, 0xd7, 0xfc, 0xdc, 0x39, 0x65, 0x43, - 0xfc, 0xd4, 0x63, 0x62, 0x39, 0xd6, 0x4e, 0x53, 0xe9, 0x96, 0x6d, 0x65, 0x6b, 0x8e, 0xaa, 0x03, - 0xad, 0x45, 0x5b, 0xc5, 0xf1, 0xa6, 0x5f, 0x0d, 0x93, 0xee, 0xa7, 0xb9, 0xa1, 0x43, 0x87, 0xaa, - 0xde, 0xd3, 0x5c, 0xc5, 0x5a, 0x39, 0xcb, 0xd6, 0x88, 0x9f, 0x00, 0x4d, 0x30, 0xf8, 0xc1, 0x07, - 0x1f, 0x34, 0x79, 0xd7, 0x60, 0x84, 0xb4, 0xe2, 0x44, 0x51, 0x4b, 0xd2, 0x68, 0x8e, 0xe3, 0x43, - 0x7d, 0x97, 0x5b, 0x76, 0x71, 0xc3, 0x86, 0x0d, 0x53, 0xdf, 0xdb, 0x4a, 0x01, 0x91, 0xd1, 0x90, - 0xfc, 0x9a, 0x8b, 0x3a, 0x58, 0x96, 0xa1, 0x95, 0x25, 0xcf, 0x2b, 0x25, 0x5f, 0x0e, 0x5d, 0xb2, - 0x64, 0x89, 0x9a, 0x81, 0xd6, 0x10, 0xcb, 0xa7, 0x96, 0xd0, 0x32, 0x8c, 0xd8, 0x31, 0xc3, 0x4b, - 0xbc, 0xf4, 0x6f, 0xcb, 0x78, 0x19, 0x4f, 0xda, 0xbb, 0xad, 0xf4, 0x5a, 0x9c, 0x3c, 0x35, 0x17, - 0x1d, 0x1d, 0x6d, 0x4e, 0xa3, 0xc5, 0x93, 0x31, 0x68, 0xd1, 0x4d, 0x9e, 0x57, 0x52, 0x59, 0x04, - 0x97, 0x97, 0x97, 0x2b, 0x6b, 0xd7, 0xae, 0x35, 0x0b, 0x5b, 0x58, 0x44, 0x99, 0xbd, 0xe4, 0x24, - 0x4a, 0x15, 0x8f, 0x13, 0x5b, 0x72, 0x32, 0x8e, 0x32, 0x33, 0x33, 0x5b, 0x8a, 0x6e, 0x53, 0xf8, - 0x8e, 0x1d, 0x3b, 0x94, 0xac, 0xac, 0xac, 0x56, 0x61, 0xbb, 0x57, 0xa3, 0x24, 0xf1, 0x35, 0x75, - 0x57, 0x86, 0xfa, 0x35, 0xad, 0x46, 0xc7, 0x0b, 0xef, 0x6e, 0x40, 0xc7, 0x71, 0xe7, 0x98, 0x94, - 0xdd, 0x14, 0x70, 0x0c, 0x1e, 0x3b, 0x9e, 0xcb, 0x0d, 0x4f, 0x81, 0x1b, 0x7e, 0x1e, 0xe8, 0x38, - 0xed, 0xae, 0x8f, 0x94, 0x37, 0x7c, 0x0f, 0xba, 0x3e, 0xd0, 0xd8, 0xf1, 0x5a, 0x74, 0x13, 0xa0, - 0xe3, 0xb8, 0x73, 0x48, 0xca, 0x2e, 0x3d, 0x92, 0x70, 0x48, 0x0d, 0xdb, 0x91, 0x89, 0xec, 0xc5, - 0x8a, 0x78, 0x6b, 0x98, 0x45, 0xb1, 0x18, 0x8a, 0x31, 0x20, 0x90, 0xc7, 0xe2, 0xbe, 0xbc, 0x31, - 0x71, 0xe7, 0x09, 0x44, 0x07, 0x2e, 0x4e, 0xda, 0x51, 0x72, 0xc7, 0x41, 0xff, 0x65, 0x08, 0x50, - 0xcd, 0x6b, 0xad, 0x3d, 0x45, 0x55, 0xf0, 0xa0, 0x9d, 0x8e, 0x64, 0xca, 0x1f, 0x89, 0xb0, 0x8f, - 0xa8, 0x35, 0x1e, 0xa3, 0x5c, 0xd2, 0xfe, 0x8a, 0x1a, 0xf8, 0xb9, 0xe8, 0x30, 0x8c, 0xd2, 0x61, - 0x91, 0x14, 0x2e, 0x71, 0x6b, 0xe3, 0x05, 0x7a, 0xc7, 0xd1, 0xda, 0xf6, 0x94, 0xd7, 0xed, 0x24, - 0x5c, 0x5e, 0x59, 0x85, 0x73, 0xd9, 0xf9, 0xa8, 0xaa, 0xad, 0xe7, 0x9d, 0x61, 0x23, 0x95, 0x5d, - 0x9d, 0x79, 0xa5, 0x46, 0xed, 0x5e, 0x8a, 0x5c, 0xf8, 0xf9, 0x78, 0x53, 0x28, 0x4c, 0xdf, 0xa4, - 0x57, 0x8b, 0x72, 0xec, 0xa9, 0x82, 0x52, 0x54, 0xd4, 0xd6, 0x62, 0x44, 0x04, 0x35, 0xb9, 0x6c, - 0x20, 0x39, 0xbf, 0xce, 0x88, 0x8d, 0x17, 0x4b, 0x79, 0x15, 0xe7, 0x82, 0x91, 0x7e, 0x1e, 0x08, - 0x75, 0x77, 0xb5, 0x09, 0xd7, 0x76, 0xf4, 0x75, 0x1e, 0xf2, 0xba, 0x23, 0x40, 0x71, 0x49, 0x29, - 0xf6, 0x1e, 0x3a, 0x8e, 0xa2, 0x2a, 0xde, 0x2e, 0x97, 0x17, 0x22, 0x65, 0xfb, 0x46, 0x1c, 0xd8, - 0xbb, 0x13, 0x25, 0xa5, 0xc5, 0xbc, 0x4a, 0x77, 0x83, 0xaf, 0x6f, 0x0f, 0x84, 0x84, 0x47, 0x22, - 0x36, 0x2e, 0x91, 0xbf, 0x41, 0x48, 0xa2, 0x86, 0x5a, 0x54, 0x64, 0x28, 0x85, 0x79, 0xf4, 0x38, - 0x57, 0x51, 0x8b, 0x43, 0xa7, 0xcf, 0xd3, 0x36, 0x9f, 0x17, 0x12, 0xfb, 0x45, 0x22, 0xc8, 0x99, - 0xac, 0xa8, 0x09, 0x99, 0x2e, 0x21, 0x4c, 0x84, 0xab, 0x0e, 0x97, 0xd5, 0xe0, 0x48, 0x51, 0x05, - 0x12, 0xa9, 0x92, 0x3d, 0xc8, 0xcf, 0x13, 0xb6, 0x8d, 0x91, 0x75, 0x1e, 0xc1, 0xf6, 0x72, 0xb8, - 0x8e, 0x08, 0x40, 0xeb, 0x42, 0xd4, 0xa4, 0xde, 0xb1, 0x2f, 0x0d, 0xae, 0x9e, 0xfe, 0xbc, 0x8b, - 0xd5, 0x61, 0xd9, 0x2b, 0x7f, 0xc6, 0xce, 0x6d, 0x9b, 0x79, 0x13, 0xee, 0xa6, 0x8a, 0xb7, 0x88, - 0xfd, 0x08, 0xb5, 0x63, 0xb3, 0xb7, 0xcb, 0x91, 0xa0, 0xa9, 0xd1, 0x04, 0x17, 0x06, 0x0c, 0x9d, - 0x3c, 0x0d, 0xc3, 0xef, 0x7d, 0x04, 0x51, 0x3a, 0x27, 0xdc, 0x3e, 0x3c, 0x1e, 0x27, 0x79, 0xd3, - 0xee, 0x13, 0xe0, 0x07, 0x5d, 0x40, 0x10, 0xf6, 0xe7, 0x97, 0xc1, 0x87, 0xec, 0x67, 0x7a, 0x58, - 0x0f, 0xf8, 0xda, 0xb8, 0x42, 0x2f, 0xa3, 0xb1, 0xa7, 0xfd, 0x25, 0xd5, 0xaa, 0x5e, 0xff, 0x84, - 0x00, 0x4f, 0x9a, 0xcd, 0xbc, 0xba, 0xb3, 0xc5, 0x75, 0x33, 0x07, 0x98, 0x88, 0x88, 0xca, 0xaa, - 0x6a, 0x9a, 0x96, 0x6b, 0x80, 0x17, 0x91, 0xe0, 0xee, 0xe1, 0x09, 0x1f, 0x51, 0xd5, 0xe5, 0x31, - 0xbe, 0x7a, 0xfe, 0x4a, 0xa4, 0x3b, 0x39, 0x89, 0x5a, 0x2f, 0x67, 0x57, 0xb2, 0x23, 0x39, 0x76, - 0x77, 0x75, 0xd2, 0xab, 0x1d, 0x2c, 0xff, 0x0c, 0x2d, 0x07, 0xa5, 0xee, 0xc1, 0xf7, 0xfb, 0xf6, - 0xe2, 0xaf, 0x19, 0x07, 0x31, 0xf1, 0xa7, 0x73, 0x30, 0xf2, 0x8e, 0x99, 0x98, 0x14, 0xef, 0x8c, - 0x87, 0x23, 0x83, 0x50, 0xa9, 0x38, 0xe1, 0x68, 0x71, 0x05, 0xf6, 0xe4, 0x97, 0x63, 0x72, 0xb8, - 0x3f, 0x06, 0x53, 0xe0, 0x4a, 0x63, 0x51, 0xbe, 0x3a, 0x67, 0xdc, 0x12, 0xe8, 0x45, 0x18, 0x20, - 0xb5, 0xc6, 0x88, 0x60, 0x96, 0xdd, 0x57, 0x64, 0x7f, 0xae, 0x92, 0xd3, 0xfd, 0x99, 0xee, 0x2a, - 0x95, 0xd5, 0x6a, 0x31, 0x72, 0x08, 0xed, 0xcc, 0x1e, 0x9a, 0x9d, 0x93, 0xa7, 0xca, 0x7a, 0x04, - 0x51, 0x66, 0x50, 0x47, 0x91, 0xba, 0x8c, 0xc3, 0x94, 0xd2, 0x24, 0xfb, 0x11, 0x49, 0x05, 0xb9, - 0x4f, 0x11, 0xc4, 0x5d, 0x7a, 0x5c, 0x5e, 0xd9, 0x34, 0x1a, 0x61, 0x88, 0x1a, 0x84, 0xf0, 0x3b, - 0x7f, 0x81, 0x24, 0x0a, 0x80, 0x21, 0x66, 0x10, 0x4e, 0x52, 0x0c, 0xe9, 0xc8, 0xca, 0xf7, 0x70, - 0x31, 0xbf, 0x18, 0xe7, 0x4b, 0xab, 0x11, 0x15, 0x12, 0x84, 0x81, 0x81, 0x7e, 0x18, 0x15, 0xe4, - 0x0b, 0x9a, 0x1a, 0xc0, 0xea, 0x9c, 0x52, 0x12, 0xd5, 0x09, 0xbd, 0x68, 0x5a, 0x4b, 0x23, 0x84, - 0x9e, 0xe1, 0xe1, 0x5c, 0x3a, 0x55, 0x33, 0xf3, 0xb4, 0x6a, 0x23, 0x7c, 0x48, 0x18, 0x4a, 0xf1, - 0x9a, 0xe3, 0x5b, 0xad, 0x7c, 0x27, 0x22, 0xaf, 0x23, 0x16, 0x24, 0xc6, 0x24, 0x1a, 0x49, 0x80, - 0x5c, 0x9c, 0x39, 0x9f, 0x0d, 0x37, 0x1a, 0x71, 0xf0, 0xa2, 0x68, 0xec, 0xe7, 0x9f, 0x7e, 0x82, - 0xa5, 0xaf, 0x2e, 0x41, 0x45, 0x59, 0xb1, 0xca, 0x8a, 0x04, 0x61, 0x42, 0x2c, 0x27, 0x8a, 0x8b, - 0x28, 0x14, 0xdc, 0xf1, 0x0b, 0x09, 0xc3, 0xf8, 0xc7, 0x17, 0xe3, 0x14, 0x8d, 0x72, 0x95, 0x1d, - 0xda, 0x85, 0x5b, 0xef, 0x5b, 0x80, 0x12, 0x4e, 0xe0, 0x67, 0x7c, 0x29, 0x7e, 0x15, 0x19, 0x85, - 0x88, 0xca, 0x52, 0xc4, 0x19, 0x28, 0x03, 0xc3, 0x34, 0x53, 0xc7, 0x26, 0xa1, 0x6f, 0xef, 0x30, - 0xa6, 0x75, 0x42, 0x09, 0x57, 0x48, 0x3b, 0x2b, 0xea, 0x10, 0x4f, 0x41, 0xd0, 0xbe, 0xee, 0xd6, - 0x8c, 0x60, 0x73, 0xb5, 0x09, 0x3d, 0x49, 0x84, 0x41, 0xa4, 0x4c, 0x57, 0x72, 0xa5, 0xeb, 0x66, - 0x04, 0x48, 0x27, 0x12, 0xc4, 0x78, 0x51, 0xe4, 0x51, 0x4f, 0x43, 0x14, 0x32, 0x77, 0xfa, 0x78, - 0xb9, 0x63, 0xe8, 0xb0, 0x91, 0xf0, 0xf6, 0x0f, 0xc1, 0xc1, 0x03, 0x29, 0xa8, 0xa4, 0x78, 0x97, - 0x7a, 0xe3, 0x47, 0x58, 0x1e, 0xb4, 0xab, 0x30, 0x75, 0x95, 0x65, 0x70, 0xa1, 0x89, 0x90, 0xa1, - 0x13, 0xa7, 0xa1, 0x98, 0x82, 0xa8, 0x07, 0x36, 0xaf, 0xa7, 0xd0, 0x5e, 0x3c, 0x46, 0x87, 0xf6, - 0x44, 0xd6, 0xc7, 0xef, 0x22, 0x2f, 0x37, 0x1b, 0xe5, 0x09, 0xa3, 0xe0, 0x16, 0x15, 0x83, 0x73, - 0x19, 0xc7, 0xb0, 0x7b, 0xe7, 0x7e, 0xf4, 0x09, 0xeb, 0x85, 0x60, 0x1f, 0x4f, 0x0c, 0x20, 0xe2, - 0x45, 0xc4, 0x79, 0x07, 0x09, 0x11, 0x4e, 0x42, 0xb8, 0x5a, 0xf4, 0xf8, 0x28, 0x8e, 0x86, 0x12, - 0xee, 0x27, 0x52, 0x6b, 0x15, 0xf4, 0x72, 0x75, 0x22, 0xbb, 0x53, 0x8b, 0xeb, 0x44, 0x5f, 0xb7, - 0x9d, 0xf4, 0xba, 0x1a, 0x01, 0x5a, 0x15, 0x6b, 0xb9, 0x94, 0xcc, 0xa5, 0xfd, 0x2e, 0x0f, 0x8e, - 0x02, 0x1d, 0x97, 0x8c, 0x4e, 0xae, 0x5e, 0x34, 0xb4, 0xb1, 0x0d, 0xcf, 0xfd, 0xe1, 0x31, 0x9c, - 0x39, 0x91, 0xce, 0xbb, 0x3a, 0x1f, 0x0a, 0x52, 0xf5, 0x41, 0xdf, 0x7e, 0xd1, 0x70, 0xf7, 0xf2, - 0x43, 0x35, 0x4d, 0x3d, 0x04, 0x45, 0xf6, 0x46, 0xc2, 0x98, 0x71, 0xc8, 0xd8, 0xf5, 0x1d, 0xb6, - 0xfe, 0xf3, 0x6b, 0x0c, 0x18, 0x3a, 0x02, 0x3f, 0x99, 0x79, 0x17, 0x0a, 0x29, 0x54, 0xb8, 0xfb, - 0x9b, 0xd5, 0x70, 0x89, 0xea, 0x83, 0xa4, 0x85, 0x8f, 0x21, 0xa0, 0xde, 0x84, 0x8a, 0xc3, 0xa9, - 0xd4, 0x26, 0xf1, 0xc2, 0xdc, 0xe9, 0x53, 0x28, 0x02, 0xea, 0xab, 0x22, 0x7a, 0x57, 0xa5, 0x09, - 0x7d, 0xdc, 0x9c, 0x39, 0x22, 0x04, 0xd3, 0xfc, 0x5d, 0x76, 0xb9, 0x84, 0xdf, 0x5e, 0xa3, 0x60, - 0x86, 0x8f, 0x0e, 0x9e, 0x16, 0xe1, 0x5a, 0x7c, 0x67, 0x9f, 0xd7, 0x25, 0x01, 0xa4, 0x51, 0xab, - 0x57, 0x7f, 0x81, 0xe2, 0xd2, 0x72, 0xfc, 0x94, 0xd6, 0x4d, 0x9c, 0xc9, 0x0a, 0xf4, 0xee, 0x9e, - 0x48, 0x3f, 0x99, 0x8d, 0x97, 0x5f, 0x7c, 0x16, 0xa6, 0x9a, 0x52, 0x4c, 0xbd, 0xf5, 0x0e, 0xf4, - 0x8e, 0x1e, 0x00, 0xf7, 0x1e, 0x41, 0x5c, 0x21, 0xe9, 0x61, 0xa4, 0x98, 0x76, 0x11, 0xcd, 0x16, - 0xe9, 0xdc, 0xf5, 0xa8, 0xa2, 0x8a, 0xc2, 0x57, 0xff, 0x78, 0x9f, 0x36, 0x8d, 0xb3, 0x10, 0x3f, - 0x6c, 0x14, 0x12, 0x46, 0x8f, 0x43, 0xee, 0xb9, 0xd3, 0x38, 0xc6, 0x49, 0x3a, 0xf0, 0xdf, 0x66, - 0xc1, 0x8d, 0x56, 0x52, 0x9c, 0x36, 0xae, 0x41, 0x04, 0xcd, 0xfc, 0xf5, 0xec, 0xd7, 0x17, 0x63, - 0x63, 0xfb, 0xd1, 0x6a, 0x44, 0x28, 0x8e, 0x42, 0x8f, 0x30, 0x72, 0xa3, 0xde, 0xcd, 0x38, 0xd2, - 0x89, 0xda, 0x46, 0x64, 0x92, 0x65, 0x4d, 0xa4, 0xd2, 0x95, 0xac, 0xba, 0x1c, 0xe9, 0xae, 0x2b, - 0x02, 0xf0, 0x3a, 0x11, 0xcf, 0x3d, 0xf7, 0x2c, 0x56, 0x7f, 0xb9, 0x06, 0x49, 0xa3, 0xc6, 0xc2, - 0xa0, 0x97, 0x49, 0x12, 0x34, 0x19, 0x33, 0x0f, 0xa1, 0x61, 0x61, 0xaa, 0x81, 0x1f, 0xc5, 0xc5, - 0x93, 0xa2, 0xe5, 0x3f, 0xe0, 0xfc, 0xe9, 0x63, 0x18, 0x92, 0x30, 0x18, 0xfd, 0x29, 0xdc, 0x2c, - 0x04, 0x68, 0xa0, 0x45, 0xa3, 0xc2, 0x82, 0x22, 0x5c, 0xc8, 0xcb, 0x47, 0x69, 0x75, 0x1d, 0x74, - 0x54, 0xc3, 0xb8, 0x70, 0xf6, 0x24, 0xd2, 0x0e, 0xec, 0x43, 0x31, 0xc5, 0x6a, 0x03, 0x69, 0x64, - 0x3a, 0x6e, 0x78, 0x12, 0xf4, 0x34, 0x7c, 0x52, 0xe0, 0xee, 0x81, 0xaa, 0xf8, 0xa1, 0x28, 0x5e, - 0xb5, 0x1c, 0x11, 0x14, 0x4b, 0x9c, 0x36, 0xe7, 0x1e, 0x04, 0xd2, 0x94, 0x53, 0x3e, 0x45, 0x6e, - 0x8b, 0x88, 0xdd, 0x71, 0x7d, 0xc2, 0xd0, 0x97, 0xd6, 0x91, 0x74, 0x24, 0xbc, 0xb8, 0x6a, 0xb2, - 0xa2, 0xcf, 0xcb, 0x1b, 0x30, 0xd3, 0xc7, 0x55, 0x5d, 0xa1, 0xa9, 0x81, 0x0e, 0xfa, 0xbb, 0x2e, - 0x08, 0x20, 0x2c, 0xe7, 0x99, 0x67, 0x9e, 0xc1, 0xd2, 0xa5, 0xcb, 0xd8, 0xd3, 0x0d, 0x18, 0x91, - 0x3c, 0x16, 0xe3, 0xb9, 0xa2, 0x71, 0xa6, 0x05, 0x25, 0xb1, 0xe5, 0x70, 0x9c, 0x22, 0xf0, 0x0b, - 0x1e, 0x9a, 0x87, 0x31, 0x63, 0xc7, 0xa8, 0xd6, 0x48, 0x83, 0x7a, 0x86, 0x21, 0xaf, 0xa4, 0x16, - 0xa9, 0x87, 0xd2, 0x68, 0x16, 0x87, 0xba, 0x2b, 0x14, 0x4a, 0x95, 0x55, 0x4d, 0x29, 0x4d, 0x96, - 0x97, 0x72, 0xd4, 0x54, 0x91, 0x25, 0x99, 0x48, 0x38, 0x03, 0x77, 0xcb, 0x26, 0x53, 0x3d, 0xad, - 0x34, 0x95, 0x73, 0x45, 0x44, 0xd9, 0x66, 0x4e, 0xf0, 0x75, 0x95, 0xe5, 0x34, 0x3d, 0x15, 0x8c, - 0xe8, 0x9f, 0xdc, 0x4e, 0x19, 0xcf, 0x5a, 0x64, 0x1d, 0xd8, 0x03, 0xa3, 0xb3, 0x2b, 0x86, 0x0c, - 0x4e, 0x40, 0x78, 0x5c, 0x3c, 0xfa, 0xf4, 0x0a, 0x20, 0x2b, 0xa2, 0xd2, 0x02, 0x05, 0xc1, 0x73, - 0x6b, 0x28, 0xc1, 0xcb, 0x2d, 0x9a, 0x27, 0x47, 0x55, 0xa2, 0x3f, 0x77, 0xdf, 0x97, 0x09, 0xe2, - 0x20, 0xdc, 0xab, 0xd9, 0x5c, 0x53, 0x02, 0xc8, 0x44, 0xba, 0x7e, 0xc3, 0x06, 0xdc, 0x77, 0xdf, - 0xfd, 0xaa, 0xaa, 0x8a, 0x88, 0x2e, 0x8b, 0x9c, 0xb5, 0x89, 0x4a, 0x43, 0x77, 0xcd, 0x99, 0x4b, - 0xd9, 0xea, 0xc1, 0xd8, 0x47, 0xb6, 0x71, 0xf6, 0xc7, 0x1f, 0x51, 0xc5, 0xde, 0xe9, 0xc9, 0x09, - 0x7a, 0xc4, 0x88, 0x24, 0xf4, 0xf0, 0xf3, 0xa3, 0x01, 0x26, 0x6f, 0x44, 0x44, 0x0d, 0x44, 0x76, - 0x7e, 0x25, 0x32, 0x8e, 0x1f, 0x43, 0x8d, 0x4c, 0xc6, 0x1c, 0x09, 0x62, 0xd3, 0x4b, 0x31, 0x19, - 0x39, 0x70, 0xb8, 0x49, 0xe3, 0x4e, 0x58, 0x34, 0x44, 0x8e, 0x1d, 0x3f, 0xc9, 0x79, 0xc4, 0x8d, - 0x3b, 0xe8, 0x50, 0xf8, 0x86, 0x85, 0xa3, 0x9c, 0xd2, 0xc1, 0x45, 0xd9, 0x59, 0x30, 0x66, 0xfe, - 0x08, 0x4f, 0x37, 0x57, 0xd5, 0x2c, 0x90, 0x89, 0xab, 0xaa, 0xd8, 0xf8, 0x44, 0xdc, 0x33, 0x73, - 0x06, 0x27, 0xe9, 0x60, 0x22, 0xc7, 0xb1, 0xac, 0xa6, 0x25, 0xa2, 0x5d, 0x53, 0x02, 0x94, 0x95, - 0x95, 0xe1, 0xe7, 0xf7, 0xfc, 0x02, 0x85, 0x54, 0xad, 0x0c, 0xa6, 0xea, 0x99, 0x58, 0x72, 0xd3, - 0xeb, 0xdd, 0x51, 0x40, 0xeb, 0x3d, 0xa2, 0x72, 0xf6, 0xfb, 0x3f, 0x3c, 0xc5, 0x5e, 0x6c, 0xc0, - 0x3a, 0xca, 0x8e, 0x8b, 0xa5, 0x1f, 0x6a, 0x39, 0x41, 0xa4, 0x94, 0x45, 0x60, 0x86, 0x86, 0x43, - 0xd4, 0x7d, 0x43, 0x30, 0xb5, 0x54, 0x06, 0x0c, 0x1e, 0x8e, 0x1a, 0x93, 0x1b, 0x8e, 0x67, 0x1c, - 0xc5, 0xd9, 0x13, 0x69, 0xe4, 0xd3, 0x5c, 0x9e, 0x92, 0x48, 0x22, 0x77, 0x7b, 0xee, 0xec, 0x79, - 0x5c, 0xa4, 0xe5, 0x1f, 0x83, 0xc1, 0x83, 0x02, 0xc4, 0xae, 0xdc, 0x07, 0x38, 0xc1, 0xe0, 0xe2, - 0xcc, 0x1d, 0xaf, 0x8e, 0xc6, 0xd5, 0x68, 0xca, 0x8b, 0xe7, 0x12, 0xa2, 0x29, 0xe0, 0x4c, 0x5b, - 0xe3, 0x82, 0xf4, 0xe4, 0x49, 0xb7, 0x61, 0xc6, 0x2d, 0x37, 0x23, 0xb6, 0x5f, 0xb8, 0xba, 0x2a, - 0x6b, 0x09, 0x71, 0x8e, 0x0a, 0xbf, 0xa6, 0x04, 0x38, 0x42, 0x55, 0x88, 0x67, 0x97, 0xbc, 0x88, - 0x3a, 0xca, 0xb6, 0xcb, 0xca, 0x46, 0x0c, 0x1f, 0xcb, 0x1c, 0xa7, 0xe3, 0xb3, 0x50, 0xb4, 0x08, - 0x0a, 0x2f, 0xaa, 0xf2, 0xeb, 0x34, 0x2e, 0x8a, 0xd4, 0x1f, 0x7e, 0x80, 0xd8, 0x8e, 0x12, 0x95, - 0x3a, 0x13, 0xed, 0x04, 0xd2, 0x0a, 0xb3, 0xaa, 0x66, 0x21, 0x44, 0x33, 0x92, 0x28, 0xa2, 0x33, - 0x32, 0x70, 0xf0, 0x30, 0x04, 0x47, 0x0e, 0x40, 0x35, 0x59, 0xda, 0xae, 0x8d, 0x5f, 0x61, 0xeb, - 0xe6, 0x0d, 0x90, 0x79, 0x25, 0x98, 0x66, 0x99, 0xbc, 0x3c, 0xbd, 0x55, 0xe1, 0x7e, 0x67, 0x2a, - 0x00, 0x34, 0x32, 0x7f, 0x77, 0x1e, 0x4f, 0xe8, 0x49, 0x04, 0x85, 0x9b, 0x3f, 0xd5, 0x6c, 0x96, - 0x88, 0xa1, 0xd3, 0xae, 0x54, 0x20, 0xc5, 0xd3, 0xc7, 0x4f, 0x99, 0x81, 0xe9, 0x93, 0xc7, 0x22, - 0x22, 0x24, 0xd0, 0x51, 0x78, 0x6e, 0x31, 0x9f, 0x6b, 0x4a, 0x80, 0x1f, 0x88, 0xd4, 0x83, 0x69, - 0x47, 0x68, 0xbf, 0x2d, 0x03, 0xa2, 0x7c, 0xec, 0x4e, 0x31, 0xf7, 0x06, 0xf6, 0xda, 0x06, 0x22, - 0x54, 0x7a, 0x7a, 0x45, 0x79, 0x19, 0x32, 0xcf, 0x9f, 0x43, 0x9f, 0x3e, 0x11, 0x48, 0x1c, 0x3c, - 0x98, 0xb2, 0xf9, 0xc5, 0xb4, 0x3e, 0x96, 0xc7, 0xc9, 0xd1, 0x85, 0xc8, 0x74, 0x55, 0x59, 0x95, - 0xb0, 0x31, 0x27, 0x22, 0x51, 0xac, 0xe6, 0xd7, 0x54, 0xd7, 0xa8, 0x87, 0x6a, 0xa1, 0x5c, 0x92, - 0x0e, 0xbf, 0x69, 0x1a, 0xfc, 0x02, 0x43, 0x70, 0x24, 0x75, 0x2f, 0x36, 0xaf, 0xfd, 0x02, 0x99, - 0x67, 0xcf, 0x70, 0x49, 0xeb, 0x0a, 0x0f, 0x4f, 0x2a, 0x31, 0x53, 0xad, 0xd6, 0x8d, 0x9a, 0x16, - 0xa2, 0x13, 0x23, 0x79, 0xc9, 0xde, 0x42, 0x21, 0x51, 0x24, 0x2f, 0x03, 0xf3, 0x1d, 0x3b, 0x69, - 0x3a, 0x6e, 0x99, 0x70, 0x33, 0x46, 0x0f, 0x1f, 0xc4, 0x53, 0xd7, 0x4e, 0x2a, 0x37, 0xb7, 0x88, - 0xfa, 0x4b, 0x11, 0xd7, 0x94, 0x00, 0x62, 0xe2, 0x7b, 0xd3, 0xa6, 0xcd, 0x70, 0x21, 0x32, 0xb6, - 0x6e, 0xdf, 0x8d, 0xb4, 0xc3, 0x47, 0x54, 0xa4, 0x88, 0x55, 0x6e, 0x99, 0x0b, 0xaa, 0xab, 0xaa, - 0x54, 0x0b, 0xdd, 0x82, 0xf8, 0xea, 0x2a, 0x7e, 0x0f, 0x24, 0x32, 0x02, 0xfe, 0xbe, 0x3e, 0xdc, - 0x90, 0x51, 0xaf, 0x86, 0x43, 0xa5, 0x87, 0x7f, 0x0f, 0x15, 0x5e, 0x88, 0x25, 0xc8, 0xa7, 0x12, - 0x36, 0x27, 0x63, 0xc0, 0x83, 0xe6, 0xdd, 0xc4, 0x56, 0x23, 0x85, 0x07, 0xd1, 0x27, 0x3a, 0x8e, - 0xb6, 0xb2, 0x65, 0x33, 0xe7, 0x8f, 0x33, 0xa7, 0x8e, 0x23, 0x65, 0xe7, 0x77, 0x38, 0x79, 0xf4, - 0xb0, 0xaa, 0x60, 0x21, 0x3b, 0x6a, 0x29, 0x5b, 0x3e, 0x78, 0xa3, 0x73, 0xb9, 0x44, 0xd0, 0xf0, - 0xc8, 0xbe, 0xaa, 0x75, 0xb5, 0x98, 0x7e, 0xbd, 0x31, 0x61, 0x74, 0x22, 0x02, 0x02, 0xfc, 0xed, - 0xa0, 0xb0, 0x73, 0xd1, 0xd7, 0x94, 0x00, 0x52, 0x75, 0x4a, 0x52, 0x62, 0x1b, 0xbf, 0x96, 0x70, - 0xf4, 0xe8, 0x51, 0x54, 0xf1, 0x30, 0x6e, 0xcb, 0xf7, 0xdb, 0x90, 0x4f, 0x5d, 0x89, 0x46, 0xb2, - 0x03, 0x8a, 0xda, 0xa9, 0x44, 0x10, 0x1b, 0xe0, 0xf5, 0x5c, 0xb1, 0x48, 0x2f, 0x17, 0x5b, 0x93, - 0x3e, 0x64, 0x57, 0x41, 0x81, 0xfe, 0xa0, 0x18, 0x1d, 0x0d, 0x07, 0x0e, 0x45, 0xf4, 0xc0, 0x18, - 0x2a, 0x0d, 0x7a, 0x91, 0x6d, 0x15, 0xaa, 0xba, 0x16, 0xa7, 0x39, 0x69, 0x8f, 0x1e, 0x9d, 0xac, - 0xea, 0x1e, 0x95, 0x71, 0x14, 0x35, 0xb2, 0x0c, 0xe9, 0xc9, 0xde, 0x3e, 0xbe, 0xf0, 0xe6, 0x11, - 0x85, 0x9b, 0x57, 0x0f, 0x4e, 0xca, 0x7a, 0x5a, 0x83, 0x6b, 0xe0, 0xf7, 0x5b, 0xaa, 0x48, 0xec, - 0xaa, 0x4b, 0xc7, 0x1a, 0xd4, 0x1e, 0xeb, 0xc9, 0xa3, 0x0d, 0x53, 0x6d, 0x15, 0xe2, 0x62, 0x22, - 0xd4, 0x45, 0x80, 0x1c, 0x06, 0x76, 0xa5, 0xbb, 0xe6, 0x04, 0xd0, 0x1a, 0x77, 0xf2, 0xd4, 0x49, - 0x75, 0x19, 0x9a, 0x47, 0x16, 0x53, 0x58, 0x58, 0x04, 0x91, 0x14, 0x2d, 0xa6, 0x2e, 0x94, 0x9c, - 0x8e, 0xca, 0xaa, 0x48, 0xd8, 0x83, 0x1b, 0x97, 0xa8, 0x72, 0x48, 0x27, 0x8a, 0x2c, 0xde, 0xde, - 0xbe, 0xea, 0x01, 0x5d, 0x4d, 0x55, 0x05, 0xaa, 0x49, 0x28, 0x13, 0x0f, 0xe5, 0x4a, 0x09, 0x1f, - 0x40, 0x3b, 0x82, 0xaf, 0xbd, 0xf6, 0x0a, 0x26, 0x4e, 0x98, 0xa8, 0x65, 0x4d, 0x44, 0xd7, 0xd1, - 0x2c, 0x5f, 0xbe, 0xaa, 0x62, 0x24, 0xcb, 0x51, 0x4f, 0x4e, 0xc8, 0x1c, 0x20, 0xaa, 0x6a, 0x52, - 0x35, 0x47, 0x5a, 0x0d, 0x97, 0xad, 0x32, 0xe2, 0x1a, 0xa8, 0x7a, 0xd4, 0x83, 0x3b, 0xe3, 0x9b, - 0x27, 0x4c, 0xe2, 0xbe, 0xe3, 0xff, 0xc1, 0x24, 0x6c, 0xc6, 0xd0, 0x65, 0x8f, 0x8c, 0x86, 0xad, - 0x5b, 0xb7, 0xe2, 0x8d, 0xbf, 0xff, 0x1d, 0x94, 0xcd, 0xa4, 0x26, 0x5c, 0x05, 0x72, 0xa8, 0xd6, - 0x27, 0x47, 0xd5, 0xc1, 0x62, 0xa4, 0x91, 0x3b, 0x57, 0x99, 0xac, 0x0d, 0x94, 0x20, 0x77, 0x27, - 0x12, 0xc5, 0x54, 0x82, 0x5c, 0xd2, 0xd4, 0x92, 0x65, 0xb9, 0x93, 0x95, 0xfc, 0xc7, 0xa2, 0x85, - 0x5c, 0xcf, 0xc7, 0xa9, 0x87, 0x75, 0xcd, 0xf3, 0xb6, 0x7c, 0x97, 0x72, 0xe4, 0x27, 0xac, 0x4b, - 0xd8, 0xa0, 0x10, 0x58, 0xe6, 0x01, 0x31, 0xc5, 0x69, 0x30, 0x78, 0x5a, 0x9e, 0x44, 0x58, 0x26, - 0xeb, 0x12, 0xff, 0x75, 0x33, 0x02, 0x2c, 0x5b, 0x27, 0xbd, 0x5d, 0x7a, 0xec, 0xaa, 0x4f, 0x3e, - 0xc1, 0xfe, 0x03, 0x07, 0xd4, 0xd5, 0x8b, 0x07, 0x11, 0x5e, 0x45, 0xdd, 0xcc, 0x32, 0x6a, 0x7f, - 0x38, 0x51, 0x85, 0x5d, 0x56, 0x4a, 0x72, 0x35, 0x10, 0xd3, 0xbf, 0x1f, 0x16, 0x3c, 0xf8, 0x00, - 0xc2, 0xc2, 0x42, 0x19, 0x7e, 0x75, 0xd6, 0xee, 0x96, 0x75, 0xed, 0xac, 0xff, 0xba, 0x24, 0x40, - 0x67, 0x1b, 0x75, 0x23, 0xa5, 0xbf, 0x74, 0xd8, 0x71, 0x23, 0xd5, 0xf8, 0x5f, 0xac, 0xae, 0xdd, - 0x04, 0xb8, 0xc6, 0x04, 0xed, 0x26, 0x40, 0x37, 0x01, 0xae, 0x1d, 0x06, 0x64, 0x05, 0x64, 0x4f, - 0xd1, 0xaa, 0xab, 0x6b, 0x77, 0xc3, 0x8e, 0x80, 0x0b, 0x17, 0x2e, 0xa8, 0xab, 0x23, 0x59, 0xf9, - 0x34, 0xff, 0xd1, 0x02, 0xaf, 0x5d, 0xbc, 0x89, 0xc9, 0x1a, 0x31, 0xfc, 0x20, 0xf6, 0x13, 0x1e, - 0x7a, 0xe8, 0x21, 0xbb, 0xf0, 0x5d, 0x05, 0xd0, 0xb5, 0xdb, 0xbc, 0xae, 0xaa, 0x35, 0xf3, 0x0d, - 0x0d, 0x0d, 0xc5, 0x4b, 0x2f, 0xbd, 0xc4, 0xe3, 0xea, 0x7d, 0xea, 0x01, 0xdd, 0x37, 0xdf, 0x7c, - 0xa3, 0x6e, 0xb8, 0xa4, 0x48, 0xd9, 0x41, 0xdb, 0x73, 0xa2, 0x41, 0xfa, 0xe5, 0x97, 0x5f, 0xaa, - 0x60, 0xad, 0x6a, 0x93, 0xda, 0xcb, 0xa8, 0x93, 0xf1, 0xed, 0x5e, 0x86, 0x52, 0x81, 0x4d, 0x55, - 0xb5, 0x2d, 0xa2, 0xc5, 0x7a, 0x39, 0x4e, 0x96, 0x63, 0x5f, 0x39, 0x1a, 0x4e, 0x4e, 0x4e, 0x56, - 0x91, 0x62, 0xab, 0x3e, 0x72, 0x22, 0x79, 0xee, 0xdc, 0x39, 0x35, 0x4a, 0x4e, 0x2f, 0x45, 0x9d, - 0xd7, 0xd2, 0xf1, 0x7b, 0x8b, 0x6a, 0x5e, 0x12, 0x26, 0xa6, 0x4a, 0xe4, 0x88, 0xb9, 0x35, 0x27, - 0x9b, 0x28, 0x49, 0x23, 0xb0, 0xa2, 0xd6, 0x2b, 0x4e, 0xbe, 0x03, 0x25, 0x7b, 0x07, 0x71, 0x42, - 0x14, 0x7e, 0xfc, 0x48, 0xf5, 0x37, 0xff, 0x93, 0xcb, 0x1f, 0xf9, 0x02, 0x99, 0xec, 0x35, 0x34, - 0x27, 0x69, 0xe5, 0xd7, 0x56, 0x27, 0xd6, 0x4a, 0x64, 0xa7, 0x2e, 0xb8, 0x90, 0xfc, 0x44, 0xb7, - 0x94, 0x56, 0x9c, 0x61, 0x4b, 0x75, 0xd8, 0x6e, 0x9e, 0xac, 0x88, 0x5d, 0xc7, 0x23, 0x60, 0x85, - 0x5b, 0x7c, 0xa9, 0x71, 0x93, 0x1f, 0x11, 0xd0, 0xe4, 0x5d, 0xe2, 0xc5, 0xf0, 0xb7, 0xa5, 0xfb, - 0xfd, 0xef, 0x7f, 0x6f, 0x05, 0xc3, 0xdd, 0xae, 0x19, 0x24, 0x2a, 0x2a, 0xaa, 0x49, 0xbc, 0x66, - 0x9e, 0xda, 0x0c, 0x40, 0x0f, 0xc5, 0x55, 0x94, 0x05, 0x0b, 0x16, 0x34, 0x81, 0x6b, 0x5e, 0x17, - 0xcb, 0x77, 0x12, 0xc0, 0x32, 0xb9, 0xd9, 0xff, 0xe9, 0xa7, 0x9f, 0xda, 0xcc, 0xa3, 0xb9, 0xc6, - 0xaf, 0x39, 0x81, 0x85, 0x67, 0xf7, 0xee, 0xdd, 0x0a, 0x3b, 0x9b, 0xcd, 0xf4, 0x96, 0x65, 0x8b, - 0xed, 0xee, 0x77, 0xdf, 0x7d, 0xd7, 0x22, 0x65, 0xeb, 0x5e, 0xe9, 0x09, 0x6d, 0x76, 0x9c, 0xb0, - 0x6c, 0xc2, 0xbe, 0xfc, 0xf2, 0xcb, 0xe6, 0x8a, 0xf5, 0xe9, 0xd3, 0xc7, 0x26, 0x8c, 0x66, 0xcc, - 0x5c, 0x2a, 0x6b, 0x49, 0x00, 0x01, 0xd6, 0x54, 0xa6, 0x25, 0xae, 0x39, 0x01, 0x44, 0x69, 0x57, - 0x53, 0xe8, 0x95, 0x78, 0xf6, 0x32, 0x25, 0x3d, 0x3d, 0xdd, 0x5c, 0xc6, 0xc9, 0x93, 0x27, 0x15, - 0x29, 0xd3, 0x12, 0x09, 0xb6, 0x14, 0x7b, 0xcd, 0x09, 0x2e, 0x7b, 0x34, 0x9b, 0xe2, 0x92, 0xce, - 0x1e, 0x01, 0xa8, 0x35, 0xdd, 0x24, 0xff, 0xe7, 0x9f, 0x7f, 0xbe, 0x79, 0x76, 0x8a, 0x7c, 0x2d, - 0x95, 0x73, 0x91, 0x19, 0x6e, 0xcc, 0x98, 0x31, 0x56, 0x30, 0xb6, 0x02, 0xda, 0x44, 0x00, 0xae, - 0x16, 0x94, 0xbb, 0xef, 0xbe, 0xbb, 0x49, 0x01, 0x96, 0x0d, 0xb6, 0xf4, 0x5b, 0x1a, 0x60, 0xb7, - 0x2c, 0xb0, 0xa3, 0x04, 0x78, 0xee, 0xb9, 0xe7, 0xcc, 0x8d, 0x92, 0x72, 0xc8, 0xca, 0x2c, 0xb3, - 0x55, 0xfd, 0x64, 0x85, 0x4d, 0x60, 0x1c, 0x49, 0x00, 0x9e, 0x17, 0xa9, 0x46, 0xe5, 0xb5, 0x36, - 0x8a, 0x1e, 0x7e, 0x4b, 0xee, 0x8d, 0x37, 0xde, 0x68, 0x52, 0x0f, 0xde, 0x77, 0xb4, 0x04, 0x6a, - 0x0e, 0xb7, 0xbb, 0x0a, 0x22, 0xa4, 0xca, 0x1f, 0xe5, 0x73, 0xe8, 0xe2, 0xa7, 0xf2, 0xbd, 0xfa, - 0x14, 0xbf, 0xf6, 0xdb, 0xbb, 0x77, 0x2f, 0xeb, 0xd7, 0xba, 0x93, 0xd5, 0x86, 0xe6, 0xc4, 0xa4, - 0x82, 0xa5, 0xe3, 0x08, 0xb0, 0x7c, 0x6d, 0xe2, 0x97, 0xdb, 0x30, 0x4b, 0x97, 0x9a, 0x9a, 0x6a, - 0xf9, 0xaa, 0xfa, 0xe5, 0x62, 0xa7, 0xab, 0x9c, 0xdc, 0x15, 0xf0, 0xd3, 0x7f, 0xe6, 0xec, 0x69, - 0xa8, 0xbe, 0xc5, 0xa5, 0xab, 0xa5, 0x79, 0x09, 0x99, 0x9b, 0x12, 0x12, 0x12, 0xcc, 0xe9, 0x5a, - 0xf4, 0x10, 0x89, 0x76, 0x9d, 0x25, 0xff, 0x97, 0x1e, 0xfe, 0xc8, 0x23, 0x8f, 0x28, 0x1f, 0xd0, - 0x0e, 0x00, 0x0d, 0xf8, 0x29, 0x13, 0x27, 0x4e, 0x6c, 0x42, 0x75, 0x16, 0xa4, 0xc8, 0xf0, 0x6b, - 0x4e, 0xfd, 0xfb, 0xf9, 0xa9, 0x02, 0x89, 0xd3, 0x7e, 0xb1, 0xb1, 0xb1, 0xaa, 0x39, 0x08, 0x4e, - 0xb8, 0xe6, 0x30, 0x89, 0xe3, 0x25, 0x89, 0x72, 0xd3, 0x4d, 0x37, 0x35, 0x61, 0x33, 0xcd, 0x59, - 0x80, 0xb0, 0xa1, 0x85, 0x0b, 0x17, 0x2a, 0x8b, 0x16, 0x2d, 0x52, 0xe4, 0xa3, 0x12, 0x5a, 0x9e, - 0xda, 0xb3, 0x7f, 0xff, 0xfe, 0x0a, 0x3b, 0x4c, 0x93, 0x76, 0x09, 0x9b, 0x93, 0xaf, 0x12, 0x86, - 0x87, 0x87, 0xab, 0x3f, 0x61, 0x75, 0x1a, 0xbc, 0xb0, 0x0e, 0x2d, 0x3c, 0x32, 0x32, 0x52, 0x35, - 0x67, 0xc1, 0x63, 0x71, 0x73, 0x7a, 0x4e, 0xb4, 0x0a, 0x91, 0x69, 0x86, 0x97, 0x74, 0xf2, 0xe9, - 0x04, 0xf9, 0xf2, 0xe1, 0x53, 0x4f, 0x3d, 0xa5, 0xb6, 0x57, 0xcb, 0x4b, 0x9e, 0xf2, 0x9d, 0xe4, - 0xb6, 0x6a, 0xda, 0x4b, 0x2f, 0xb6, 0xeb, 0xb8, 0xea, 0x50, 0xbf, 0xe7, 0x68, 0xc9, 0x46, 0xa4, - 0x20, 0xb1, 0x45, 0x20, 0x26, 0x31, 0x68, 0x93, 0x4c, 0xf9, 0xe8, 0xa3, 0x8f, 0xf8, 0x85, 0xdc, - 0x1e, 0x6a, 0x25, 0xfb, 0xf5, 0xeb, 0xa7, 0x6c, 0xd9, 0xb2, 0xc5, 0x2a, 0xdf, 0x55, 0xab, 0x56, - 0xa9, 0xfc, 0x56, 0xab, 0xac, 0xa4, 0x9f, 0x3d, 0x7b, 0xb6, 0xc2, 0x15, 0x95, 0xf9, 0x0b, 0x1c, - 0x12, 0xc7, 0x55, 0x92, 0x42, 0x71, 0x94, 0x26, 0xe9, 0x85, 0x0d, 0x3e, 0xfb, 0xec, 0xb3, 0x4a, - 0xf3, 0x3a, 0x08, 0xe2, 0xa4, 0x2c, 0xe1, 0xcb, 0x1a, 0x0f, 0x96, 0xaf, 0x79, 0xd0, 0x56, 0x5a, - 0x93, 0xf4, 0xef, 0xbf, 0xff, 0xbe, 0x3a, 0x7f, 0x68, 0x65, 0xb7, 0xf4, 0x94, 0x3c, 0xc4, 0x06, - 0x83, 0x2d, 0x04, 0x8a, 0xc9, 0x8d, 0x17, 0x5f, 0x7c, 0x51, 0x9d, 0xa7, 0x9a, 0xa7, 0x97, 0x7a, - 0x49, 0xc7, 0x94, 0xb6, 0xb4, 0xc7, 0xb5, 0x7b, 0x19, 0xca, 0x82, 0xbb, 0x9d, 0x03, 0x31, 0x60, - 0x77, 0x0e, 0x70, 0x60, 0x59, 0xdd, 0x59, 0xd9, 0xc0, 0x40, 0x37, 0x01, 0x6c, 0x20, 0xe5, 0x6a, - 0x06, 0x75, 0x13, 0xe0, 0x6a, 0x62, 0xdb, 0x46, 0x59, 0xdd, 0x04, 0xb0, 0x81, 0x94, 0xab, 0x19, - 0xd4, 0x4d, 0x80, 0xab, 0x89, 0x6d, 0x1b, 0x65, 0x75, 0x13, 0xc0, 0x06, 0x52, 0xae, 0x66, 0x50, - 0x37, 0x01, 0xae, 0x26, 0xb6, 0x6d, 0x94, 0xd5, 0x4d, 0x00, 0x1b, 0x48, 0xb9, 0x9a, 0x41, 0xff, - 0x07, 0xaf, 0xf3, 0x8d, 0x60, 0xda, 0x1b, 0x41, 0x87, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, - 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXJSIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x38, 0x38, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x0e, - 0x0a, 0xaa, 0x03, 0x00, 0x00, 0x05, 0x39, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x7d, - 0x48, 0x5b, 0x57, 0x14, 0xcf, 0x8b, 0x2f, 0x31, 0xd1, 0x1a, 0x4d, 0xb4, 0x06, 0xc7, 0xfc, 0x88, - 0x55, 0x59, 0x97, 0x5a, 0xf1, 0xb3, 0x43, 0x83, 0xba, 0x32, 0x97, 0x0d, 0x3a, 0x0b, 0x2b, 0x08, - 0x75, 0x65, 0x82, 0x8c, 0xc1, 0xdc, 0x1f, 0xab, 0x48, 0xdd, 0x64, 0x62, 0x19, 0x6e, 0x73, 0xc2, - 0xa6, 0x83, 0x6e, 0x38, 0x46, 0xff, 0x28, 0xc3, 0x75, 0x6b, 0x51, 0x36, 0x54, 0x56, 0x23, 0x88, - 0x3a, 0x3b, 0xa1, 0x22, 0xd4, 0xd8, 0xc9, 0x28, 0x9b, 0x1f, 0x0c, 0xad, 0x4c, 0xa3, 0xb5, 0x89, - 0x71, 0xd1, 0x7c, 0xb8, 0x63, 0x9f, 0xbc, 0x3c, 0x93, 0x98, 0x9b, 0xbc, 0x7b, 0xcd, 0x10, 0xde, - 0x23, 0x84, 0x73, 0xcf, 0xfb, 0xdd, 0x73, 0x7e, 0xbf, 0x73, 0xee, 0xbb, 0x2f, 0xb9, 0xd4, 0xce, - 0xce, 0x8e, 0xe8, 0x28, 0x5f, 0xe2, 0xa3, 0x4c, 0x7e, 0x97, 0xbb, 0x20, 0xe0, 0xff, 0xee, 0xa0, - 0xd0, 0x01, 0xa1, 0x03, 0x98, 0x15, 0x10, 0x96, 0x10, 0x66, 0x01, 0xb1, 0xa7, 0xd3, 0xd8, 0x11, - 0xf6, 0x02, 0xac, 0x8f, 0x19, 0xcc, 0x13, 0xbf, 0xba, 0xec, 0xdb, 0x30, 0x56, 0x16, 0xe9, 0xa3, - 0x5f, 0x78, 0xc9, 0x23, 0xf2, 0xfc, 0x17, 0x57, 0x18, 0x8f, 0x34, 0xfe, 0x99, 0xf8, 0x73, 0x97, - 0x68, 0xe5, 0x71, 0x0f, 0x00, 0xbf, 0x21, 0x19, 0x01, 0xb3, 0x1f, 0xbf, 0xb3, 0x74, 0xeb, 0x1b, - 0x96, 0x41, 0x58, 0x64, 0x94, 0xb7, 0x80, 0xc5, 0x1b, 0x9f, 0xb3, 0x80, 0x85, 0x6f, 0x3f, 0xc9, - 0xfc, 0xee, 0xae, 0x5c, 0xf3, 0x1c, 0xeb, 0xe1, 0x6d, 0x10, 0x78, 0x06, 0x2c, 0xc6, 0x31, 0x2e, - 0xfb, 0x40, 0xa8, 0xd8, 0xd7, 0x57, 0xe7, 0x5a, 0x2f, 0x07, 0x82, 0x44, 0x62, 0x08, 0x74, 0xc0, - 0x32, 0x39, 0xc6, 0xa6, 0x49, 0xfd, 0xe0, 0x4b, 0xa5, 0xee, 0x55, 0x5a, 0x19, 0xc7, 0x7a, 0x58, - 0x23, 0xf7, 0x97, 0x3f, 0x1d, 0xe6, 0xf5, 0xbf, 0xae, 0xbe, 0x65, 0x7d, 0x68, 0x04, 0x27, 0x77, - 0x16, 0x8b, 0xe1, 0x61, 0x10, 0xe8, 0x80, 0x63, 0xc3, 0xcc, 0x24, 0xa6, 0x15, 0x31, 0x09, 0x6f, - 0xbc, 0x27, 0x4b, 0xce, 0xa0, 0x15, 0x2a, 0x6f, 0x2a, 0xb2, 0xc4, 0xb4, 0x63, 0xda, 0xbc, 0xf8, - 0xf3, 0x55, 0xcc, 0x2d, 0x87, 0xd5, 0xe2, 0x8d, 0xe1, 0xe1, 0x21, 0x20, 0x80, 0xcd, 0x2a, 0x0e, - 0x97, 0xb3, 0xf6, 0x41, 0x46, 0x20, 0x98, 0x83, 0xe6, 0xfa, 0xf4, 0x93, 0x14, 0xe0, 0x33, 0xc1, - 0x61, 0x3b, 0x05, 0x01, 0x22, 0x91, 0x63, 0x7d, 0x95, 0x29, 0x33, 0x45, 0x4b, 0x90, 0xf5, 0x16, - 0x4b, 0xdc, 0x18, 0x87, 0x79, 0x0d, 0x89, 0x47, 0x02, 0x70, 0x3b, 0xb0, 0xbd, 0xf2, 0x68, 0x75, - 0xf0, 0x27, 0x26, 0x4d, 0xc4, 0x89, 0xe7, 0x91, 0xf9, 0xe4, 0xa9, 0x6e, 0xcc, 0xd2, 0xcd, 0xaf, - 0x90, 0x78, 0x24, 0x00, 0x4b, 0xc0, 0xc2, 0xf5, 0x4f, 0xef, 0x97, 0x9f, 0xdc, 0x5e, 0x59, 0x82, - 0x34, 0x61, 0x32, 0x79, 0xe2, 0xdb, 0x1f, 0x22, 0xf3, 0x45, 0x9d, 0x3e, 0xa3, 0x2a, 0x7d, 0x8d, - 0x81, 0xfd, 0xfd, 0xf5, 0xd5, 0xa9, 0x8b, 0xf9, 0x5b, 0x0b, 0xb3, 0xc8, 0x59, 0x7e, 0x00, 0x58, - 0x02, 0x36, 0xa6, 0xee, 0x31, 0x7b, 0xa8, 0x44, 0x75, 0x3c, 0xe3, 0xb3, 0xce, 0xa8, 0x6c, 0x9d, - 0x9f, 0x4c, 0x7b, 0xb7, 0x28, 0x71, 0x46, 0xeb, 0xf7, 0xb1, 0x2f, 0x96, 0x33, 0x43, 0xcb, 0xef, - 0x13, 0xf6, 0x27, 0x7b, 0x2b, 0x10, 0x3d, 0xd7, 0x17, 0x02, 0x4b, 0x40, 0xac, 0xbe, 0x22, 0x32, - 0x23, 0x13, 0xc2, 0xda, 0xd7, 0x56, 0xfe, 0xb8, 0x7c, 0xc1, 0x74, 0xe7, 0x07, 0x5f, 0x29, 0xf6, - 0xf9, 0x5c, 0x5b, 0xff, 0x3e, 0x78, 0x53, 0xb7, 0x3a, 0xd4, 0x03, 0x5e, 0xb1, 0x34, 0x5c, 0xfd, - 0x7a, 0x75, 0xb8, 0xfa, 0xd9, 0x7d, 0x88, 0x60, 0x07, 0x70, 0x2a, 0x81, 0x73, 0xb9, 0xb6, 0x6d, - 0xf7, 0x2f, 0x64, 0xdd, 0x3d, 0x25, 0x82, 0xcf, 0xd4, 0xa5, 0x42, 0x64, 0xa8, 0xc7, 0xbf, 0xf5, - 0x33, 0x60, 0xf8, 0x36, 0x19, 0x6e, 0x23, 0xf1, 0x48, 0x00, 0x56, 0x07, 0xa0, 0x58, 0x94, 0x24, - 0x5c, 0xa9, 0x7b, 0x85, 0xa9, 0x9a, 0x6d, 0x71, 0x0e, 0x59, 0x3e, 0xdb, 0x82, 0x1b, 0xa3, 0x3a, - 0x7b, 0x1e, 0x89, 0x47, 0x02, 0x70, 0x05, 0x40, 0x02, 0x4a, 0x22, 0x45, 0xa6, 0xf1, 0x09, 0xa0, - 0x68, 0x9e, 0x13, 0xb9, 0xd1, 0x08, 0x08, 0xe0, 0x86, 0x0b, 0xbd, 0x2d, 0x08, 0xe0, 0xd4, 0xdc, - 0x69, 0x35, 0x8b, 0x5c, 0x4e, 0x8e, 0xc3, 0x87, 0xe9, 0x34, 0x3f, 0xf6, 0xe1, 0xc5, 0x70, 0x11, - 0xf8, 0x3f, 0x20, 0x8d, 0x55, 0x33, 0x04, 0x9c, 0x9b, 0x56, 0xf8, 0xb9, 0x1f, 0x53, 0xf8, 0x72, - 0x64, 0xc6, 0x69, 0xf9, 0x09, 0xad, 0x07, 0x2b, 0x53, 0xff, 0x8f, 0x4e, 0xcb, 0x93, 0x47, 0x37, - 0xaf, 0x31, 0x7e, 0x69, 0x6c, 0xbc, 0x07, 0x80, 0xdf, 0x90, 0x80, 0x80, 0xe8, 0x33, 0x67, 0x29, - 0x9a, 0xde, 0x71, 0x38, 0x80, 0xc1, 0x3f, 0x3f, 0xdf, 0x80, 0x4f, 0xd2, 0xbb, 0x1f, 0x25, 0x7a, - 0x09, 0x78, 0x78, 0xe5, 0x22, 0x97, 0x62, 0x4c, 0xa1, 0x9e, 0x3b, 0xe4, 0x6d, 0x13, 0x78, 0x06, - 0xe4, 0x9a, 0x93, 0xa9, 0x0d, 0xd7, 0xe0, 0xad, 0x14, 0x38, 0x89, 0xa8, 0x53, 0x79, 0x9a, 0xf7, - 0xdb, 0x03, 0xc7, 0xfb, 0x41, 0x52, 0xf0, 0xa6, 0xf0, 0x73, 0x3b, 0xf0, 0x5b, 0xdb, 0xcb, 0x8b, - 0x1b, 0x0f, 0xee, 0x31, 0xa7, 0x12, 0x91, 0xe9, 0x99, 0x3e, 0x96, 0x90, 0xe1, 0x16, 0x13, 0x4d, - 0x1a, 0x97, 0xa0, 0xc8, 0xd1, 0x89, 0x28, 0x02, 0xb5, 0x83, 0x80, 0xc4, 0x04, 0x04, 0x2e, 0x95, - 0x2c, 0x92, 0x4c, 0x19, 0xc8, 0x72, 0x0a, 0x2a, 0x9a, 0x20, 0x20, 0xa8, 0x72, 0x1d, 0x02, 0x58, - 0xe8, 0xc0, 0x21, 0x14, 0x35, 0xa8, 0x90, 0x84, 0x3b, 0x70, 0xfd, 0xe9, 0x15, 0x14, 0x03, 0x4c, - 0x30, 0xc9, 0x6d, 0x74, 0x6b, 0x6b, 0x2b, 0x22, 0x22, 0x22, 0x2c, 0x2c, 0x6c, 0x73, 0x73, 0x93, - 0xa6, 0x09, 0xbc, 0xe3, 0x03, 0xd1, 0x46, 0x38, 0x4d, 0x74, 0x74, 0xb4, 0x5c, 0x2e, 0x0f, 0x19, - 0x7b, 0x50, 0x48, 0xb2, 0x03, 0x10, 0xce, 0xe5, 0x72, 0xc1, 0xb7, 0x58, 0x8c, 0x5e, 0x99, 0x80, - 0x0c, 0x04, 0x86, 0x6c, 0x02, 0x81, 0x0e, 0x8c, 0x8e, 0x8e, 0x36, 0x35, 0x35, 0xc1, 0xb2, 0x61, - 0x93, 0x55, 0x54, 0x54, 0xd4, 0xd5, 0xd5, 0xb1, 0x43, 0x30, 0x7a, 0x7b, 0x7b, 0xbb, 0xba, 0xba, - 0xfa, 0xfb, 0xfb, 0x2d, 0x16, 0x8b, 0x56, 0xab, 0x85, 0xc5, 0x96, 0x94, 0x94, 0xd4, 0xd7, 0xd7, - 0xc7, 0xc5, 0xf0, 0xb3, 0xc9, 0x08, 0x18, 0x1e, 0x1e, 0xe6, 0xa6, 0x4f, 0x4b, 0x4b, 0xe3, 0x0e, - 0x07, 0x07, 0x07, 0xcb, 0xcb, 0x77, 0xcf, 0x51, 0xf4, 0x7a, 0xbd, 0xd3, 0xe9, 0x84, 0x21, 0xfc, - 0x00, 0xb3, 0xdb, 0xed, 0x5c, 0x0c, 0x6f, 0x9b, 0x80, 0x80, 0xda, 0xda, 0xda, 0xfc, 0xfc, 0x7c, - 0xab, 0xd5, 0x0a, 0x24, 0x3a, 0x3b, 0x3b, 0xbb, 0xbb, 0xbb, 0x3d, 0xd8, 0x18, 0x0c, 0x06, 0xf0, - 0x40, 0xe1, 0xa1, 0x03, 0x60, 0xcc, 0xcf, 0xcf, 0x37, 0x37, 0x37, 0x83, 0x12, 0x0f, 0x18, 0xbf, - 0x21, 0x01, 0x01, 0xf0, 0xd4, 0x96, 0x95, 0x95, 0x31, 0xe9, 0xc7, 0xc7, 0xc7, 0xbd, 0x79, 0x14, - 0x14, 0x14, 0x80, 0x73, 0x7a, 0x7a, 0x3a, 0x2b, 0x2b, 0xab, 0xa4, 0xa4, 0x24, 0x3b, 0x3b, 0xbb, - 0xb1, 0xb1, 0x51, 0xa3, 0xd1, 0x78, 0x23, 0xf9, 0x78, 0x90, 0x07, 0x2f, 0x41, 0x01, 0x1a, 0x1a, - 0x1a, 0x80, 0x44, 0x65, 0x65, 0x25, 0x77, 0x16, 0xac, 0x16, 0x9d, 0x6e, 0xdf, 0xa1, 0x1d, 0x45, - 0x51, 0x35, 0x35, 0x35, 0x5c, 0x0c, 0x6f, 0x1b, 0xbd, 0x5d, 0xf0, 0xa9, 0xca, 0xfe, 0x39, 0xb0, - 0xab, 0x0e, 0x0c, 0x0c, 0x18, 0x8d, 0xc6, 0xfa, 0xfa, 0xfa, 0xe2, 0xe2, 0x62, 0x89, 0x44, 0x02, - 0x74, 0x3b, 0x3a, 0x3a, 0xe6, 0xe6, 0xdc, 0x67, 0x44, 0xfb, 0x67, 0x04, 0x31, 0x0a, 0x85, 0x80, - 0xb6, 0xb6, 0x36, 0xd8, 0x73, 0x60, 0x9b, 0x6a, 0x6d, 0x6d, 0x1d, 0x19, 0x19, 0x99, 0x99, 0x99, - 0x91, 0xc9, 0x64, 0xa0, 0x61, 0x68, 0x68, 0x28, 0x08, 0xa6, 0x07, 0x40, 0x09, 0x3c, 0x03, 0x07, - 0x44, 0x76, 0xbb, 0xa1, 0xd2, 0x26, 0x93, 0xa9, 0xb4, 0xb4, 0x14, 0x96, 0x4d, 0x6e, 0x6e, 0xee, - 0xe4, 0xe4, 0xa4, 0xcd, 0x66, 0x83, 0x97, 0x00, 0x3c, 0xfa, 0x6e, 0x10, 0x5f, 0x8b, 0xb0, 0x00, - 0x60, 0xe6, 0xcd, 0x44, 0xa1, 0x50, 0xc0, 0xa2, 0x87, 0x85, 0xd4, 0xde, 0xbe, 0xf7, 0x3f, 0x38, - 0x2e, 0x2e, 0xae, 0xa5, 0xa5, 0x25, 0x33, 0x73, 0xf7, 0x60, 0x18, 0xf3, 0x22, 0x2c, 0x00, 0xb6, - 0x48, 0x20, 0x94, 0x90, 0x90, 0xc0, 0xa5, 0x05, 0x4f, 0x76, 0x75, 0x75, 0x75, 0x4a, 0x4a, 0xca, - 0xec, 0xec, 0xec, 0xda, 0xda, 0x9a, 0x4a, 0xa5, 0x4a, 0x4e, 0x4e, 0x96, 0x4a, 0x09, 0x9c, 0x2b, - 0x42, 0x16, 0x02, 0x02, 0x7a, 0x7a, 0x7a, 0x26, 0x26, 0x26, 0xd4, 0x6a, 0x35, 0xec, 0xa1, 0xcc, - 0xcb, 0xb5, 0xa8, 0xa8, 0x88, 0x2b, 0xe0, 0xd8, 0xd3, 0x0b, 0x3c, 0xe9, 0xe9, 0xe9, 0x5c, 0x3f, - 0x19, 0x9b, 0xf7, 0xfe, 0xc5, 0x4e, 0x64, 0xde, 0xb2, 0x2c, 0x9b, 0xaa, 0xaa, 0x2a, 0xf6, 0x56, - 0x08, 0x0c, 0x02, 0x3f, 0xe6, 0x96, 0x97, 0x97, 0x61, 0x3f, 0x81, 0xc5, 0xa3, 0x54, 0x2a, 0xf3, - 0xf2, 0xf2, 0x72, 0x72, 0x72, 0x58, 0x31, 0x21, 0x30, 0x08, 0x08, 0x08, 0x01, 0x4b, 0x3f, 0x29, - 0x42, 0xf1, 0x1e, 0xf0, 0x93, 0x1e, 0xff, 0x96, 0x20, 0x00, 0xbf, 0x86, 0x78, 0x11, 0x84, 0x0e, - 0xe0, 0xd5, 0x0f, 0x7f, 0xb6, 0xd0, 0x01, 0xfc, 0x1a, 0xe2, 0x45, 0x38, 0xf2, 0x1d, 0xf8, 0x0f, - 0x1c, 0x65, 0x73, 0xb3, 0xdd, 0xbe, 0x50, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, - 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXJSIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0b, 0x56, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x6b, 0x6c, 0x14, 0xc7, 0xf9, 0xbb, 0xf3, 0xf9, 0x89, 0x0d, 0x7e, 0xc7, 0x02, 0x0a, 0x85, - 0x26, 0xa9, 0x04, 0x49, 0x4a, 0x69, 0x6d, 0x41, 0x84, 0x30, 0xd8, 0x16, 0x21, 0xe1, 0x51, 0x89, - 0xd6, 0x32, 0x8f, 0x52, 0x35, 0xf4, 0x87, 0x8d, 0x94, 0x54, 0xfd, 0x51, 0x54, 0x14, 0xaa, 0x2a, - 0x15, 0x34, 0xa8, 0x85, 0x16, 0x45, 0xa8, 0x56, 0x5c, 0x29, 0x45, 0x40, 0x91, 0x6a, 0x70, 0x48, - 0x7e, 0x14, 0xa2, 0xd0, 0x40, 0x51, 0xc1, 0x55, 0x15, 0x5a, 0x09, 0x1c, 0x6a, 0x51, 0xd3, 0x18, - 0x81, 0x0d, 0xc6, 0x36, 0x06, 0xe3, 0xf7, 0xe3, 0x7c, 0xdb, 0xf9, 0xd6, 0xec, 0xdc, 0x3e, 0x66, - 0x6f, 0x5f, 0xb3, 0x77, 0x7b, 0x64, 0x47, 0xb2, 0xf7, 0x9b, 0x6f, 0xbe, 0xf7, 0xb7, 0x33, 0x3b, - 0xbb, 0x3b, 0xb3, 0x17, 0x10, 0x48, 0x01, 0x0b, 0x25, 0x68, 0x81, 0x56, 0x24, 0x65, 0x32, 0x74, - 0x7f, 0x2b, 0x20, 0x36, 0x4a, 0x47, 0x85, 0x50, 0x34, 0x49, 0xaf, 0x4c, 0x75, 0x77, 0x68, 0x9a, - 0x40, 0x8d, 0xb9, 0xbf, 0x54, 0x89, 0x52, 0xd7, 0x95, 0xad, 0x2a, 0x6e, 0x96, 0x06, 0xa6, 0x0f, - 0xc3, 0xf5, 0x3f, 0x17, 0xcd, 0x1e, 0x6d, 0x7a, 0x4f, 0x61, 0x3e, 0x56, 0x02, 0x28, 0x54, 0x83, - 0x8d, 0x81, 0x60, 0x6a, 0x88, 0x41, 0x0f, 0x4c, 0x86, 0x40, 0x60, 0x3a, 0xac, 0xd2, 0x51, 0x2e, - 0x80, 0xc9, 0x20, 0x11, 0xb0, 0xac, 0x65, 0x32, 0xb0, 0x08, 0x25, 0x21, 0x09, 0x70, 0xfa, 0xf1, - 0xae, 0xef, 0x4a, 0xda, 0x21, 0xf2, 0xa0, 0x8b, 0xc2, 0x14, 0xc0, 0x3c, 0xc8, 0x8b, 0xfc, 0x54, - 0x90, 0xc3, 0x12, 0x8d, 0xc6, 0xe9, 0xac, 0xcd, 0x6f, 0x52, 0x61, 0x29, 0x05, 0xcf, 0x50, 0x98, - 0x02, 0x12, 0xa7, 0x74, 0x94, 0x4b, 0x95, 0xc3, 0x52, 0xbb, 0x36, 0x4a, 0x93, 0xe3, 0x00, 0xa9, - 0xe9, 0x54, 0xa0, 0x1a, 0xd0, 0x32, 0xa8, 0x29, 0x54, 0x75, 0x8d, 0x0f, 0xaa, 0x76, 0x4d, 0x55, - 0x97, 0x61, 0xd5, 0xaa, 0x55, 0x10, 0x0a, 0x85, 0x34, 0x0c, 0x9a, 0x0e, 0xb4, 0x75, 0xeb, 0x56, - 0xc9, 0x3f, 0xe6, 0xd1, 0xb2, 0x0f, 0x96, 0x19, 0xb4, 0x36, 0xc6, 0xc6, 0xe8, 0xfa, 0x1c, 0x9b, - 0xcd, 0x7c, 0xab, 0x29, 0x05, 0xac, 0xf1, 0x6f, 0xf0, 0x37, 0x6f, 0x00, 0x0b, 0xaf, 0x56, 0x6d, - 0x4a, 0x81, 0x9a, 0x09, 0xeb, 0x39, 0x3f, 0x7d, 0x97, 0x85, 0xd6, 0xe0, 0x6c, 0x2b, 0x60, 0xf6, - 0x44, 0x8d, 0x78, 0x60, 0x8f, 0x61, 0x0c, 0x3a, 0x18, 0xd8, 0xb3, 0x55, 0x81, 0x7e, 0xb0, 0x61, - 0x81, 0xa2, 0xae, 0x57, 0xf1, 0xce, 0x59, 0xc4, 0x1a, 0x91, 0xf5, 0xac, 0x96, 0xe3, 0x4d, 0xe5, - 0x60, 0xfd, 0xfa, 0xf5, 0x72, 0x1e, 0x40, 0x65, 0xa3, 0xa3, 0xa3, 0xb0, 0x61, 0xc3, 0x06, 0x05, - 0x9e, 0x59, 0x61, 0xf6, 0x57, 0x06, 0x92, 0x30, 0x53, 0x2c, 0xc2, 0x69, 0x69, 0x69, 0xc2, 0xd2, - 0xa5, 0x4b, 0x29, 0x4e, 0x0f, 0xf0, 0x4e, 0x0e, 0x98, 0xee, 0x9b, 0x40, 0x26, 0xbf, 0x07, 0xa6, - 0xce, 0x22, 0x13, 0x91, 0xd0, 0x25, 0xf1, 0x86, 0x02, 0x1c, 0x35, 0x7b, 0x4a, 0x53, 0xa8, 0x95, - 0x58, 0x37, 0x33, 0x92, 0x22, 0x83, 0xa1, 0x07, 0x3d, 0xcb, 0xa6, 0x2f, 0xd1, 0xc5, 0x57, 0xa6, - 0xa8, 0x82, 0x67, 0xfe, 0x6d, 0x7e, 0x92, 0x67, 0xa8, 0x40, 0x98, 0x9c, 0xa0, 0x82, 0xed, 0x00, - 0x86, 0x0a, 0x50, 0x68, 0x20, 0x33, 0x8b, 0x29, 0x7b, 0xe2, 0x1f, 0x1f, 0x33, 0xf1, 0x0a, 0xa4, - 0x5e, 0x17, 0x47, 0xfc, 0x78, 0xf3, 0x59, 0x81, 0x35, 0xdd, 0xc1, 0x36, 0x9c, 0x52, 0xeb, 0xb5, - 0x61, 0xbb, 0x54, 0xa2, 0x03, 0x8c, 0x84, 0x51, 0x1d, 0x51, 0x08, 0x4b, 0x10, 0xe2, 0x22, 0x43, - 0x8f, 0x55, 0xd4, 0xda, 0xaa, 0xa9, 0x10, 0x29, 0x5c, 0x96, 0x55, 0x02, 0x33, 0x66, 0xca, 0x6a, - 0x6c, 0xd0, 0x50, 0x41, 0xe8, 0xd9, 0x17, 0x44, 0xce, 0xe1, 0xf7, 0x7e, 0x41, 0x25, 0x48, 0x37, - 0x12, 0x14, 0x11, 0x03, 0x30, 0x54, 0x50, 0xd0, 0xf8, 0x39, 0x64, 0xd7, 0xbe, 0xad, 0x11, 0x91, - 0xfb, 0xbb, 0x8f, 0x34, 0x38, 0x16, 0xe2, 0x4b, 0x32, 0xd8, 0x91, 0x73, 0x83, 0xe5, 0xbd, 0x29, - 0x9c, 0x61, 0x0e, 0x50, 0x8a, 0xdd, 0x0b, 0x3e, 0xf2, 0x1a, 0x2a, 0xd8, 0xbb, 0x77, 0x2f, 0xe0, - 0x45, 0x3f, 0x23, 0x23, 0x03, 0xe9, 0xa9, 0xb2, 0xec, 0xec, 0x6c, 0xb1, 0x6e, 0xf4, 0xcf, 0x74, - 0x92, 0x51, 0xc1, 0xd8, 0xd8, 0x98, 0x28, 0x4f, 0xf2, 0xc8, 0x4c, 0xe8, 0x0c, 0x3d, 0x50, 0x5b, - 0x28, 0x09, 0x57, 0xe3, 0xf5, 0xea, 0x8c, 0x7b, 0x12, 0x25, 0xe9, 0xf2, 0xe5, 0xcb, 0x61, 0x60, - 0x60, 0x00, 0xea, 0xeb, 0xeb, 0xc5, 0x06, 0x33, 0x56, 0xcb, 0x25, 0x98, 0x0e, 0x91, 0x9c, 0xc9, - 0x0a, 0x6c, 0x39, 0x44, 0x56, 0x84, 0x23, 0xad, 0xeb, 0x0a, 0x5c, 0x0f, 0x91, 0x55, 0x8f, 0xad, - 0xd2, 0xbb, 0x1e, 0x21, 0xab, 0x06, 0x59, 0xa5, 0xf7, 0x1d, 0xb0, 0x1a, 0x31, 0xde, 0xf4, 0x86, - 0xe3, 0x90, 0x19, 0x85, 0xc3, 0xf5, 0x7b, 0x60, 0xe8, 0xfd, 0x77, 0x28, 0x69, 0x20, 0x18, 0x04, - 0xf9, 0x34, 0x53, 0x6a, 0x50, 0xcf, 0x65, 0xad, 0x4c, 0x3f, 0x25, 0x19, 0xea, 0x23, 0x97, 0x4e, - 0x2c, 0x37, 0xcc, 0xc8, 0xa8, 0x48, 0x77, 0x07, 0xf4, 0xbe, 0x36, 0x4f, 0xb4, 0xc3, 0x88, 0x56, - 0x6d, 0x2c, 0xab, 0x1e, 0xff, 0x3e, 0xf0, 0xe4, 0x21, 0x2b, 0xcb, 0x18, 0x3b, 0x38, 0x47, 0x0e, - 0x4c, 0xdd, 0x6d, 0x87, 0xde, 0x95, 0xd1, 0x89, 0x69, 0xde, 0xef, 0x3f, 0x31, 0xb4, 0x21, 0x58, - 0x3c, 0x97, 0xce, 0x18, 0x30, 0x73, 0x83, 0xef, 0xd4, 0x19, 0xf2, 0xc4, 0x22, 0x70, 0xe4, 0x40, - 0xca, 0x9c, 0x85, 0x90, 0xfb, 0xee, 0x5f, 0xa8, 0xfc, 0x91, 0x3f, 0xfd, 0x96, 0xc2, 0xb1, 0x00, - 0xe9, 0x7a, 0x1e, 0xcc, 0x2b, 0x84, 0x9c, 0xb7, 0xb4, 0x4f, 0xe0, 0x63, 0xf1, 0xaa, 0xdb, 0xe2, - 0xdf, 0x07, 0x7a, 0x3a, 0xa1, 0xf7, 0xd5, 0xaf, 0x88, 0x76, 0x24, 0x65, 0x1f, 0x10, 0x46, 0x86, - 0xd4, 0x41, 0x74, 0x54, 0xe7, 0x92, 0x81, 0xc8, 0x83, 0x7b, 0xd0, 0xfb, 0xca, 0x1c, 0x6a, 0x88, - 0x99, 0x61, 0x14, 0x1f, 0xe9, 0x17, 0x9e, 0xbb, 0x4f, 0x79, 0xec, 0x02, 0x5c, 0x1c, 0xb0, 0xab, - 0x9c, 0x07, 0x9f, 0xa3, 0x4e, 0xcc, 0xc3, 0x00, 0xa7, 0x32, 0x7c, 0x07, 0xe4, 0x11, 0xec, 0xe8, - 0xe8, 0x10, 0xc7, 0xf8, 0xc1, 0xc1, 0x41, 0x39, 0xda, 0x55, 0x98, 0x4b, 0x06, 0xf0, 0x16, 0x16, - 0x6f, 0x06, 0xe7, 0xcd, 0x9b, 0x9e, 0x22, 0xcc, 0x9f, 0x3f, 0x5f, 0x61, 0xf4, 0xad, 0x5b, 0xb7, - 0xc4, 0x76, 0xa4, 0xc1, 0x3f, 0x7c, 0x3d, 0xb5, 0x69, 0xd3, 0x26, 0x05, 0x8d, 0xed, 0x0a, 0xb9, - 0xa8, 0x70, 0x2d, 0xc4, 0x10, 0x21, 0x3d, 0x3d, 0x5d, 0x21, 0x13, 0x71, 0xf8, 0x47, 0x0c, 0x17, - 0x36, 0x6f, 0xde, 0x2c, 0x5c, 0xbe, 0x7c, 0x59, 0xd1, 0xee, 0xa4, 0x62, 0xf8, 0x00, 0xcd, 0xaa, - 0x70, 0x3d, 0x07, 0x4e, 0x9d, 0x3a, 0x45, 0x45, 0xe5, 0xe6, 0xe6, 0x8a, 0x0e, 0x51, 0x84, 0x03, - 0x80, 0xcb, 0x74, 0x9a, 0x18, 0xad, 0x28, 0x73, 0xe7, 0xce, 0x55, 0xd4, 0xcf, 0x9f, 0x3f, 0x0f, - 0x15, 0x15, 0x15, 0x70, 0xf1, 0xe2, 0x45, 0xc0, 0xfe, 0x71, 0xe7, 0xce, 0x1d, 0xc8, 0xc9, 0xc9, - 0x51, 0xd0, 0xd8, 0xae, 0x38, 0x70, 0x9e, 0xb2, 0xce, 0x9c, 0x39, 0x53, 0x8c, 0x28, 0x31, 0x42, - 0x38, 0x74, 0xe8, 0x10, 0xc5, 0xc7, 0x03, 0xf0, 0x2f, 0x64, 0xb6, 0x53, 0xcf, 0x89, 0x91, 0xcb, - 0x30, 0xca, 0xc9, 0x16, 0x5b, 0x62, 0xfc, 0x53, 0xc8, 0x56, 0xd8, 0x38, 0x32, 0x25, 0xfd, 0x29, - 0xe4, 0x3b, 0xc0, 0xf1, 0x6c, 0xb0, 0x25, 0xca, 0xcf, 0x80, 0xad, 0xb0, 0x71, 0x64, 0x4a, 0xfa, - 0x0c, 0x70, 0x99, 0xcc, 0xa9, 0x6f, 0xea, 0x59, 0x8f, 0x4b, 0xe4, 0x8f, 0x1f, 0x33, 0xaa, 0xbe, - 0x07, 0xb3, 0x7e, 0x7d, 0x8a, 0x4b, 0x1e, 0xb8, 0x64, 0x40, 0xfe, 0x44, 0xc2, 0x8c, 0x55, 0x63, - 0x9f, 0x36, 0x81, 0xfc, 0xed, 0xb0, 0x19, 0x1e, 0x3d, 0x1a, 0x0e, 0x0e, 0xe0, 0x44, 0x74, 0xba, - 0x64, 0x6d, 0xf9, 0x31, 0xb0, 0xa2, 0x8f, 0xad, 0x88, 0x97, 0xb7, 0x0d, 0x1f, 0x3b, 0xf0, 0x84, - 0xcb, 0xd9, 0xc1, 0xb9, 0x03, 0x91, 0x08, 0xb5, 0x60, 0xc6, 0x0f, 0x7f, 0x46, 0x61, 0x23, 0x40, - 0x18, 0x9f, 0x7e, 0xe9, 0x69, 0x44, 0x67, 0xd4, 0xee, 0xdc, 0x01, 0x85, 0x86, 0xe9, 0xe5, 0xbd, - 0x0a, 0x94, 0xcb, 0x15, 0xce, 0x0e, 0xb8, 0x6c, 0x2d, 0x43, 0xbc, 0x63, 0x07, 0x26, 0x9a, 0xa3, - 0x4b, 0x63, 0x82, 0xac, 0x15, 0xc0, 0x2a, 0xa5, 0x81, 0x8c, 0x4c, 0x15, 0xc6, 0x59, 0xd5, 0x91, - 0x03, 0xf8, 0x6c, 0xff, 0xd1, 0x4f, 0xa6, 0x97, 0x01, 0xe2, 0xf3, 0x50, 0x08, 0x18, 0x8b, 0xcb, - 0x3d, 0xf0, 0x01, 0xb5, 0xb8, 0xb7, 0x7c, 0x16, 0x4c, 0x75, 0xdc, 0xa4, 0x75, 0x3b, 0x80, 0xb1, - 0xc6, 0x18, 0x52, 0x47, 0x3e, 0x68, 0x10, 0x5b, 0x53, 0x0a, 0x4b, 0xa0, 0xf0, 0xe3, 0x8e, 0x18, - 0x94, 0xd1, 0xa6, 0xb4, 0x97, 0x5f, 0x85, 0xac, 0x9a, 0x37, 0x44, 0x44, 0x64, 0x68, 0x00, 0xc2, - 0xed, 0xad, 0xd1, 0x46, 0x1b, 0x90, 0xe3, 0x1b, 0x9a, 0xde, 0xca, 0x42, 0x88, 0xf4, 0xf7, 0x89, - 0xaa, 0xe5, 0xc3, 0xa4, 0x9e, 0x2d, 0xfd, 0x3b, 0xab, 0x60, 0xfc, 0xb3, 0xf3, 0x62, 0x73, 0xfe, - 0xfb, 0x97, 0x20, 0x75, 0xc9, 0x0a, 0x3d, 0x52, 0x53, 0x78, 0x47, 0x19, 0x40, 0x0d, 0x85, 0x1f, - 0xb6, 0x51, 0x45, 0x66, 0x56, 0xf7, 0x4a, 0xc6, 0x23, 0x93, 0x53, 0xe3, 0x51, 0x86, 0x63, 0x07, - 0x02, 0xd9, 0xb3, 0x50, 0x4e, 0xc2, 0x8a, 0x63, 0x07, 0x12, 0x66, 0xf9, 0x13, 0xc5, 0x5c, 0x1d, - 0x10, 0x46, 0xf9, 0xbe, 0x3e, 0x32, 0x13, 0x1c, 0xe7, 0x0e, 0x04, 0xa3, 0x2b, 0x4b, 0xfb, 0xaa, - 0x17, 0x83, 0xde, 0xb2, 0x3d, 0xc4, 0x3f, 0x7e, 0x6b, 0x0b, 0xb5, 0x29, 0xf5, 0xf9, 0x6f, 0x50, - 0xd8, 0x09, 0xe0, 0x78, 0x14, 0x42, 0xe5, 0xbd, 0x55, 0xc5, 0x10, 0x79, 0xd4, 0x4b, 0xed, 0x60, - 0x8d, 0x46, 0xf2, 0xe9, 0x34, 0x12, 0x16, 0x9d, 0xeb, 0x82, 0x60, 0x41, 0x09, 0xe5, 0xb1, 0x0b, - 0x70, 0xb9, 0x1f, 0x28, 0xfa, 0xb4, 0x07, 0xc6, 0x2f, 0x7e, 0x04, 0xe1, 0xd6, 0x7f, 0xe9, 0xda, - 0x91, 0xfd, 0xa3, 0x3d, 0xd3, 0x6d, 0xa9, 0x69, 0x30, 0xe3, 0xf5, 0xdd, 0x00, 0xa1, 0x34, 0x5d, - 0x5a, 0x2b, 0x0d, 0x5c, 0x32, 0x60, 0x45, 0x21, 0x6f, 0x5a, 0xe7, 0x7d, 0x80, 0xb7, 0x45, 0x16, - 0xe5, 0xf9, 0x0e, 0x58, 0x0c, 0x18, 0x77, 0x72, 0x3f, 0x03, 0xf2, 0x90, 0xae, 0x58, 0xb1, 0x02, - 0x96, 0x2d, 0x5b, 0x26, 0x47, 0xb9, 0x0e, 0x73, 0x1d, 0x85, 0xa4, 0x75, 0xb7, 0xe4, 0xd5, 0x92, - 0xeb, 0x86, 0x4b, 0x0a, 0xb8, 0x5c, 0x07, 0x24, 0x61, 0xf1, 0x34, 0x5c, 0xd2, 0xe9, 0xb8, 0x0f, - 0x48, 0x6f, 0xe7, 0xa5, 0x97, 0xd8, 0x52, 0x16, 0x24, 0x05, 0x78, 0x5c, 0xbd, 0x7a, 0xb5, 0xe2, - 0x45, 0x37, 0x8b, 0x46, 0x4e, 0x6f, 0x09, 0x76, 0xfa, 0x26, 0x71, 0x72, 0x72, 0x52, 0xd8, 0xb8, - 0x71, 0xa3, 0xb0, 0x6e, 0xdd, 0x3a, 0xa1, 0xb4, 0xb4, 0x54, 0xf3, 0xfe, 0xf7, 0xd2, 0xa5, 0x4b, - 0x22, 0xee, 0xcc, 0x99, 0x33, 0xa2, 0xaa, 0xfd, 0xfb, 0xf7, 0x6b, 0x68, 0x9c, 0xd8, 0xc0, 0xf5, - 0x45, 0xf7, 0xd9, 0xb3, 0x67, 0x35, 0xc6, 0x5d, 0xbd, 0x7a, 0x55, 0xc4, 0x91, 0xa8, 0x8a, 0xbb, - 0xdc, 0x0e, 0x1e, 0x3c, 0x28, 0x84, 0xc3, 0x61, 0x27, 0x36, 0x2b, 0x78, 0x5d, 0x77, 0x00, 0xb5, - 0x35, 0x35, 0x35, 0x09, 0x64, 0x05, 0x3f, 0x75, 0x04, 0x9d, 0x69, 0x6e, 0x6e, 0x56, 0x18, 0x62, - 0xb7, 0xe2, 0xb8, 0x0f, 0x18, 0x9d, 0xaf, 0x57, 0xae, 0x5c, 0x81, 0xed, 0xdb, 0xb7, 0x8b, 0x1b, - 0x19, 0x89, 0x91, 0x70, 0xf7, 0xee, 0x5d, 0x91, 0xe5, 0xe8, 0xd1, 0xa3, 0x46, 0xac, 0xa6, 0xda, - 0xb9, 0x8e, 0x42, 0x11, 0xd9, 0x63, 0x46, 0x49, 0xfb, 0x8d, 0x1b, 0x37, 0x44, 0xe3, 0xb1, 0xe3, - 0xe2, 0x2a, 0x15, 0x72, 0xfa, 0x88, 0x4d, 0xe4, 0x8d, 0xbe, 0x44, 0xe2, 0xe8, 0xc8, 0xd5, 0x01, - 0x34, 0x56, 0x5d, 0xb6, 0x6d, 0xdb, 0x26, 0x5e, 0xdc, 0x32, 0x33, 0x33, 0x01, 0xb3, 0xb1, 0x60, - 0xc1, 0x02, 0x58, 0xb2, 0x64, 0x89, 0x9a, 0xcc, 0x7e, 0xdd, 0xee, 0xb9, 0x27, 0xf1, 0x9d, 0x3e, - 0x7d, 0x5a, 0xa8, 0xac, 0xac, 0x14, 0x76, 0xec, 0xd8, 0x41, 0xcf, 0x71, 0xa9, 0x2d, 0x1e, 0x47, - 0x2e, 0x19, 0xc0, 0xd5, 0x28, 0x58, 0x4a, 0x4a, 0x4a, 0xe0, 0xf6, 0xed, 0xdb, 0xf6, 0xa3, 0x69, - 0x83, 0x93, 0xeb, 0x54, 0xc2, 0x86, 0x7e, 0xc7, 0x2c, 0xae, 0x8f, 0x42, 0x8e, 0x2d, 0x34, 0x10, - 0xe0, 0x3b, 0x60, 0x10, 0x20, 0xd7, 0x9b, 0xfd, 0x0c, 0xb8, 0x1e, 0x62, 0x03, 0x05, 0x49, 0x3f, - 0x0a, 0x19, 0xf8, 0xe7, 0xf9, 0xe6, 0xa4, 0xef, 0x02, 0x9e, 0x8f, 0xb0, 0x81, 0x81, 0x7e, 0x02, - 0x0c, 0x02, 0xe4, 0x76, 0xb3, 0x9f, 0x00, 0xb7, 0x23, 0x6c, 0x20, 0xdf, 0x4f, 0x80, 0x41, 0x80, - 0xdc, 0x6e, 0xf6, 0x13, 0xe0, 0x76, 0x84, 0x0d, 0xe4, 0xfb, 0x09, 0x30, 0x08, 0x90, 0xdb, 0xcd, - 0x5c, 0xee, 0xe6, 0x79, 0x1b, 0x89, 0xbb, 0xa5, 0xc3, 0x37, 0x5b, 0x40, 0x08, 0x4f, 0x46, 0x45, - 0x93, 0x07, 0x4a, 0xe9, 0xe5, 0xdf, 0x89, 0xd6, 0x63, 0x40, 0xf8, 0xaa, 0x54, 0x5e, 0x02, 0xa1, - 0x54, 0x08, 0x91, 0x17, 0xd2, 0xb8, 0x07, 0xd8, 0x6b, 0xc5, 0x3b, 0xf7, 0x01, 0x63, 0x23, 0xd0, - 0xf7, 0x83, 0x32, 0x08, 0x7f, 0xf1, 0x1f, 0x66, 0x8c, 0xf4, 0x36, 0x96, 0xb2, 0x88, 0xd5, 0x2f, - 0xd3, 0xe5, 0x34, 0xa9, 0xcf, 0xbd, 0x04, 0xf9, 0x47, 0xff, 0x09, 0x90, 0xce, 0x77, 0xc5, 0x98, - 0x5c, 0x87, 0x15, 0xd8, 0x33, 0x3d, 0xe0, 0x61, 0x5d, 0x05, 0x33, 0xf8, 0xa1, 0xf9, 0xcf, 0x03, - 0x6e, 0x18, 0x07, 0x5c, 0xc9, 0x66, 0xb2, 0xa4, 0xbf, 0xbc, 0x56, 0xa4, 0x9c, 0xea, 0xfc, 0x02, - 0xc2, 0x77, 0x94, 0x2b, 0xd9, 0x26, 0x49, 0xcf, 0x7a, 0x44, 0xd6, 0x5a, 0xe5, 0xfd, 0xb1, 0xd9, - 0xa4, 0x34, 0x77, 0xc9, 0xbc, 0xd1, 0x03, 0x22, 0x53, 0xd0, 0x5d, 0xaa, 0x3d, 0x17, 0x0a, 0x1a, - 0x5b, 0x20, 0xf4, 0xec, 0x8b, 0x8e, 0x22, 0x10, 0x6e, 0xbb, 0x0a, 0x7d, 0x5b, 0xbe, 0xa9, 0x91, - 0xc1, 0x5a, 0x86, 0xa2, 0x21, 0x8a, 0x03, 0xc2, 0xfc, 0x69, 0x15, 0x07, 0x63, 0xd4, 0x2a, 0x82, - 0xb9, 0x85, 0x6a, 0x94, 0xe5, 0x3a, 0x0f, 0x19, 0x96, 0x95, 0x5a, 0x60, 0xf0, 0x74, 0x02, 0x2c, - 0xf8, 0x91, 0xb4, 0xa4, 0x9e, 0x48, 0x80, 0x30, 0x3c, 0xc0, 0x0e, 0x20, 0x99, 0xf9, 0x38, 0x2e, - 0x3a, 0x32, 0x74, 0x75, 0x3a, 0x56, 0x68, 0x4d, 0x40, 0xc2, 0x13, 0x10, 0x79, 0xd8, 0x0d, 0x0f, - 0xb7, 0x97, 0x69, 0xac, 0x4e, 0x7b, 0x69, 0x39, 0x97, 0x65, 0x80, 0xc1, 0xa2, 0x39, 0x90, 0xfa, - 0x82, 0x56, 0xfe, 0xc3, 0xef, 0x7f, 0x1b, 0x84, 0xfe, 0xe8, 0xd2, 0x44, 0x8d, 0x01, 0x71, 0x42, - 0x24, 0xec, 0x22, 0x8c, 0xdf, 0xe0, 0x7c, 0xf4, 0xe6, 0x6b, 0x1a, 0x37, 0x53, 0x9f, 0x7b, 0x11, - 0x66, 0xec, 0xdc, 0x6b, 0x7a, 0xce, 0xaf, 0x11, 0xa0, 0x83, 0x18, 0xff, 0xdb, 0x87, 0x30, 0x44, - 0xbe, 0x43, 0x19, 0xfe, 0xdf, 0x75, 0x0d, 0x05, 0x7e, 0x2e, 0xd2, 0xec, 0x3d, 0x86, 0x86, 0xd9, - 0x21, 0x22, 0x61, 0x3d, 0x20, 0x98, 0x57, 0x04, 0xa1, 0xaf, 0x2d, 0xd6, 0x98, 0x3f, 0x79, 0xf3, - 0x73, 0x18, 0x78, 0xfb, 0x75, 0xc7, 0x1b, 0x21, 0xe4, 0x82, 0xa7, 0x6e, 0xff, 0x17, 0x06, 0x7e, - 0xb9, 0x83, 0x19, 0x7c, 0xb4, 0x21, 0x98, 0xcf, 0xf8, 0xd6, 0xbc, 0x5c, 0x80, 0x8b, 0x70, 0xc2, - 0x7a, 0x80, 0xdc, 0xa7, 0xf1, 0xbf, 0x9e, 0x84, 0xfe, 0xdd, 0x35, 0x72, 0x14, 0x04, 0xb3, 0xb2, - 0xa1, 0xe8, 0xef, 0x8f, 0x4d, 0xed, 0x62, 0x51, 0x30, 0xaa, 0x2b, 0x53, 0x61, 0xe8, 0x21, 0x3b, - 0x5b, 0x84, 0xd1, 0x11, 0x45, 0x4b, 0xee, 0x81, 0x26, 0x48, 0xaf, 0x88, 0xfe, 0xa4, 0x80, 0xa2, - 0x31, 0x8e, 0x95, 0x84, 0xf5, 0x00, 0xb9, 0x8f, 0xe9, 0x95, 0xda, 0x40, 0x44, 0xc8, 0x77, 0x9f, - 0x22, 0x7d, 0xdd, 0x72, 0x32, 0x5b, 0x70, 0xa4, 0xef, 0xbe, 0x26, 0xf8, 0x28, 0xc8, 0x0b, 0xc1, - 0x47, 0x3b, 0x3c, 0x91, 0x00, 0x34, 0xe4, 0xcb, 0x5a, 0xfc, 0x04, 0x24, 0x38, 0xf3, 0xde, 0x48, - 0x00, 0x99, 0xab, 0x8b, 0xbb, 0x16, 0x55, 0xc1, 0x18, 0x3b, 0xd7, 0xa8, 0xc2, 0x58, 0xaf, 0x8e, - 0x7d, 0xf2, 0x67, 0x0d, 0x53, 0x20, 0x25, 0xba, 0xc5, 0x47, 0xd3, 0x18, 0x67, 0x84, 0x27, 0x2e, - 0xc2, 0xe8, 0xf3, 0xe0, 0xaf, 0x6a, 0x61, 0xe4, 0xf4, 0x1f, 0x74, 0xdd, 0xe7, 0xf5, 0x34, 0x14, - 0x15, 0x64, 0x55, 0xef, 0x84, 0x9c, 0xdd, 0xf5, 0xba, 0xba, 0xe2, 0xd9, 0xe0, 0x8d, 0x1e, 0x40, - 0x3c, 0xce, 0xd9, 0xd3, 0x00, 0x05, 0xe4, 0x31, 0x31, 0x3e, 0xfd, 0x74, 0xab, 0x84, 0xbe, 0xfa, - 0x75, 0x28, 0x38, 0xfe, 0x99, 0x67, 0x82, 0x8f, 0x7e, 0x7a, 0xa6, 0x07, 0xb8, 0x15, 0x74, 0xaf, - 0xcb, 0xf5, 0x4c, 0x0f, 0xf0, 0x7a, 0xa0, 0xdc, 0xb2, 0xcf, 0x4f, 0x80, 0x5b, 0x91, 0x35, 0x29, - 0xd7, 0x4f, 0x80, 0xc9, 0x40, 0xb9, 0x45, 0xe6, 0x27, 0xc0, 0xad, 0xc8, 0x9a, 0x94, 0xeb, 0xf9, - 0x04, 0xf4, 0xf7, 0xf7, 0x9b, 0x74, 0x25, 0x39, 0xc9, 0x3c, 0x9b, 0x80, 0x7b, 0xf7, 0xee, 0x89, - 0x1b, 0x14, 0xf3, 0xf2, 0xf2, 0xc4, 0x63, 0x3c, 0x3f, 0x35, 0x1c, 0xcf, 0x54, 0x7a, 0x36, 0x01, - 0xb3, 0x67, 0xcf, 0x86, 0xb5, 0x6b, 0xd7, 0x42, 0x7e, 0x7e, 0xbe, 0xf8, 0x6b, 0x40, 0xdc, 0xbe, - 0x61, 0x1b, 0xcf, 0xe8, 0x9a, 0xd0, 0xe5, 0x99, 0xfb, 0x00, 0xb2, 0xeb, 0x15, 0xda, 0xda, 0xda, - 0x60, 0x6a, 0x2a, 0xfa, 0x13, 0x70, 0x72, 0xfb, 0x8b, 0x8b, 0x8b, 0xc5, 0x6d, 0x5c, 0x72, 0x1c, - 0x0b, 0x6e, 0x69, 0x69, 0x81, 0xeb, 0xd7, 0xaf, 0x43, 0x67, 0x67, 0x27, 0x90, 0x9f, 0x51, 0x14, - 0x79, 0xca, 0xca, 0xca, 0x20, 0x85, 0x3c, 0x7e, 0x38, 0x72, 0xe4, 0x08, 0x54, 0x57, 0x57, 0xc3, - 0xe2, 0xc5, 0xda, 0xf7, 0x10, 0x2c, 0x59, 0x71, 0xc1, 0xc5, 0x63, 0x33, 0x9d, 0x91, 0x8e, 0x0b, - 0x17, 0x2e, 0xd0, 0x4d, 0x7e, 0xc4, 0x69, 0x26, 0xac, 0xfe, 0xd6, 0xb6, 0x5c, 0x26, 0xf9, 0x41, - 0x4c, 0x81, 0x04, 0x95, 0xf2, 0x05, 0x83, 0x41, 0x61, 0xd1, 0xa2, 0x45, 0xc2, 0xca, 0x95, 0x2b, - 0x05, 0xe9, 0x13, 0xd6, 0x92, 0x5c, 0xb2, 0xad, 0x5f, 0xce, 0x9a, 0x70, 0x98, 0xeb, 0x6e, 0x61, - 0xde, 0xde, 0x48, 0xdb, 0xa7, 0x31, 0x78, 0xb1, 0x12, 0x70, 0xec, 0xd8, 0x31, 0x1a, 0x7c, 0xa4, - 0x25, 0x3f, 0x62, 0x26, 0x90, 0x5f, 0xe8, 0x52, 0x98, 0x43, 0x36, 0x40, 0x0a, 0xfb, 0xf6, 0xed, - 0x13, 0xae, 0x5d, 0xbb, 0xa6, 0xc0, 0x27, 0xba, 0xf2, 0x54, 0x24, 0x00, 0x83, 0x58, 0x57, 0x57, - 0xa7, 0x48, 0x82, 0x74, 0xc6, 0xcb, 0x8f, 0x0b, 0x17, 0x2e, 0x14, 0x1a, 0x1b, 0x1b, 0x13, 0x1d, - 0x73, 0x85, 0x7e, 0xcf, 0x5e, 0x84, 0x49, 0xe0, 0x4c, 0x17, 0xe2, 0x91, 0xf8, 0x5b, 0x05, 0xf8, - 0x1b, 0x06, 0x08, 0x8f, 0x8f, 0x8f, 0x03, 0xf9, 0xd0, 0x00, 0x90, 0x9e, 0x01, 0x64, 0x0f, 0x33, - 0xe0, 0x05, 0x1d, 0x4b, 0x7b, 0x7b, 0x3b, 0xd4, 0xd4, 0xd4, 0xc0, 0xae, 0x5d, 0xbb, 0x4c, 0xcb, - 0x76, 0x9d, 0x50, 0x91, 0x0e, 0x8f, 0x55, 0xcc, 0x0e, 0x41, 0xc7, 0x8f, 0x1f, 0xa7, 0x67, 0x3f, - 0x8e, 0xff, 0xb5, 0xb5, 0xb5, 0x42, 0x6b, 0x6b, 0xab, 0x30, 0x31, 0x31, 0x21, 0x90, 0x9f, 0x39, - 0x14, 0x4e, 0x9e, 0x3c, 0x29, 0x90, 0xed, 0xfa, 0x94, 0xa6, 0xa1, 0xa1, 0xc1, 0x33, 0x9e, 0x7a, - 0x7a, 0x08, 0x3a, 0x71, 0xe2, 0x04, 0x0d, 0x1a, 0x7e, 0x71, 0x42, 0xaf, 0x90, 0x9f, 0x5c, 0x10, - 0xe9, 0xc8, 0x4c, 0x47, 0x20, 0x1b, 0xde, 0x29, 0x0f, 0x39, 0x7b, 0x29, 0x4c, 0x3e, 0x37, 0x20, - 0x0e, 0x53, 0x5d, 0x5d, 0x5d, 0x7a, 0x62, 0x12, 0x82, 0xd7, 0xae, 0x88, 0x75, 0xbd, 0xcf, 0x99, - 0x53, 0x80, 0xd3, 0xd2, 0xc3, 0x87, 0x0f, 0x53, 0x62, 0xf2, 0x49, 0x04, 0x0a, 0xab, 0x81, 0xf2, - 0xf2, 0x72, 0x71, 0xe8, 0x51, 0xe3, 0x93, 0xa2, 0x9e, 0x90, 0xb4, 0xab, 0x94, 0xae, 0x59, 0xb3, - 0x86, 0x9e, 0xa9, 0x24, 0x68, 0x1a, 0xb8, 0xaa, 0xaa, 0x4a, 0x20, 0x5f, 0x03, 0x51, 0x71, 0x3d, - 0x1d, 0x55, 0xcf, 0xdc, 0x88, 0xe1, 0xa7, 0x54, 0xf0, 0x46, 0x0c, 0x9f, 0xfd, 0xe0, 0x4f, 0xd4, - 0x92, 0x19, 0x0b, 0x90, 0x39, 0x7c, 0x52, 0x9c, 0xc4, 0x4e, 0x8c, 0xf4, 0x4c, 0x02, 0x9c, 0x38, - 0x91, 0xcc, 0xbc, 0x4f, 0xc5, 0x34, 0xd4, 0x4f, 0x40, 0x32, 0x47, 0x20, 0xc1, 0xb6, 0xfb, 0x3d, - 0xc0, 0x4f, 0x40, 0x82, 0x23, 0x90, 0x60, 0xf5, 0x7e, 0x0f, 0x48, 0x70, 0x02, 0xfe, 0x0f, 0x63, - 0xba, 0xa3, 0x5c, 0x3e, 0x86, 0x45, 0x02, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, - 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXPlistIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x33, 0x35, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc8, - 0x4f, 0xd5, 0xc2, 0x00, 0x00, 0x06, 0xa8, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x7b, - 0x4c, 0x53, 0x57, 0x18, 0xb7, 0xef, 0x77, 0x91, 0x87, 0x82, 0x20, 0x68, 0x01, 0xd1, 0xf8, 0x20, - 0x6e, 0x09, 0xd1, 0x44, 0xc1, 0xcc, 0xa0, 0xce, 0x4c, 0x0d, 0xfc, 0xb7, 0x11, 0xa6, 0x93, 0xb0, - 0x65, 0x53, 0x18, 0x31, 0x41, 0xcd, 0x4c, 0x4c, 0x96, 0x25, 0xfe, 0xb3, 0xa0, 0x46, 0x8c, 0x61, - 0x03, 0x5f, 0x7f, 0xb0, 0x31, 0x46, 0x74, 0x31, 0x6e, 0xcb, 0x62, 0x80, 0x6c, 0x73, 0x8a, 0x12, - 0xc5, 0xa0, 0x19, 0xbe, 0x98, 0x48, 0x43, 0x71, 0x56, 0x94, 0xd2, 0x07, 0xa5, 0x94, 0xb6, 0xfb, - 0xe1, 0x71, 0xb7, 0x87, 0xdb, 0xf6, 0xda, 0x7b, 0x5b, 0x75, 0x66, 0xbd, 0x69, 0x9a, 0xef, 0x7c, - 0x8f, 0xdf, 0xf9, 0x5e, 0xe7, 0x3b, 0xed, 0x15, 0xf9, 0x7c, 0xbe, 0x69, 0xaf, 0xf3, 0x23, 0x7e, - 0x9d, 0x9d, 0x9f, 0xf4, 0x3d, 0x16, 0xc0, 0xab, 0xae, 0x60, 0xac, 0x02, 0xb1, 0x0a, 0x44, 0x98, - 0x81, 0x58, 0x0b, 0x45, 0x98, 0xc0, 0x88, 0xcd, 0x63, 0x15, 0x88, 0x38, 0x85, 0x11, 0x02, 0xc4, - 0x2a, 0x10, 0x61, 0x02, 0x23, 0x36, 0x8f, 0x55, 0x20, 0x58, 0x0a, 0x87, 0xdc, 0xde, 0x40, 0xb6, - 0xcd, 0xe3, 0xf3, 0x04, 0x72, 0x23, 0xe6, 0x44, 0xb9, 0x02, 0x5d, 0xd6, 0xf1, 0x0f, 0xba, 0x1f, - 0xcf, 0x6b, 0x37, 0x05, 0x3a, 0xf6, 0xfb, 0xe3, 0xb1, 0xcc, 0x36, 0xd3, 0x97, 0x7f, 0x59, 0x87, - 0x83, 0x85, 0x17, 0xa8, 0x1f, 0x26, 0x47, 0x14, 0x95, 0xff, 0x03, 0x48, 0xed, 0x0f, 0x0f, 0x46, - 0x0f, 0xf5, 0xd9, 0xfe, 0x78, 0x32, 0x86, 0x8d, 0x95, 0x12, 0x91, 0x73, 0x7d, 0x06, 0xcb, 0x83, - 0x9f, 0xcc, 0xce, 0x0d, 0x9d, 0x66, 0x30, 0xd5, 0x12, 0xf1, 0xfb, 0xb3, 0x35, 0x9f, 0x1a, 0x74, - 0x0b, 0xb5, 0x32, 0x96, 0x8e, 0x80, 0xa5, 0x54, 0x80, 0x0d, 0x6d, 0xf2, 0xc4, 0xed, 0x3d, 0x6a, - 0xb4, 0x1f, 0xb9, 0x6f, 0x33, 0x3a, 0x27, 0x68, 0x3e, 0x07, 0x3d, 0xea, 0xf1, 0x7e, 0xdd, 0x6f, - 0xc3, 0xa7, 0x70, 0x86, 0xaa, 0xca, 0xa0, 0x7b, 0x67, 0xa6, 0x4a, 0xc4, 0xa1, 0xfd, 0x3c, 0x91, - 0xf0, 0x00, 0xfe, 0xb4, 0xbb, 0x6b, 0xfb, 0x6c, 0x8d, 0x03, 0x0e, 0x38, 0x44, 0xef, 0x32, 0x4b, - 0x29, 0xdd, 0x9a, 0xae, 0xa1, 0x39, 0x84, 0xce, 0xd5, 0xcb, 0x4b, 0x67, 0x6b, 0x4f, 0x3d, 0x18, - 0x75, 0xfe, 0xab, 0xdf, 0xfa, 0xc8, 0x89, 0x4f, 0xb6, 0x46, 0x56, 0x31, 0x57, 0xb7, 0x35, 0x5d, - 0xab, 0x97, 0x0a, 0x09, 0x84, 0x77, 0x0b, 0xc1, 0xd9, 0x9f, 0xcd, 0x4e, 0x74, 0x0b, 0xf6, 0xa6, - 0xbd, 0x94, 0x89, 0x45, 0x1b, 0x92, 0x55, 0x65, 0xe9, 0xda, 0xf5, 0x33, 0x55, 0x12, 0x5a, 0x30, - 0x95, 0xb6, 0x4c, 0xf8, 0xbe, 0x35, 0x39, 0x8e, 0x1a, 0x6d, 0xd7, 0x46, 0xc6, 0x69, 0x89, 0x4e, - 0x2a, 0x46, 0x0c, 0x95, 0x06, 0x5d, 0xb6, 0x9a, 0x5f, 0x4e, 0x79, 0x07, 0xb0, 0xbe, 0xd3, 0xfc, - 0x8b, 0x79, 0x8a, 0xeb, 0x8b, 0xf5, 0x72, 0xf8, 0x5d, 0x9a, 0xa6, 0x99, 0x21, 0xe7, 0x31, 0x12, - 0xae, 0x59, 0xdd, 0x08, 0x03, 0xc1, 0x58, 0xa8, 0x33, 0x2d, 0x12, 0x89, 0xea, 0x73, 0x13, 0xca, - 0xd3, 0xb5, 0x74, 0x6c, 0xdc, 0x34, 0xbf, 0x70, 0x81, 0x35, 0x34, 0xee, 0x6f, 0x98, 0xe2, 0x59, - 0xea, 0xcf, 0xb2, 0xe3, 0xf2, 0xe2, 0xe4, 0xdc, 0x7b, 0x04, 0x95, 0xbe, 0xa1, 0x97, 0x1d, 0x59, - 0x9c, 0x50, 0xb3, 0x30, 0x1e, 0x4d, 0xf5, 0xc5, 0xdd, 0x91, 0xbb, 0x76, 0x37, 0xd4, 0x30, 0x51, - 0xcc, 0x2e, 0x3f, 0x7e, 0x50, 0x43, 0x16, 0x93, 0x77, 0x00, 0xb4, 0xfd, 0x8f, 0x0f, 0x9d, 0xe2, - 0x69, 0xa2, 0x8f, 0xe6, 0x68, 0xd7, 0x24, 0x29, 0x05, 0xf4, 0xaf, 0xd3, 0xeb, 0xfb, 0x7e, 0x70, - 0x14, 0x33, 0x80, 0x78, 0x4f, 0x23, 0x87, 0x4f, 0xf3, 0x0e, 0xe0, 0xc3, 0x0c, 0xad, 0xd9, 0xe5, - 0x21, 0x33, 0xc7, 0xed, 0xf5, 0x9d, 0x7a, 0xe0, 0xc0, 0x67, 0xae, 0x5a, 0x5a, 0x9e, 0x81, 0x83, - 0xa8, 0x49, 0x55, 0x70, 0xf4, 0xbf, 0xdf, 0x2b, 0xd2, 0x3f, 0xdf, 0x98, 0x1c, 0x23, 0x54, 0xff, - 0x40, 0x5c, 0x90, 0xa8, 0x5c, 0x33, 0x43, 0xe9, 0xd7, 0x0b, 0x83, 0xe2, 0x7d, 0x06, 0x80, 0xc9, - 0x9a, 0xfa, 0xcc, 0x2e, 0x52, 0xb1, 0x08, 0x33, 0x11, 0x11, 0xbe, 0x1d, 0xe2, 0x1c, 0x5b, 0x27, - 0x7c, 0x4d, 0x83, 0x8e, 0x06, 0xa3, 0xfd, 0xaa, 0xc5, 0xc5, 0x58, 0x81, 0x90, 0x8b, 0x45, 0xef, - 0xa5, 0x69, 0xaa, 0x0c, 0x7a, 0xf4, 0x15, 0xcd, 0x0f, 0x87, 0x16, 0x12, 0x00, 0x83, 0x7b, 0x75, - 0x64, 0x1c, 0xe3, 0xa8, 0x79, 0xd0, 0x31, 0xee, 0x9d, 0xf2, 0x76, 0x2c, 0x4b, 0x23, 0xeb, 0x7d, - 0x2b, 0x95, 0x51, 0x23, 0x44, 0x87, 0x65, 0xbc, 0xb0, 0xe3, 0x21, 0x6b, 0xe6, 0x26, 0x2b, 0x24, - 0x9f, 0xcc, 0xd5, 0x7d, 0x3c, 0x47, 0x97, 0xcc, 0x67, 0x00, 0xd0, 0xc8, 0x11, 0x05, 0x40, 0x80, - 0xfe, 0x76, 0x79, 0xbf, 0xea, 0xb7, 0xd5, 0xf5, 0xdb, 0xd0, 0x5a, 0x84, 0xc3, 0x7d, 0x13, 0x13, - 0x9d, 0x37, 0xe3, 0x14, 0xb8, 0xc5, 0xde, 0x4d, 0xd3, 0xc8, 0x05, 0x9c, 0x1e, 0x2a, 0x02, 0xde, - 0x67, 0x80, 0xb2, 0x7d, 0x46, 0xa6, 0x28, 0xc4, 0x9f, 0xe7, 0xc4, 0x61, 0x1c, 0x7d, 0x37, 0xe8, - 0x38, 0xd4, 0x67, 0x65, 0x0d, 0x78, 0x96, 0xbe, 0x44, 0x24, 0x2a, 0x4a, 0x51, 0xc3, 0xf5, 0xfc, - 0x04, 0x05, 0x4b, 0x24, 0x70, 0x89, 0xc9, 0x15, 0xdd, 0xe7, 0xb7, 0xc7, 0x63, 0x25, 0x5d, 0x8f, - 0x02, 0x31, 0xc1, 0xaf, 0xee, 0x19, 0xbe, 0x3f, 0x3a, 0x11, 0x28, 0x8a, 0x84, 0x13, 0x85, 0x16, - 0x12, 0x98, 0xb9, 0x28, 0x99, 0xf1, 0xb8, 0x3b, 0xa3, 0xb4, 0x63, 0x94, 0x61, 0x62, 0x01, 0x44, - 0x39, 0xa1, 0xbc, 0xe1, 0x62, 0x15, 0xe0, 0x9d, 0xb2, 0x28, 0x1b, 0xc4, 0x2a, 0x10, 0xe5, 0x84, - 0xf2, 0x86, 0xfb, 0x7f, 0x57, 0x60, 0xe2, 0xe9, 0xe3, 0xf5, 0x86, 0xfc, 0x0b, 0x02, 0xf9, 0x81, - 0x03, 0x07, 0x4e, 0x9f, 0x3e, 0xcd, 0x3b, 0xb1, 0xe1, 0x1b, 0x08, 0xbb, 0xc6, 0x7b, 0x7b, 0x7b, - 0x13, 0x12, 0x12, 0xc8, 0x2e, 0xd3, 0xa7, 0x4f, 0x0f, 0x05, 0x72, 0xfb, 0xf6, 0x6d, 0xe8, 0x64, - 0x66, 0x66, 0x86, 0x52, 0xe0, 0xe0, 0xbb, 0xdd, 0xee, 0xf6, 0xf6, 0xf6, 0xc1, 0xc1, 0x41, 0x0e, - 0x1d, 0x88, 0x04, 0xb6, 0x90, 0x4e, 0xa7, 0x9b, 0x3f, 0x7f, 0x7e, 0x6a, 0xea, 0xe4, 0x6f, 0x66, - 0x87, 0xc3, 0x11, 0x2a, 0x5f, 0x72, 0xb9, 0x5c, 0xa1, 0x50, 0xa4, 0xa5, 0xa5, 0x85, 0x52, 0xe0, - 0xe0, 0x9f, 0x3b, 0x77, 0x6e, 0xf5, 0xea, 0xd5, 0xe5, 0xe5, 0xe5, 0x1c, 0x3a, 0x93, 0x22, 0xee, - 0xf8, 0xb8, 0xa5, 0x57, 0xae, 0x5c, 0x01, 0x82, 0x4c, 0x26, 0xe3, 0x50, 0x43, 0x22, 0x39, 0xa4, - 0xb4, 0xc8, 0xe3, 0xf1, 0xd0, 0xcb, 0x93, 0x27, 0x4f, 0x02, 0x3c, 0x2f, 0x2f, 0x8f, 0x66, 0x06, - 0xd2, 0x41, 0x2a, 0xb0, 0x77, 0xef, 0xde, 0x65, 0xcb, 0x96, 0xad, 0x5d, 0xbb, 0xb6, 0xb3, 0xb3, - 0x73, 0xf9, 0xf2, 0xe5, 0x6a, 0xb5, 0x7a, 0xc9, 0x92, 0x25, 0x35, 0x35, 0x35, 0x1c, 0xbd, 0x8e, - 0x9d, 0x02, 0x9f, 0xcd, 0x9b, 0x37, 0x03, 0x67, 0xc5, 0x8a, 0x15, 0x2b, 0x57, 0xae, 0xb4, 0x58, - 0x2c, 0x2c, 0x85, 0xb3, 0x67, 0xcf, 0x6e, 0xd9, 0xb2, 0x25, 0x39, 0x39, 0x19, 0xf8, 0xf0, 0x32, - 0x37, 0x37, 0x77, 0xd3, 0xa6, 0x4d, 0x8c, 0xce, 0xcd, 0x9b, 0x37, 0x6f, 0xdd, 0xba, 0x85, 0xa5, - 0xcd, 0x66, 0xfb, 0xf5, 0xe9, 0x03, 0x67, 0x70, 0xa2, 0x18, 0x05, 0x3f, 0x11, 0x18, 0x93, 0xc1, - 0x60, 0x20, 0x62, 0x8d, 0x66, 0xca, 0xfb, 0xa9, 0xd2, 0xd2, 0x52, 0x96, 0x32, 0x47, 0x05, 0xb0, - 0xb1, 0x54, 0xea, 0xff, 0xb3, 0xd1, 0xd7, 0xd7, 0x47, 0xdb, 0xb6, 0xb6, 0xb6, 0x92, 0x2d, 0xd6, - 0xad, 0x5b, 0x57, 0x58, 0x58, 0x88, 0xb7, 0x29, 0x58, 0x2e, 0x58, 0xb0, 0x80, 0xe8, 0x74, 0x75, - 0x75, 0xf9, 0xfd, 0xa3, 0xa8, 0x7d, 0xfb, 0xf6, 0xd1, 0x20, 0x84, 0x0e, 0xd2, 0x42, 0xf7, 0xee, - 0xdd, 0x43, 0x62, 0x60, 0x18, 0x1f, 0x1f, 0x5f, 0x5f, 0x5f, 0x7f, 0xfd, 0xfa, 0xf5, 0xe2, 0xe2, - 0x62, 0x82, 0x83, 0x8d, 0x69, 0x08, 0x8e, 0x00, 0xa0, 0x76, 0xe3, 0xc6, 0x8d, 0xe6, 0xe6, 0x66, - 0x62, 0xc8, 0x0a, 0x60, 0xe7, 0xce, 0x9d, 0xe0, 0x2f, 0x5a, 0xb4, 0x88, 0xa0, 0x41, 0x5a, 0x56, - 0x56, 0x86, 0x82, 0x90, 0xa5, 0xd9, 0x6c, 0xce, 0xcf, 0xcf, 0x27, 0x3e, 0xe0, 0x08, 0xcd, 0x7b, - 0xfa, 0x2c, 0x5d, 0xba, 0x14, 0xa7, 0x82, 0x28, 0xd0, 0xdf, 0x41, 0x02, 0x80, 0x18, 0x73, 0x03, - 0x1b, 0x6c, 0xdb, 0xb6, 0x8d, 0xa8, 0x0e, 0x0d, 0x0d, 0x49, 0x24, 0x93, 0xaf, 0x1b, 0x76, 0xef, - 0xde, 0x4d, 0x1b, 0x73, 0x07, 0x00, 0x4d, 0xa7, 0xf3, 0xd9, 0x2b, 0x30, 0x56, 0x00, 0x2d, 0x2d, - 0x2d, 0x24, 0x30, 0x74, 0x4e, 0x65, 0x65, 0xe5, 0xf1, 0xe3, 0xc7, 0x91, 0x35, 0x1a, 0x19, 0xb4, - 0xf0, 0x33, 0x40, 0xa0, 0xf1, 0xbd, 0x6a, 0xd5, 0x2a, 0x42, 0x27, 0x26, 0x26, 0x22, 0x5b, 0xa0, - 0x07, 0x06, 0x06, 0x18, 0x69, 0x24, 0x44, 0x51, 0x51, 0x11, 0x0e, 0x06, 0x10, 0x50, 0xde, 0xc3, - 0x87, 0x0f, 0x23, 0xfd, 0x59, 0x59, 0x59, 0xdb, 0xb7, 0x6f, 0x17, 0x80, 0x19, 0xe4, 0x10, 0x33, - 0x28, 0x17, 0x2e, 0x5c, 0x20, 0xf4, 0xf0, 0xf0, 0x70, 0x4f, 0x4f, 0x0f, 0x68, 0xe6, 0x78, 0x30, - 0x3a, 0xc2, 0x08, 0x1c, 0x0f, 0xf4, 0x43, 0x77, 0x77, 0xf7, 0xae, 0x5d, 0xbb, 0x0a, 0x0a, 0x0a, - 0xc8, 0x1c, 0xab, 0xab, 0xab, 0x43, 0xa1, 0x18, 0x40, 0xb1, 0x78, 0xd2, 0x37, 0xbb, 0xdd, 0xce, - 0x70, 0x82, 0x13, 0xac, 0xc2, 0x91, 0x25, 0x69, 0xa1, 0xa4, 0xa4, 0xa4, 0xa6, 0xa6, 0x26, 0x14, - 0xb7, 0xa4, 0xa4, 0x84, 0x18, 0x9f, 0x3f, 0x7f, 0x9e, 0xd1, 0xc7, 0x7c, 0xbc, 0x7c, 0xf9, 0x32, - 0xf8, 0xd8, 0x1e, 0x34, 0x46, 0x04, 0x23, 0x22, 0x04, 0x38, 0x38, 0xca, 0xc4, 0x10, 0x17, 0x1f, - 0x3d, 0x4f, 0xf7, 0xef, 0xdf, 0x0f, 0xf0, 0x8e, 0x8e, 0x0e, 0xa2, 0x69, 0x34, 0x1a, 0x95, 0xca, - 0xc9, 0xf7, 0x59, 0xc7, 0x8e, 0x1d, 0x63, 0x40, 0xce, 0x9c, 0x39, 0x03, 0x0e, 0x5a, 0x17, 0x0e, - 0x8c, 0x8d, 0x8d, 0xb5, 0xb5, 0xb5, 0xa1, 0xa5, 0xd1, 0x57, 0x8c, 0x02, 0x21, 0xb8, 0xce, 0x00, - 0xd9, 0x9b, 0xf9, 0xc6, 0x58, 0x24, 0x36, 0x56, 0xab, 0x35, 0xe8, 0xdd, 0x84, 0xc9, 0xcb, 0xa0, - 0x63, 0x32, 0x32, 0x86, 0x0c, 0x91, 0x9d, 0x9d, 0xed, 0x72, 0xb9, 0xa0, 0x53, 0x51, 0x51, 0x01, - 0x26, 0x0e, 0xe8, 0x8e, 0x1d, 0x3b, 0x1a, 0x1b, 0x1b, 0xab, 0xab, 0xab, 0xb1, 0x44, 0xca, 0xd1, - 0x51, 0x0c, 0x02, 0xb9, 0xc5, 0x09, 0x5f, 0xa5, 0x52, 0x11, 0x10, 0x7a, 0x0b, 0xa2, 0xc9, 0x15, - 0xc0, 0x9e, 0x3d, 0x7b, 0x30, 0x0d, 0x52, 0x52, 0x52, 0x70, 0x1b, 0x1c, 0x3c, 0x78, 0x10, 0xf7, - 0x00, 0xb1, 0x41, 0x00, 0x19, 0x19, 0x19, 0x04, 0x91, 0xfe, 0xc6, 0x4c, 0x64, 0xb6, 0xc7, 0x0d, - 0x40, 0x8b, 0x08, 0x9d, 0x93, 0x93, 0x83, 0x5c, 0x42, 0x07, 0xc8, 0x18, 0x9d, 0xf4, 0x98, 0x46, - 0x41, 0x1a, 0x1a, 0x1a, 0x18, 0x73, 0x42, 0xd4, 0xd6, 0xd6, 0xe2, 0xca, 0x87, 0x2d, 0x62, 0xc3, - 0x90, 0xc5, 0xad, 0x6c, 0x32, 0x99, 0x58, 0x3a, 0x5c, 0x01, 0x5c, 0xbc, 0x78, 0x91, 0xa5, 0x1d, - 0xad, 0x25, 0x5a, 0x0b, 0x4d, 0x85, 0x1e, 0xbb, 0x73, 0xe7, 0xce, 0xa5, 0x4b, 0x97, 0xf0, 0x4d, - 0x2a, 0x13, 0x88, 0x8f, 0xac, 0xf5, 0xf7, 0xf7, 0x23, 0x65, 0x81, 0x22, 0xc2, 0x61, 0x07, 0x80, - 0x2b, 0x13, 0x8d, 0x88, 0xb1, 0x83, 0xb8, 0xab, 0xaa, 0xaa, 0x4e, 0x9c, 0x38, 0xc1, 0x61, 0x1c, - 0x0a, 0xf4, 0x65, 0xf2, 0xd9, 0x01, 0xe0, 0xe6, 0x62, 0x95, 0x3e, 0xf0, 0xdc, 0xbc, 0x4c, 0xff, - 0x9e, 0xbb, 0x97, 0xff, 0xb6, 0x27, 0x7e, 0x63, 0x42, 0xe3, 0xd7, 0x25, 0x33, 0x3d, 0xf4, 0x7a, - 0xfd, 0xc6, 0x8d, 0x1b, 0x59, 0x21, 0xfd, 0xa7, 0x96, 0xb1, 0x37, 0x73, 0xaf, 0xba, 0x1c, 0x5c, - 0x37, 0xf1, 0xab, 0xf6, 0x2d, 0xac, 0xfd, 0x63, 0x01, 0x84, 0x95, 0xa6, 0x17, 0xa8, 0x14, 0xab, - 0xc0, 0x0b, 0x4c, 0x6e, 0x58, 0xd0, 0xb1, 0x0a, 0x84, 0x95, 0xa6, 0x17, 0xa8, 0xf4, 0x0f, 0x7b, - 0x3c, 0x70, 0xd0, 0xa5, 0xfc, 0x34, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, - 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXPlistIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x10, 0xc5, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x09, 0x90, 0x15, 0xc5, 0xf5, 0xb1, 0x17, 0xbb, 0x2c, 0xcb, 0x1e, 0x20, 0xec, 0xc2, 0x1e, - 0xb2, 0x1c, 0xe1, 0x46, 0x08, 0x8b, 0x20, 0x97, 0x68, 0x20, 0x80, 0x10, 0x90, 0x80, 0x80, 0xd1, - 0xa4, 0x62, 0x45, 0x41, 0x28, 0x83, 0x5c, 0x52, 0x42, 0x52, 0xa9, 0x04, 0x04, 0x2a, 0x12, 0x10, - 0xa5, 0x10, 0xca, 0x12, 0x15, 0x85, 0x0a, 0xa7, 0x84, 0x08, 0x28, 0xe7, 0x22, 0x87, 0x01, 0xe4, - 0x94, 0x4b, 0xc0, 0x05, 0xf6, 0x3e, 0x60, 0xd9, 0x5d, 0xf6, 0xbe, 0x26, 0xef, 0xf5, 0xff, 0xdd, - 0x3b, 0x33, 0x7f, 0x66, 0x76, 0xfe, 0xbd, 0xc8, 0xef, 0xaa, 0xff, 0xa7, 0x8f, 0x77, 0xf5, 0x7b, - 0x3d, 0xdd, 0x3d, 0xd3, 0xdd, 0x6f, 0x1a, 0x49, 0x18, 0xc0, 0x8e, 0xe0, 0x67, 0x07, 0x2c, 0x03, - 0x75, 0x1e, 0xa1, 0xd1, 0x57, 0x77, 0x18, 0xa5, 0xa2, 0x6a, 0x8b, 0xa4, 0x3c, 0x2d, 0x24, 0xa1, - 0x3a, 0xf0, 0x00, 0xff, 0xbd, 0xcd, 0xa3, 0x92, 0x6e, 0x5c, 0x40, 0x58, 0x23, 0x3f, 0x95, 0x54, - 0xa9, 0xb3, 0x14, 0xe9, 0x46, 0x94, 0x12, 0xec, 0x4c, 0x44, 0x5c, 0x50, 0xe9, 0x46, 0x8d, 0x34, - 0xf9, 0x3c, 0xff, 0xfc, 0xf3, 0x2c, 0x5f, 0xc1, 0x21, 0x35, 0x35, 0x55, 0x00, 0x37, 0xb2, 0x22, - 0xf2, 0xab, 0x28, 0xe0, 0x35, 0x9a, 0x31, 0x63, 0x06, 0x8f, 0x1a, 0x5e, 0xed, 0xae, 0xb4, 0xdd, - 0x08, 0x8a, 0x3a, 0x08, 0x39, 0x0d, 0x22, 0xce, 0x21, 0x5c, 0x28, 0xaa, 0x82, 0x7b, 0x55, 0xb5, - 0x8c, 0x7e, 0xe2, 0xa1, 0x4c, 0x08, 0xde, 0x5b, 0xa7, 0x35, 0xc1, 0x94, 0xab, 0xa4, 0xd9, 0xd7, - 0xa9, 0x3c, 0xaa, 0xb8, 0xbe, 0x7f, 0xab, 0x48, 0x91, 0x06, 0x45, 0xca, 0x9a, 0xe0, 0x0d, 0x2f, - 0x66, 0x7f, 0xba, 0x4d, 0x71, 0x43, 0xd5, 0x12, 0xb5, 0x97, 0x25, 0x4b, 0x96, 0x08, 0x45, 0xc8, - 0x23, 0xea, 0xb6, 0xc4, 0xea, 0x40, 0x99, 0x58, 0x3b, 0x39, 0x9c, 0x6e, 0x9c, 0x19, 0xce, 0x2c, - 0x30, 0x51, 0xb1, 0x5b, 0x4b, 0xba, 0xac, 0x75, 0x0a, 0xec, 0x6e, 0x4a, 0x3a, 0x74, 0x74, 0xb3, - 0x1d, 0x62, 0x60, 0xd3, 0xb5, 0xe9, 0x92, 0xc7, 0x02, 0x9b, 0xa6, 0x65, 0xcd, 0xa0, 0xd6, 0xd7, - 0xfd, 0x48, 0xa6, 0x4d, 0x31, 0x6f, 0x95, 0xf2, 0x02, 0xca, 0x9b, 0x7b, 0xe5, 0xbe, 0x3c, 0x4b, - 0xc4, 0x75, 0x19, 0x10, 0x04, 0x21, 0x3e, 0xb6, 0x2f, 0xad, 0x0e, 0x58, 0xd6, 0xef, 0xf2, 0x4c, - 0x82, 0x99, 0x70, 0x26, 0x8f, 0x27, 0x6d, 0xae, 0x86, 0x0c, 0xe4, 0xd0, 0x1d, 0x0f, 0x67, 0x48, - 0xb9, 0x15, 0x35, 0xf2, 0x2c, 0x53, 0x71, 0xef, 0xb7, 0xa2, 0xc3, 0x87, 0x0f, 0x2b, 0x4c, 0x18, - 0x15, 0x15, 0xa5, 0x48, 0xd7, 0x9b, 0x90, 0xd7, 0x93, 0x6c, 0x3e, 0x75, 0xea, 0x54, 0xba, 0xe5, - 0x44, 0xb6, 0x3c, 0x5e, 0x5c, 0x5c, 0xac, 0x59, 0x16, 0x1a, 0x1a, 0xca, 0xe0, 0x09, 0x96, 0xff, - 0x38, 0x01, 0x85, 0x8a, 0xe4, 0xf7, 0x39, 0x02, 0x80, 0xbd, 0x69, 0x24, 0x2e, 0x70, 0x6a, 0x6b, - 0x6b, 0x59, 0x5c, 0xc1, 0x80, 0x00, 0x5c, 0x1d, 0x1c, 0xba, 0xd1, 0xec, 0x11, 0xe2, 0xe1, 0xaf, - 0x81, 0xdb, 0x55, 0xf4, 0x08, 0x32, 0x38, 0x71, 0xbf, 0x02, 0x7e, 0x77, 0xee, 0xae, 0xf9, 0x86, - 0xc4, 0xef, 0x38, 0xad, 0x2b, 0xf5, 0x94, 0xd8, 0xf7, 0x2b, 0x8a, 0x28, 0x8f, 0x42, 0x19, 0xf6, - 0x7b, 0x14, 0xff, 0x26, 0xaf, 0x4c, 0x51, 0xae, 0x4e, 0xd4, 0xf5, 0x09, 0xb2, 0x92, 0x15, 0x29, - 0x45, 0x8a, 0x69, 0xb0, 0xac, 0x48, 0xf2, 0x57, 0x31, 0x7c, 0xf6, 0xbb, 0x1c, 0x5d, 0x58, 0xc2, - 0xd3, 0x64, 0x40, 0x92, 0xbd, 0x7d, 0xcd, 0x76, 0x00, 0xe1, 0xd2, 0xcb, 0x19, 0x32, 0x22, 0x08, - 0x1f, 0xb8, 0x5b, 0x59, 0x53, 0x0e, 0xa3, 0xd9, 0x8a, 0xa4, 0xd1, 0x09, 0x50, 0x8c, 0x33, 0x7f, - 0x1a, 0x1a, 0xa9, 0xf7, 0xd2, 0x0b, 0x1d, 0x93, 0x33, 0x2d, 0x30, 0x08, 0x5f, 0x39, 0x2a, 0x5e, - 0x1b, 0x8c, 0x73, 0xd2, 0xbb, 0x06, 0x59, 0x25, 0xd3, 0x92, 0xf0, 0x54, 0x41, 0x85, 0x1e, 0x9a, - 0xc8, 0xd7, 0xac, 0x81, 0x5c, 0x94, 0x0a, 0xab, 0x64, 0x55, 0xb5, 0xb6, 0x75, 0x49, 0x0a, 0x0f, - 0x92, 0x83, 0x6a, 0xc6, 0x7d, 0x7d, 0x91, 0xa6, 0x5a, 0xe4, 0x99, 0x86, 0x36, 0xa0, 0xf1, 0x38, - 0x27, 0x27, 0x47, 0x0e, 0x0f, 0x9f, 0x7d, 0xf6, 0x99, 0x22, 0x5d, 0x6f, 0x42, 0x98, 0x5b, 0x27, - 0x32, 0x62, 0xc4, 0x08, 0x9d, 0x12, 0xdb, 0x6c, 0x64, 0x66, 0x93, 0x29, 0x6a, 0xb0, 0x66, 0xcd, - 0x1a, 0x36, 0x86, 0x2e, 0x5a, 0xb4, 0x48, 0x8c, 0xab, 0x6a, 0xe9, 0xc6, 0x8c, 0x19, 0x03, 0x11, - 0x11, 0x11, 0x22, 0x9b, 0xc6, 0xec, 0xb2, 0xb2, 0x32, 0xa0, 0xfc, 0xfd, 0xfb, 0xf7, 0xb3, 0x7c, - 0xca, 0x3b, 0x73, 0xe6, 0x8c, 0x80, 0x51, 0xb0, 0x1c, 0x34, 0x68, 0x10, 0x93, 0x00, 0x4b, 0x85, - 0x24, 0xea, 0x1a, 0x84, 0x87, 0x87, 0x8b, 0xb2, 0x21, 0x43, 0x86, 0xb0, 0x59, 0x84, 0xbf, 0xbf, - 0xbf, 0x0d, 0x1e, 0x07, 0xaa, 0xa3, 0x84, 0x39, 0x61, 0x61, 0x61, 0x0c, 0xe1, 0xe2, 0xc5, 0x8b, - 0x02, 0x81, 0x98, 0x71, 0x86, 0x3c, 0x2e, 0x4f, 0x07, 0x05, 0x05, 0x49, 0xbd, 0x7b, 0xf7, 0x66, - 0xf0, 0xf1, 0xf1, 0xf1, 0x0c, 0x96, 0x97, 0x53, 0xa6, 0x60, 0x30, 0x6d, 0xda, 0x34, 0xa9, 0x7d, - 0xfb, 0xf6, 0x0c, 0xd0, 0x95, 0x7f, 0xbe, 0x1b, 0x0d, 0xd5, 0x6d, 0x1c, 0xdc, 0xae, 0x22, 0x63, - 0xf6, 0xce, 0x97, 0x8a, 0xfb, 0xcc, 0x79, 0x52, 0xde, 0xa1, 0xe0, 0xab, 0x80, 0x77, 0xf4, 0x5e, - 0xc7, 0xd5, 0x63, 0x16, 0xb8, 0x55, 0x56, 0x5d, 0xc7, 0xd5, 0x85, 0x31, 0xa7, 0x2b, 0x30, 0x05, - 0xe7, 0xc0, 0xf5, 0xbd, 0xb6, 0x08, 0xd8, 0x9d, 0x0a, 0x89, 0x07, 0x33, 0x14, 0x62, 0x13, 0xce, - 0xd3, 0xdf, 0x29, 0x47, 0x62, 0x05, 0x80, 0xc9, 0x84, 0x43, 0xbd, 0x50, 0x02, 0x0a, 0x93, 0x6a, - 0xd5, 0xe8, 0xea, 0xee, 0x51, 0x30, 0x23, 0x21, 0x4c, 0x97, 0x5d, 0xdb, 0x43, 0x19, 0x70, 0xbb, - 0xb4, 0x1a, 0x8a, 0x46, 0xc6, 0x43, 0x98, 0xbf, 0xf2, 0xad, 0xec, 0x97, 0xd9, 0x65, 0x30, 0xfe, - 0xfb, 0x5c, 0x86, 0x1b, 0x11, 0xe8, 0x07, 0xf9, 0xbf, 0x8e, 0x03, 0x25, 0x84, 0x2e, 0x59, 0x51, - 0x60, 0xba, 0x02, 0xfe, 0xa8, 0xc5, 0x5a, 0x1c, 0xfa, 0x28, 0x64, 0x0e, 0x8b, 0x85, 0x98, 0xc6, - 0xfe, 0x82, 0x88, 0x5e, 0x64, 0xf2, 0xd9, 0xbb, 0xb0, 0x39, 0xb3, 0x04, 0x8e, 0x0d, 0x88, 0x86, - 0x01, 0x91, 0x8d, 0xf5, 0xc0, 0x58, 0xfe, 0x83, 0x1a, 0x09, 0xa2, 0xbe, 0x49, 0x83, 0x6a, 0xeb, - 0xdc, 0x94, 0x66, 0xde, 0x66, 0x82, 0xe9, 0x0a, 0x10, 0xb1, 0xff, 0x15, 0x54, 0x42, 0xff, 0x63, - 0x59, 0x82, 0xee, 0xc5, 0x21, 0xad, 0xa1, 0x7b, 0x58, 0xa0, 0x48, 0xcb, 0x23, 0x1f, 0xdc, 0x7e, - 0x00, 0x7f, 0xbe, 0x94, 0x0f, 0xcb, 0x3a, 0x47, 0xc2, 0xfc, 0x76, 0xcd, 0xe4, 0x45, 0x8a, 0x78, - 0x46, 0x79, 0x0d, 0xc4, 0x1e, 0x48, 0x17, 0x79, 0x5f, 0x26, 0xb5, 0x84, 0x71, 0xad, 0x42, 0x44, - 0xba, 0xbe, 0x88, 0x5d, 0x15, 0x50, 0x13, 0x8b, 0xc7, 0xa6, 0x94, 0x66, 0x6d, 0x4a, 0x47, 0x9e, - 0x8a, 0x86, 0xc1, 0x51, 0x16, 0x2d, 0x9f, 0x29, 0xac, 0x84, 0x3e, 0x47, 0xb3, 0x60, 0x4c, 0xab, - 0x26, 0xb0, 0x2b, 0xe9, 0x31, 0x35, 0x1a, 0x64, 0x56, 0xd4, 0x40, 0x9b, 0xfd, 0x16, 0xa1, 0xc3, - 0xb1, 0xe9, 0xdc, 0x1d, 0x1e, 0x07, 0x01, 0xf6, 0xb6, 0x1d, 0x2b, 0x55, 0xa7, 0x2a, 0x60, 0x23, - 0x19, 0x66, 0x94, 0x62, 0x13, 0x08, 0xdd, 0x93, 0x0a, 0xd1, 0xc1, 0xfe, 0x90, 0xf5, 0xab, 0x58, - 0x2d, 0x10, 0x97, 0xe6, 0xb9, 0xbc, 0x02, 0x24, 0xdd, 0xd6, 0xac, 0x52, 0x98, 0x18, 0xd3, 0xc4, - 0xa5, 0x82, 0xea, 0x11, 0x73, 0x4b, 0x05, 0xf4, 0x98, 0xb9, 0x23, 0xdf, 0xe9, 0x71, 0xc0, 0x1d, - 0x42, 0xd9, 0x43, 0xf3, 0xd1, 0xad, 0xc0, 0xac, 0x59, 0xb3, 0x2c, 0x6f, 0x5a, 0xf1, 0x29, 0x6f, - 0xe4, 0xc8, 0x91, 0xba, 0x4a, 0xa3, 0xa7, 0xc0, 0xd7, 0x5e, 0x7b, 0x4d, 0xb7, 0xdc, 0xa8, 0x20, - 0x24, 0x24, 0x04, 0xbe, 0xf8, 0xe2, 0x0b, 0x23, 0x10, 0xd9, 0xe3, 0xa3, 0xec, 0x41, 0x2c, 0x36, - 0x36, 0x96, 0x3d, 0xbc, 0xe1, 0xa3, 0xa8, 0x78, 0x88, 0xa3, 0x07, 0x42, 0x7c, 0x3d, 0x2c, 0x83, - 0xb2, 0x44, 0x91, 0xba, 0xa4, 0x7e, 0xf2, 0xa4, 0x92, 0x0b, 0x17, 0x2e, 0x08, 0xdc, 0xe8, 0xe8, - 0x68, 0x1b, 0xbc, 0x94, 0x94, 0x14, 0x51, 0x4e, 0x34, 0xe8, 0xc9, 0x14, 0xd7, 0x49, 0x19, 0x5c, - 0x75, 0x75, 0xb5, 0xb4, 0x72, 0xe5, 0x4a, 0x56, 0xde, 0xad, 0x5b, 0x37, 0x69, 0xc5, 0x8a, 0x15, - 0xd2, 0xaa, 0x55, 0xab, 0x6c, 0x68, 0x50, 0x86, 0x78, 0xa8, 0x54, 0x97, 0x12, 0x51, 0xf9, 0x43, - 0x26, 0x2d, 0xa1, 0x52, 0x5e, 0x5e, 0x9e, 0x72, 0x71, 0x43, 0xaf, 0x02, 0x9c, 0x1e, 0x95, 0xcb, - 0x1f, 0xa5, 0xe5, 0xf9, 0x54, 0x16, 0x10, 0x10, 0x20, 0x4d, 0x9e, 0x3c, 0x59, 0x3a, 0x76, 0xec, - 0x18, 0x2f, 0x12, 0x57, 0x2a, 0x1f, 0x37, 0x6e, 0x9c, 0x48, 0x6b, 0x45, 0x0c, 0x2b, 0x40, 0x04, - 0x6e, 0xdf, 0xbe, 0x2d, 0x95, 0x96, 0x96, 0x0a, 0x6d, 0xa9, 0x89, 0x10, 0x8c, 0x96, 0x05, 0x38, - 0x1c, 0x95, 0xeb, 0x55, 0x60, 0xeb, 0xd6, 0xad, 0x1c, 0x4c, 0xc2, 0x17, 0x12, 0x8c, 0x87, 0xc8, - 0xc0, 0x08, 0xe1, 0x92, 0xe5, 0x29, 0x5c, 0xbb, 0x76, 0x4d, 0x4a, 0x4a, 0x4a, 0x62, 0x71, 0xf9, - 0x9f, 0x61, 0x05, 0x5e, 0x7f, 0xfd, 0x75, 0x39, 0xac, 0x4b, 0xe3, 0x07, 0x0f, 0x1e, 0x64, 0xf4, - 0xf0, 0xfd, 0x90, 0xb4, 0x6b, 0xd7, 0x2e, 0xa9, 0xa8, 0x48, 0xb9, 0xcc, 0xcb, 0x99, 0x51, 0x73, - 0x22, 0xeb, 0x94, 0x94, 0x94, 0xf0, 0x2c, 0xc5, 0x55, 0x73, 0x1c, 0x90, 0x2f, 0xa3, 0xa0, 0x16, - 0xa8, 0x92, 0x74, 0x69, 0x90, 0x21, 0x40, 0x4b, 0xaa, 0x86, 0x2c, 0xb0, 0x5a, 0xde, 0x47, 0x77, - 0x1c, 0x50, 0x6b, 0xc2, 0x5b, 0x69, 0xcd, 0x7b, 0xc0, 0x5b, 0xc2, 0x38, 0xc2, 0xd7, 0xd7, 0x84, - 0x1c, 0xd1, 0x9a, 0x2b, 0x71, 0x7c, 0x16, 0x70, 0xa5, 0x36, 0x1d, 0xa1, 0xe5, 0xb3, 0x80, 0x23, - 0x5a, 0x73, 0x25, 0x8e, 0xcf, 0x02, 0xae, 0xd4, 0xa6, 0x23, 0xb4, 0x3c, 0x62, 0x81, 0xb3, 0x45, - 0x95, 0x8e, 0xc8, 0x66, 0x0a, 0xc7, 0x23, 0x23, 0x31, 0x7f, 0xf9, 0x6b, 0xf6, 0x75, 0xa1, 0x29, - 0xc9, 0xad, 0x40, 0x4e, 0x59, 0x20, 0xbb, 0x02, 0x77, 0x20, 0xe1, 0x5b, 0xe6, 0x85, 0x3f, 0x16, - 0xe8, 0xf2, 0xbc, 0x5d, 0x56, 0xc3, 0xca, 0x06, 0x46, 0x05, 0x0b, 0x98, 0x4d, 0x99, 0xa5, 0x0c, - 0xef, 0x6a, 0xb1, 0xf3, 0xaf, 0xdc, 0x1d, 0xae, 0x40, 0xff, 0xe3, 0xd9, 0x10, 0xb3, 0x3f, 0x8d, - 0x09, 0x95, 0x8b, 0x15, 0xd1, 0x0b, 0x3d, 0xbf, 0xcd, 0x64, 0x45, 0xc9, 0x4f, 0xb5, 0x12, 0x20, - 0x3f, 0x16, 0x57, 0xb1, 0x78, 0x97, 0xe4, 0x0c, 0xe8, 0x70, 0xd8, 0x52, 0x2e, 0x0a, 0xed, 0x8c, - 0xd8, 0xdd, 0x84, 0x76, 0xe5, 0x94, 0xc1, 0xd8, 0xd3, 0x75, 0xaf, 0xc4, 0xef, 0xe1, 0x2b, 0x71, - 0x3d, 0x2d, 0x90, 0xee, 0x03, 0xd0, 0x42, 0xcd, 0xf0, 0xfd, 0x67, 0x21, 0xc2, 0xa9, 0x83, 0xfc, - 0x35, 0xfd, 0x87, 0x3d, 0x9a, 0xc3, 0xb4, 0xf8, 0xa6, 0x6a, 0x90, 0x7a, 0xd3, 0xa6, 0x2b, 0x40, - 0xc2, 0x44, 0x7c, 0x9d, 0x86, 0x9b, 0x4d, 0x2c, 0xda, 0x3e, 0x8a, 0xaf, 0xcc, 0x07, 0xd6, 0xf3, - 0xca, 0x7c, 0xc0, 0x89, 0x1c, 0x38, 0x91, 0x5f, 0x0e, 0xb7, 0x9e, 0x8d, 0x85, 0xc7, 0x43, 0xb4, - 0x5f, 0xc7, 0x5f, 0x2b, 0xa9, 0x86, 0xce, 0x87, 0x2d, 0x8b, 0x1f, 0x01, 0x7e, 0x8d, 0xa0, 0x00, - 0x2b, 0x1a, 0xaa, 0x5a, 0x47, 0x30, 0xaa, 0x85, 0x9e, 0xf2, 0x14, 0x38, 0x7f, 0xc1, 0x36, 0x4e, - 0x9a, 0x24, 0xe1, 0xa7, 0xb4, 0x09, 0x05, 0xba, 0x19, 0xeb, 0x13, 0x9e, 0x08, 0x90, 0xf0, 0x14, - 0xf4, 0x84, 0xa7, 0xb2, 0x4e, 0xa1, 0x01, 0x8c, 0xde, 0x1c, 0x7c, 0x05, 0x4f, 0x6b, 0x03, 0x4d, - 0x71, 0xdf, 0xf4, 0x84, 0x33, 0xe6, 0x77, 0x3e, 0x99, 0xaa, 0x40, 0x6c, 0x48, 0xdd, 0x93, 0xe7, - 0x8e, 0xec, 0x52, 0x28, 0xc1, 0xc5, 0x88, 0xfa, 0xc2, 0x5b, 0x57, 0x2d, 0x37, 0xf6, 0xa6, 0xde, - 0xb6, 0xaf, 0xd7, 0xd5, 0xb8, 0x64, 0xdd, 0x8f, 0x53, 0x8b, 0x45, 0x76, 0x62, 0x93, 0x3a, 0x7e, - 0x22, 0x53, 0x27, 0x62, 0xba, 0x09, 0x11, 0x7e, 0xd2, 0xb1, 0x6c, 0xf8, 0xbe, 0xa0, 0x82, 0x91, - 0x1a, 0xd2, 0x3c, 0x18, 0x92, 0xfb, 0xd7, 0xdd, 0x98, 0x6a, 0xfa, 0x66, 0xbb, 0x4e, 0x5a, 0x63, - 0xfb, 0x77, 0x46, 0x09, 0x43, 0x6f, 0xdb, 0x24, 0x10, 0x52, 0x9e, 0x69, 0xad, 0x26, 0x65, 0x98, - 0x36, 0x65, 0x01, 0x4e, 0xe1, 0xf4, 0xc0, 0x68, 0xb8, 0x3f, 0x22, 0x1e, 0xfc, 0xf1, 0x75, 0xe1, - 0x91, 0x7b, 0xe5, 0xac, 0x2b, 0xfc, 0x38, 0xad, 0x4e, 0x73, 0x1c, 0x6e, 0x27, 0xde, 0xe8, 0x14, - 0x66, 0x3c, 0xae, 0xbf, 0x32, 0xb3, 0x27, 0xd7, 0x82, 0xcf, 0x85, 0xbf, 0x83, 0x6b, 0x09, 0xf6, - 0x0a, 0x4f, 0x3c, 0xec, 0xb2, 0x00, 0x21, 0xf0, 0xb0, 0x05, 0xd7, 0x00, 0x26, 0x9d, 0xc9, 0x63, - 0x49, 0x7a, 0x0d, 0x53, 0xfb, 0x5c, 0xdd, 0xce, 0xb0, 0xfa, 0xb4, 0x1f, 0x82, 0xed, 0xbc, 0xdc, - 0xda, 0x0c, 0xdf, 0xeb, 0x1a, 0x05, 0x33, 0xdb, 0xea, 0x2f, 0x12, 0x72, 0x7e, 0xba, 0x57, 0xc5, - 0x5b, 0x22, 0x07, 0x12, 0xbf, 0x39, 0x9d, 0x2b, 0x5d, 0x2d, 0xae, 0x3b, 0xa6, 0x92, 0x5e, 0x86, - 0x7b, 0xe2, 0x70, 0x2f, 0xdd, 0x13, 0xdf, 0xda, 0x6e, 0xf4, 0xe6, 0xe4, 0x0b, 0x70, 0x97, 0x59, - 0xdf, 0x63, 0x59, 0x3c, 0xe9, 0xd4, 0xd5, 0x61, 0x0b, 0xe8, 0x69, 0xa4, 0xf9, 0xbe, 0x74, 0xc8, - 0xaf, 0xac, 0x81, 0x8a, 0xe7, 0x12, 0x20, 0xc8, 0xc1, 0x75, 0x2f, 0x3d, 0xda, 0x5a, 0xf9, 0x76, - 0xdd, 0x03, 0x5a, 0x04, 0xe4, 0x79, 0xd4, 0x37, 0x91, 0xf0, 0xc1, 0xd8, 0x8f, 0x7b, 0x42, 0x78, - 0xe2, 0xed, 0x72, 0x0b, 0xd0, 0x30, 0x77, 0x13, 0x07, 0xa7, 0x8e, 0xd8, 0xbf, 0x7b, 0x22, 0xb8, - 0xbc, 0x02, 0x9e, 0x10, 0x5a, 0xce, 0xc3, 0xa5, 0x4d, 0x48, 0x4e, 0xd8, 0x53, 0x71, 0x5f, 0x05, - 0x3c, 0xa5, 0x69, 0x3d, 0x3e, 0x3e, 0x0b, 0xe8, 0x69, 0xc6, 0x53, 0xf9, 0x0e, 0x5b, 0x00, 0xd7, - 0xce, 0x80, 0xb6, 0x0f, 0xab, 0x8f, 0xf4, 0xc8, 0x05, 0xdf, 0xb3, 0x67, 0x0f, 0xd0, 0x52, 0xa9, - 0x5b, 0x83, 0xa3, 0xe3, 0x38, 0x0a, 0xc5, 0x16, 0xe1, 0xe8, 0xaa, 0x17, 0x66, 0xce, 0x9c, 0xc9, - 0x60, 0xf4, 0xca, 0x8d, 0xf2, 0x93, 0x93, 0x93, 0xd9, 0x0a, 0xa6, 0x11, 0x0c, 0x95, 0xe9, 0x73, - 0xaf, 0x0f, 0x13, 0xcb, 0x67, 0xcf, 0x9e, 0xed, 0xb0, 0x80, 0xf5, 0x91, 0xc7, 0x85, 0x74, 0x53, - 0xb4, 0x6d, 0x9a, 0x10, 0xae, 0x0a, 0x8a, 0x15, 0xf8, 0xe1, 0xc3, 0x87, 0x8b, 0x38, 0xed, 0xdf, - 0xb6, 0x27, 0x50, 0xd3, 0xa1, 0x59, 0xaa, 0x7a, 0xc1, 0x90, 0xd3, 0x18, 0x3a, 0x74, 0xa8, 0x28, - 0x57, 0xc3, 0x1d, 0x38, 0x70, 0x00, 0xce, 0x9e, 0x3d, 0xcb, 0x40, 0x71, 0xc1, 0x1b, 0xe8, 0x77, - 0xf4, 0xe8, 0x51, 0x8e, 0xaa, 0xbc, 0x6a, 0x69, 0x82, 0x16, 0xb8, 0x11, 0x4a, 0xf2, 0xf3, 0xf3, - 0x93, 0x36, 0x6c, 0xd8, 0x20, 0xe1, 0x51, 0x35, 0x96, 0xc6, 0xed, 0xf1, 0x0a, 0x70, 0x23, 0x0b, - 0x2c, 0x5c, 0xb8, 0x50, 0xea, 0xd3, 0xa7, 0x8f, 0xa6, 0x16, 0x51, 0x18, 0x96, 0xbf, 0x7b, 0xf7, - 0x6e, 0x46, 0x6f, 0xe9, 0xd2, 0xa5, 0x0a, 0x38, 0xe2, 0xad, 0xf5, 0x53, 0x30, 0xb7, 0x26, 0x34, - 0x9b, 0xd0, 0x9c, 0x39, 0x73, 0x14, 0x04, 0x09, 0x96, 0x13, 0x94, 0x13, 0x31, 0xaa, 0x00, 0xc1, - 0xd1, 0xfa, 0x2f, 0xe1, 0xa9, 0xc3, 0xf9, 0xf3, 0xe7, 0x05, 0x3d, 0xda, 0x9b, 0xbe, 0x7c, 0xf9, - 0x72, 0x89, 0xd6, 0x83, 0xe5, 0xc1, 0xe1, 0x26, 0x84, 0x0c, 0xdd, 0x1e, 0x7a, 0xf6, 0xec, 0x09, - 0xdb, 0xb6, 0x6d, 0x83, 0xe0, 0xe0, 0x60, 0xd6, 0x54, 0xe6, 0xce, 0x9d, 0x0b, 0xb8, 0xe5, 0x00, - 0x4e, 0x9c, 0x38, 0x61, 0x37, 0x6f, 0x9b, 0x7b, 0x40, 0x4e, 0xa1, 0x5f, 0xbf, 0x7e, 0x2c, 0x89, - 0x9b, 0xf3, 0xd9, 0x75, 0xfa, 0xf4, 0xe9, 0xf2, 0x62, 0x87, 0xe3, 0xa7, 0x4f, 0x9f, 0x86, 0x97, - 0x5f, 0x7e, 0x99, 0x9d, 0x6f, 0x40, 0xad, 0x43, 0x46, 0x86, 0xe5, 0xb5, 0x8a, 0xfc, 0x04, 0x07, - 0x6e, 0x31, 0x60, 0xf4, 0xef, 0xdc, 0xb9, 0xc3, 0xae, 0xef, 0xbe, 0xfb, 0x2e, 0xbc, 0xf2, 0xca, - 0x2b, 0xb6, 0x3c, 0xe5, 0x66, 0xe3, 0x71, 0xde, 0x84, 0x10, 0x5a, 0x98, 0xba, 0x7b, 0xf7, 0xee, - 0xbc, 0x98, 0xed, 0x7d, 0x90, 0x97, 0xf1, 0x38, 0x1e, 0xc0, 0x67, 0x30, 0x78, 0xf3, 0x0b, 0x3c, - 0x5e, 0x46, 0xd7, 0xcf, 0x3f, 0xff, 0x9c, 0x95, 0xd3, 0x7d, 0xc5, 0xf3, 0x69, 0xb3, 0x07, 0x8f, - 0xcb, 0xb7, 0x13, 0x94, 0x97, 0x97, 0x8b, 0x7c, 0x5e, 0x3e, 0x6a, 0xd4, 0x28, 0x21, 0x03, 0x8f, - 0xd8, 0x36, 0x50, 0x2c, 0xe1, 0x15, 0xe0, 0x40, 0xae, 0xbe, 0xd6, 0xd4, 0xd4, 0x48, 0xd7, 0xaf, - 0x5f, 0x97, 0xd2, 0xd2, 0xd2, 0xa4, 0x1d, 0x3b, 0x76, 0x48, 0xe7, 0xce, 0x9d, 0xd3, 0x65, 0x41, - 0x70, 0xf4, 0xd3, 0x0b, 0x36, 0x15, 0xa0, 0xcd, 0x17, 0x9d, 0x3a, 0x75, 0x62, 0xb5, 0xa7, 0x6d, - 0x30, 0xc7, 0x8f, 0x1f, 0xd7, 0xc3, 0x6d, 0x10, 0xf9, 0x36, 0x15, 0x18, 0x36, 0x6c, 0x98, 0xc2, - 0x74, 0x7c, 0x13, 0x52, 0x83, 0x90, 0x56, 0x43, 0x08, 0xdf, 0x13, 0x19, 0xde, 0x60, 0x5e, 0x0d, - 0x86, 0xdd, 0xa8, 0x57, 0x25, 0x33, 0xc9, 0xdc, 0x57, 0x01, 0x93, 0x8a, 0x72, 0x1b, 0xd8, 0x43, - 0x6f, 0x81, 0x87, 0xbe, 0x17, 0x72, 0x9b, 0x69, 0x3d, 0x44, 0xf8, 0xa1, 0x6f, 0x41, 0x1e, 0xd2, - 0x93, 0xdb, 0xd8, 0xf8, 0x0c, 0xe0, 0x36, 0xd5, 0x9a, 0x23, 0xec, 0x33, 0x80, 0x39, 0x3d, 0xb9, - 0x0d, 0xca, 0x67, 0x00, 0xb7, 0xa9, 0xd6, 0x1c, 0x61, 0x9f, 0x01, 0xcc, 0xe9, 0xc9, 0x6d, 0x50, - 0x3e, 0x03, 0xb8, 0x4d, 0xb5, 0xe6, 0x08, 0xfb, 0x0c, 0x60, 0x4e, 0x4f, 0x6e, 0x83, 0xf2, 0x19, - 0xc0, 0x6d, 0xaa, 0x35, 0x47, 0xf8, 0x67, 0x65, 0x80, 0x27, 0x71, 0x03, 0x25, 0xf9, 0x1d, 0x98, - 0x88, 0x27, 0xe0, 0x4f, 0xe2, 0xa1, 0xf3, 0x87, 0x21, 0x34, 0x08, 0x03, 0xec, 0xbb, 0x5b, 0x0e, - 0x23, 0x4f, 0xe5, 0x42, 0xb9, 0xfe, 0xa6, 0xd3, 0x7a, 0x75, 0x49, 0x4a, 0x3f, 0x85, 0x0e, 0xd2, - 0x6a, 0xf0, 0x25, 0xfd, 0x36, 0x74, 0x3f, 0x80, 0xdb, 0x1e, 0x35, 0xc3, 0x4b, 0xe7, 0xef, 0xc1, - 0xa7, 0xe9, 0x96, 0x8d, 0x6d, 0x9a, 0x00, 0x1e, 0xce, 0xf4, 0xca, 0xab, 0x08, 0xd2, 0xf3, 0xba, - 0x3b, 0xc5, 0x80, 0x6e, 0xd4, 0xa0, 0xd0, 0xea, 0x9f, 0x96, 0xea, 0x1d, 0x88, 0x5a, 0x3b, 0x3b, - 0x28, 0x06, 0xba, 0xe9, 0xb8, 0x47, 0xd0, 0xd3, 0xcd, 0xec, 0x2b, 0xf7, 0x61, 0x65, 0x4a, 0x91, - 0x28, 0xde, 0xde, 0xa7, 0x25, 0x8c, 0x8f, 0x56, 0x2e, 0x4a, 0xe7, 0x23, 0x9f, 0xce, 0xe8, 0x31, - 0x0d, 0xbd, 0x6a, 0x0a, 0xb8, 0x20, 0xe4, 0xf7, 0x56, 0xbb, 0x70, 0x58, 0xd8, 0x21, 0x1c, 0x82, - 0xbd, 0xd4, 0x14, 0x3d, 0x66, 0x00, 0xda, 0x5f, 0xfa, 0xb7, 0xeb, 0x05, 0xf0, 0x5e, 0xca, 0x03, - 0xd6, 0x4a, 0x85, 0x16, 0x30, 0xd2, 0x3b, 0xbc, 0x31, 0xac, 0x41, 0xaf, 0x20, 0x4f, 0x46, 0x04, - 0xc9, 0xb3, 0x4d, 0xc5, 0x57, 0xde, 0x7a, 0x00, 0xb3, 0x2f, 0xe7, 0x0b, 0xd8, 0x95, 0xb8, 0x71, - 0xf0, 0x4d, 0x83, 0x8d, 0x83, 0x3f, 0xa1, 0x67, 0x91, 0x37, 0xd0, 0xc7, 0xc5, 0xde, 0x5c, 0xcb, - 0x6e, 0x4a, 0x81, 0x88, 0x11, 0xda, 0xc8, 0x4b, 0xf8, 0xad, 0x82, 0x3c, 0x67, 0x0d, 0xb7, 0x1a, - 0x20, 0x1d, 0x1d, 0x75, 0x50, 0x65, 0x77, 0xe2, 0x06, 0x5f, 0x79, 0xa0, 0xb5, 0xec, 0xdf, 0xc7, - 0x86, 0xc2, 0x3f, 0xd1, 0xd1, 0x47, 0x4b, 0x27, 0x2a, 0xbb, 0x1d, 0xe9, 0x4e, 0xf8, 0xde, 0xb2, - 0xdb, 0x93, 0xe8, 0xcf, 0x4a, 0x6c, 0x06, 0x2b, 0xba, 0x44, 0xca, 0x59, 0x19, 0xc6, 0xc9, 0xed, - 0xc5, 0xa2, 0xeb, 0x85, 0xf0, 0x2f, 0xbc, 0x7b, 0xd4, 0x1e, 0xfa, 0xfa, 0xe1, 0x56, 0xf0, 0xb5, - 0xdd, 0x9b, 0x43, 0xcf, 0x66, 0xda, 0xce, 0x4a, 0x0c, 0x09, 0xdb, 0x51, 0xe8, 0x72, 0x03, 0x9c, - 0x46, 0x47, 0x24, 0x53, 0x2f, 0xde, 0x83, 0x73, 0x78, 0x95, 0x87, 0xb0, 0x00, 0x3f, 0xf8, 0xfb, - 0x2f, 0x22, 0xe0, 0x8d, 0xc7, 0xc3, 0x1c, 0x76, 0x3c, 0x22, 0xa7, 0x77, 0x0a, 0x07, 0xd9, 0x27, - 0x65, 0x9e, 0x5d, 0x7e, 0x1b, 0x13, 0x0a, 0xdb, 0x7e, 0xd9, 0x42, 0x0e, 0x62, 0x77, 0x7c, 0x33, - 0x6e, 0xdf, 0x9d, 0x7d, 0xf9, 0x3e, 0x64, 0x96, 0x2b, 0x8f, 0x62, 0xc4, 0xe3, 0x6e, 0x71, 0xf2, - 0xdb, 0x33, 0xa6, 0xa5, 0xb2, 0x5b, 0xb3, 0x9b, 0x81, 0x06, 0x82, 0x4b, 0x0d, 0xd0, 0x0b, 0x3d, - 0xc0, 0x9c, 0x57, 0x29, 0xbe, 0x4b, 0x58, 0x10, 0xfc, 0x07, 0x3d, 0xc2, 0xb4, 0xb7, 0x63, 0x0b, - 0xba, 0x86, 0x9c, 0x8a, 0xac, 0x34, 0xbc, 0xb3, 0x12, 0xd1, 0x51, 0x11, 0xf7, 0xdd, 0xd3, 0x17, - 0x5b, 0xeb, 0x49, 0x3c, 0xc0, 0xe0, 0xaa, 0x90, 0x57, 0x59, 0x0b, 0x2f, 0xe1, 0x2e, 0xf4, 0x7d, - 0x79, 0xca, 0x6e, 0x8a, 0xc6, 0x28, 0x5d, 0x6f, 0x9b, 0x0e, 0x32, 0x77, 0xa9, 0x01, 0x48, 0x86, - 0x1c, 0x14, 0x7e, 0xfe, 0xd5, 0xfb, 0xb0, 0x01, 0x67, 0x1a, 0xb8, 0x0a, 0xaa, 0x10, 0x8b, 0xce, - 0x1d, 0x2c, 0xc7, 0x2e, 0x62, 0x92, 0x13, 0x8e, 0x62, 0x8a, 0x71, 0x2c, 0x89, 0x43, 0xff, 0x43, - 0xb8, 0xdf, 0x9a, 0xd1, 0x8e, 0x43, 0x9a, 0x29, 0xcf, 0xb4, 0x71, 0xfa, 0xae, 0x3a, 0x92, 0x5f, - 0xc1, 0xba, 0xcb, 0x1f, 0x34, 0x8e, 0x88, 0x0d, 0x7f, 0x2c, 0x04, 0x56, 0x75, 0x8b, 0x62, 0x87, - 0x33, 0x14, 0x15, 0x72, 0x41, 0xc2, 0xe5, 0x06, 0x90, 0xcb, 0x44, 0x2a, 0x5a, 0x8f, 0xc7, 0x09, - 0x16, 0x5c, 0x2b, 0x80, 0x3c, 0xd9, 0xec, 0x83, 0x60, 0xe8, 0xc8, 0xc1, 0x74, 0xec, 0x8e, 0xfe, - 0x81, 0xdd, 0x52, 0x84, 0x49, 0x67, 0x48, 0x44, 0xaf, 0x23, 0x1e, 0x72, 0xc2, 0x6f, 0x38, 0x10, - 0x09, 0x08, 0xc5, 0x6e, 0x2d, 0xed, 0xd9, 0x36, 0x10, 0x89, 0x67, 0x8a, 0xec, 0x0d, 0x95, 0xd8, - 0x36, 0xd0, 0x63, 0x2e, 0x2c, 0xbe, 0x51, 0x08, 0x25, 0xd6, 0x63, 0x40, 0x9c, 0x46, 0x88, 0xbf, - 0x1f, 0xbc, 0xdd, 0xbe, 0x19, 0xcc, 0xc3, 0x19, 0x92, 0xbb, 0x67, 0x47, 0x6e, 0x35, 0x00, 0xaf, - 0x10, 0xbf, 0x5e, 0x7a, 0x50, 0x05, 0x6f, 0xe0, 0x8c, 0x25, 0x19, 0xe7, 0xfd, 0xea, 0x90, 0x14, - 0xd1, 0x18, 0x3e, 0xc0, 0x56, 0x66, 0x34, 0x13, 0x1a, 0x82, 0x4e, 0xdc, 0xbe, 0xc5, 0x73, 0x22, - 0x14, 0x68, 0x20, 0xff, 0xf1, 0xe9, 0xd6, 0xd0, 0xc1, 0x8e, 0x2d, 0xe5, 0x34, 0x03, 0x7a, 0x13, - 0xfb, 0xf8, 0xaf, 0x72, 0x94, 0x93, 0x02, 0xa2, 0xd7, 0x15, 0xbb, 0xca, 0xf7, 0xbb, 0x45, 0xc2, - 0x33, 0x78, 0x90, 0xc6, 0x93, 0xc1, 0xa3, 0x06, 0x90, 0x57, 0x8c, 0x66, 0x20, 0x4b, 0xb0, 0xf5, - 0x2d, 0xc7, 0x56, 0x88, 0x0e, 0xef, 0x59, 0xd1, 0x20, 0xac, 0xfc, 0x11, 0x3c, 0x45, 0xa4, 0xf5, - 0x0c, 0x45, 0x0f, 0x50, 0x1b, 0xd3, 0xeb, 0x0e, 0xe7, 0x1c, 0xea, 0x1f, 0x0d, 0x43, 0x9b, 0x1b, - 0xfb, 0x79, 0x93, 0xf3, 0xa3, 0xf8, 0xb4, 0x1f, 0xf2, 0xf1, 0xf9, 0xe3, 0x01, 0xcb, 0x26, 0x03, - 0xfe, 0x31, 0x2e, 0x14, 0x96, 0x76, 0x72, 0x6e, 0x26, 0xa6, 0xe6, 0x61, 0x6f, 0xda, 0x6b, 0x06, - 0x50, 0x0b, 0x9a, 0x82, 0xad, 0x53, 0xef, 0xac, 0xd8, 0xdb, 0xd8, 0x85, 0x2d, 0xbb, 0x59, 0x28, - 0x50, 0x3e, 0x7d, 0xa2, 0x05, 0xfc, 0x01, 0xa7, 0xb1, 0x8e, 0x04, 0x3a, 0x88, 0x9a, 0x80, 0x27, - 0x08, 0xb5, 0x8c, 0xec, 0x08, 0x3d, 0x67, 0x71, 0x1a, 0x8c, 0x01, 0xf4, 0x2a, 0xf2, 0x21, 0x3e, - 0x31, 0x4f, 0xff, 0xe1, 0x9e, 0x28, 0xa6, 0x31, 0xe3, 0xaf, 0xf8, 0xe4, 0xfa, 0x73, 0x09, 0xf6, - 0x8f, 0x5e, 0x1e, 0xac, 0x39, 0xbd, 0x34, 0xa0, 0xf1, 0xb9, 0x43, 0x53, 0xcb, 0xc3, 0xd0, 0x9f, - 0xe2, 0xc3, 0x7e, 0x56, 0xca, 0x27, 0x55, 0x36, 0xf8, 0x3b, 0xc0, 0x83, 0xf6, 0xf6, 0x0a, 0xab, - 0x06, 0x7d, 0x07, 0x78, 0x45, 0x23, 0x1e, 0x66, 0xea, 0x33, 0x80, 0x87, 0x15, 0xae, 0x66, 0xe7, - 0x33, 0x80, 0x5a, 0x23, 0x1e, 0x4e, 0xfb, 0x0c, 0xe0, 0x61, 0x85, 0xab, 0xd9, 0xf9, 0x0c, 0xa0, - 0xd6, 0x88, 0x87, 0xd3, 0x0f, 0xbd, 0x01, 0xaa, 0xaa, 0xaa, 0x00, 0x5d, 0x9e, 0x7a, 0x58, 0x6d, - 0xae, 0x63, 0xe7, 0x71, 0x03, 0xac, 0x5e, 0xbd, 0xda, 0xe6, 0x90, 0x21, 0xbd, 0x16, 0x18, 0x3b, - 0x76, 0xac, 0xdd, 0xb5, 0xc2, 0xe3, 0x48, 0x80, 0x9f, 0x72, 0x01, 0xfc, 0x02, 0x9d, 0xc3, 0xae, - 0x87, 0xed, 0x66, 0x6a, 0x45, 0x20, 0xa3, 0x17, 0x14, 0xe8, 0xbb, 0x7e, 0x32, 0x4b, 0xd7, 0xe3, - 0x06, 0xa0, 0x2f, 0xf7, 0xcc, 0x9f, 0x3f, 0x1f, 0x26, 0x4c, 0x98, 0x00, 0x1d, 0x3a, 0x74, 0x10, - 0x72, 0x56, 0x56, 0x2a, 0x17, 0x70, 0x44, 0x81, 0x41, 0x84, 0x4e, 0xa3, 0xb6, 0x6d, 0xdb, 0x96, - 0xfd, 0x28, 0xee, 0xa9, 0xb0, 0x60, 0xc1, 0x02, 0x66, 0xf4, 0xc8, 0xc8, 0x48, 0x78, 0xf1, 0xc5, - 0x17, 0x9d, 0x62, 0x6b, 0xda, 0x3b, 0x05, 0x7d, 0x72, 0xf0, 0xc6, 0x8d, 0x1b, 0x50, 0x51, 0x51, - 0xc1, 0xce, 0x38, 0x76, 0xec, 0xd8, 0x11, 0x28, 0xef, 0xf2, 0xe5, 0xcb, 0x70, 0xea, 0xd4, 0x29, - 0x20, 0x05, 0xa2, 0x0f, 0x68, 0xa0, 0x73, 0x90, 0xcd, 0x9a, 0xe9, 0x7b, 0xad, 0x49, 0x48, 0x48, - 0x80, 0x65, 0xcb, 0x96, 0x31, 0xa1, 0xa9, 0x05, 0xa3, 0xcf, 0x68, 0xbb, 0x2b, 0x80, 0xa7, 0xf8, - 0x98, 0x2c, 0x31, 0x31, 0x31, 0xb0, 0x73, 0xe7, 0x4e, 0x86, 0xdf, 0xaa, 0x95, 0xbe, 0x2b, 0x20, - 0x2d, 0x06, 0xf8, 0xc1, 0x24, 0xb8, 0x74, 0xe9, 0x12, 0xa4, 0xa7, 0xa7, 0xb3, 0xbb, 0x08, 0x7d, - 0x5f, 0x43, 0xdf, 0xbe, 0x7d, 0x01, 0xfd, 0x5b, 0xc3, 0x27, 0x9f, 0x7c, 0x02, 0x13, 0x27, 0x4e, - 0x84, 0xae, 0x5d, 0xbb, 0x6a, 0xa1, 0x02, 0xf1, 0xe7, 0x81, 0x3e, 0x07, 0xe5, 0x54, 0xd0, 0x38, - 0x3a, 0x66, 0x93, 0x95, 0x95, 0x95, 0x25, 0x61, 0x37, 0xa1, 0x38, 0xff, 0x86, 0x4a, 0x56, 0xa4, - 0x51, 0x08, 0x45, 0xfa, 0x85, 0x17, 0x5e, 0xb0, 0xa1, 0xa3, 0xce, 0xe0, 0xa7, 0x75, 0x09, 0xd7, - 0xc8, 0x35, 0xb5, 0x1c, 0x6f, 0xcb, 0x96, 0x2d, 0x0a, 0x3e, 0x9c, 0xaf, 0x96, 0xeb, 0x6a, 0x39, - 0x1e, 0xc5, 0x51, 0x59, 0x12, 0x2a, 0x55, 0xe0, 0xd3, 0x71, 0xe8, 0x2e, 0x5d, 0xba, 0x48, 0x83, - 0x07, 0x0f, 0x16, 0x6e, 0xad, 0x39, 0xbd, 0x81, 0x03, 0x07, 0x2a, 0xd0, 0xf7, 0xee, 0xdd, 0x2b, - 0xf0, 0x38, 0x8c, 0xd1, 0xf5, 0xe4, 0xc9, 0x93, 0x0a, 0x7c, 0xbd, 0x84, 0xcd, 0x41, 0x43, 0x3d, - 0x40, 0xca, 0xe7, 0x47, 0x40, 0x39, 0xe3, 0xf5, 0xeb, 0xd7, 0x2b, 0xc0, 0x6f, 0xde, 0xbc, 0x29, - 0x35, 0x69, 0xd2, 0x44, 0x08, 0x1a, 0x17, 0x17, 0xa7, 0x28, 0x57, 0x27, 0x1c, 0x31, 0x80, 0x9c, - 0x06, 0x3f, 0x4e, 0x4d, 0xf2, 0x98, 0x31, 0x80, 0xfc, 0x8c, 0x2c, 0xe1, 0xe0, 0xc7, 0xcf, 0x6c, - 0xdc, 0x71, 0xe3, 0xe1, 0x5e, 0x69, 0xf1, 0xe2, 0xc5, 0xcc, 0x33, 0xbc, 0x9c, 0x17, 0x1d, 0x4f, - 0x3d, 0x74, 0xe8, 0x10, 0xf3, 0xf8, 0x4e, 0x06, 0xe3, 0x3a, 0xe0, 0x9e, 0xdf, 0xc9, 0xfb, 0x3b, - 0xf7, 0x00, 0xaf, 0xe5, 0x64, 0x5d, 0x4e, 0x4b, 0x1e, 0x77, 0xd8, 0x00, 0x38, 0x68, 0xca, 0xe9, - 0x88, 0xf8, 0xda, 0xb5, 0x6b, 0x85, 0x70, 0x24, 0xa4, 0x91, 0x30, 0x9e, 0x36, 0x00, 0x09, 0x49, - 0x9f, 0x55, 0xe3, 0xca, 0xd3, 0xbb, 0x26, 0x26, 0x26, 0x4a, 0x9b, 0x37, 0x6f, 0x16, 0x75, 0x52, - 0x47, 0xf8, 0x59, 0x78, 0xc2, 0xaf, 0xcf, 0x73, 0xbd, 0x1a, 0x57, 0x9d, 0x76, 0x78, 0x10, 0xde, - 0xb7, 0x6f, 0x1f, 0xc8, 0x3f, 0x8f, 0x8e, 0xc2, 0xb0, 0x35, 0xe0, 0x8f, 0x3e, 0xfa, 0x88, 0xa2, - 0x2c, 0xd0, 0x58, 0x30, 0x60, 0xc0, 0x00, 0x9e, 0xf4, 0xfa, 0x15, 0x2b, 0x0f, 0xe3, 0xc7, 0x8f, - 0x87, 0x5b, 0xb7, 0x6e, 0x31, 0x59, 0x69, 0x3c, 0x43, 0xe7, 0x03, 0x80, 0x77, 0x06, 0x3b, 0xca, - 0xde, 0xba, 0x75, 0x6b, 0x26, 0x23, 0x7e, 0xf7, 0x00, 0x26, 0x4d, 0x9a, 0x04, 0xf3, 0xe6, 0xcd, - 0xd3, 0x94, 0x99, 0xc6, 0x09, 0x1e, 0x9c, 0x9e, 0x09, 0xa9, 0x2d, 0x62, 0x94, 0x56, 0x77, 0x41, - 0x28, 0x04, 0x6b, 0x4d, 0xf4, 0x31, 0x88, 0xc0, 0xc0, 0x40, 0x45, 0xcb, 0x6a, 0xd3, 0xa6, 0x8d, - 0x54, 0x58, 0x58, 0xa8, 0x20, 0xf7, 0xce, 0x3b, 0xef, 0x48, 0x9d, 0x3b, 0x77, 0x96, 0x08, 0x9e, - 0x7e, 0x4d, 0x9b, 0x36, 0x15, 0x38, 0xe8, 0xbc, 0x40, 0xe4, 0xb7, 0x6b, 0xd7, 0x4e, 0x7a, 0xf5, - 0xd5, 0x57, 0x15, 0xb8, 0x94, 0xd8, 0xbe, 0x7d, 0x3b, 0xfb, 0xbc, 0x00, 0xc7, 0x6f, 0xd1, 0xa2, - 0x85, 0xc0, 0xa7, 0x31, 0x8a, 0xe7, 0xd3, 0x97, 0x05, 0x47, 0x8f, 0x1e, 0x2d, 0x65, 0x67, 0x67, - 0x2b, 0x68, 0xd0, 0x71, 0x7d, 0x2e, 0x33, 0xf5, 0xff, 0xf4, 0xd1, 0xe5, 0x2b, 0x57, 0xae, 0x48, - 0x38, 0x81, 0x90, 0xe8, 0x78, 0x3e, 0x8d, 0x2f, 0xf2, 0xb1, 0x6e, 0xdd, 0xba, 0x75, 0x0a, 0x7c, - 0x9e, 0xd8, 0xb8, 0x71, 0xa3, 0xa0, 0x43, 0xf4, 0x88, 0x16, 0x7d, 0xf6, 0x00, 0x27, 0x02, 0x8a, - 0x7c, 0x2a, 0x23, 0xfa, 0x46, 0xc1, 0xe1, 0x2e, 0x88, 0x3e, 0x9b, 0x40, 0xae, 0x59, 0x68, 0xb0, - 0xed, 0xd1, 0xa3, 0x07, 0xfb, 0x90, 0x05, 0xb6, 0x2e, 0xe6, 0xbe, 0x82, 0x2a, 0xa3, 0x15, 0xa8, - 0xcb, 0xe1, 0x9f, 0x6d, 0xe4, 0x8a, 0xd0, 0xba, 0xd2, 0x67, 0x1a, 0x49, 0x81, 0xea, 0x80, 0xb3, - 0x13, 0x09, 0x67, 0x3e, 0x36, 0x95, 0x54, 0xd3, 0x20, 0x25, 0xf6, 0xea, 0xd5, 0x4b, 0xe2, 0xfe, - 0x13, 0x38, 0x1d, 0x92, 0x97, 0x60, 0xe9, 0x4b, 0x1e, 0xf4, 0xc5, 0x0f, 0x35, 0x1e, 0xa5, 0xd1, - 0x59, 0x0a, 0xeb, 0xa6, 0x68, 0xe2, 0x61, 0x14, 0x72, 0x73, 0x73, 0xa5, 0x29, 0x53, 0xa6, 0xd8, - 0x34, 0x3c, 0x6a, 0x88, 0xe4, 0xaf, 0x61, 0xd3, 0xa6, 0x4d, 0x46, 0xe8, 0xa2, 0xcc, 0x29, 0x03, - 0x08, 0x2a, 0xbe, 0x88, 0xc3, 0x1a, 0x30, 0xb5, 0x20, 0x43, 0x0f, 0x4c, 0x38, 0xc3, 0xc1, 0x06, - 0xa2, 0x1d, 0xf0, 0x0e, 0x00, 0xfc, 0x9e, 0x8c, 0x76, 0xa1, 0x2f, 0xd7, 0x50, 0x03, 0xa6, 0x0c, - 0xc0, 0x1f, 0xb8, 0xf0, 0x0b, 0x2a, 0x36, 0xc4, 0xe8, 0x69, 0x10, 0xfb, 0x75, 0x5d, 0xff, 0x46, - 0x36, 0x08, 0xbe, 0x0c, 0x85, 0x06, 0x4c, 0x19, 0x40, 0x81, 0xe1, 0x4b, 0xb8, 0x54, 0x03, 0x0e, - 0x4f, 0x43, 0x5d, 0x2a, 0xc5, 0x23, 0x4c, 0xcc, 0x67, 0x00, 0x2f, 0x1b, 0xdf, 0x67, 0x00, 0x9f, - 0x01, 0xbc, 0xac, 0x01, 0x2f, 0xb3, 0xf7, 0xdd, 0x01, 0x5e, 0x36, 0xc0, 0xff, 0x01, 0x60, 0x99, - 0xd3, 0x96, 0x0f, 0xf3, 0xae, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, - 0x60, 0x82 -}; - -static const u_int8_t FLEXTextIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x38, 0x33, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xd4, - 0x6c, 0xf8, 0x31, 0x00, 0x00, 0x05, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x5b, - 0x2c, 0x6c, 0x57, 0x18, 0x9e, 0x61, 0xce, 0x5c, 0x5c, 0xe2, 0x5a, 0xd7, 0x10, 0x97, 0x53, 0xd7, - 0xba, 0x3d, 0xd0, 0x3e, 0x20, 0x2a, 0x82, 0x88, 0x22, 0x1e, 0x08, 0xaa, 0x24, 0x08, 0x21, 0x12, - 0x11, 0x91, 0xf4, 0xa9, 0x69, 0x1a, 0xf5, 0x26, 0x22, 0xc1, 0x83, 0x04, 0x91, 0xa6, 0x09, 0x5e, - 0x2a, 0x8d, 0x34, 0x91, 0xa0, 0xe1, 0xd4, 0x83, 0x07, 0xd2, 0x70, 0x8a, 0xe8, 0x11, 0xe2, 0x1a, - 0x8a, 0xc1, 0x30, 0x86, 0x41, 0xbf, 0xb1, 0xcc, 0xea, 0x9c, 0x33, 0xec, 0xd9, 0x33, 0xb3, 0x9c, - 0x46, 0xb2, 0x57, 0x64, 0xe7, 0x5f, 0xff, 0xff, 0xfd, 0xf7, 0xb5, 0xd6, 0xac, 0xbd, 0x89, 0xef, - 0xee, 0xee, 0x44, 0x2f, 0x79, 0xd8, 0xbc, 0xe4, 0xe0, 0x75, 0xb1, 0x0b, 0x09, 0xfc, 0xdf, 0x1d, - 0x14, 0x3a, 0x20, 0x74, 0xc0, 0xca, 0x0a, 0x08, 0x4b, 0xc8, 0xca, 0x02, 0x5a, 0xad, 0x2e, 0x74, - 0xc0, 0xea, 0x12, 0x5a, 0x69, 0x40, 0xe8, 0x80, 0x95, 0x05, 0xb4, 0x5a, 0x5d, 0x62, 0xb5, 0x05, - 0x9d, 0x01, 0xad, 0xe8, 0x6e, 0x4a, 0xa5, 0x7c, 0xa7, 0x51, 0xdf, 0x9a, 0xba, 0x1a, 0xda, 0x88, - 0xc5, 0xaf, 0x65, 0x8a, 0x24, 0x07, 0x67, 0x89, 0x48, 0xcc, 0xc4, 0x35, 0x9b, 0x04, 0x7e, 0x3d, - 0xf9, 0x27, 0xff, 0xdd, 0x9f, 0xfc, 0x03, 0xfa, 0x25, 0x38, 0x26, 0xd7, 0xe9, 0x13, 0xfe, 0x78, - 0x0e, 0x24, 0x9b, 0x3d, 0xb0, 0xae, 0x51, 0x73, 0xf8, 0x30, 0x16, 0xad, 0x99, 0x89, 0x37, 0xb6, - 0x40, 0x39, 0x6c, 0x3a, 0x70, 0x7e, 0x7b, 0x43, 0x2c, 0xba, 0x49, 0xa4, 0x9e, 0xaf, 0xa4, 0xa0, - 0x8f, 0xb5, 0xd7, 0xbb, 0xd7, 0x1a, 0xc2, 0xf4, 0x91, 0xca, 0x9c, 0x6d, 0x5f, 0x81, 0xde, 0xbb, - 0xd6, 0x1c, 0x69, 0xaf, 0x41, 0x5c, 0xdc, 0xde, 0x12, 0x91, 0xf5, 0x4f, 0x36, 0x1d, 0x50, 0xeb, - 0x03, 0xaa, 0x76, 0xf7, 0x7d, 0x1b, 0xfe, 0x05, 0xfe, 0xbe, 0xf7, 0x09, 0xa6, 0xc1, 0xfd, 0xe0, - 0x1d, 0x4c, 0x98, 0x95, 0xee, 0xbe, 0x84, 0xa9, 0xbe, 0x7b, 0x48, 0x98, 0x62, 0x2c, 0x26, 0x18, - 0x25, 0x70, 0xf7, 0x50, 0x51, 0x99, 0x0d, 0x97, 0x41, 0xb9, 0xf8, 0x41, 0x7a, 0xa9, 0x4f, 0xd8, - 0xe2, 0xb8, 0xa9, 0x22, 0x97, 0x3f, 0x0a, 0x32, 0x49, 0xa8, 0xf5, 0x4b, 0x88, 0x86, 0xf8, 0xa8, - 0x8a, 0x42, 0x9f, 0x1e, 0xed, 0xd8, 0xa3, 0x30, 0xb3, 0x98, 0x6c, 0x12, 0x08, 0x95, 0xdb, 0x13, - 0xaf, 0x81, 0x32, 0x05, 0x87, 0xfb, 0x68, 0x85, 0x23, 0x91, 0x86, 0xc8, 0xed, 0x38, 0x60, 0x66, - 0x89, 0xd8, 0x6c, 0xe2, 0x6f, 0x5c, 0xbd, 0x4f, 0x6e, 0xb4, 0x38, 0xda, 0xbf, 0x72, 0x72, 0xe7, - 0x70, 0xff, 0xa5, 0xa3, 0xcb, 0x8f, 0xbe, 0xaf, 0x51, 0xfe, 0xaf, 0x5d, 0xbd, 0x38, 0x60, 0x66, - 0x89, 0xd8, 0x24, 0xe0, 0x6a, 0x2b, 0xf9, 0xce, 0x2b, 0xd0, 0xa4, 0x63, 0x85, 0xd8, 0xe6, 0x5b, - 0xcf, 0x00, 0x93, 0x30, 0xb3, 0x00, 0x6c, 0x96, 0x90, 0x59, 0x2e, 0xd9, 0x82, 0x85, 0x04, 0xd8, - 0xd6, 0xd3, 0x7c, 0x6b, 0x2f, 0xbe, 0x03, 0x6c, 0x36, 0x31, 0x2d, 0xdc, 0xd1, 0x8d, 0xf6, 0xaf, - 0x4b, 0x15, 0xa6, 0x7f, 0x6b, 0x2e, 0x28, 0x73, 0x55, 0x73, 0xf1, 0xe6, 0x5c, 0x29, 0x16, 0x89, - 0xc3, 0xe5, 0xf6, 0xd8, 0xee, 0x94, 0xcf, 0x84, 0x10, 0x33, 0xfc, 0x36, 0xfa, 0xf3, 0xf1, 0x5e, - 0xe9, 0xfa, 0x5b, 0x8e, 0x1b, 0x35, 0xee, 0xd2, 0x3f, 0x05, 0x7c, 0x56, 0xe4, 0xe2, 0xc9, 0x24, - 0x74, 0x62, 0x84, 0xe5, 0x12, 0xfa, 0x43, 0x75, 0xc2, 0x11, 0x3d, 0xfc, 0x41, 0xfa, 0x46, 0xa5, - 0x64, 0x18, 0x3d, 0x4c, 0xb1, 0x4c, 0xa0, 0xc4, 0xd5, 0x2b, 0x4a, 0xe1, 0xc0, 0x11, 0x1f, 0xa4, - 0xc0, 0x70, 0x00, 0x2c, 0x10, 0xb1, 0x5c, 0x42, 0x16, 0xb8, 0xb7, 0x5e, 0x85, 0x65, 0x07, 0xac, - 0x8f, 0xc6, 0x02, 0x0b, 0x42, 0x02, 0x16, 0x14, 0x8d, 0xa9, 0x8a, 0xd0, 0x01, 0xa6, 0xe5, 0xb4, - 0xc0, 0x98, 0xd0, 0x01, 0x0b, 0x8a, 0xc6, 0x54, 0x85, 0x6f, 0x07, 0xb4, 0x5a, 0xed, 0xe4, 0xe4, - 0xe4, 0xee, 0xee, 0x2e, 0x53, 0xef, 0xef, 0x19, 0xdb, 0xd8, 0xd8, 0x98, 0x9a, 0x9a, 0x32, 0xfb, - 0x6a, 0x03, 0x05, 0x3e, 0x63, 0x74, 0x74, 0x14, 0xde, 0xb2, 0xb2, 0xb2, 0xf8, 0x80, 0x2d, 0xc3, - 0xc4, 0xc7, 0xc7, 0xc3, 0xc5, 0xec, 0xec, 0xac, 0x59, 0xea, 0x7c, 0x3b, 0x70, 0x70, 0x70, 0x00, - 0xeb, 0xe4, 0xf9, 0x5e, 0xdd, 0xd8, 0x4d, 0x2c, 0x73, 0xc1, 0x2b, 0x81, 0xa5, 0xa5, 0xa5, 0xe5, - 0xe5, 0x65, 0x84, 0x7a, 0x76, 0x76, 0xf6, 0xfb, 0xfd, 0x40, 0x9d, 0xb0, 0xa8, 0x0c, 0x83, 0x3f, - 0x3d, 0x3d, 0x6d, 0x6c, 0x6c, 0x8c, 0x89, 0x89, 0x71, 0x70, 0x70, 0x88, 0x8c, 0x8c, 0x6c, 0x6e, - 0x6e, 0x3e, 0x3f, 0x3f, 0xa7, 0x80, 0xfa, 0xfa, 0xfa, 0xcf, 0xef, 0x47, 0x45, 0x45, 0x05, 0x0a, - 0x5c, 0x54, 0x54, 0x84, 0x59, 0x62, 0x62, 0xe2, 0xe0, 0xe0, 0x20, 0x30, 0x2a, 0x95, 0x6a, 0x7a, - 0x7a, 0xfa, 0xf2, 0xf2, 0x12, 0xf4, 0xc2, 0xc2, 0x02, 0x71, 0xb1, 0xb3, 0xb3, 0x43, 0xd5, 0xb9, - 0x08, 0x93, 0xfd, 0x9a, 0x9b, 0x9b, 0x7b, 0x54, 0xbf, 0xa5, 0xa5, 0x85, 0xea, 0x62, 0x6f, 0xf8, - 0xf9, 0xf9, 0x11, 0x98, 0x9b, 0x9b, 0x1b, 0x21, 0x22, 0x22, 0x22, 0x90, 0x03, 0x30, 0x48, 0xd5, - 0xde, 0xfe, 0xe1, 0xbb, 0x8b, 0x4c, 0x26, 0x53, 0x2a, 0x95, 0x36, 0xfa, 0x0f, 0x44, 0x25, 0x25, - 0x25, 0x00, 0xe4, 0xe4, 0xe4, 0x18, 0xbb, 0xb0, 0xb3, 0xb3, 0xbb, 0xba, 0xba, 0xa2, 0x2e, 0x9e, - 0x22, 0x44, 0x4f, 0x09, 0x28, 0x7f, 0x7f, 0x7f, 0x3f, 0x29, 0x29, 0xc9, 0xd3, 0x53, 0x77, 0x89, - 0x87, 0xfb, 0x4f, 0xef, 0x47, 0x6c, 0x6c, 0xec, 0xd8, 0xd8, 0x18, 0xc5, 0xe4, 0xe5, 0xe5, 0x41, - 0x9a, 0x96, 0x96, 0xb6, 0xb5, 0xb5, 0x05, 0xe6, 0xfc, 0xfc, 0xbc, 0xaf, 0xaf, 0xee, 0x2b, 0x62, - 0x53, 0x53, 0x13, 0xc1, 0xa0, 0x81, 0x65, 0x65, 0x65, 0xe0, 0x24, 0x24, 0x24, 0x1c, 0x1f, 0x1f, - 0x87, 0x87, 0x87, 0x4b, 0xa5, 0xd2, 0xde, 0xde, 0xde, 0xa3, 0xa3, 0x23, 0x00, 0x3a, 0x3a, 0x3a, - 0xc2, 0xc2, 0xc2, 0x24, 0x12, 0xdd, 0xbb, 0x8e, 0x8f, 0x8f, 0x0f, 0x71, 0x51, 0x58, 0x58, 0x48, - 0xed, 0x73, 0x10, 0xa6, 0x13, 0x20, 0xca, 0xfd, 0xfd, 0xfd, 0xb0, 0x8e, 0x7d, 0x66, 0x6c, 0x4b, - 0xad, 0x56, 0xdb, 0xda, 0xda, 0x42, 0xda, 0xde, 0xde, 0xfe, 0x9b, 0x7e, 0x60, 0xa9, 0x80, 0x13, - 0x1d, 0x1d, 0x4d, 0xf1, 0xe8, 0x43, 0x66, 0x66, 0x26, 0x98, 0x5e, 0x5e, 0xba, 0x1b, 0x75, 0x5f, - 0x5f, 0x1f, 0x15, 0x11, 0x22, 0x20, 0x20, 0x00, 0x7c, 0x9c, 0x16, 0x1f, 0xf0, 0xb9, 0xa7, 0x0c, - 0x5e, 0xf0, 0x56, 0x57, 0x57, 0x6f, 0x6e, 0x74, 0x1f, 0x6b, 0x1b, 0x1a, 0x1a, 0xf0, 0x34, 0x1c, - 0x17, 0x17, 0xff, 0xbd, 0x58, 0x22, 0xc9, 0xa1, 0xa1, 0xa1, 0xc0, 0xc0, 0xc0, 0xbd, 0xbd, 0xbd, - 0x94, 0x94, 0x94, 0xf2, 0xf2, 0x72, 0x43, 0xa4, 0xc5, 0x34, 0xdf, 0x04, 0xc8, 0xaa, 0xc5, 0x6e, - 0x33, 0xf6, 0x84, 0xa6, 0x13, 0x66, 0x4f, 0x4f, 0x4f, 0x54, 0x54, 0x14, 0x05, 0x20, 0xe2, 0x90, - 0x90, 0x10, 0x3a, 0x05, 0xd1, 0xd6, 0xd6, 0x76, 0x78, 0x78, 0x28, 0x97, 0xcb, 0xb1, 0x4d, 0x3b, - 0x3b, 0x3b, 0xeb, 0xea, 0xea, 0x0c, 0xa5, 0x1c, 0x2e, 0x0c, 0x61, 0x1f, 0xd2, 0xdc, 0x0d, 0xa2, - 0xd2, 0x91, 0x91, 0x11, 0x68, 0x22, 0xa6, 0xb5, 0xb5, 0x35, 0x1c, 0x17, 0xe3, 0xe3, 0xe3, 0xb5, - 0xb5, 0xb5, 0x58, 0x57, 0x04, 0x10, 0x1a, 0x1a, 0x0a, 0x69, 0x7a, 0x7a, 0x3a, 0xd9, 0xb5, 0x60, - 0x2e, 0x2e, 0x2e, 0x56, 0x57, 0x57, 0xb7, 0xb6, 0xb6, 0x52, 0x0b, 0xdd, 0xdd, 0xdd, 0xc0, 0xe0, - 0xe4, 0x81, 0xc8, 0xd9, 0xd9, 0x19, 0xe1, 0x0e, 0x0f, 0x0f, 0x53, 0x29, 0x88, 0xb8, 0xb8, 0x38, - 0x00, 0xaa, 0xaa, 0xaa, 0xb0, 0xd8, 0xd6, 0xd7, 0xd7, 0xbb, 0xba, 0xba, 0x4a, 0x4b, 0x4b, 0x91, - 0xb0, 0x21, 0xc6, 0x98, 0xe6, 0xbb, 0x07, 0x56, 0x56, 0x56, 0x60, 0x1d, 0x03, 0x8e, 0x15, 0x8a, - 0x87, 0x2f, 0xb8, 0x88, 0x98, 0x58, 0xc4, 0x8f, 0xb4, 0x58, 0xac, 0xfb, 0x9f, 0x17, 0x44, 0xa9, - 0xa9, 0xa9, 0x64, 0x07, 0x63, 0x5a, 0x50, 0x50, 0x40, 0x00, 0xd8, 0xdf, 0x3a, 0x65, 0x91, 0x28, - 0x3f, 0x3f, 0x1f, 0x9b, 0xd8, 0xdb, 0xdb, 0x9b, 0x4c, 0x33, 0x32, 0x32, 0x68, 0x4c, 0xc5, 0xc5, - 0xc5, 0x84, 0x49, 0x8f, 0x2c, 0x4c, 0x67, 0x66, 0x66, 0x28, 0xe0, 0x51, 0x82, 0x6f, 0x02, 0x50, - 0xc6, 0x59, 0xe1, 0xe8, 0xa8, 0xfb, 0xbc, 0x8c, 0x1c, 0x70, 0x68, 0x54, 0x56, 0x56, 0x6e, 0x6f, - 0x6f, 0x53, 0xa3, 0x13, 0x13, 0x13, 0x38, 0x9a, 0x48, 0x04, 0x00, 0xe0, 0x9c, 0xa9, 0xa9, 0xa9, - 0x21, 0x87, 0x0c, 0x30, 0xf8, 0x09, 0x27, 0xa2, 0xdc, 0xdc, 0x5c, 0x24, 0xe0, 0xe1, 0xe1, 0x81, - 0x29, 0x72, 0xce, 0xce, 0xce, 0xa6, 0x16, 0x50, 0xf5, 0xe4, 0xe4, 0x64, 0x02, 0x73, 0x72, 0x72, - 0x42, 0x21, 0x06, 0x06, 0x06, 0xa8, 0xf4, 0x29, 0xc2, 0xbc, 0x77, 0x62, 0x58, 0xd9, 0xdc, 0xdc, - 0x74, 0x71, 0x71, 0x21, 0x99, 0x10, 0x67, 0x86, 0x4f, 0xfc, 0x9c, 0xe1, 0x4a, 0x13, 0x14, 0x14, - 0x64, 0x58, 0x45, 0x43, 0x80, 0x49, 0x1a, 0xdb, 0x0c, 0xcb, 0xc6, 0xdf, 0xdf, 0x9f, 0xb4, 0xd4, - 0x24, 0xde, 0xbc, 0x04, 0x4c, 0x9a, 0xfb, 0xf8, 0x00, 0x5e, 0x57, 0x89, 0x8f, 0x1f, 0x16, 0x7f, - 0x8f, 0x42, 0x02, 0xfc, 0x6b, 0xf5, 0x3c, 0x48, 0xa1, 0x03, 0xcf, 0x53, 0x57, 0xfe, 0x56, 0x85, - 0x0e, 0xf0, 0xaf, 0xd5, 0xf3, 0x20, 0x85, 0x0e, 0x3c, 0x4f, 0x5d, 0xf9, 0x5b, 0x15, 0x3a, 0xc0, - 0xbf, 0x56, 0xcf, 0x83, 0xfc, 0x17, 0xab, 0x70, 0xa9, 0x05, 0xf0, 0x5c, 0xd1, 0x77, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXTextIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0b, 0x9d, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x59, 0x6c, 0x14, 0xc9, 0xf5, 0xf9, 0x02, 0xdb, 0xd8, 0x66, 0x8d, 0xd6, 0xf6, 0x2e, 0xc1, - 0x46, 0x59, 0x41, 0x62, 0x2c, 0xc2, 0x8d, 0x20, 0x80, 0x04, 0x24, 0x8a, 0x11, 0x88, 0x0f, 0x20, - 0xc1, 0x12, 0x20, 0x21, 0x81, 0x58, 0x89, 0x0f, 0x40, 0x80, 0x20, 0x04, 0x14, 0xe0, 0x0b, 0x3e, - 0x88, 0xb8, 0x43, 0x40, 0x09, 0x87, 0x10, 0xe7, 0x86, 0x2b, 0x8a, 0x84, 0x20, 0xe6, 0x10, 0x26, - 0x2c, 0x87, 0x82, 0x62, 0x90, 0x02, 0xd8, 0x60, 0x0e, 0x1f, 0xd8, 0x6b, 0x7b, 0x85, 0xef, 0x03, - 0x7b, 0x3c, 0x9d, 0x7a, 0x65, 0x57, 0x4d, 0xf7, 0x74, 0x4f, 0x4f, 0x77, 0xbb, 0x0f, 0x1f, 0x55, - 0x52, 0x4f, 0x55, 0xbd, 0x7a, 0xf7, 0xab, 0xea, 0xee, 0xe9, 0xae, 0xaa, 0x8e, 0x90, 0x48, 0x02, - 0x13, 0x29, 0xd2, 0x04, 0x2e, 0x45, 0x8d, 0x0e, 0x26, 0xb8, 0x93, 0xfd, 0x9a, 0x82, 0x06, 0x26, - 0x47, 0x43, 0x44, 0x54, 0x04, 0x4c, 0x3f, 0xff, 0x53, 0x25, 0x0a, 0xaa, 0x14, 0x9c, 0xca, 0xff, - 0x55, 0x47, 0x41, 0xb7, 0x7f, 0x53, 0x28, 0xe1, 0x21, 0x4f, 0x61, 0x55, 0xfa, 0x75, 0xee, 0xcf, - 0x14, 0x12, 0xc2, 0x12, 0x54, 0x7f, 0xdf, 0xa8, 0x20, 0x88, 0x40, 0x71, 0x0a, 0x48, 0x98, 0x4a, - 0x58, 0x09, 0xc1, 0xf4, 0x86, 0x08, 0x9e, 0x3f, 0x7f, 0xce, 0xe9, 0x34, 0x09, 0x16, 0x2e, 0x5c, - 0x48, 0x11, 0x22, 0x22, 0x22, 0x38, 0x22, 0x2b, 0x38, 0x6f, 0x83, 0xf3, 0x12, 0x14, 0x46, 0x63, - 0x3f, 0x62, 0x07, 0x1a, 0x99, 0xff, 0xfb, 0x32, 0x66, 0x6b, 0x20, 0x97, 0xf7, 0x13, 0x2c, 0xb3, - 0xbe, 0xa3, 0xd5, 0x8f, 0xb0, 0x5d, 0x21, 0x21, 0xc0, 0x06, 0x00, 0xfb, 0x50, 0xc2, 0xf0, 0x81, - 0x72, 0x10, 0x2d, 0x87, 0x24, 0xc0, 0xd6, 0xc6, 0xe2, 0xcf, 0x2a, 0x02, 0x17, 0xbd, 0xb4, 0x71, - 0xe3, 0x46, 0x95, 0x78, 0x04, 0xd4, 0xd7, 0xd7, 0x2b, 0xe0, 0x2a, 0x1b, 0xb0, 0xff, 0xb0, 0xbe, - 0xa4, 0xc0, 0xec, 0xaa, 0x38, 0x6f, 0x83, 0x69, 0x09, 0x5a, 0x6a, 0xea, 0xc1, 0x54, 0x36, 0xeb, - 0x21, 0x5b, 0x69, 0x33, 0x24, 0x00, 0xfb, 0x6f, 0x45, 0xae, 0x32, 0x1a, 0x08, 0x7b, 0xf2, 0x6d, - 0x71, 0x58, 0x99, 0x86, 0x04, 0x84, 0xe5, 0xa2, 0x83, 0xd0, 0x73, 0x05, 0xe0, 0x60, 0xf4, 0x35, - 0xf9, 0xe9, 0xf0, 0xd7, 0x31, 0x00, 0xfa, 0x68, 0x2f, 0xc2, 0xe1, 0xc9, 0x0e, 0x34, 0x1f, 0xcb, - 0xef, 0xdf, 0xbf, 0xa7, 0x39, 0xd6, 0xa3, 0xa3, 0x3b, 0x2f, 0xba, 0x03, 0x07, 0x76, 0x9e, 0xaf, - 0x18, 0x2e, 0xe6, 0xaa, 0x84, 0x67, 0xbd, 0xe0, 0xd4, 0xda, 0xda, 0x8a, 0x97, 0x3b, 0x7a, 0x60, - 0xdb, 0xe0, 0xc1, 0x83, 0x15, 0x75, 0x6c, 0xc3, 0xc4, 0x72, 0x56, 0x96, 0xd7, 0x29, 0x02, 0xf9, - 0xe9, 0xfd, 0x31, 0xe8, 0xfd, 0x16, 0xf4, 0xdc, 0x91, 0x4c, 0x7a, 0x8c, 0xa1, 0xa4, 0xba, 0x8b, - 0x64, 0x54, 0x78, 0xb6, 0xd4, 0x4a, 0xec, 0x9e, 0xef, 0xfb, 0xa5, 0xef, 0xd5, 0x77, 0x98, 0x5a, - 0x04, 0xac, 0xbf, 0x86, 0xca, 0x0b, 0x8f, 0x54, 0xf1, 0xbb, 0x07, 0x39, 0x0e, 0xbb, 0xa3, 0x90, - 0xc3, 0xb4, 0xca, 0x96, 0x62, 0xc0, 0xac, 0x63, 0xb9, 0x96, 0xe2, 0x0c, 0x66, 0x49, 0x00, 0x73, - 0x13, 0xcb, 0x19, 0x33, 0xad, 0xdc, 0x92, 0x00, 0x2d, 0x46, 0xa1, 0x60, 0x3d, 0x5b, 0xc0, 0x9b, - 0xbf, 0x56, 0x43, 0x7b, 0x5d, 0x47, 0x28, 0xe5, 0x29, 0xdc, 0xb2, 0x05, 0x3f, 0x5f, 0x93, 0x0a, - 0x25, 0x97, 0x6b, 0xa0, 0xb5, 0xda, 0xa7, 0x2b, 0x40, 0x9c, 0x8b, 0x74, 0xdd, 0x83, 0x8d, 0x96, - 0x63, 0x10, 0x96, 0x73, 0x17, 0x82, 0xa6, 0x00, 0xcd, 0x6b, 0xab, 0x0e, 0x47, 0x3d, 0x7c, 0xd5, - 0xc9, 0x8e, 0x21, 0x63, 0x4e, 0xce, 0x2d, 0xf0, 0xe8, 0xd1, 0x23, 0x38, 0x78, 0xf0, 0x20, 0x24, - 0x25, 0x25, 0xc1, 0x90, 0x21, 0x43, 0x60, 0xdc, 0xb8, 0x71, 0xb0, 0x64, 0xc9, 0x12, 0x88, 0x89, - 0x89, 0x81, 0x93, 0x27, 0x4f, 0xc2, 0xd1, 0xa3, 0x47, 0xa9, 0x68, 0x86, 0xaf, 0xd2, 0x43, 0xeb, - 0x04, 0x45, 0x90, 0x38, 0x18, 0xcb, 0x0b, 0x16, 0x2c, 0xa0, 0xc7, 0xce, 0x9d, 0x3b, 0x29, 0x3c, - 0x27, 0x27, 0x47, 0x4a, 0x4b, 0x4b, 0x53, 0xe0, 0xf0, 0x4a, 0x50, 0x41, 0x65, 0x01, 0xd3, 0x00, - 0x35, 0x9a, 0x37, 0x6f, 0x1e, 0xb5, 0x82, 0x59, 0x35, 0x74, 0xe8, 0x50, 0xc8, 0xcc, 0xcc, 0x84, - 0xc2, 0xc2, 0x42, 0x8a, 0x26, 0xd7, 0x1a, 0xcb, 0x89, 0x89, 0x89, 0xaa, 0xbf, 0x2c, 0x62, 0x1c, - 0x30, 0x8f, 0x86, 0xcc, 0x35, 0xbb, 0x69, 0x48, 0x6c, 0x0b, 0x0d, 0x8e, 0xc7, 0xc0, 0x82, 0x4e, - 0xa6, 0x48, 0x1c, 0xf7, 0x90, 0x29, 0x6d, 0x2c, 0x20, 0x0b, 0x03, 0x2c, 0x38, 0xcd, 0x56, 0x92, - 0x90, 0x27, 0x3a, 0x3d, 0x29, 0x46, 0xee, 0xe6, 0x18, 0x3d, 0x3e, 0x25, 0x9d, 0xf1, 0xdd, 0x37, - 0xac, 0xca, 0xff, 0xf2, 0xe2, 0xb3, 0xa8, 0x29, 0x7f, 0x1b, 0xce, 0xe1, 0x56, 0x0b, 0xb6, 0x0c, - 0xe2, 0xd7, 0x7f, 0xa9, 0x86, 0xd2, 0x7f, 0xd4, 0x50, 0x1d, 0xb2, 0x36, 0x7d, 0x05, 0x5f, 0x67, - 0x27, 0xa9, 0xf4, 0xd1, 0x33, 0xda, 0xc8, 0xdd, 0xa7, 0x8a, 0x61, 0x17, 0xc0, 0x52, 0x04, 0x42, - 0x31, 0xd3, 0x83, 0x8f, 0xde, 0xf6, 0x35, 0x6d, 0xfe, 0xdf, 0xee, 0x0a, 0x9a, 0xc7, 0xa6, 0xc4, - 0xc0, 0x88, 0x6f, 0xbf, 0xd4, 0x23, 0x31, 0xd4, 0xe6, 0x9a, 0x01, 0x69, 0xb3, 0x12, 0x15, 0x06, - 0x44, 0xc7, 0x47, 0x02, 0x83, 0x19, 0xd2, 0x34, 0x04, 0x92, 0x38, 0x0b, 0x85, 0x70, 0x4c, 0x58, - 0x70, 0xeb, 0x8f, 0xfa, 0x77, 0xfb, 0x61, 0x19, 0x74, 0x21, 0xb8, 0x1e, 0x81, 0xf8, 0x9f, 0x0c, - 0xa0, 0xa2, 0x7d, 0x4d, 0x1d, 0xfc, 0x19, 0x7c, 0x7d, 0x41, 0xab, 0x51, 0x7d, 0x55, 0x78, 0xb6, - 0x9c, 0x85, 0x54, 0x5c, 0x5d, 0x04, 0xb8, 0x1e, 0x01, 0xbb, 0x6d, 0x13, 0x06, 0xd8, 0xed, 0x51, - 0xb3, 0xfc, 0x0c, 0x47, 0x20, 0x2f, 0x2f, 0x8f, 0xfe, 0xd3, 0x33, 0x2b, 0xc0, 0x0c, 0xbe, 0xfc, - 0x3f, 0x98, 0x61, 0xba, 0xa0, 0x3f, 0x81, 0x9a, 0xd5, 0x5b, 0xb7, 0x6e, 0x49, 0x33, 0x67, 0xce, - 0xa4, 0x8f, 0x8e, 0xf7, 0xed, 0xdb, 0x27, 0xe1, 0x71, 0xff, 0xfe, 0x7d, 0x05, 0xee, 0xb3, 0x67, - 0xcf, 0xf8, 0xe3, 0x66, 0x22, 0x5c, 0x3a, 0x7c, 0xf8, 0x30, 0x6f, 0x9f, 0x32, 0x65, 0x0a, 0x6f, - 0x43, 0x20, 0xb6, 0xe3, 0x31, 0x71, 0xe2, 0x44, 0x8a, 0x53, 0x52, 0x52, 0x22, 0xed, 0xde, 0xbd, - 0x9b, 0xc2, 0x36, 0x6d, 0xda, 0x44, 0xf9, 0x9f, 0x39, 0x73, 0x86, 0xd3, 0xeb, 0x15, 0x02, 0xff, - 0x7f, 0xf5, 0xb0, 0x48, 0xdb, 0x86, 0x0d, 0x1b, 0xa8, 0x00, 0x2d, 0x34, 0xa6, 0xd0, 0xe9, 0xd3, - 0xa7, 0x25, 0x76, 0x44, 0x46, 0x46, 0xaa, 0xf0, 0x11, 0x2f, 0x2a, 0x2a, 0x4a, 0x05, 0x47, 0x9e, - 0x75, 0x75, 0x75, 0x14, 0x8e, 0x8e, 0x30, 0x93, 0x0c, 0x1b, 0xb0, 0x63, 0xc7, 0x0e, 0x2a, 0xe0, - 0xc3, 0x87, 0x0f, 0x94, 0xff, 0x9e, 0x3d, 0x7b, 0xa4, 0x15, 0x2b, 0x56, 0xd0, 0xf2, 0xf4, 0xe9, - 0xd3, 0x69, 0xdb, 0xcb, 0x97, 0x2f, 0xb9, 0xec, 0xf3, 0xe7, 0xcf, 0x73, 0x0f, 0x23, 0x70, 0xd9, - 0xb2, 0x65, 0x5c, 0x71, 0x34, 0x64, 0xd8, 0xb0, 0x61, 0x1c, 0x17, 0x0b, 0x3e, 0x9f, 0x8f, 0xb6, - 0x93, 0x37, 0x90, 0x14, 0x7e, 0xfd, 0xfa, 0x75, 0x05, 0xbd, 0x02, 0x59, 0x56, 0x31, 0x7d, 0x1d, - 0x78, 0xf3, 0xe6, 0x0d, 0x91, 0x0f, 0x30, 0x72, 0xe4, 0x48, 0x9a, 0xcb, 0x7f, 0x08, 0x5f, 0xb8, - 0x7d, 0xfb, 0x36, 0x90, 0x87, 0x16, 0x30, 0x66, 0xcc, 0x18, 0x79, 0x93, 0xe1, 0x72, 0x4d, 0x4d, - 0x0d, 0x10, 0x27, 0xc1, 0xf8, 0xf1, 0xe3, 0x0d, 0xd1, 0x98, 0x36, 0xc0, 0x10, 0x57, 0x17, 0x91, - 0x0c, 0x9f, 0x85, 0x5c, 0xd4, 0xc9, 0x94, 0x28, 0x61, 0x80, 0x29, 0x77, 0x39, 0x80, 0x2c, 0xc6, - 0x80, 0x03, 0x4e, 0x35, 0xc5, 0x52, 0x8c, 0x01, 0x53, 0xee, 0x72, 0x00, 0x59, 0x44, 0xc0, 0x01, - 0xa7, 0x9a, 0x62, 0x29, 0x22, 0x60, 0xca, 0x5d, 0x0e, 0x20, 0x9b, 0x7e, 0xb0, 0xe5, 0x6b, 0xf0, - 0x43, 0xde, 0x6f, 0x8b, 0x0c, 0xab, 0x22, 0x7f, 0x6c, 0xf8, 0xfc, 0x8f, 0xe5, 0xd0, 0xf8, 0xae, - 0x73, 0xba, 0x9d, 0x6a, 0x46, 0xa9, 0x61, 0x8e, 0x4a, 0x44, 0xd3, 0x06, 0x28, 0xc9, 0xcd, 0xd5, - 0xda, 0xea, 0x7c, 0xd0, 0xfa, 0x63, 0xbb, 0x39, 0xa2, 0x30, 0xd8, 0xa6, 0x0d, 0x88, 0x4e, 0x8c, - 0xa4, 0x33, 0x1d, 0xe5, 0x7c, 0xe5, 0x0f, 0x6e, 0xe5, 0x1e, 0x97, 0xe3, 0x38, 0x55, 0x36, 0x6d, - 0x80, 0x15, 0x45, 0x8a, 0xff, 0x5e, 0x03, 0x45, 0xc7, 0xab, 0x15, 0xa4, 0x76, 0x19, 0xdd, 0xeb, - 0xcf, 0x42, 0xae, 0x44, 0x20, 0xe5, 0x97, 0x09, 0x10, 0x9b, 0x1a, 0x0d, 0x05, 0xfb, 0x2b, 0xc1, - 0xd7, 0xe2, 0xa7, 0x91, 0x60, 0x8f, 0xdb, 0x15, 0x61, 0xb1, 0x50, 0x71, 0xc5, 0x80, 0xf8, 0xf4, - 0x18, 0xc0, 0xa3, 0xf0, 0xcf, 0x55, 0x00, 0x2d, 0x9d, 0x5a, 0xda, 0xf1, 0x68, 0x1d, 0x39, 0xf5, - 0xfa, 0x2e, 0x24, 0x0c, 0xb0, 0xd0, 0x6d, 0x6d, 0x25, 0x11, 0x11, 0x30, 0xe3, 0xce, 0xc8, 0x18, - 0x8d, 0x69, 0xb2, 0x66, 0x18, 0x68, 0xe0, 0xba, 0x1a, 0x81, 0x2f, 0x7e, 0x11, 0xc7, 0x55, 0xc8, - 0x5b, 0x50, 0x04, 0x3f, 0xdc, 0xaa, 0x87, 0xca, 0x7b, 0x0d, 0x1c, 0x66, 0xa5, 0xe0, 0xaa, 0x01, - 0x59, 0x9b, 0xbf, 0xe2, 0x3a, 0xfa, 0x9a, 0xfd, 0xf0, 0xe2, 0x4f, 0x3f, 0x00, 0x7b, 0xed, 0xca, - 0x1b, 0x4c, 0x16, 0x5c, 0x35, 0x00, 0xbb, 0xd0, 0xaf, 0xae, 0x8f, 0x84, 0xc1, 0xa3, 0xe2, 0xe8, - 0x1a, 0x27, 0xd4, 0xb5, 0xbb, 0xdd, 0x4a, 0x3c, 0x56, 0x31, 0x19, 0x71, 0xdb, 0xd1, 0x5d, 0xed, - 0x42, 0xb6, 0x6b, 0x8f, 0x5d, 0xd0, 0x09, 0xa6, 0x6e, 0xf2, 0x14, 0x06, 0xb8, 0xe9, 0x6d, 0x2d, - 0x59, 0x22, 0x02, 0x5a, 0x5e, 0x71, 0x13, 0x66, 0x38, 0x02, 0x71, 0x71, 0x71, 0x70, 0xf6, 0xec, - 0x59, 0xc7, 0x74, 0x9b, 0x3b, 0x77, 0x2e, 0x64, 0x65, 0x65, 0x99, 0xe7, 0x2f, 0x7b, 0xe1, 0xa7, - 0x5b, 0x24, 0x9c, 0xe9, 0x0c, 0x64, 0x5d, 0xa4, 0x6e, 0x34, 0x22, 0x7f, 0x3c, 0xcc, 0xa6, 0xb0, - 0x11, 0xe8, 0xe8, 0xe8, 0x80, 0x03, 0x07, 0x0e, 0x50, 0xcf, 0x14, 0x15, 0x15, 0xc1, 0xfe, 0xfd, - 0xfb, 0xe1, 0xd0, 0xa1, 0x43, 0xb4, 0x2e, 0xff, 0x21, 0x2f, 0xc2, 0xf9, 0x42, 0xae, 0xe4, 0xe4, - 0x64, 0x40, 0x3a, 0x96, 0xf0, 0x0d, 0x3c, 0x1e, 0x63, 0xc7, 0x8e, 0x85, 0x63, 0xc7, 0x8e, 0x71, - 0x3c, 0xd6, 0x7e, 0xea, 0xd4, 0x29, 0x56, 0xa4, 0xfc, 0x51, 0x46, 0x65, 0x65, 0x25, 0x87, 0xe9, - 0x16, 0xc2, 0x59, 0x9c, 0x9b, 0x9b, 0x4b, 0x3d, 0x43, 0x98, 0x28, 0xf2, 0xa7, 0x4f, 0x9f, 0x72, - 0x52, 0xb2, 0xca, 0x8c, 0xb6, 0xe1, 0xbb, 0xe1, 0xcb, 0x97, 0x2f, 0xab, 0x5e, 0x66, 0x93, 0x05, - 0xa4, 0xb4, 0x7d, 0xed, 0xda, 0xb5, 0x52, 0x7e, 0x7e, 0x3e, 0x2d, 0x2f, 0x5a, 0xb4, 0x88, 0xd3, - 0x07, 0xf3, 0xc6, 0xfa, 0xfc, 0xf9, 0xf3, 0x79, 0xbb, 0x5e, 0xc1, 0x70, 0xcc, 0x90, 0x29, 0x4e, - 0x64, 0x0f, 0x4e, 0xe4, 0xbd, 0x2e, 0x55, 0x08, 0x27, 0xb7, 0xb3, 0xb7, 0xf4, 0x24, 0x42, 0x14, - 0x46, 0xde, 0x19, 0x73, 0x74, 0x9c, 0x9e, 0xc0, 0x14, 0x25, 0xb3, 0xea, 0x39, 0x9c, 0x15, 0x58, - 0x1b, 0xab, 0x1b, 0xcd, 0x0d, 0xdf, 0xcc, 0x61, 0x17, 0x20, 0x06, 0xc0, 0xb5, 0x6b, 0xd7, 0x88, - 0xac, 0x40, 0x7a, 0xf8, 0xf0, 0x21, 0x90, 0x37, 0xf5, 0x30, 0x67, 0xce, 0x1c, 0xc0, 0x81, 0xce, - 0x12, 0x2e, 0x01, 0x38, 0x71, 0xe2, 0x04, 0x9d, 0x34, 0x8f, 0x30, 0xec, 0x52, 0x6c, 0x3d, 0xe0, - 0xab, 0x57, 0xaf, 0xe8, 0x44, 0x7b, 0x86, 0x8b, 0x39, 0xf2, 0xc7, 0x44, 0x14, 0xa7, 0xb9, 0xe1, - 0x1f, 0xa3, 0x96, 0x22, 0x6f, 0x32, 0x83, 0x9f, 0xa2, 0x17, 0x14, 0x14, 0x48, 0x93, 0x27, 0x4f, - 0xe6, 0xa4, 0xd8, 0x16, 0x1b, 0x1b, 0xcb, 0xeb, 0x0d, 0x0d, 0x0d, 0xb4, 0xbd, 0xad, 0xad, 0x8d, - 0xc2, 0x88, 0xf2, 0xd4, 0xfb, 0xcb, 0x97, 0x2f, 0x97, 0xd6, 0xac, 0x59, 0x43, 0xcb, 0xef, 0xde, - 0xbd, 0xe3, 0xf8, 0x58, 0x20, 0x06, 0x50, 0x38, 0x4e, 0x39, 0x40, 0x7a, 0x9c, 0x9a, 0x70, 0xef, - 0xde, 0x3d, 0x05, 0x8e, 0x56, 0xc5, 0x70, 0x17, 0xca, 0xc8, 0xc8, 0xa0, 0x02, 0x50, 0x59, 0x76, - 0xf8, 0xfd, 0x7e, 0xca, 0xf3, 0xca, 0x95, 0x2b, 0x1c, 0xc6, 0xda, 0x30, 0x67, 0x89, 0xc1, 0xa6, - 0x4e, 0x9d, 0x2a, 0x91, 0x65, 0x0f, 0x1c, 0xf7, 0xc2, 0x85, 0x0b, 0x0c, 0x45, 0xc2, 0x6e, 0xc5, - 0xf0, 0x58, 0x8e, 0xb3, 0x64, 0xc2, 0xa5, 0x80, 0x94, 0x70, 0x98, 0xa4, 0x1d, 0xbd, 0xf3, 0xe0, - 0xc1, 0x03, 0xa9, 0xa9, 0xa9, 0x49, 0x13, 0xbb, 0xb8, 0xb8, 0x58, 0xc2, 0x41, 0x8f, 0x33, 0x4f, - 0xac, 0xa6, 0xc7, 0x8f, 0x1f, 0x4b, 0xe5, 0xe5, 0xe5, 0x86, 0xc9, 0x0d, 0x8f, 0x01, 0xe2, 0x95, - 0x1e, 0x99, 0xc2, 0x5e, 0x07, 0x7a, 0xa4, 0xd6, 0x32, 0xa5, 0x84, 0x01, 0x32, 0x67, 0x78, 0x52, - 0x14, 0x11, 0xf0, 0xc4, 0xed, 0x32, 0xa1, 0x22, 0x02, 0x32, 0x67, 0x78, 0x52, 0xec, 0xf5, 0xd7, - 0x01, 0x4f, 0xbc, 0x66, 0xa3, 0xd0, 0x5e, 0x3f, 0x04, 0x6c, 0xf4, 0x85, 0x27, 0xac, 0x44, 0x00, - 0x3c, 0x71, 0x7b, 0x40, 0xa8, 0x08, 0x40, 0xc0, 0x17, 0x9e, 0x94, 0x44, 0x00, 0x3c, 0x71, 0x7b, - 0x40, 0xa8, 0x08, 0x40, 0xc0, 0x17, 0x9e, 0x94, 0x44, 0x00, 0x3c, 0x71, 0x7b, 0x40, 0xa8, 0x2b, - 0x13, 0x85, 0x70, 0x8a, 0xe3, 0xfd, 0xdf, 0xbd, 0x0d, 0x48, 0xb5, 0xb1, 0x34, 0x60, 0x48, 0x14, - 0xcc, 0xb8, 0xf0, 0x8d, 0x8d, 0x1c, 0xdd, 0x65, 0xe5, 0x4a, 0x00, 0xd0, 0x24, 0xf2, 0x84, 0xca, - 0x19, 0xcb, 0x3a, 0x67, 0xae, 0x69, 0xf2, 0xfe, 0xcf, 0xda, 0x12, 0xa8, 0x2f, 0x54, 0xae, 0x90, - 0xb5, 0x6b, 0x0d, 0xbf, 0xa6, 0x40, 0x0b, 0x40, 0xd7, 0x02, 0x10, 0x6e, 0x2a, 0x84, 0x44, 0x5e, - 0x83, 0x48, 0x7e, 0x75, 0x90, 0x22, 0xc9, 0x76, 0xb1, 0x7a, 0x2f, 0xb1, 0x23, 0x1c, 0x98, 0xb9, - 0x63, 0xc1, 0x8f, 0x96, 0x49, 0x5c, 0x09, 0x00, 0xce, 0xf1, 0x9d, 0x4d, 0xe6, 0xa6, 0xe8, 0x25, - 0xf9, 0x86, 0x0e, 0x72, 0xbc, 0xcc, 0x0d, 0x69, 0x9a, 0x9b, 0x3b, 0xc8, 0x71, 0x58, 0xd9, 0x4f, - 0xf6, 0x10, 0xf4, 0xb5, 0x06, 0x86, 0x04, 0x06, 0x35, 0x38, 0xf9, 0xc9, 0xf3, 0xfd, 0xb6, 0x5a, - 0x75, 0xc3, 0x80, 0x2f, 0xa2, 0x82, 0x51, 0x5d, 0xa9, 0xbb, 0x12, 0x00, 0x57, 0x2c, 0x21, 0x42, - 0x4a, 0xff, 0x59, 0xab, 0x9a, 0xd7, 0x1c, 0x2c, 0xbb, 0xb9, 0xac, 0x0d, 0xfe, 0x9d, 0xa3, 0xbe, - 0x1e, 0xb9, 0x3d, 0xd1, 0x9b, 0xe9, 0x25, 0xee, 0x82, 0x98, 0x27, 0x3c, 0xca, 0xfb, 0xd4, 0x08, - 0x18, 0x9e, 0x93, 0x0c, 0x78, 0xb0, 0x84, 0x77, 0x5e, 0xed, 0xf5, 0xca, 0xd3, 0x4d, 0x4f, 0xbb, - 0x08, 0x8b, 0x11, 0xc0, 0xa2, 0xe5, 0x51, 0x2e, 0x02, 0xe0, 0x91, 0xe3, 0x99, 0x58, 0x11, 0x00, - 0xe6, 0x09, 0x8f, 0x72, 0x11, 0x00, 0x8f, 0x1c, 0xcf, 0xc4, 0xf6, 0xbb, 0x00, 0x38, 0xf6, 0x8f, - 0x9c, 0x79, 0xd4, 0x64, 0xde, 0xa7, 0x03, 0xc0, 0x36, 0xef, 0x92, 0xfb, 0xa4, 0xa9, 0xa4, 0x0d, - 0x3e, 0xfd, 0xb7, 0x59, 0x0e, 0xf2, 0xb4, 0xdc, 0xa7, 0x6e, 0x43, 0x83, 0x3d, 0x99, 0x3a, 0x23, - 0x01, 0xea, 0x5e, 0x75, 0x2d, 0x13, 0x94, 0x35, 0xe6, 0xff, 0xa1, 0x4c, 0x56, 0xeb, 0x2c, 0x4e, - 0x3e, 0x94, 0x01, 0x49, 0x99, 0xb1, 0x2a, 0xb8, 0xd3, 0x80, 0x3e, 0x3d, 0x02, 0x32, 0x16, 0x27, - 0xc3, 0xc4, 0x7d, 0xe9, 0x10, 0xfb, 0x65, 0x8c, 0xd3, 0x7e, 0xb4, 0xcc, 0xbf, 0x7f, 0xce, 0x8a, - 0x20, 0xcf, 0xfc, 0xe8, 0xf3, 0x20, 0x92, 0x47, 0xc5, 0x46, 0x40, 0x14, 0xd9, 0xa2, 0xd2, 0xab, - 0xd4, 0x3f, 0x03, 0xe0, 0x95, 0xb7, 0x35, 0xe4, 0x7a, 0x17, 0x7a, 0x0d, 0x65, 0xfa, 0x23, 0x48, - 0x04, 0xc0, 0xe3, 0xa8, 0x8b, 0x00, 0x88, 0x00, 0x78, 0xec, 0x01, 0x8f, 0xc5, 0x8b, 0x11, 0x20, - 0x02, 0xe0, 0xb1, 0x07, 0x3c, 0x16, 0xef, 0xc8, 0x08, 0x68, 0x6e, 0x6e, 0x86, 0xda, 0xda, 0x5a, - 0x8f, 0x4d, 0xeb, 0x9e, 0xf8, 0x8a, 0x8a, 0x0a, 0xe7, 0x66, 0x72, 0xc8, 0x54, 0xb3, 0x3d, 0x00, - 0xdb, 0xb6, 0x6d, 0x83, 0x41, 0x83, 0x06, 0x01, 0xae, 0xf8, 0x5c, 0xba, 0x74, 0xa9, 0x4c, 0x54, - 0xef, 0x28, 0xb6, 0xb4, 0xb4, 0x00, 0xd9, 0xb9, 0x18, 0xf0, 0xbb, 0x3d, 0x64, 0x67, 0x63, 0x78, - 0xfd, 0x5a, 0xfb, 0x13, 0x6c, 0x76, 0x59, 0x63, 0xfb, 0xb3, 0x20, 0xf2, 0x79, 0x43, 0xae, 0x1b, - 0x1a, 0x63, 0x35, 0x7d, 0xfc, 0xf8, 0x11, 0xc8, 0x92, 0x46, 0xea, 0x80, 0x84, 0x84, 0x04, 0x18, - 0x35, 0x6a, 0x14, 0x5d, 0x10, 0x1d, 0x1f, 0x1f, 0x1f, 0x92, 0xe5, 0xdb, 0xb7, 0x6f, 0x81, 0x2c, - 0xc2, 0xa3, 0xed, 0xe8, 0x44, 0xfc, 0xf0, 0x11, 0xe6, 0x98, 0xca, 0xca, 0xca, 0xe0, 0xd3, 0xa7, - 0x4f, 0xb4, 0x8c, 0x3c, 0x46, 0x8c, 0x18, 0x41, 0xcb, 0xc1, 0x3f, 0xed, 0xed, 0xed, 0x40, 0x56, - 0x20, 0x72, 0x70, 0x77, 0x6c, 0xe0, 0x4c, 0xf4, 0x0a, 0x86, 0x97, 0xf4, 0xe9, 0x20, 0xde, 0xb8, - 0x71, 0x03, 0x27, 0xf4, 0x18, 0x3e, 0x9e, 0x3c, 0x79, 0xa2, 0xc9, 0x8d, 0xac, 0xab, 0xe6, 0x4b, - 0x8d, 0xf5, 0xf8, 0xcd, 0x9e, 0x3d, 0x5b, 0x22, 0x8e, 0xe2, 0x3c, 0xf0, 0x9b, 0x96, 0x64, 0xa1, - 0xac, 0x4a, 0x3e, 0x2e, 0x63, 0xfe, 0xfc, 0xf9, 0xb3, 0xb4, 0x7a, 0xf5, 0x6a, 0x55, 0x1b, 0xf9, - 0x80, 0xa6, 0x44, 0x9c, 0xcb, 0x79, 0xc8, 0x37, 0x1f, 0xd7, 0x93, 0x8d, 0x6d, 0x64, 0x75, 0x3c, - 0xa7, 0xeb, 0x6e, 0xc1, 0x96, 0x47, 0x11, 0xd8, 0x63, 0x70, 0xeb, 0x78, 0xfc, 0x8a, 0x34, 0xae, - 0x26, 0x26, 0xbb, 0xae, 0x13, 0x3d, 0x01, 0x46, 0x8f, 0x1e, 0x0d, 0x2b, 0x57, 0xae, 0xa4, 0x65, - 0xfc, 0xc1, 0xde, 0x48, 0x76, 0x53, 0xa7, 0xab, 0x8b, 0x39, 0xb0, 0xab, 0x80, 0xb8, 0x2f, 0x5e, - 0xbc, 0xa0, 0x35, 0x5c, 0x79, 0x7c, 0xf3, 0xe6, 0xcd, 0x60, 0x14, 0x58, 0xb7, 0x6e, 0x1d, 0x90, - 0x1d, 0xdb, 0x29, 0x1c, 0x57, 0x17, 0xe3, 0x16, 0xda, 0xe4, 0x03, 0xa2, 0x0a, 0x3c, 0xfc, 0x48, - 0xd9, 0xaa, 0x55, 0xab, 0xe8, 0xf9, 0x1b, 0x3f, 0xef, 0x75, 0xe7, 0xce, 0x1d, 0xd8, 0xbc, 0x79, - 0x33, 0xd5, 0x0f, 0x4f, 0x29, 0x17, 0x2f, 0x5e, 0x84, 0xc5, 0x8b, 0x17, 0x2b, 0x68, 0xb0, 0x42, - 0x96, 0x97, 0x02, 0x59, 0xa6, 0x0a, 0x78, 0xee, 0xc7, 0xd3, 0x28, 0x4b, 0x64, 0xa7, 0x77, 0x7a, - 0x3a, 0x62, 0xf5, 0x94, 0x94, 0x14, 0xba, 0x32, 0x1a, 0x73, 0x5b, 0x52, 0x77, 0x23, 0x18, 0x4c, - 0xcf, 0x76, 0x90, 0x27, 0xca, 0x69, 0xae, 0x4f, 0x0f, 0xc6, 0xc7, 0xfa, 0xdd, 0xbb, 0x77, 0x55, - 0x3d, 0x14, 0xe9, 0xc3, 0x1d, 0xf2, 0xc5, 0xc6, 0xc1, 0x7c, 0xb7, 0x6f, 0xdf, 0xae, 0xa0, 0x27, - 0xc1, 0x0b, 0x46, 0xd1, 0xac, 0xb3, 0x1d, 0xea, 0x99, 0x6c, 0xb3, 0x3b, 0xd5, 0x6b, 0x32, 0xd5, - 0x01, 0x9a, 0x5a, 0xec, 0xac, 0xc3, 0x87, 0x37, 0xe1, 0xb7, 0x01, 0x98, 0xf2, 0xb3, 0x66, 0xcd, - 0xe2, 0x70, 0xbd, 0x42, 0x63, 0x63, 0xa3, 0xc4, 0xb6, 0xf2, 0x47, 0x5a, 0xf6, 0x65, 0x3c, 0x3d, - 0x9a, 0x50, 0x6d, 0xb8, 0x20, 0x9b, 0x7c, 0xb2, 0x8f, 0xeb, 0x30, 0x6d, 0xda, 0x34, 0x5e, 0x26, - 0x17, 0x56, 0x89, 0x6c, 0x6c, 0x1f, 0x8a, 0x94, 0xc2, 0x51, 0x17, 0xa6, 0x3f, 0xe6, 0x46, 0x96, - 0xbc, 0xeb, 0x32, 0x0c, 0xd3, 0x68, 0x7b, 0x00, 0xce, 0x9d, 0x3b, 0xa7, 0x30, 0x00, 0x1d, 0x8b, - 0x7b, 0x03, 0xe0, 0x27, 0x06, 0xe5, 0x86, 0x61, 0x59, 0xfe, 0x29, 0x02, 0x72, 0xb7, 0x21, 0x91, - 0x8b, 0x2d, 0xc7, 0xc1, 0xf5, 0xff, 0x13, 0x26, 0x4c, 0x90, 0xb6, 0x6e, 0xdd, 0x2a, 0x6d, 0xd9, - 0xb2, 0x45, 0xc2, 0x73, 0x34, 0xdb, 0x9a, 0x02, 0x69, 0xb1, 0x9d, 0x5c, 0x58, 0xb9, 0x79, 0x47, - 0x8e, 0x1c, 0x91, 0xd2, 0xd3, 0xd3, 0x15, 0xf4, 0x6c, 0x84, 0xe0, 0x67, 0x0a, 0xc8, 0x06, 0x0a, - 0xbc, 0x8d, 0x5c, 0x84, 0xa5, 0xec, 0xec, 0x6c, 0xa9, 0xba, 0xba, 0x9a, 0xd3, 0xcb, 0x0b, 0xe4, - 0xab, 0x03, 0x1c, 0x17, 0x65, 0xa5, 0xa6, 0xa6, 0x4a, 0x93, 0x26, 0x4d, 0x52, 0xc8, 0x47, 0x38, - 0x7e, 0x3a, 0xb1, 0xbb, 0xc9, 0xf6, 0x00, 0xa0, 0x42, 0x55, 0x55, 0x55, 0xb4, 0x17, 0xca, 0x8d, - 0x46, 0x85, 0xb1, 0x8e, 0x86, 0xe3, 0xde, 0x1e, 0xa1, 0x12, 0xd9, 0x6c, 0x44, 0x22, 0xd7, 0x0d, - 0x09, 0x9d, 0x84, 0x34, 0xf2, 0x03, 0xe9, 0xc9, 0xf5, 0x41, 0xba, 0x7a, 0xf5, 0xaa, 0x8a, 0x7c, - 0xd7, 0xae, 0x5d, 0x12, 0xb9, 0xf5, 0xe5, 0xf8, 0x48, 0xbf, 0x77, 0xef, 0x5e, 0x8a, 0x77, 0xfc, - 0xf8, 0x71, 0xba, 0x59, 0x04, 0xe3, 0x85, 0x9d, 0x02, 0xbf, 0xec, 0xa1, 0xb7, 0xad, 0xc0, 0xa5, - 0x4b, 0x97, 0x24, 0xad, 0x3d, 0x1a, 0x10, 0xb6, 0x7e, 0xfd, 0x7a, 0xa9, 0xb4, 0xb4, 0x54, 0xa5, - 0x83, 0x15, 0x80, 0x2d, 0x17, 0x61, 0x62, 0x98, 0x48, 0x16, 0x3d, 0x60, 0xfb, 0x1f, 0x31, 0x8b, - 0x7a, 0xf4, 0x5b, 0x32, 0x11, 0x00, 0x8f, 0x43, 0x2f, 0x02, 0x20, 0x02, 0xe0, 0xb1, 0x07, 0x3c, - 0x16, 0x2f, 0x46, 0x80, 0x08, 0x80, 0xc7, 0x1e, 0xf0, 0x58, 0xbc, 0x18, 0x01, 0x22, 0x00, 0x1e, - 0x7b, 0xc0, 0x63, 0xf1, 0xff, 0x07, 0x81, 0x2f, 0x8c, 0xaf, 0x25, 0xdb, 0xd9, 0x2e, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXVideoIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x37, 0x39, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xcc, - 0x4b, 0x33, 0xb9, 0x00, 0x00, 0x09, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x7b, - 0x4c, 0x54, 0xd9, 0x19, 0x9f, 0x99, 0x7b, 0x67, 0x18, 0x9e, 0x83, 0xc0, 0xcc, 0x30, 0x83, 0x2c, - 0xa2, 0x80, 0x3c, 0x15, 0x96, 0xe2, 0xae, 0x8f, 0xd4, 0xf5, 0x11, 0x13, 0xb7, 0xb6, 0x31, 0xa6, - 0xd5, 0x08, 0x6a, 0xb4, 0xba, 0x3e, 0x6a, 0x1a, 0x13, 0x63, 0xac, 0x35, 0x21, 0x9a, 0xfe, 0x63, - 0x62, 0x8d, 0xb1, 0x35, 0x46, 0x8d, 0xd1, 0xac, 0xa6, 0x35, 0xd1, 0xa6, 0x66, 0xdd, 0x9a, 0xad, - 0x31, 0x0d, 0x6e, 0xa3, 0x8d, 0x6f, 0x08, 0x6f, 0x99, 0x05, 0x11, 0x81, 0x85, 0x79, 0xc0, 0xbc, - 0x98, 0xc7, 0xbd, 0x33, 0xf7, 0x4e, 0x7f, 0x77, 0xce, 0xee, 0x75, 0x32, 0x28, 0x8f, 0x19, 0x08, - 0x6b, 0x32, 0x07, 0xb8, 0x7c, 0xe7, 0x9c, 0xef, 0x3b, 0xe7, 0xfb, 0x7d, 0xdf, 0x77, 0xce, 0x77, - 0xee, 0xb9, 0xd2, 0x40, 0x20, 0x20, 0xf9, 0x90, 0x8b, 0xec, 0x43, 0x56, 0x5e, 0xd0, 0x3d, 0x06, - 0x60, 0xa6, 0x3d, 0x18, 0xf3, 0x40, 0xcc, 0x03, 0x51, 0x5a, 0x60, 0x86, 0x43, 0xe8, 0xd9, 0xb3, - 0x67, 0x83, 0x83, 0x83, 0xd1, 0x60, 0x98, 0x19, 0x00, 0x0c, 0xc3, 0xb4, 0xb6, 0x77, 0x9d, 0xf9, - 0xeb, 0xc5, 0x23, 0x7f, 0xfc, 0xc3, 0xed, 0xdb, 0x5f, 0x45, 0x03, 0x80, 0x8e, 0x46, 0x78, 0xb2, - 0xb2, 0x83, 0x83, 0x16, 0xe3, 0x90, 0xcd, 0x60, 0xe8, 0xf9, 0xde, 0x62, 0x4d, 0x4e, 0x4e, 0xee, - 0x1d, 0xb4, 0xf5, 0xf5, 0x7e, 0xff, 0xe2, 0xc5, 0x8b, 0xc9, 0x8e, 0x13, 0xca, 0x1f, 0x15, 0x80, - 0xbb, 0x77, 0xef, 0x32, 0x5e, 0x6f, 0x5c, 0x42, 0xb2, 0xcb, 0xed, 0x95, 0x4a, 0xa5, 0x18, 0x97, - 0xa6, 0x69, 0xa5, 0x52, 0x91, 0x9c, 0x94, 0xa4, 0xce, 0x48, 0xcb, 0xd4, 0x6a, 0x92, 0x92, 0x92, - 0xd0, 0xd8, 0xdf, 0x6f, 0x6c, 0x6c, 0xed, 0xec, 0x37, 0x59, 0x19, 0x2f, 0x23, 0x95, 0xd1, 0x1f, - 0x65, 0xeb, 0xca, 0xb4, 0x6a, 0x9e, 0x93, 0x98, 0x4c, 0x96, 0x21, 0xab, 0xfd, 0xf1, 0xe3, 0xc7, - 0x0e, 0x87, 0x23, 0x25, 0x25, 0x25, 0x54, 0xad, 0x89, 0xd3, 0x51, 0x01, 0x18, 0x1a, 0x1a, 0xea, - 0xea, 0xfc, 0x4e, 0x9d, 0x53, 0x2e, 0x97, 0xcb, 0xe7, 0xcc, 0xce, 0xc0, 0xa1, 0x84, 0x65, 0x39, - 0x37, 0xe3, 0xb3, 0xd8, 0x6c, 0xcd, 0x86, 0x01, 0x9b, 0xfd, 0x89, 0x67, 0xc4, 0xe9, 0xb0, 0x19, - 0xfb, 0x8c, 0xb6, 0xb4, 0x0c, 0x5d, 0x41, 0x5e, 0xee, 0xec, 0xac, 0xcc, 0xa4, 0xe4, 0x44, 0xc0, - 0x18, 0x30, 0x5a, 0xad, 0x56, 0x67, 0xf7, 0xeb, 0x3e, 0xa9, 0x4c, 0x3e, 0x38, 0x68, 0xec, 0xea, - 0xea, 0xaa, 0xa8, 0xa8, 0x98, 0xb8, 0xd2, 0xa1, 0x9c, 0x51, 0x01, 0x50, 0x05, 0x8b, 0x5e, 0xa7, - 0xcb, 0xc9, 0xd6, 0xe6, 0xe7, 0xea, 0x29, 0x19, 0xdc, 0x00, 0x3f, 0x08, 0x0f, 0x9e, 0x97, 0x70, - 0x5c, 0x80, 0xf1, 0xb1, 0x76, 0xa7, 0xbb, 0x7f, 0xc0, 0xdc, 0xfa, 0xb2, 0xeb, 0xf5, 0xab, 0xae, - 0xde, 0xbe, 0x3e, 0xf4, 0x26, 0x26, 0x26, 0x3b, 0x9c, 0xae, 0xef, 0xda, 0x5b, 0xf4, 0x9a, 0xa4, - 0x3f, 0x1d, 0xaf, 0x8d, 0x53, 0x50, 0x5a, 0xad, 0x36, 0x54, 0xa7, 0x49, 0xd1, 0x51, 0x01, 0xa8, - 0xab, 0xab, 0x63, 0x3d, 0x9e, 0xf8, 0xb4, 0x5c, 0x4d, 0xba, 0xca, 0x6e, 0x77, 0xd0, 0x32, 0x4a, - 0x4a, 0x41, 0x7b, 0x19, 0x0d, 0x24, 0x40, 0x23, 0x91, 0xc4, 0xc9, 0xa9, 0xcc, 0x8c, 0x94, 0x2c, - 0xad, 0x6a, 0x51, 0x79, 0x01, 0xc3, 0xfa, 0x7b, 0x7a, 0x07, 0x9a, 0x5a, 0x0d, 0xf7, 0x1f, 0xd4, - 0x1b, 0xda, 0x1b, 0xaa, 0x7f, 0xfd, 0xf9, 0x6f, 0xb7, 0x57, 0xc3, 0x75, 0x93, 0x52, 0x77, 0x34, - 0x73, 0x54, 0x00, 0x1a, 0x1a, 0x1a, 0x1c, 0x56, 0x2b, 0x9d, 0xf2, 0x51, 0x6e, 0x4e, 0xae, 0xd5, - 0xee, 0xa2, 0x64, 0x28, 0xd0, 0x5f, 0x22, 0x10, 0xf8, 0x93, 0x0a, 0x0f, 0x50, 0x14, 0x25, 0x21, - 0xf4, 0x6c, 0x9d, 0x7a, 0xb6, 0x5e, 0xf3, 0xf3, 0x25, 0x95, 0x4f, 0xea, 0x5f, 0xb6, 0xb7, 0xb5, - 0x3e, 0x7b, 0xd1, 0xb4, 0xe4, 0xd3, 0xca, 0xd1, 0x3a, 0x4d, 0xaa, 0x25, 0x2a, 0x00, 0x1e, 0x8f, - 0x47, 0x4a, 0xd1, 0x0c, 0xcb, 0xf5, 0xf4, 0x9b, 0x38, 0xde, 0x27, 0xa7, 0x69, 0xb9, 0x9c, 0xa2, - 0x69, 0x4a, 0x4e, 0x09, 0x4f, 0xc1, 0x17, 0x14, 0x01, 0x22, 0x38, 0xe6, 0x47, 0x54, 0x52, 0x84, - 0xd8, 0xa7, 0x1f, 0x17, 0x16, 0xe4, 0xcd, 0xfe, 0xe6, 0xde, 0xa3, 0xaf, 0xbf, 0xf9, 0x0f, 0xcd, - 0x3b, 0xf7, 0xed, 0xdb, 0x97, 0x95, 0x95, 0x35, 0x29, 0xbd, 0x45, 0xe6, 0xa8, 0x00, 0x64, 0x66, - 0x66, 0x42, 0x43, 0x9b, 0xd5, 0xf2, 0x8f, 0x7f, 0xfe, 0xab, 0xb4, 0xa4, 0x38, 0x0b, 0xb1, 0x92, - 0x9c, 0xa8, 0x4a, 0x49, 0x50, 0x25, 0x27, 0xc4, 0xc7, 0x2b, 0x04, 0x00, 0xf8, 0x09, 0x16, 0xc1, - 0x1d, 0x32, 0xf8, 0x41, 0x08, 0x2c, 0x50, 0x41, 0x5a, 0xb6, 0xf8, 0x93, 0x8a, 0x53, 0xa7, 0xeb, - 0x92, 0x65, 0xce, 0xa6, 0xa6, 0xa6, 0x99, 0x01, 0x70, 0xf2, 0xe4, 0x49, 0xa4, 0xa4, 0x53, 0xa7, - 0xff, 0xd2, 0xd3, 0xd1, 0xa8, 0xd5, 0xaa, 0x0b, 0x8b, 0xe7, 0x27, 0x26, 0xd0, 0x71, 0x71, 0x4a, - 0xa8, 0xe8, 0xf7, 0x07, 0xa4, 0xd2, 0x80, 0xa0, 0x2e, 0x60, 0xc8, 0xa4, 0x3c, 0x4f, 0xd0, 0x70, - 0xa8, 0x52, 0x94, 0x54, 0xc6, 0x07, 0x38, 0xce, 0xef, 0xf3, 0xb1, 0x0a, 0x05, 0x9d, 0xae, 0x4a, - 0x17, 0x82, 0x2c, 0xd2, 0x12, 0x95, 0x07, 0x0a, 0x0a, 0x0a, 0x30, 0x6f, 0xda, 0xac, 0x59, 0x99, - 0x5a, 0xb5, 0x32, 0x4e, 0x9e, 0xa8, 0xa4, 0x52, 0x92, 0xe2, 0x3b, 0x0d, 0x2f, 0x47, 0x1c, 0xc3, - 0x89, 0x49, 0x49, 0x64, 0x3f, 0x12, 0x00, 0x08, 0x19, 0x22, 0xe8, 0x08, 0x81, 0x90, 0xb8, 0xdd, - 0x6e, 0x8d, 0x36, 0xb3, 0xb0, 0xa8, 0x94, 0xe3, 0x78, 0xaf, 0xcb, 0x5b, 0xf7, 0xfc, 0xf1, 0x2f, - 0xd6, 0xfd, 0x52, 0xe8, 0x88, 0xa8, 0x44, 0x05, 0x80, 0xcc, 0x18, 0x90, 0x04, 0x54, 0xaa, 0xd4, - 0x00, 0xcf, 0xf9, 0x18, 0x6c, 0x9b, 0x72, 0x1f, 0xeb, 0x5b, 0xbe, 0x7c, 0x79, 0x5a, 0x5a, 0x3a, - 0x72, 0x1c, 0xb4, 0x86, 0xe6, 0x34, 0x25, 0xc3, 0x53, 0x22, 0x81, 0x43, 0x64, 0xf1, 0x4a, 0x65, - 0x6f, 0x7f, 0x7f, 0x73, 0x6b, 0x1b, 0x03, 0xfb, 0xe3, 0x97, 0xf5, 0x19, 0x4d, 0xc6, 0x68, 0x5e, - 0x6b, 0xa7, 0x00, 0x00, 0x76, 0xcf, 0x0c, 0xb5, 0x9a, 0xe7, 0x39, 0xb7, 0x87, 0x89, 0x53, 0xca, - 0x19, 0x96, 0x0d, 0x48, 0xa9, 0xcb, 0x97, 0x2e, 0x74, 0xb4, 0x37, 0x05, 0xfd, 0x20, 0xc5, 0x82, - 0x86, 0xa2, 0x00, 0x33, 0x3c, 0x6c, 0x59, 0xf7, 0xab, 0xdf, 0xfc, 0x6c, 0xd1, 0x12, 0x96, 0xf5, - 0xb3, 0x00, 0xcb, 0xf8, 0x59, 0x24, 0x0a, 0xbb, 0x23, 0x1a, 0x00, 0x53, 0x70, 0x98, 0xc3, 0x8e, - 0xa3, 0xd5, 0x68, 0xfc, 0x7e, 0x0e, 0xeb, 0xc1, 0xeb, 0x15, 0xdc, 0xe0, 0x74, 0xba, 0xe5, 0x0a, - 0x79, 0x4d, 0xcd, 0xe6, 0x3d, 0xbb, 0xbf, 0x58, 0xb7, 0xee, 0x73, 0x43, 0xc7, 0x4b, 0xb3, 0xd9, - 0x58, 0x55, 0x55, 0x69, 0x36, 0x19, 0x5f, 0xf7, 0xf4, 0xb0, 0x1c, 0x0f, 0x3c, 0x5e, 0x2f, 0xcb, - 0xb0, 0x3e, 0x9e, 0x27, 0x77, 0x0a, 0x91, 0x5f, 0x2c, 0x4c, 0x01, 0x00, 0xb9, 0x9c, 0xd6, 0x68, - 0xb5, 0x7e, 0xbf, 0x1f, 0x1e, 0xf0, 0x7a, 0xa0, 0x16, 0xeb, 0x74, 0x8e, 0x28, 0xe4, 0xf2, 0xfc, - 0xfc, 0xfc, 0xd2, 0x92, 0x12, 0xbd, 0x5e, 0xf7, 0xaa, 0xfb, 0xd5, 0x67, 0x9f, 0x2d, 0x37, 0x18, - 0x0c, 0x26, 0x8b, 0xd9, 0xef, 0xe7, 0x3d, 0x6e, 0xaf, 0x00, 0x80, 0x65, 0xbd, 0x8c, 0x8f, 0xf7, - 0x73, 0x11, 0x45, 0xfe, 0x5b, 0xa1, 0x29, 0x08, 0x21, 0x8a, 0xa6, 0x34, 0x6a, 0x35, 0xc7, 0x75, - 0xc2, 0x01, 0x0c, 0x93, 0x80, 0xf0, 0xc0, 0xd9, 0xce, 0x64, 0xb6, 0x7c, 0xfb, 0x6d, 0x9d, 0x5e, - 0x9f, 0xdd, 0xd2, 0xda, 0x1c, 0x17, 0x17, 0x67, 0xe8, 0x30, 0x48, 0xa4, 0x92, 0x8a, 0xf2, 0x72, - 0x97, 0xdb, 0xed, 0x72, 0x7b, 0x58, 0x9f, 0x1f, 0xda, 0xc3, 0x09, 0x7e, 0xde, 0xff, 0x56, 0x97, - 0x88, 0xa8, 0x29, 0x00, 0x40, 0x53, 0x74, 0x7a, 0x3a, 0xb6, 0xc2, 0x60, 0xfa, 0x52, 0x20, 0x97, - 0xd1, 0xd0, 0xaf, 0xec, 0xe3, 0xa5, 0x76, 0xbb, 0xb5, 0xcf, 0xcc, 0xa4, 0xeb, 0x8a, 0x0e, 0xd7, - 0xfe, 0x19, 0x51, 0x8e, 0x83, 0x2a, 0x96, 0xad, 0x5a, 0xa3, 0x19, 0x71, 0xb9, 0x20, 0x82, 0xbd, - 0x15, 0x8d, 0x3c, 0xcf, 0xc3, 0x75, 0x08, 0xbf, 0x88, 0x94, 0x17, 0x84, 0xa6, 0x00, 0x00, 0x96, - 0xaf, 0x5e, 0xa7, 0x4d, 0x49, 0x55, 0x69, 0x35, 0x50, 0x2f, 0xdd, 0xed, 0x1c, 0x52, 0xa9, 0x52, - 0x32, 0x34, 0x6a, 0xa4, 0x01, 0x21, 0x7f, 0x61, 0xdf, 0xa7, 0x29, 0x09, 0x94, 0x0d, 0xf0, 0xd8, - 0x8b, 0xc0, 0x3c, 0x64, 0x36, 0xa5, 0xce, 0x52, 0xcd, 0x52, 0xa5, 0x3a, 0xdd, 0x01, 0x5a, 0xae, - 0x28, 0x2a, 0x2a, 0x8a, 0xf8, 0x2c, 0x1d, 0x2d, 0x00, 0x28, 0x85, 0xbd, 0x25, 0x5e, 0x19, 0xff, - 0xdf, 0xff, 0x3d, 0xf1, 0x30, 0xfc, 0x90, 0xc3, 0x23, 0xa1, 0xdd, 0x43, 0x76, 0x37, 0x6d, 0xb4, - 0x8f, 0xb0, 0x32, 0xf4, 0x06, 0x01, 0x08, 0x89, 0x80, 0xc7, 0x5e, 0x8b, 0xe5, 0x8a, 0x7f, 0x52, - 0xc9, 0x88, 0xc3, 0x6e, 0x32, 0xdb, 0xe8, 0x04, 0x4b, 0x7b, 0x5b, 0xdb, 0xc1, 0xdf, 0x7f, 0xb1, - 0x64, 0xd1, 0x02, 0x8d, 0x46, 0x13, 0xb1, 0x07, 0x04, 0x3f, 0x46, 0x26, 0xec, 0xf3, 0xf9, 0x90, - 0x92, 0x46, 0x46, 0x46, 0xcc, 0x66, 0x4b, 0x43, 0x63, 0xd3, 0xc9, 0x93, 0xa7, 0xcc, 0x96, 0x21, - 0xe4, 0x54, 0xa4, 0x58, 0xc1, 0xee, 0x38, 0x2d, 0x08, 0x23, 0x23, 0x0f, 0x08, 0xc3, 0x07, 0xa9, - 0xe0, 0x3f, 0xa1, 0xc6, 0x23, 0x85, 0xc1, 0x1b, 0xc5, 0x85, 0x05, 0x7f, 0xff, 0xdb, 0x97, 0x19, - 0x19, 0x6a, 0x9c, 0x49, 0x11, 0x60, 0x42, 0xcf, 0xe4, 0x4b, 0x84, 0x62, 0x64, 0x22, 0x44, 0x30, - 0xc7, 0x71, 0x0a, 0x85, 0x1c, 0x47, 0xb3, 0xdf, 0xed, 0xdd, 0x69, 0x32, 0x99, 0x84, 0xa0, 0x41, - 0xce, 0x22, 0x56, 0x79, 0x8f, 0x65, 0xd0, 0x8f, 0x13, 0x2a, 0xf8, 0xf2, 0xf2, 0xf3, 0x81, 0xd0, - 0xeb, 0xf5, 0x46, 0xac, 0x3d, 0xd4, 0x88, 0xdc, 0x03, 0x10, 0x86, 0x9e, 0xc0, 0x80, 0x02, 0x02, - 0x56, 0x14, 0x54, 0x9f, 0x64, 0x01, 0xfe, 0x1f, 0x30, 0x4f, 0x52, 0x50, 0x64, 0x8f, 0x0a, 0x80, - 0x38, 0xca, 0x0c, 0x12, 0x53, 0x90, 0xc8, 0x66, 0x50, 0x7b, 0x4c, 0x1d, 0x03, 0x30, 0xb3, 0xf6, - 0x8f, 0x79, 0x60, 0xa6, 0xed, 0x1f, 0xf3, 0xc0, 0x87, 0xec, 0x01, 0x9c, 0x21, 0x4f, 0x9f, 0x3e, - 0x7d, 0xeb, 0xd6, 0xad, 0xb1, 0x41, 0x20, 0xcd, 0x05, 0xcf, 0x9b, 0xd1, 0x1e, 0x9b, 0xdf, 0x3b, - 0x0b, 0x92, 0x68, 0x64, 0xa5, 0xa3, 0xa3, 0x03, 0x83, 0xce, 0x9d, 0x3b, 0x77, 0x0c, 0xf1, 0xa3, - 0x47, 0x8f, 0x8a, 0x37, 0x0e, 0xb8, 0xfc, 0x19, 0x83, 0x33, 0xe2, 0xae, 0xc8, 0xf3, 0x80, 0x42, - 0xa1, 0xc0, 0x9b, 0xca, 0xd8, 0xf7, 0x39, 0x39, 0x39, 0x39, 0xf3, 0xe6, 0xcd, 0x4b, 0x4b, 0x4b, - 0x03, 0x54, 0x5c, 0x41, 0xbf, 0xd7, 0x8a, 0xd1, 0x74, 0x44, 0x0c, 0x1d, 0x82, 0x38, 0x90, 0x4e, - 0x44, 0x1c, 0x91, 0x06, 0x0d, 0xb7, 0x6c, 0xd9, 0x32, 0x11, 0xe6, 0xc9, 0xf2, 0x84, 0x7b, 0xe0, - 0xc8, 0x91, 0x23, 0x9f, 0x04, 0xcb, 0x9a, 0x35, 0x6b, 0xda, 0xda, 0xda, 0x9e, 0x3f, 0x7f, 0xbe, - 0x6a, 0xd5, 0x2a, 0x34, 0x2c, 0x5d, 0xba, 0xf4, 0xda, 0xb5, 0x6b, 0xa2, 0xa5, 0xb6, 0x6d, 0xdb, - 0x46, 0x1a, 0x97, 0x2d, 0x5b, 0x66, 0xb3, 0xd9, 0xc4, 0x76, 0x91, 0xb8, 0x71, 0xe3, 0xc6, 0xd6, - 0xad, 0x5b, 0x31, 0xc8, 0xf1, 0xe3, 0xc7, 0x47, 0xdb, 0x1e, 0x2d, 0x07, 0x0f, 0x1e, 0x5c, 0xb8, - 0x70, 0x21, 0x3e, 0x20, 0x94, 0x94, 0x94, 0x1c, 0x3e, 0x7c, 0xd8, 0xe5, 0x72, 0x89, 0xb2, 0x20, - 0xfa, 0xfb, 0xfb, 0x77, 0xec, 0xd8, 0x51, 0x58, 0x58, 0x08, 0x86, 0xf2, 0xf2, 0xf2, 0xd1, 0x0c, - 0x6f, 0x99, 0xc3, 0x10, 0xeb, 0x74, 0x3a, 0xb1, 0xef, 0xea, 0xd5, 0xab, 0x67, 0xcf, 0x9e, 0x15, - 0xab, 0x1b, 0x36, 0x6c, 0x20, 0xcc, 0x4e, 0xa7, 0x33, 0xf4, 0x00, 0xdc, 0xdd, 0xdd, 0x1d, 0x36, - 0xc8, 0xae, 0x5d, 0xbb, 0x44, 0x29, 0x10, 0xe4, 0x94, 0x2a, 0x7a, 0x60, 0x60, 0x60, 0x20, 0x3b, - 0x3b, 0x9b, 0x30, 0xe0, 0x5d, 0x94, 0x10, 0xc5, 0xc5, 0xc5, 0xc0, 0x40, 0xc6, 0xc1, 0x37, 0x9b, - 0xd1, 0xef, 0x68, 0xb9, 0xb9, 0xb9, 0x16, 0x8b, 0x25, 0x6c, 0x22, 0x54, 0x85, 0x23, 0x71, 0x68, - 0xe9, 0xec, 0xec, 0x2c, 0x2d, 0x2d, 0xc5, 0xa0, 0xbb, 0x77, 0xef, 0x46, 0x84, 0xe0, 0xa6, 0x64, - 0xf3, 0xe6, 0xcd, 0xa8, 0x6e, 0xda, 0xb4, 0x29, 0x54, 0xbe, 0xb9, 0xb9, 0x19, 0x36, 0x26, 0x73, - 0x87, 0x01, 0xb8, 0x7d, 0xfb, 0x36, 0x69, 0x87, 0x73, 0xae, 0x5c, 0xb9, 0xb2, 0x62, 0xc5, 0x0a, - 0x52, 0xad, 0xa9, 0xa9, 0x21, 0x13, 0xad, 0x5f, 0xbf, 0x1e, 0x2d, 0xab, 0x57, 0xaf, 0xee, 0xeb, - 0xeb, 0x43, 0x0b, 0xae, 0xb8, 0xc9, 0x42, 0x3a, 0x74, 0xe8, 0x10, 0xaa, 0x98, 0x94, 0x28, 0x00, - 0x53, 0x9e, 0x3b, 0x77, 0x0e, 0xfa, 0x1c, 0x3b, 0x76, 0x2c, 0x3e, 0x3e, 0x1e, 0x22, 0xd5, 0xd5, - 0xd5, 0xa1, 0xaa, 0x12, 0x3a, 0x1c, 0x00, 0x5a, 0x2f, 0x5e, 0xbc, 0x08, 0x6e, 0x7c, 0x32, 0x01, - 0x8d, 0xf3, 0x3a, 0x16, 0x22, 0x4c, 0x88, 0x3d, 0x27, 0x4c, 0x18, 0x57, 0xd3, 0x44, 0xb3, 0x30, - 0x00, 0x44, 0x3f, 0xbc, 0x25, 0x42, 0x96, 0x88, 0x60, 0x04, 0x70, 0x12, 0x00, 0x90, 0x22, 0xfb, - 0xd2, 0x99, 0x33, 0x67, 0xfe, 0xfd, 0x63, 0xd9, 0xb9, 0x73, 0x27, 0x18, 0x16, 0x2c, 0x58, 0x00, - 0x7e, 0x5c, 0xf4, 0x92, 0x61, 0xb1, 0x72, 0xc4, 0x19, 0x21, 0x8b, 0x46, 0xa5, 0x52, 0x89, 0x1d, - 0x59, 0x6c, 0x24, 0xc4, 0x3b, 0x00, 0x20, 0x42, 0xf0, 0x05, 0x0e, 0x02, 0xf5, 0xf5, 0xf5, 0x77, - 0xee, 0xdc, 0x01, 0xb1, 0x76, 0xed, 0xda, 0x30, 0x31, 0x54, 0xdf, 0x07, 0x00, 0x81, 0x0b, 0x91, - 0xed, 0xdb, 0xb7, 0x8b, 0x22, 0xfb, 0xf7, 0xef, 0x47, 0x0b, 0x01, 0x20, 0xea, 0x87, 0x96, 0xb0, - 0x92, 0x97, 0x97, 0x07, 0x91, 0x9b, 0x37, 0x6f, 0x92, 0x76, 0x7c, 0x77, 0x12, 0x47, 0x10, 0x1b, - 0xe1, 0x10, 0xb1, 0x91, 0x10, 0xef, 0x78, 0xa5, 0xc4, 0xba, 0x41, 0xbc, 0x9e, 0x3f, 0x7f, 0xfe, - 0xf2, 0xe5, 0xcb, 0x3d, 0x3d, 0x3d, 0x18, 0xee, 0xc0, 0x81, 0x03, 0x61, 0x93, 0x8d, 0x51, 0x85, - 0x38, 0x7a, 0xe1, 0x16, 0x91, 0x27, 0x94, 0xd6, 0xeb, 0xf5, 0xa4, 0xfd, 0xd2, 0xa5, 0x4b, 0x65, - 0x65, 0x65, 0x22, 0x0f, 0xdc, 0x42, 0xae, 0x8a, 0xc5, 0x45, 0x88, 0x4f, 0xc8, 0x48, 0x32, 0x84, - 0x01, 0x34, 0x08, 0x04, 0x02, 0x2e, 0xf4, 0x45, 0x91, 0x1f, 0x88, 0x30, 0x40, 0xa4, 0xda, 0xd8, - 0xd8, 0x88, 0x6e, 0xf8, 0x01, 0xef, 0x7b, 0xb0, 0x28, 0x79, 0x69, 0x0c, 0xe5, 0x84, 0x2b, 0xe1, - 0x28, 0x32, 0x04, 0xac, 0x12, 0xba, 0x9f, 0xee, 0xd9, 0xb3, 0x07, 0xed, 0x50, 0xe8, 0xe1, 0xc3, - 0x87, 0x10, 0x79, 0xfa, 0xf4, 0x29, 0xd2, 0x05, 0x5a, 0xc4, 0x35, 0x30, 0x7f, 0xfe, 0x7c, 0x54, - 0xb1, 0x41, 0x89, 0xab, 0xb6, 0xa5, 0xa5, 0x05, 0x52, 0x27, 0x4e, 0x9c, 0x00, 0xbf, 0xdd, 0x6e, - 0x27, 0xfe, 0xc7, 0xbe, 0xf7, 0xe6, 0xcd, 0x1b, 0xb4, 0x60, 0x91, 0x10, 0xd8, 0x24, 0xaa, 0x43, - 0xd5, 0x00, 0xfd, 0x8e, 0x10, 0x22, 0x1c, 0x8b, 0x17, 0x2f, 0x26, 0xfa, 0x61, 0x25, 0x85, 0xc9, - 0x54, 0x55, 0x55, 0x91, 0xae, 0xd0, 0x27, 0x02, 0x00, 0x2b, 0x1e, 0x9c, 0x98, 0x35, 0x31, 0x31, - 0x91, 0x74, 0x91, 0x70, 0x22, 0x34, 0xec, 0x57, 0x5b, 0x5b, 0x0b, 0x86, 0xfb, 0xf7, 0xef, 0x93, - 0x7d, 0x09, 0x4b, 0x73, 0xe5, 0xca, 0x95, 0x62, 0x2a, 0xdc, 0xb8, 0x71, 0x23, 0x99, 0xe8, 0xc2, - 0x85, 0x0b, 0x44, 0x04, 0x7b, 0x1d, 0xb6, 0x5a, 0x42, 0xc3, 0x22, 0x8f, 0x1e, 0x3d, 0x0a, 0xd3, - 0x04, 0xd5, 0xf7, 0x02, 0xb8, 0x77, 0xef, 0x5e, 0x6a, 0x6a, 0x2a, 0xd6, 0x1f, 0x2e, 0x4e, 0xc2, - 0xc4, 0x90, 0x01, 0xc8, 0xa0, 0xa1, 0x4f, 0x04, 0x00, 0xee, 0x17, 0x08, 0x27, 0x66, 0xc2, 0x75, - 0x15, 0xe9, 0x45, 0x48, 0x60, 0xbd, 0xc2, 0x93, 0xd0, 0x86, 0x00, 0x00, 0x0f, 0xbe, 0x0e, 0x62, - 0x77, 0x27, 0x0c, 0xe8, 0x02, 0xf3, 0xde, 0xbd, 0x7b, 0x87, 0x87, 0x87, 0xc5, 0x89, 0xae, 0x5f, - 0xbf, 0x4e, 0x96, 0x3e, 0xe1, 0xa9, 0xac, 0xac, 0x7c, 0xf0, 0xe0, 0x81, 0xd8, 0x1b, 0x4a, 0x8c, - 0xf5, 0x52, 0x8f, 0xcf, 0xc0, 0x30, 0x15, 0x39, 0x08, 0x84, 0xea, 0x3a, 0x41, 0x1a, 0xfb, 0x3d, - 0x82, 0x04, 0x47, 0x09, 0x62, 0xef, 0xd1, 0x52, 0x48, 0x67, 0x58, 0x63, 0x08, 0x74, 0xd1, 0x63, - 0x61, 0x3c, 0xd8, 0xb8, 0x31, 0xc8, 0x9c, 0x39, 0x73, 0x48, 0x50, 0x85, 0xf5, 0x92, 0xea, 0x58, - 0x00, 0xde, 0x29, 0xf0, 0x53, 0x6b, 0x0c, 0x3f, 0x4a, 0xfc, 0xd4, 0xf4, 0x1b, 0x57, 0x9f, 0x18, - 0x80, 0x71, 0x4d, 0x34, 0xcd, 0x0c, 0x31, 0x0f, 0x4c, 0xb3, 0x81, 0xc7, 0x1d, 0x3e, 0xe6, 0x81, - 0x71, 0x4d, 0x34, 0xcd, 0x0c, 0x31, 0x0f, 0x4c, 0xb3, 0x81, 0xc7, 0x1d, 0x3e, 0xe6, 0x81, 0x71, - 0x4d, 0x34, 0xcd, 0x0c, 0xff, 0x07, 0x71, 0xef, 0x64, 0x50, 0x13, 0xcd, 0x1c, 0x52, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXVideoIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x1d, 0x7b, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x5d, 0x09, 0x5c, 0x55, 0xd5, 0xd6, 0xff, 0x33, 0x5f, 0x66, 0x10, 0x70, 0x46, 0xc0, 0x11, 0x4d, - 0x02, 0x51, 0xeb, 0xe5, 0x94, 0xa5, 0x69, 0x8e, 0x5f, 0x45, 0xa9, 0x2f, 0xfd, 0x5e, 0x59, 0xaf, - 0xb9, 0xac, 0x34, 0x9b, 0x9e, 0x59, 0x9f, 0xf6, 0x9e, 0xcd, 0xbe, 0xcc, 0x29, 0x2d, 0x7d, 0x95, - 0xe6, 0x33, 0x87, 0xd4, 0xd2, 0x1c, 0x32, 0x07, 0x1c, 0x02, 0x19, 0x84, 0x00, 0x11, 0x04, 0x19, - 0x45, 0xe6, 0x79, 0x1e, 0xce, 0xb7, 0xd6, 0xbe, 0xf7, 0x1c, 0xef, 0xbd, 0x70, 0x91, 0x0b, 0xc8, - 0xd5, 0xf7, 0xd8, 0xfc, 0x2e, 0xe7, 0xec, 0x79, 0xaf, 0xb5, 0xf6, 0xb8, 0xf6, 0x5a, 0xeb, 0x98, - 0x49, 0xe4, 0x60, 0x84, 0x33, 0x6f, 0x2e, 0xed, 0xd5, 0xac, 0x2b, 0xd8, 0xb4, 0x6e, 0xb5, 0x4e, - 0x12, 0x33, 0xfd, 0x1a, 0x96, 0xbf, 0xb5, 0x08, 0x92, 0xb9, 0x25, 0xac, 0xa8, 0xa8, 0x32, 0x95, - 0x2b, 0x8a, 0x2e, 0x9e, 0xc3, 0x9a, 0x6f, 0x77, 0x29, 0x99, 0x2c, 0x95, 0x37, 0xcd, 0xcb, 0x98, - 0xb1, 0x77, 0xa3, 0xa8, 0xb0, 0x10, 0xc5, 0x6e, 0x5e, 0x48, 0x4f, 0x4a, 0xc2, 0xc2, 0x25, 0x2b, - 0x74, 0x92, 0x34, 0x6a, 0xd2, 0xee, 0xed, 0xdf, 0x21, 0x22, 0xbb, 0x14, 0x97, 0x62, 0xa2, 0x71, - 0xcf, 0x6d, 0x03, 0x91, 0x96, 0x99, 0xa9, 0x93, 0xa1, 0x51, 0x93, 0x38, 0xf6, 0x8d, 0xbf, 0x7f, - 0x0c, 0xa9, 0xa1, 0x01, 0x97, 0x92, 0x93, 0xb1, 0x7b, 0xf3, 0x97, 0x3a, 0x19, 0x1a, 0x35, 0x89, - 0x63, 0x33, 0x2f, 0xc5, 0xc3, 0xc1, 0xc9, 0x05, 0x9e, 0x0e, 0xd6, 0x3a, 0x89, 0xd9, 0xd3, 0x64, - 0x0d, 0x8d, 0x52, 0x69, 0x05, 0x34, 0x82, 0x41, 0x2b, 0xae, 0xc9, 0x57, 0x25, 0xc3, 0xe2, 0xc5, - 0x8b, 0x45, 0x02, 0x33, 0x33, 0x33, 0xbc, 0xfe, 0xfa, 0xeb, 0x4a, 0xe2, 0x07, 0x1f, 0x7c, 0x10, - 0x0d, 0x04, 0x8f, 0xec, 0x6e, 0x7c, 0x93, 0xda, 0xaf, 0x86, 0x2d, 0xff, 0xda, 0x84, 0x2b, 0x57, - 0xae, 0xc8, 0x4d, 0x57, 0x9e, 0x8d, 0xe8, 0x50, 0x5a, 0x52, 0x0c, 0x47, 0x27, 0x67, 0x1c, 0x3f, - 0xb8, 0x17, 0x31, 0x99, 0x79, 0xe8, 0x52, 0x99, 0x87, 0xd7, 0xdf, 0xff, 0xa8, 0xe9, 0x0c, 0xc7, - 0x0f, 0xee, 0x47, 0x68, 0x42, 0x0a, 0x02, 0xc6, 0x4f, 0x84, 0xca, 0x27, 0x00, 0xdf, 0xfd, 0x73, - 0x19, 0xd2, 0xb3, 0x4b, 0x94, 0xc4, 0xfc, 0xa2, 0xa0, 0x95, 0x3d, 0xfb, 0xf6, 0xec, 0x42, 0x69, - 0x3d, 0x10, 0x7c, 0xe4, 0x30, 0x1c, 0xa9, 0xbb, 0xbe, 0xbc, 0x78, 0x29, 0xcc, 0xcd, 0x75, 0x92, - 0xe8, 0x66, 0xf8, 0x6c, 0xfd, 0x26, 0xd4, 0x56, 0x57, 0xa1, 0xa6, 0xaa, 0x12, 0xc5, 0xb5, 0x12, - 0xe2, 0x32, 0x72, 0xb8, 0x1c, 0x1d, 0xd7, 0x08, 0x86, 0xe4, 0xb8, 0x68, 0xd8, 0x58, 0x58, 0xc2, - 0xce, 0xd1, 0x19, 0x36, 0x35, 0x95, 0x3a, 0x89, 0xd9, 0xd3, 0x7e, 0x68, 0xe5, 0x2e, 0xd2, 0x94, - 0x13, 0x4d, 0xe2, 0x48, 0xed, 0xb9, 0x40, 0xc6, 0xbf, 0xb7, 0xb7, 0x37, 0x86, 0x0d, 0x1b, 0x06, - 0x2b, 0x2b, 0x2b, 0xec, 0xd8, 0xb1, 0x43, 0xa4, 0x69, 0xbf, 0x26, 0x35, 0xd5, 0x1c, 0x0e, 0x33, - 0xba, 0x06, 0x43, 0x05, 0x19, 0x0a, 0x6f, 0x44, 0x06, 0x43, 0x09, 0xe5, 0xf0, 0x7d, 0xfb, 0xf6, - 0xe1, 0xfb, 0xcd, 0x5f, 0xc0, 0xab, 0x97, 0x17, 0x60, 0x61, 0x81, 0xb2, 0xd2, 0x7c, 0xdc, 0x3f, - 0x73, 0x2e, 0x66, 0x3c, 0xf0, 0xa0, 0x9c, 0x44, 0xe7, 0xa9, 0xdb, 0x4d, 0x74, 0xa2, 0x80, 0x9f, - 0xf7, 0xed, 0xc1, 0xd1, 0x23, 0x87, 0x44, 0xe8, 0x3b, 0x8b, 0x17, 0x20, 0x37, 0x37, 0x07, 0x71, - 0x51, 0x61, 0x88, 0x88, 0x8c, 0x86, 0x95, 0x8f, 0x3f, 0xf2, 0xf2, 0x8a, 0x10, 0x7b, 0x21, 0x1e, - 0xb1, 0x11, 0x21, 0x7a, 0x39, 0xaf, 0x79, 0x5b, 0x84, 0xa2, 0x27, 0x5e, 0xfb, 0x1b, 0x06, 0xfa, - 0x0e, 0x42, 0x75, 0x45, 0x05, 0x88, 0x74, 0xc8, 0x4e, 0x4b, 0xc1, 0x50, 0xff, 0x40, 0x24, 0x44, - 0x9d, 0xc3, 0x6b, 0xaf, 0xbe, 0x82, 0xde, 0xbd, 0x7b, 0x5f, 0x2b, 0x51, 0xef, 0xed, 0xba, 0x28, - 0xaa, 0xab, 0xab, 0x43, 0x8f, 0x1e, 0xdd, 0x50, 0x52, 0x50, 0x40, 0x59, 0x69, 0x19, 0xa1, 0x0a, - 0x12, 0xe2, 0x62, 0x10, 0x7b, 0x3e, 0x02, 0x66, 0x0d, 0x75, 0xc8, 0xcd, 0xc9, 0x69, 0x5b, 0x05, - 0x96, 0x96, 0x96, 0xc8, 0xce, 0x48, 0x47, 0x55, 0x59, 0x39, 0x15, 0x2f, 0xc1, 0xa3, 0x7b, 0x0f, - 0xf4, 0xf7, 0x0b, 0xc0, 0xe3, 0x0f, 0x4d, 0xc7, 0xd6, 0x1f, 0x0f, 0x60, 0x58, 0x60, 0xa0, 0x5e, - 0x9b, 0x75, 0xbd, 0x2d, 0x42, 0x91, 0x6e, 0x16, 0xe3, 0x7c, 0xcd, 0x12, 0x99, 0x8b, 0xf2, 0xf3, - 0xf3, 0xd3, 0x29, 0xf1, 0xe4, 0xc9, 0x93, 0x38, 0x77, 0xee, 0x9c, 0x4e, 0x58, 0xb3, 0x1e, 0x5e, - 0x3d, 0xd9, 0xc5, 0xc4, 0xc4, 0xf0, 0x3a, 0x2d, 0xe5, 0xe5, 0xe5, 0x89, 0x27, 0x87, 0xcd, 0x9b, - 0x37, 0x4f, 0x79, 0x67, 0x3f, 0xc7, 0xdb, 0xd9, 0xd9, 0x29, 0x61, 0xec, 0x8f, 0x8c, 0x8c, 0xd4, - 0xf1, 0x7f, 0xfd, 0xf5, 0xd7, 0x8a, 0x5f, 0xe4, 0xe1, 0x7f, 0xda, 0x8e, 0x33, 0xc9, 0x8e, 0xdf, - 0xe5, 0x1f, 0x87, 0xc9, 0xef, 0x72, 0x1a, 0x43, 0xfe, 0x2e, 0x5d, 0xba, 0xc8, 0x45, 0x48, 0xa6, - 0xa7, 0x01, 0xb5, 0xb2, 0x4d, 0xee, 0xd6, 0x87, 0xe0, 0xba, 0xdd, 0x54, 0x1f, 0x3f, 0xbc, 0x71, - 0xf8, 0xe0, 0x9d, 0xc5, 0x28, 0x2a, 0xc8, 0xc7, 0x8a, 0x25, 0xaf, 0xa1, 0xbe, 0x9e, 0x96, 0xc1, - 0x66, 0x9c, 0xd1, 0x15, 0x14, 0xe6, 0xe7, 0x22, 0x22, 0x2a, 0x0a, 0x2f, 0x3c, 0x35, 0x17, 0x97, - 0x93, 0x13, 0x11, 0x1e, 0x16, 0xd6, 0x4c, 0xf1, 0x7a, 0xeb, 0xb2, 0x7e, 0xca, 0xed, 0x5b, 0xb7, - 0x20, 0x35, 0xe5, 0x32, 0xb2, 0xae, 0x64, 0xe2, 0xeb, 0xd5, 0x9f, 0x89, 0xd6, 0x2e, 0xfb, 0xdb, - 0x62, 0x5a, 0x55, 0x81, 0x51, 0x53, 0x1f, 0x85, 0x54, 0x5f, 0x87, 0x1d, 0xff, 0x5a, 0xa7, 0x9f, - 0x4d, 0xc7, 0x6f, 0x10, 0x82, 0xb3, 0x21, 0xa1, 0x98, 0x3d, 0x77, 0x1e, 0xb6, 0x7f, 0xfb, 0x0d, - 0x4d, 0xdb, 0xfb, 0xf0, 0xe4, 0x8b, 0x0b, 0xf1, 0xf5, 0xda, 0xcf, 0xe1, 0xd6, 0xb3, 0x0f, 0x06, - 0x4e, 0x9c, 0x85, 0xac, 0xc2, 0x22, 0xc4, 0x24, 0x26, 0x62, 0x80, 0xdf, 0x30, 0x9d, 0x02, 0xf5, - 0x3d, 0x06, 0x67, 0xd3, 0x43, 0xbb, 0xb6, 0xa2, 0xaa, 0x20, 0x07, 0xc5, 0x36, 0x4e, 0x48, 0x4e, - 0x4a, 0x47, 0x8f, 0xe3, 0x67, 0x61, 0x33, 0x20, 0x10, 0xde, 0x03, 0xcd, 0x90, 0x18, 0x1b, 0x83, - 0x72, 0xda, 0xe3, 0x4c, 0x1c, 0x35, 0x1a, 0xe9, 0xf1, 0x71, 0xfa, 0x65, 0xea, 0xf8, 0x0d, 0x42, - 0x50, 0x48, 0x7b, 0xe7, 0x7b, 0xa6, 0x4c, 0x47, 0x41, 0x72, 0x1c, 0x26, 0x3f, 0xf0, 0x30, 0xce, - 0x9d, 0x3f, 0x8f, 0xcb, 0x09, 0xf1, 0x48, 0xa1, 0x5f, 0x17, 0x7b, 0x3b, 0x54, 0xe4, 0xe7, 0xa0, - 0xd2, 0xd2, 0x01, 0xcb, 0x57, 0xe9, 0xee, 0x7a, 0x75, 0x4a, 0x27, 0x8f, 0x41, 0x08, 0x3e, 0xdf, - 0xf8, 0x2d, 0xe2, 0xe2, 0x13, 0x30, 0x60, 0xe4, 0x28, 0x44, 0x86, 0x9e, 0x15, 0x5b, 0x04, 0xd4, - 0x4b, 0x68, 0xa0, 0x2d, 0xc5, 0xb0, 0xdb, 0x06, 0x21, 0x3f, 0x23, 0x09, 0xdd, 0xbb, 0xf6, 0xd0, - 0x2f, 0xaf, 0x91, 0xdf, 0x20, 0x04, 0x9c, 0x72, 0x88, 0xef, 0x40, 0xd4, 0xd6, 0xd6, 0xa2, 0x9e, - 0x7f, 0x75, 0xfc, 0xab, 0x13, 0xbf, 0xb7, 0xdf, 0x7b, 0x0f, 0x47, 0x0e, 0x1f, 0x41, 0xf0, 0xa9, - 0x93, 0x8d, 0x0a, 0xd4, 0x0f, 0x30, 0x08, 0x81, 0x9c, 0x50, 0x5d, 0x68, 0xad, 0x1a, 0x02, 0x9a, - 0xee, 0x1a, 0xa4, 0x06, 0xb8, 0x79, 0x7a, 0x43, 0x65, 0x67, 0x8f, 0x6f, 0xa9, 0x67, 0x5d, 0xcf, - 0x5d, 0xb7, 0x82, 0xea, 0xea, 0x6a, 0x64, 0x5c, 0x4e, 0xe1, 0x0d, 0x0e, 0x1a, 0xea, 0x1b, 0xd0, - 0xb5, 0x67, 0x4f, 0x8c, 0xf6, 0xf3, 0x45, 0x45, 0x55, 0x95, 0xe8, 0xbe, 0xde, 0x3e, 0x7d, 0x9b, - 0xad, 0xe3, 0xba, 0x15, 0xf4, 0xed, 0xea, 0x81, 0xa4, 0x98, 0x18, 0xf0, 0x76, 0xce, 0x82, 0x66, - 0xec, 0x2a, 0xea, 0x3d, 0x61, 0xf1, 0xe9, 0x00, 0x55, 0x76, 0xbd, 0xc2, 0xb9, 0xe6, 0xff, 0xf0, - 0xc9, 0x6e, 0xf2, 0xe4, 0xc9, 0x8d, 0xf0, 0x7b, 0xec, 0xd8, 0xb1, 0x46, 0x61, 0xcd, 0x05, 0x18, - 0x8d, 0xa2, 0x6e, 0xdd, 0xba, 0x21, 0x3b, 0x3b, 0xbb, 0xb9, 0x32, 0x75, 0xe3, 0xe4, 0xc5, 0x93, - 0x42, 0xa5, 0x23, 0x47, 0x8e, 0x48, 0xb4, 0xf7, 0x96, 0xa8, 0x95, 0x22, 0xd8, 0xc9, 0xc9, 0x49, - 0x8e, 0x16, 0xeb, 0xf1, 0x84, 0x09, 0x13, 0xc4, 0x93, 0x03, 0xa7, 0x4f, 0x9f, 0x2e, 0x2d, 0x5f, - 0xbe, 0x5c, 0x1a, 0x3a, 0x74, 0xa8, 0x94, 0x9e, 0x9e, 0x2e, 0x79, 0x79, 0x79, 0x49, 0x53, 0xa6, - 0x4c, 0x91, 0xe8, 0xd0, 0x22, 0x45, 0x45, 0x45, 0x5d, 0xcb, 0xa7, 0xbc, 0xd1, 0x8b, 0x8f, 0x8f, - 0x8f, 0x52, 0x00, 0x87, 0x07, 0x06, 0x06, 0x2a, 0xd1, 0xdc, 0x00, 0x76, 0xd4, 0x9b, 0xc4, 0x93, - 0xfd, 0x0f, 0x3c, 0xf0, 0x80, 0xf8, 0x1d, 0x3c, 0x78, 0x50, 0x27, 0x9f, 0x9c, 0x96, 0x13, 0x5e, - 0xdb, 0x42, 0xb0, 0x47, 0x53, 0x88, 0x88, 0xa0, 0x77, 0xf6, 0xcb, 0x61, 0x23, 0x47, 0x8e, 0x14, - 0xef, 0xdc, 0x88, 0xbb, 0xee, 0xba, 0x4b, 0xaa, 0xa8, 0xa8, 0x50, 0xe2, 0xa3, 0xa3, 0xa3, 0xa5, - 0xf8, 0xf8, 0x78, 0xc5, 0xcf, 0xf9, 0x65, 0x67, 0x34, 0x0d, 0xa8, 0x42, 0xa3, 0x5c, 0xb3, 0x73, - 0x91, 0x51, 0x25, 0x19, 0x48, 0x7c, 0xeb, 0x57, 0x70, 0xc3, 0x69, 0x60, 0x00, 0x73, 0xed, 0x16, - 0x7c, 0xdd, 0xc9, 0xb4, 0xdd, 0x6a, 0xa2, 0x82, 0x78, 0xed, 0x3a, 0xfd, 0xdb, 0x6f, 0x28, 0xc9, - 0xbf, 0x0a, 0x6b, 0x07, 0x17, 0x8c, 0x9f, 0x34, 0x09, 0x2a, 0x95, 0x6d, 0x9b, 0xaa, 0xe8, 0x10, - 0x0a, 0x7c, 0xf2, 0x8f, 0x65, 0xe8, 0x41, 0x6b, 0x60, 0x7e, 0x5a, 0x12, 0xce, 0x45, 0xfe, 0x0e, - 0xda, 0xdc, 0xc3, 0x8c, 0xb8, 0x20, 0x7d, 0x3d, 0xfb, 0xa1, 0xab, 0x77, 0x7f, 0x24, 0x44, 0x47, - 0x61, 0xe9, 0x87, 0x9f, 0xb6, 0x0a, 0x90, 0x36, 0x03, 0x90, 0x97, 0x97, 0x8f, 0x90, 0x93, 0xbf, - 0x21, 0xeb, 0xea, 0x55, 0xb8, 0x51, 0xc3, 0xfc, 0x47, 0xde, 0x89, 0xbe, 0xfd, 0xfa, 0x2b, 0x8d, - 0xf9, 0xe8, 0xef, 0xef, 0xc2, 0xad, 0x6b, 0x37, 0xfc, 0xb0, 0x75, 0x13, 0x2a, 0xca, 0xcb, 0x30, - 0xe6, 0x8e, 0xd1, 0xa8, 0xb1, 0xb4, 0x81, 0x3d, 0xea, 0x71, 0x3e, 0x2e, 0x0a, 0xf6, 0xb4, 0xff, - 0x09, 0x7a, 0xf4, 0x09, 0x84, 0x1e, 0x3f, 0x86, 0x8f, 0xd6, 0x7e, 0xad, 0xe4, 0x6b, 0xe9, 0x4b, - 0xab, 0x47, 0xf1, 0x87, 0x7f, 0x5f, 0x86, 0x0b, 0xb4, 0xbb, 0x5b, 0xbf, 0xf2, 0x03, 0x0c, 0x1f, - 0x35, 0x16, 0x7f, 0x7d, 0xfe, 0x25, 0x3c, 0x38, 0x67, 0x2e, 0x7e, 0xda, 0xf6, 0x2d, 0xce, 0x9e, - 0x0e, 0xc6, 0xab, 0xcf, 0xfd, 0x55, 0xb4, 0xa1, 0xe0, 0xea, 0x15, 0x1c, 0xfa, 0x69, 0x2f, 0xac, - 0xad, 0xec, 0xd0, 0xd3, 0x6b, 0x30, 0x6a, 0x7b, 0xfa, 0x22, 0x9e, 0x98, 0x58, 0x59, 0x92, 0x3d, - 0xcc, 0xea, 0x24, 0xd4, 0x55, 0xd5, 0x62, 0xdf, 0xf6, 0xad, 0xb0, 0x6e, 0x65, 0x4b, 0x5a, 0x45, - 0x81, 0xb7, 0x16, 0xbd, 0x84, 0x15, 0x9f, 0x7e, 0xa1, 0x20, 0xe9, 0xad, 0x97, 0x9f, 0xc5, 0x80, - 0xa1, 0xc4, 0x55, 0x38, 0x1f, 0x82, 0x65, 0x2b, 0xd7, 0xc1, 0xda, 0xda, 0x1a, 0x89, 0xa9, 0x99, - 0xd8, 0xb1, 0x6b, 0x37, 0x2c, 0x89, 0x57, 0x32, 0x62, 0xe4, 0x08, 0xec, 0xf9, 0xe5, 0x20, 0x54, - 0xf6, 0x8e, 0xb0, 0xa2, 0xb8, 0xf4, 0xc4, 0x78, 0xa4, 0x47, 0x06, 0xa3, 0x9b, 0xbb, 0x1b, 0x72, - 0x8b, 0xf2, 0x28, 0xee, 0x14, 0xf1, 0x56, 0x36, 0xe2, 0x99, 0x05, 0x0b, 0x95, 0x32, 0x5b, 0xfa, - 0xd2, 0x2a, 0x00, 0xde, 0x5e, 0xf0, 0x34, 0xfa, 0xf4, 0x1d, 0x48, 0x75, 0xd0, 0x52, 0x45, 0x67, - 0x9b, 0xd3, 0x89, 0xe9, 0xc8, 0x49, 0xbd, 0x0c, 0x67, 0xda, 0xd4, 0x4f, 0x0f, 0x9a, 0x85, 0xea, - 0x1a, 0xda, 0x8e, 0xa5, 0xa5, 0x51, 0xbc, 0x9a, 0x63, 0xc6, 0xbb, 0xa9, 0x8b, 0x91, 0x61, 0x50, - 0x39, 0xbb, 0xc0, 0xd6, 0xde, 0x01, 0x76, 0xb4, 0x1f, 0xec, 0xef, 0xe3, 0x8d, 0xac, 0xf0, 0xa3, - 0xb0, 0x25, 0xc6, 0xd8, 0xa2, 0xf7, 0x3f, 0x23, 0x9e, 0x10, 0x1d, 0x37, 0x5a, 0xe1, 0x5a, 0x05, - 0xc0, 0x49, 0xda, 0xb3, 0x98, 0x99, 0x9b, 0x61, 0xec, 0xdd, 0xe3, 0x71, 0xfc, 0xf8, 0x6f, 0xf8, - 0xd7, 0xfa, 0xb5, 0x98, 0xf9, 0xc2, 0xeb, 0x88, 0x08, 0x0d, 0x11, 0x18, 0x67, 0x6e, 0x09, 0x37, - 0x9e, 0xd6, 0x4b, 0x5e, 0x7d, 0xc5, 0x80, 0xb5, 0xa0, 0x2d, 0x60, 0xd0, 0x43, 0x8f, 0x50, 0x43, - 0xad, 0x50, 0x55, 0x98, 0x0e, 0x07, 0x02, 0xc4, 0xd1, 0xc9, 0x11, 0x39, 0xb4, 0x35, 0xd1, 0xe7, - 0x53, 0x18, 0x03, 0x47, 0xab, 0x00, 0xe0, 0x0a, 0xf8, 0x94, 0xb9, 0xe2, 0xbd, 0xbf, 0x21, 0x37, - 0x35, 0x11, 0x7d, 0xc6, 0x4e, 0x43, 0x51, 0x69, 0x05, 0x6d, 0x8a, 0xe5, 0x93, 0xa6, 0x06, 0x04, - 0x6e, 0x3f, 0xfd, 0x99, 0x9b, 0x99, 0xe3, 0xfc, 0xd9, 0xd3, 0xe8, 0xd3, 0xa7, 0x0f, 0x54, 0xb6, - 0x76, 0xf8, 0xf5, 0x00, 0x8d, 0x09, 0x6b, 0x1b, 0x01, 0xdc, 0x9b, 0x6f, 0xbe, 0x81, 0xa0, 0xa0, - 0x20, 0x63, 0xda, 0xac, 0x93, 0xb6, 0xd5, 0x00, 0x68, 0x97, 0xf2, 0xd1, 0xba, 0xf5, 0x28, 0x2a, - 0xab, 0xa2, 0xee, 0xc4, 0x3c, 0x77, 0xc6, 0xfe, 0xb5, 0x87, 0xa0, 0x00, 0x01, 0x10, 0x71, 0xe6, - 0x18, 0xca, 0x68, 0xc0, 0xf2, 0x71, 0x42, 0xa5, 0xb2, 0x81, 0x87, 0x8b, 0x2b, 0x36, 0x7f, 0xb9, - 0x46, 0x9d, 0xb6, 0x0d, 0xff, 0xdb, 0x65, 0x21, 0xab, 0xa9, 0xa9, 0x45, 0x2d, 0x1d, 0x43, 0xf8, - 0x12, 0x84, 0x1d, 0xed, 0xfa, 0xe8, 0xbf, 0xfa, 0x9d, 0xfb, 0x3f, 0x77, 0x25, 0xdf, 0x80, 0x91, - 0x28, 0x2f, 0x2f, 0x27, 0x76, 0x62, 0x39, 0x9c, 0x5c, 0xba, 0xc0, 0x9a, 0xf8, 0xd6, 0x97, 0x2e, - 0x5d, 0x42, 0xff, 0xfe, 0xd7, 0xa6, 0x5c, 0x91, 0xd9, 0xc8, 0x7f, 0xed, 0x02, 0x40, 0xf6, 0x95, - 0x2c, 0x3a, 0x47, 0x55, 0xa3, 0xa2, 0xb4, 0x54, 0xa9, 0x9e, 0x1b, 0xcd, 0xdd, 0xac, 0x87, 0x67, - 0x1f, 0x11, 0x56, 0x49, 0x9c, 0xc4, 0xfb, 0x47, 0xdf, 0x01, 0xef, 0xbe, 0x3e, 0x08, 0x0b, 0x0b, - 0x47, 0x44, 0xcc, 0x45, 0xb1, 0xa0, 0x29, 0x19, 0x5a, 0xf9, 0xd2, 0x2e, 0x5d, 0x88, 0xeb, 0x8e, - 0x88, 0x3c, 0x8f, 0x6d, 0xff, 0xde, 0x86, 0xec, 0x9c, 0x5c, 0x54, 0x56, 0x6a, 0x6e, 0x03, 0x34, - 0x63, 0x40, 0xdd, 0xab, 0xd4, 0x00, 0x75, 0xe9, 0xe2, 0x8a, 0x87, 0x1f, 0x0a, 0xc2, 0xe4, 0xc9, - 0x93, 0xc4, 0x59, 0xaf, 0x95, 0xed, 0x56, 0xb2, 0xb5, 0x1b, 0x00, 0x4a, 0x89, 0x1d, 0xfc, 0xd2, - 0xca, 0xf5, 0xaf, 0x83, 0x5b, 0xd9, 0x4c, 0x75, 0x6d, 0x02, 0x80, 0x07, 0x28, 0xff, 0x0c, 0xb9, - 0xb3, 0x67, 0xcf, 0x8a, 0xf8, 0xeb, 0xa5, 0x33, 0x94, 0xbf, 0x45, 0xe1, 0xf2, 0xe1, 0x4c, 0x7e, - 0x7e, 0xfc, 0xf1, 0xc7, 0x3c, 0x0f, 0x8a, 0xdf, 0xa3, 0x8f, 0x3e, 0x2a, 0xfd, 0xfa, 0xeb, 0xaf, - 0x8a, 0xff, 0xc9, 0x27, 0x9f, 0x94, 0x93, 0x29, 0x61, 0x9c, 0xb6, 0x29, 0x77, 0xc7, 0x1d, 0x77, - 0x88, 0x34, 0x01, 0x01, 0x01, 0x92, 0x87, 0x87, 0x87, 0x78, 0xd7, 0x4e, 0xf7, 0xc1, 0x07, 0x1f, - 0xe8, 0x94, 0x71, 0xf1, 0xe2, 0x45, 0xed, 0x68, 0xe9, 0xa9, 0xa7, 0x9e, 0xd2, 0x89, 0x8f, 0x8b, - 0x8b, 0xd3, 0x89, 0x97, 0x3d, 0x4d, 0xd6, 0x2e, 0x1f, 0x73, 0xf3, 0xf3, 0xf3, 0x45, 0x3a, 0x6e, - 0xe4, 0xc6, 0x8d, 0x1b, 0xe5, 0x3c, 0xca, 0x93, 0x8f, 0xcd, 0xfa, 0x00, 0xec, 0xd9, 0xb3, 0x47, - 0x84, 0x6d, 0xda, 0xb4, 0x49, 0x49, 0x27, 0x23, 0x44, 0x0e, 0x60, 0xbf, 0xbf, 0xbf, 0xbf, 0xf4, - 0xcd, 0x37, 0xdf, 0x28, 0x3f, 0x0e, 0x1b, 0x33, 0x66, 0x8c, 0x48, 0xc2, 0xef, 0x83, 0x06, 0x0d, - 0x92, 0x93, 0x2b, 0x61, 0xcc, 0x13, 0xd0, 0x77, 0x4d, 0x02, 0xc0, 0x89, 0x96, 0x2c, 0x59, 0xa2, - 0x60, 0xe0, 0x9d, 0x77, 0xde, 0xd1, 0xcf, 0x27, 0xfc, 0x4d, 0x01, 0x20, 0x1f, 0xbf, 0x7d, 0x7d, - 0x7d, 0x45, 0x1a, 0x62, 0x25, 0x2a, 0xe5, 0xc8, 0x85, 0xc8, 0x00, 0x11, 0x8f, 0x58, 0x0e, 0x92, - 0x5e, 0x78, 0xe1, 0x05, 0x69, 0xcb, 0x96, 0x2d, 0xc2, 0x2f, 0xc7, 0x13, 0xeb, 0x4b, 0xf8, 0x3f, - 0xfd, 0xf4, 0x53, 0x51, 0xc6, 0xd4, 0xa9, 0x53, 0x95, 0xf4, 0xf2, 0x8b, 0x41, 0x00, 0x38, 0x01, - 0xb1, 0x50, 0x24, 0xba, 0x95, 0x94, 0xd3, 0x1a, 0xf5, 0xe4, 0xc6, 0x31, 0x25, 0x9b, 0x73, 0xa5, - 0xa5, 0xa5, 0xd2, 0x4f, 0x3f, 0xfd, 0x24, 0x25, 0x27, 0x27, 0x37, 0x99, 0x2c, 0x27, 0x27, 0x47, - 0x74, 0x61, 0x5a, 0x4f, 0x9a, 0x8c, 0xe7, 0xc0, 0xce, 0x69, 0x94, 0xc8, 0x6d, 0x52, 0xd7, 0xa6, - 0x69, 0xd4, 0xa4, 0x2d, 0xd7, 0x54, 0x7e, 0xcb, 0x03, 0xd0, 0x39, 0x06, 0x4c, 0xdd, 0x8d, 0x6e, - 0xf9, 0x2e, 0xd4, 0x2e, 0xe7, 0x81, 0x96, 0x50, 0x81, 0xcf, 0x06, 0x97, 0x49, 0xe2, 0xeb, 0x8f, - 0xd0, 0x33, 0xbc, 0xf6, 0x60, 0xf0, 0xb0, 0xe1, 0x18, 0x34, 0xf8, 0xb6, 0x6b, 0x7b, 0x29, 0xba, - 0x65, 0x02, 0x49, 0x21, 0x18, 0xeb, 0x3a, 0x64, 0x0c, 0x24, 0x51, 0xc3, 0x7f, 0xd9, 0xb1, 0x05, - 0x7d, 0x06, 0x0c, 0xc1, 0xb8, 0x7b, 0x27, 0xd0, 0x46, 0x41, 0xc2, 0xb1, 0xdf, 0x7e, 0xc5, 0xd5, - 0xc4, 0x58, 0x4c, 0x7a, 0x78, 0x1e, 0xfa, 0xf5, 0x1f, 0x60, 0x6c, 0xbb, 0x95, 0xf4, 0x37, 0x1c, - 0x80, 0x98, 0x98, 0x58, 0xe2, 0x87, 0x1e, 0x44, 0xd2, 0xa5, 0x24, 0xba, 0xa8, 0xaa, 0xa1, 0xc3, - 0x7f, 0x21, 0xac, 0x6d, 0x6c, 0xe0, 0xe2, 0xec, 0x06, 0x3b, 0x95, 0x3d, 0x31, 0x2f, 0xcc, 0x30, - 0x63, 0xd6, 0x3c, 0x0c, 0xb9, 0xed, 0x36, 0xa5, 0x51, 0xc6, 0xbc, 0xdc, 0xf0, 0x31, 0xb0, 0x93, - 0x58, 0x8a, 0xbe, 0xb7, 0x07, 0xd0, 0x31, 0x32, 0x18, 0xee, 0x6e, 0x1e, 0xc8, 0x2b, 0x28, 0x44, - 0x61, 0x71, 0x19, 0x1c, 0x6d, 0xed, 0x11, 0x13, 0x13, 0x86, 0x29, 0x0f, 0x06, 0xe1, 0x9b, 0x75, - 0x2b, 0xa9, 0xcd, 0xbc, 0xdd, 0x31, 0xde, 0xb5, 0x99, 0x02, 0xbf, 0x13, 0x1b, 0x31, 0x25, 0x29, - 0x11, 0x75, 0xc4, 0x79, 0xee, 0xe3, 0xe5, 0x83, 0xb1, 0x13, 0xee, 0x53, 0xfa, 0x75, 0x7c, 0xfc, - 0x05, 0xba, 0x92, 0xf5, 0xc0, 0xdc, 0xd9, 0xd3, 0x51, 0x57, 0x53, 0x87, 0xba, 0xba, 0x7a, 0x8c, - 0xfe, 0xd3, 0x68, 0xd4, 0x9b, 0x59, 0x20, 0x95, 0xba, 0x4f, 0x1d, 0x1d, 0xfc, 0x6d, 0x55, 0x96, - 0x78, 0x7b, 0xf9, 0x6a, 0x64, 0x90, 0xcc, 0xd0, 0x3d, 0x13, 0x27, 0x19, 0x0d, 0x81, 0xf1, 0xa3, - 0x46, 0x53, 0x45, 0x72, 0x72, 0x0a, 0x8e, 0xee, 0xdf, 0x09, 0xef, 0xfe, 0xbe, 0x98, 0x38, 0x75, - 0x06, 0x31, 0xb4, 0x2c, 0x51, 0x90, 0x9f, 0x8b, 0x55, 0x2b, 0xde, 0xc5, 0xf0, 0xd1, 0x13, 0x30, - 0xe6, 0xee, 0xbb, 0x71, 0x25, 0x2d, 0x15, 0x27, 0x0e, 0x1f, 0x44, 0x0f, 0x8f, 0x6e, 0xc4, 0xb1, - 0x20, 0x0c, 0x93, 0x44, 0x69, 0xbd, 0x47, 0x5f, 0x38, 0x39, 0x3a, 0xc2, 0x8d, 0xce, 0xcd, 0x35, - 0x25, 0xb9, 0xb0, 0xb6, 0xb4, 0x40, 0xf0, 0xd1, 0x43, 0x68, 0xa8, 0xad, 0x6a, 0x15, 0x00, 0xad, - 0xea, 0x42, 0x99, 0x24, 0xb7, 0xf8, 0xfd, 0xe6, 0xf5, 0x70, 0xec, 0xd2, 0x15, 0x29, 0x74, 0xd3, - 0xeb, 0xee, 0xee, 0x01, 0x17, 0x57, 0x57, 0x84, 0x45, 0x44, 0x21, 0x37, 0xbf, 0x10, 0xd5, 0x55, - 0xe5, 0x38, 0xb4, 0x7f, 0xbf, 0xa0, 0x4a, 0x4a, 0x4a, 0x12, 0xb2, 0x73, 0x0b, 0x91, 0x44, 0x00, - 0xf7, 0x1b, 0x37, 0x1d, 0xa1, 0x27, 0x8e, 0xe2, 0xdc, 0xf1, 0x5f, 0x51, 0x54, 0x54, 0x4c, 0x5c, - 0xb9, 0x5c, 0xe2, 0x6a, 0xe7, 0x20, 0x36, 0x3a, 0x42, 0x47, 0x8e, 0xd3, 0x18, 0x32, 0x18, 0x0d, - 0x00, 0x4f, 0x87, 0x1b, 0x3f, 0xff, 0x14, 0x4b, 0x96, 0x7f, 0x80, 0x59, 0x7f, 0x9e, 0x87, 0xec, - 0xf4, 0x24, 0x92, 0xac, 0x48, 0x11, 0x53, 0x63, 0x6a, 0x6c, 0x18, 0x5e, 0x7d, 0xfb, 0x3d, 0x4c, - 0x98, 0x3c, 0x95, 0x38, 0xd7, 0x91, 0x70, 0x76, 0x73, 0xc7, 0x6b, 0x6f, 0x2d, 0x45, 0x5a, 0x46, - 0x1a, 0x7a, 0x0d, 0x1d, 0x41, 0xec, 0xf5, 0x0a, 0xdc, 0x39, 0x71, 0x0a, 0xfa, 0x92, 0x80, 0x56, - 0x51, 0x56, 0x1a, 0x72, 0x8a, 0x0a, 0x50, 0x52, 0x5e, 0x8c, 0xc5, 0xef, 0xae, 0x80, 0x67, 0xbf, - 0x41, 0xc6, 0xb4, 0x5b, 0x49, 0x6b, 0x74, 0x17, 0x4a, 0xcf, 0xc8, 0xc0, 0xd0, 0x61, 0x6a, 0xa9, - 0x30, 0x16, 0xd5, 0x1c, 0x1c, 0x70, 0x27, 0x36, 0xaf, 0xfb, 0x02, 0x96, 0x34, 0xb3, 0xb0, 0x04, - 0x83, 0x9b, 0x9b, 0x1b, 0x2a, 0x2a, 0xab, 0x30, 0xf0, 0x8e, 0x7b, 0x11, 0x1e, 0x9b, 0x80, 0x90, - 0xe8, 0x0b, 0xb8, 0x67, 0xfa, 0x6c, 0xd8, 0x75, 0xf7, 0xa4, 0x1b, 0xf2, 0x06, 0x31, 0x3e, 0x7e, - 0xfc, 0x66, 0x0d, 0x1e, 0x21, 0xb6, 0xca, 0xf1, 0x90, 0xb3, 0x98, 0xf3, 0xd8, 0xf3, 0xd8, 0xb2, - 0x71, 0x2d, 0x01, 0xfe, 0xae, 0xd2, 0x28, 0x63, 0x5e, 0x8c, 0x06, 0x20, 0x3c, 0xe4, 0x77, 0x14, - 0xe7, 0xe5, 0xe2, 0x18, 0x09, 0xab, 0x32, 0x27, 0xae, 0xb0, 0xb8, 0x14, 0x35, 0xce, 0xdd, 0x51, - 0x4e, 0x83, 0x58, 0x55, 0x59, 0x84, 0x43, 0xbf, 0x1c, 0x80, 0xa3, 0xef, 0x70, 0xe4, 0x56, 0xd7, - 0xc0, 0xbe, 0x97, 0x37, 0xcd, 0x2d, 0x12, 0x7c, 0x6c, 0x9d, 0x91, 0x4a, 0x42, 0x34, 0x4e, 0xd4, - 0xcd, 0x98, 0x3b, 0xed, 0x4c, 0x5c, 0xea, 0x33, 0xe1, 0x11, 0x98, 0x3c, 0x61, 0x12, 0xc9, 0xe7, - 0x79, 0xa2, 0x57, 0x2f, 0xcf, 0x56, 0x73, 0xa7, 0x8d, 0x06, 0xa0, 0x86, 0x58, 0xe7, 0xa9, 0x29, - 0xc9, 0xa8, 0x25, 0x19, 0x0d, 0x9e, 0xf8, 0x32, 0x73, 0xf3, 0x10, 0x12, 0xfe, 0x07, 0xc9, 0x6d, - 0xd4, 0xc0, 0x7f, 0xfc, 0xfd, 0xb0, 0xe9, 0x3b, 0x04, 0x87, 0x7f, 0xde, 0xcb, 0xbc, 0x69, 0x35, - 0x22, 0x69, 0xd1, 0xaa, 0xa2, 0x9b, 0x99, 0xcc, 0xb4, 0xcb, 0xc4, 0xf0, 0xaa, 0x80, 0x8d, 0xad, - 0x2d, 0xa6, 0xcf, 0x7f, 0x19, 0xa3, 0x07, 0x7b, 0xe3, 0xec, 0xcf, 0x3f, 0xd0, 0xec, 0x54, 0x8e, - 0x69, 0x0f, 0x3c, 0x62, 0x0c, 0xd2, 0x75, 0xd2, 0x1a, 0x3d, 0x8d, 0xc6, 0xc5, 0xc5, 0xa2, 0xb8, - 0x30, 0x1f, 0x77, 0x8d, 0x1e, 0x27, 0x0a, 0x3a, 0x7c, 0xf0, 0x20, 0x7e, 0x3c, 0x7a, 0x1c, 0x6e, - 0xbd, 0x7c, 0x30, 0x7c, 0xc4, 0x30, 0x62, 0xb1, 0x9f, 0xa3, 0x1d, 0x81, 0x9a, 0xd7, 0xcf, 0x5b, - 0x06, 0x66, 0xa9, 0x94, 0x91, 0x88, 0x8d, 0xb3, 0xbd, 0x3d, 0x9c, 0xbb, 0xb8, 0xe1, 0x4a, 0x7a, - 0x0a, 0xca, 0x8a, 0x0b, 0xa1, 0x32, 0xab, 0x47, 0xf7, 0x9e, 0xbd, 0xb1, 0x68, 0xd1, 0x22, 0x9d, - 0x06, 0x19, 0xeb, 0x31, 0x9a, 0x02, 0x83, 0x07, 0x0f, 0xc1, 0x82, 0xf9, 0x73, 0x05, 0x00, 0x3c, - 0xa0, 0x7f, 0xfe, 0xf7, 0x66, 0x0c, 0xb9, 0x7b, 0x26, 0xea, 0xa9, 0xd1, 0x11, 0xe7, 0x42, 0x85, - 0x08, 0xb3, 0x8e, 0x40, 0x17, 0x11, 0xa2, 0x8a, 0xe4, 0x52, 0x1e, 0x7e, 0x68, 0x36, 0x9c, 0x48, - 0x98, 0xba, 0xa4, 0x30, 0x1b, 0x6e, 0x2c, 0xd4, 0x4e, 0x80, 0x95, 0x97, 0x11, 0x4b, 0x9e, 0xca, - 0xd0, 0x17, 0x7b, 0x36, 0x06, 0x08, 0xa3, 0x01, 0x60, 0x8c, 0xbe, 0xfa, 0xce, 0x32, 0xac, 0xfe, - 0x68, 0x05, 0xba, 0xf5, 0xf1, 0x46, 0x15, 0x2c, 0x50, 0x43, 0x97, 0x1d, 0xc5, 0xb9, 0xf9, 0xa2, - 0x5e, 0x96, 0xca, 0xe1, 0xbd, 0x8e, 0xec, 0x98, 0x0a, 0x7c, 0xd9, 0x91, 0x9f, 0x16, 0x8f, 0x6a, - 0x62, 0xad, 0x5f, 0x22, 0x25, 0x81, 0xec, 0xbc, 0x6c, 0x5a, 0x37, 0xac, 0xa8, 0xe1, 0x66, 0x18, - 0x32, 0xc4, 0xb7, 0x4d, 0x00, 0x18, 0xdd, 0x85, 0xe4, 0x86, 0x25, 0x26, 0x5e, 0xc4, 0xa7, 0x4b, - 0x5f, 0x47, 0xcf, 0x81, 0x7e, 0xb0, 0xea, 0xd5, 0x0f, 0xe5, 0xcc, 0x99, 0xd6, 0xb4, 0x5b, 0x5c, - 0x6f, 0x28, 0x30, 0xd0, 0x18, 0x28, 0x2b, 0xa3, 0x95, 0x37, 0x01, 0x3e, 0xde, 0x3e, 0x48, 0xb8, - 0x18, 0x4f, 0xdd, 0xe8, 0x32, 0xcb, 0x1f, 0x89, 0x59, 0xe9, 0x1c, 0x51, 0xad, 0xb5, 0xd7, 0x4b, - 0xdc, 0x16, 0xa3, 0x29, 0x20, 0x03, 0x30, 0x60, 0xc0, 0x20, 0xac, 0xfb, 0x7e, 0x0f, 0x7e, 0xd8, - 0xb9, 0x03, 0x49, 0xf9, 0xa5, 0xe2, 0x72, 0x43, 0xdd, 0x66, 0x05, 0x0a, 0x4d, 0x52, 0xf5, 0x0d, - 0x4d, 0x52, 0xc2, 0x05, 0xe4, 0xd0, 0x8d, 0x65, 0x25, 0xdd, 0x11, 0xa8, 0x68, 0xca, 0x75, 0x74, - 0x72, 0x42, 0x57, 0x0f, 0xf7, 0x36, 0x35, 0xbe, 0x4d, 0x00, 0x70, 0x66, 0xee, 0x4e, 0xee, 0x74, - 0x07, 0x9c, 0x90, 0x53, 0x24, 0x04, 0xba, 0xd4, 0x14, 0xb8, 0x06, 0x00, 0x53, 0x82, 0xc4, 0xb1, - 0x68, 0xba, 0xad, 0x83, 0x05, 0x5d, 0x29, 0x59, 0xd0, 0xf5, 0x92, 0xbb, 0xab, 0x1b, 0x5d, 0x33, - 0xa9, 0xf0, 0xf4, 0xbc, 0xd9, 0x98, 0x72, 0xff, 0x54, 0x0d, 0x90, 0xad, 0x7f, 0xb4, 0x9a, 0x02, - 0x72, 0x95, 0xd4, 0x07, 0x49, 0xae, 0xb1, 0x4e, 0xdc, 0x56, 0xaa, 0xbb, 0xfe, 0x35, 0x00, 0x38, - 0x0d, 0x8f, 0x09, 0x07, 0x6a, 0x74, 0xd7, 0x3e, 0x7d, 0xc5, 0x36, 0x9a, 0x45, 0xa7, 0x2d, 0x2d, - 0xad, 0x90, 0x91, 0xc3, 0xb2, 0xd9, 0x6d, 0x77, 0x6d, 0x06, 0x80, 0x9b, 0xdb, 0x40, 0xa7, 0x29, - 0xde, 0x69, 0xf2, 0xe0, 0x15, 0xcd, 0x17, 0xff, 0x1a, 0xc4, 0x3b, 0x5f, 0xf0, 0x15, 0x91, 0x20, - 0xb9, 0xef, 0xc0, 0x01, 0xe2, 0x46, 0xd2, 0x86, 0xee, 0xc7, 0x9c, 0x1d, 0x9d, 0x70, 0xe9, 0x62, - 0x62, 0xdb, 0x5b, 0x4f, 0x25, 0xb4, 0x19, 0x00, 0x96, 0x76, 0xaf, 0xa5, 0x5f, 0x16, 0xed, 0x77, - 0x64, 0x46, 0xbb, 0x9a, 0x12, 0x54, 0x38, 0xed, 0x50, 0xdd, 0xba, 0x75, 0x15, 0x8b, 0x5a, 0xfa, - 0xe5, 0x64, 0xbc, 0xf4, 0xd4, 0x7c, 0x94, 0x95, 0x94, 0x62, 0xd7, 0xc1, 0xa3, 0x70, 0xa3, 0x2b, - 0xd6, 0xf6, 0x70, 0x6d, 0x06, 0x40, 0x65, 0x6d, 0x89, 0x6a, 0xda, 0xfb, 0x88, 0x2b, 0x56, 0x0d, - 0x05, 0x18, 0x10, 0xf5, 0x22, 0x26, 0x5e, 0xa8, 0x1b, 0x49, 0xb0, 0xb5, 0xb1, 0x86, 0x0b, 0xdd, - 0x4c, 0x3a, 0x38, 0x38, 0x50, 0x77, 0xa3, 0x31, 0x61, 0x46, 0xd3, 0x6d, 0x3b, 0xb8, 0x56, 0x4f, - 0xa3, 0x72, 0xdd, 0xdc, 0xd0, 0xff, 0x99, 0x3d, 0x97, 0x4e, 0x58, 0x3c, 0xaf, 0x6b, 0xf0, 0xa1, - 0x86, 0x40, 0x5c, 0x6a, 0xf3, 0xde, 0x87, 0x01, 0xa8, 0x2e, 0x2f, 0xa5, 0x15, 0xa3, 0x01, 0x35, - 0xb4, 0xa8, 0x55, 0x56, 0xd5, 0x61, 0xf9, 0xfb, 0xef, 0x62, 0xb0, 0xef, 0x60, 0xb9, 0x98, 0x56, - 0x3f, 0x8d, 0x07, 0x80, 0xba, 0x8b, 0x3e, 0xf7, 0x80, 0x57, 0xde, 0xb5, 0xeb, 0xd7, 0x23, 0x3a, - 0xfa, 0x0f, 0x94, 0xd0, 0x7a, 0xc0, 0xab, 0xab, 0x70, 0x34, 0x16, 0xe4, 0x35, 0x41, 0xa2, 0xc1, - 0x6c, 0x61, 0x41, 0xbb, 0xd7, 0xc1, 0x83, 0xb1, 0xf0, 0x95, 0x57, 0x68, 0x43, 0xe7, 0xdc, 0xea, - 0x46, 0x6b, 0x67, 0x34, 0x1e, 0x00, 0xed, 0xdc, 0x37, 0xc1, 0xbb, 0xd1, 0x07, 0x9a, 0x9b, 0xa0, - 0xcd, 0x3a, 0x4d, 0xe8, 0x04, 0x40, 0x07, 0x1d, 0x26, 0xf0, 0xb4, 0x69, 0x1a, 0xe5, 0xad, 0x04, - 0xaf, 0x03, 0x86, 0x36, 0x63, 0x74, 0x85, 0x44, 0xfc, 0x20, 0xb5, 0x2a, 0xc3, 0xf8, 0xf1, 0xe3, - 0xc5, 0xd6, 0xa3, 0xdd, 0x61, 0xa4, 0x69, 0xb0, 0x55, 0xae, 0xa0, 0xa0, 0x80, 0xd7, 0x5b, 0x29, - 0x33, 0x33, 0xd3, 0x60, 0x7e, 0x8e, 0x97, 0x7f, 0x21, 0x21, 0x21, 0x06, 0xd3, 0xb5, 0x25, 0xa2, - 0xd5, 0x14, 0x70, 0xa5, 0xf3, 0x2d, 0x55, 0xdc, 0x2c, 0x42, 0xe5, 0x78, 0xa6, 0x14, 0xff, 0x6e, - 0x84, 0x6b, 0x34, 0x88, 0xf9, 0x74, 0xa4, 0x5d, 0x21, 0xcb, 0xbf, 0x69, 0xfb, 0xb9, 0x11, 0x74, - 0x01, 0xae, 0x84, 0x7d, 0xf9, 0x65, 0x63, 0x4d, 0x8b, 0x5f, 0x7e, 0xf9, 0x85, 0xc4, 0xca, 0xec, - 0xc4, 0x41, 0x65, 0xef, 0xde, 0xbd, 0x8d, 0xda, 0x5d, 0x53, 0x53, 0x03, 0x47, 0x62, 0x6e, 0xc9, - 0xe5, 0xea, 0x4b, 0xb2, 0xe7, 0xe6, 0xe6, 0x8a, 0x6e, 0x29, 0xc7, 0x4f, 0x22, 0xf9, 0x52, 0x83, - 0x4e, 0x9f, 0x7c, 0x8f, 0x3d, 0xf6, 0x98, 0x20, 0xfb, 0xd8, 0xb1, 0x63, 0x45, 0xd4, 0x2b, 0xaf, - 0xbc, 0x22, 0xfc, 0xd3, 0xa6, 0x4d, 0x53, 0x92, 0x1e, 0x3e, 0x7c, 0x58, 0x62, 0x3f, 0x15, 0x2a, - 0xad, 0x5c, 0xb9, 0x52, 0x09, 0xe7, 0x97, 0xb5, 0x6b, 0xd7, 0x8a, 0x70, 0x95, 0x4a, 0x25, 0x51, - 0xc5, 0xe2, 0x9d, 0xd3, 0x69, 0x77, 0x21, 0xf6, 0x93, 0xf4, 0x96, 0x14, 0x1a, 0x1a, 0x2a, 0x7d, - 0xf8, 0xe1, 0x87, 0x22, 0x0d, 0xb1, 0x63, 0x44, 0x39, 0xda, 0xf7, 0xca, 0x6b, 0xd6, 0xac, 0x91, - 0xe6, 0xcf, 0x9f, 0xaf, 0x94, 0xa7, 0x53, 0x91, 0xc6, 0xc3, 0xdd, 0xa0, 0x91, 0xe3, 0x0a, 0x6c, - 0x6d, 0x6d, 0x45, 0xf8, 0xec, 0xd9, 0xb3, 0x45, 0x01, 0x8d, 0x12, 0x51, 0x40, 0x53, 0x00, 0x70, - 0x18, 0xff, 0x64, 0xb7, 0x7b, 0xf7, 0x6e, 0xe1, 0x97, 0x01, 0x90, 0x11, 0xa2, 0x7d, 0x4b, 0x3f, - 0x71, 0xe2, 0x44, 0x25, 0xcf, 0xf0, 0xe1, 0xc3, 0xc5, 0xbb, 0xf6, 0x25, 0xf8, 0x9c, 0x39, 0x73, - 0x44, 0x98, 0x7c, 0xf1, 0x2d, 0x97, 0xcd, 0xcf, 0x46, 0x5d, 0x88, 0x2a, 0xc7, 0x86, 0x0d, 0x1b, - 0x84, 0xcc, 0x0f, 0x6f, 0x09, 0xb6, 0x6f, 0xdf, 0x8e, 0x4f, 0x3e, 0xf9, 0x84, 0x83, 0x5b, 0xe5, - 0xf4, 0xbb, 0x47, 0x6c, 0x6c, 0xac, 0x28, 0xe7, 0xc7, 0x1f, 0x7f, 0x84, 0xfc, 0xe3, 0x0d, 0xde, - 0x33, 0xcf, 0x3c, 0x23, 0xc2, 0xe9, 0xa6, 0x5f, 0x3c, 0xb5, 0x0f, 0xfa, 0xac, 0xf6, 0xcb, 0x8e, - 0x25, 0xbc, 0x1a, 0x39, 0x6d, 0x68, 0xb4, 0xdf, 0x29, 0xa1, 0x64, 0x6f, 0x6f, 0xaf, 0x60, 0x46, - 0x3b, 0x4e, 0x7e, 0xe7, 0x34, 0xfa, 0x5d, 0x88, 0xfa, 0xad, 0xc8, 0xc3, 0xb7, 0xec, 0xec, 0x64, - 0x71, 0x04, 0x99, 0x02, 0xac, 0x07, 0xc1, 0xf9, 0xb8, 0x6b, 0xc8, 0x8e, 0x05, 0x39, 0xba, 0x77, - 0xef, 0x2e, 0xbc, 0x4b, 0x97, 0x2e, 0x15, 0xf1, 0x8f, 0x3f, 0xfe, 0xb8, 0x1c, 0x2d, 0xfc, 0x9c, - 0xa7, 0x29, 0xd7, 0x74, 0x28, 0xa5, 0x94, 0xc7, 0xc2, 0x82, 0x05, 0x0b, 0x74, 0xf2, 0x9d, 0x39, - 0x73, 0x46, 0x29, 0x90, 0x0b, 0x95, 0x7f, 0xfd, 0xfa, 0xf5, 0x13, 0xe9, 0xca, 0xca, 0xca, 0x94, - 0x30, 0x8e, 0xa3, 0x13, 0x98, 0xe2, 0x97, 0x0b, 0xba, 0xef, 0xbe, 0xfb, 0x94, 0x30, 0x39, 0xbf, - 0x0c, 0x00, 0xa7, 0x19, 0x30, 0x60, 0x40, 0xa3, 0x78, 0x9a, 0x18, 0xe4, 0xec, 0x3a, 0x4f, 0x83, - 0x00, 0x70, 0xaa, 0x43, 0x87, 0x0e, 0xe9, 0x24, 0x36, 0xc6, 0xc3, 0xe2, 0x33, 0x69, 0x69, 0x69, - 0xcd, 0x66, 0x09, 0x0f, 0x0f, 0x97, 0x18, 0x21, 0xd4, 0x55, 0x9b, 0x4c, 0x17, 0x1c, 0x1c, 0x2c, - 0x34, 0x50, 0x9a, 0x8c, 0xd4, 0x04, 0x76, 0xee, 0x46, 0xa9, 0x0b, 0x98, 0xd4, 0x35, 0x39, 0x0b, - 0x99, 0xb4, 0x45, 0x46, 0x56, 0xde, 0x09, 0x80, 0x91, 0x08, 0x6b, 0xf7, 0xe4, 0x9d, 0x14, 0x68, - 0x77, 0x94, 0x1a, 0x59, 0xe0, 0x2d, 0x4f, 0x81, 0x5b, 0x7e, 0x1d, 0x30, 0x92, 0x60, 0x37, 0x5d, - 0xf2, 0x5b, 0xbe, 0x07, 0xdd, 0x74, 0x18, 0x35, 0xb2, 0x41, 0x9d, 0x04, 0x30, 0x12, 0x61, 0xed, - 0x9d, 0xbc, 0xd5, 0x2c, 0x89, 0xf6, 0x6e, 0x48, 0x7b, 0x94, 0x47, 0xdb, 0x6b, 0x30, 0xb7, 0x20, - 0x92, 0xf4, 0x5b, 0xe2, 0xff, 0x38, 0x8f, 0xab, 0x99, 0x29, 0xc4, 0xb4, 0x6a, 0x80, 0x25, 0xab, - 0x4b, 0xd1, 0x75, 0x28, 0x2b, 0xbc, 0xd5, 0x54, 0x55, 0x88, 0xcb, 0x8a, 0x9e, 0xa4, 0xd8, 0x39, - 0x74, 0xd8, 0x48, 0x0c, 0xf1, 0xf3, 0x17, 0xba, 0x60, 0xcc, 0x3d, 0x30, 0x85, 0xfb, 0x8f, 0x58, - 0x03, 0xf8, 0xdc, 0x7e, 0x81, 0xac, 0x36, 0x1d, 0xda, 0xb7, 0x1b, 0x52, 0x5d, 0x95, 0x50, 0xc4, - 0xe3, 0xdb, 0xae, 0x41, 0x43, 0xfd, 0x90, 0x4a, 0xda, 0xb3, 0xf9, 0xb9, 0x57, 0xc5, 0x0d, 0x2a, - 0x13, 0xa2, 0x47, 0x4f, 0x4f, 0x38, 0xd3, 0x7d, 0x5d, 0x66, 0x72, 0x12, 0xcc, 0xea, 0x49, 0xf3, - 0xaa, 0xa6, 0x1a, 0xb5, 0xc4, 0x16, 0xb8, 0x9f, 0x44, 0x1d, 0xfc, 0x02, 0x02, 0xda, 0x74, 0x5f, - 0xdd, 0x1a, 0x02, 0xde, 0xf2, 0x04, 0x28, 0x20, 0x3b, 0x2c, 0xdf, 0x6f, 0xda, 0x40, 0x36, 0x41, - 0x6a, 0x30, 0xff, 0xb9, 0x05, 0x38, 0x73, 0xea, 0x38, 0xbe, 0xfe, 0xf2, 0x0b, 0xf8, 0xf6, 0x1b, - 0x48, 0x42, 0x61, 0x0e, 0x64, 0xa0, 0xe4, 0x02, 0x6a, 0xea, 0xaa, 0x49, 0xe3, 0xd7, 0x9e, 0x2e, - 0x89, 0x00, 0x1b, 0x6b, 0x15, 0x7a, 0xf7, 0xe8, 0x8d, 0xda, 0xca, 0x32, 0x14, 0x94, 0x14, 0x21, - 0x68, 0xde, 0x7c, 0xf8, 0x0e, 0x09, 0xc0, 0x57, 0xab, 0x3e, 0xa1, 0x5b, 0x60, 0x5b, 0x3c, 0x49, - 0x0a, 0xb9, 0x2c, 0x2d, 0xd4, 0x51, 0xee, 0xa6, 0x23, 0x00, 0xf3, 0xb9, 0x99, 0x1b, 0xa4, 0xcd, - 0x11, 0x32, 0x84, 0x8c, 0x52, 0x12, 0x5e, 0xf8, 0x6a, 0xcd, 0x2a, 0x12, 0xd6, 0x1c, 0x8a, 0x00, - 0x52, 0xc1, 0x5e, 0xb1, 0xec, 0x4d, 0x24, 0x5f, 0x4a, 0xa0, 0x1b, 0xb8, 0x2a, 0xe2, 0x68, 0x55, - 0x23, 0xd0, 0x7f, 0x38, 0x89, 0x1b, 0x76, 0xc5, 0x05, 0x92, 0x0f, 0xc8, 0x27, 0xd9, 0x1a, 0x96, - 0x97, 0xec, 0xef, 0xd3, 0x9f, 0xf4, 0x0d, 0x2b, 0x10, 0x97, 0x10, 0x07, 0x73, 0x2b, 0x4b, 0xb8, - 0x38, 0x39, 0xc0, 0xc5, 0xbd, 0x1b, 0x96, 0x2c, 0xfb, 0x0c, 0x1b, 0x56, 0x7f, 0x4e, 0x56, 0xc5, - 0xf2, 0xc9, 0xd4, 0xe3, 0x7b, 0x42, 0x24, 0xc5, 0x50, 0xbd, 0xed, 0x19, 0x6e, 0x32, 0x02, 0x14, - 0xd3, 0x45, 0x71, 0x64, 0x78, 0x18, 0xd9, 0xe3, 0xb9, 0x40, 0x06, 0x80, 0x2e, 0xc1, 0x82, 0xae, - 0xee, 0xbb, 0x93, 0x5d, 0x18, 0x47, 0x07, 0x47, 0x61, 0xe1, 0x26, 0x3b, 0xfb, 0x2a, 0x4a, 0x48, - 0xa0, 0xa8, 0xab, 0x47, 0x57, 0x78, 0xf5, 0x1b, 0x80, 0xc1, 0xb7, 0x07, 0x92, 0xc2, 0x65, 0x3f, - 0x1d, 0xd8, 0x43, 0xce, 0x9c, 0x42, 0x44, 0x58, 0x28, 0x49, 0x4a, 0x05, 0xe1, 0xe3, 0x15, 0xef, - 0x21, 0xea, 0x7c, 0x18, 0xc9, 0x34, 0xf0, 0x5c, 0xde, 0x40, 0x92, 0x86, 0x35, 0x42, 0x14, 0x66, - 0xc4, 0x9d, 0xe3, 0xd0, 0xc5, 0xc7, 0x97, 0x64, 0x3b, 0xcd, 0x60, 0x49, 0xb7, 0xed, 0x15, 0xb9, - 0x99, 0x88, 0x8f, 0x3c, 0x8d, 0x92, 0xb2, 0x62, 0x61, 0x89, 0x80, 0xe7, 0x7e, 0xbe, 0x23, 0xf6, - 0xea, 0x7f, 0x1b, 0x16, 0xbd, 0xf9, 0x1e, 0x36, 0xaf, 0x59, 0x89, 0x6e, 0x3d, 0x7b, 0xe1, 0x09, - 0x1a, 0x4d, 0x1d, 0xe1, 0x3a, 0x9c, 0x00, 0xb1, 0x71, 0x71, 0xf8, 0x85, 0x2c, 0xf1, 0x65, 0x5c, - 0x4e, 0x84, 0xab, 0xab, 0x8b, 0x30, 0x71, 0x38, 0x3d, 0xe8, 0xcf, 0xb8, 0x3d, 0xa0, 0xb1, 0x29, - 0x27, 0xbe, 0xd9, 0x59, 0x4b, 0x92, 0x91, 0x16, 0x34, 0xaf, 0x5f, 0x25, 0xbb, 0x76, 0x2a, 0x12, - 0x51, 0xbe, 0xeb, 0x9e, 0xfb, 0x30, 0x6d, 0xc6, 0x4c, 0x71, 0x23, 0x74, 0xf4, 0xd0, 0x01, 0x44, - 0x9e, 0x39, 0x41, 0x97, 0xe5, 0xe6, 0x42, 0x4a, 0x80, 0xe5, 0x31, 0x78, 0x21, 0x6e, 0xa0, 0x05, - 0xa0, 0xa4, 0xb4, 0x04, 0xb6, 0xbd, 0xfa, 0xa2, 0xc2, 0xdc, 0x0e, 0x25, 0x57, 0xd3, 0x31, 0x6e, - 0xfc, 0xbd, 0x34, 0x3a, 0x12, 0x91, 0x45, 0xf2, 0x4c, 0x1e, 0x24, 0x68, 0x65, 0x5d, 0xc6, 0xac, - 0x7b, 0x2b, 0x16, 0x61, 0x62, 0x66, 0x25, 0xb1, 0xf8, 0xf9, 0xd6, 0xd8, 0x52, 0xb0, 0x18, 0xbb, - 0xd2, 0x3a, 0x31, 0xff, 0xa5, 0xd7, 0x3a, 0x02, 0xff, 0x6d, 0x17, 0x91, 0x68, 0x69, 0x2b, 0x79, - 0x77, 0xb2, 0x81, 0xee, 0xc0, 0xf3, 0x68, 0x67, 0xf2, 0xf8, 0xb3, 0x2f, 0x82, 0x0d, 0x13, 0x25, - 0x26, 0x5c, 0xc4, 0xde, 0x1d, 0xff, 0xc6, 0xe1, 0xbd, 0x3b, 0x49, 0xfe, 0x23, 0x07, 0x77, 0xdf, - 0x7b, 0xaf, 0x20, 0x08, 0x97, 0x19, 0x4f, 0x32, 0x20, 0xfb, 0x77, 0x6d, 0x43, 0x3d, 0x89, 0x93, - 0x7a, 0xf4, 0xf3, 0xc5, 0xc2, 0xa5, 0xff, 0x10, 0xc2, 0x30, 0x87, 0x0f, 0xfc, 0x8c, 0x37, 0x5e, - 0x7e, 0x0e, 0x73, 0x9f, 0x78, 0x86, 0xe6, 0x6a, 0x77, 0xd8, 0x38, 0xb9, 0x62, 0xca, 0xcc, 0x20, - 0x2c, 0x25, 0xe3, 0x5f, 0x31, 0xd1, 0x91, 0xa8, 0x22, 0x3b, 0x9c, 0x36, 0xb6, 0x0e, 0x98, 0x10, - 0xf4, 0xbf, 0xe8, 0xd2, 0xdd, 0x07, 0x66, 0x95, 0xe5, 0x28, 0x2d, 0xb2, 0xc5, 0x8e, 0x1f, 0xb6, - 0xc3, 0xbd, 0x7b, 0x4f, 0x58, 0x35, 0xd4, 0xe0, 0x44, 0xf0, 0x7e, 0x94, 0x55, 0x94, 0xd0, 0x7a, - 0x60, 0x23, 0xa6, 0x3a, 0x6b, 0xb2, 0xa4, 0xd0, 0x7f, 0x90, 0x1f, 0x5e, 0x7f, 0x7b, 0x19, 0xbe, - 0xdb, 0xb0, 0x16, 0x2e, 0xbc, 0x82, 0x77, 0x90, 0xeb, 0x90, 0x11, 0xc0, 0xc8, 0x5f, 0xf5, 0xcf, - 0x95, 0xa8, 0x26, 0x81, 0xfb, 0xb7, 0xfe, 0xef, 0x1f, 0x3a, 0xf3, 0x7b, 0x16, 0x09, 0x2f, 0x6f, - 0xd9, 0xb4, 0x1e, 0x12, 0x09, 0x71, 0xf6, 0x19, 0x70, 0x1b, 0x66, 0x3c, 0xf4, 0x30, 0x22, 0xc2, - 0x23, 0x71, 0xea, 0xc8, 0xcf, 0x42, 0x26, 0x72, 0xfc, 0xd4, 0x99, 0xb8, 0x9f, 0x24, 0xb2, 0x65, - 0xc7, 0x3d, 0x3c, 0xf6, 0x8f, 0x68, 0x6c, 0xfb, 0x6e, 0x33, 0x86, 0xdf, 0x39, 0x1a, 0x31, 0x64, - 0xaf, 0xf2, 0x81, 0x47, 0xe6, 0x90, 0xa1, 0x07, 0x27, 0x3c, 0xfd, 0xf8, 0x1c, 0x58, 0x3a, 0xb8, - 0x22, 0x70, 0xfc, 0x14, 0xda, 0x76, 0x9a, 0x8b, 0x6d, 0xa7, 0x19, 0x8d, 0x0e, 0x2b, 0x6b, 0x2b, - 0x21, 0xb1, 0x1d, 0x1f, 0x7e, 0x06, 0xaa, 0x0a, 0x9e, 0xd6, 0xdc, 0x11, 0x4d, 0x8b, 0x33, 0xdb, - 0x5c, 0xb0, 0x55, 0xd1, 0x68, 0x20, 0x42, 0x6c, 0xfc, 0x76, 0x27, 0xa2, 0xff, 0x88, 0x45, 0xc8, - 0xd1, 0xfd, 0x78, 0x76, 0xd1, 0xdb, 0xe8, 0xde, 0xa3, 0xa7, 0x5c, 0xe5, 0x0d, 0x7d, 0x76, 0x08, - 0x01, 0x8e, 0x90, 0x39, 0xd9, 0xe0, 0xc3, 0xfb, 0x31, 0x6b, 0xde, 0x13, 0x18, 0x34, 0x84, 0xc4, - 0x52, 0x68, 0x37, 0xc2, 0x5c, 0x7f, 0x79, 0xe7, 0x4d, 0x26, 0x1b, 0x71, 0xfc, 0xd4, 0x69, 0xd4, - 0x5b, 0xa9, 0xc8, 0x4a, 0x09, 0x84, 0xed, 0xce, 0x82, 0xd4, 0x8b, 0x98, 0x4c, 0x32, 0xf8, 0x93, - 0xa7, 0x4d, 0x17, 0x37, 0x80, 0xa5, 0x15, 0x55, 0x08, 0xbb, 0x98, 0x8c, 0xf2, 0x7a, 0x0b, 0x38, - 0xd2, 0xb5, 0x28, 0xd9, 0x4d, 0x12, 0x53, 0x0f, 0x8b, 0xbf, 0xb0, 0x71, 0x16, 0x6b, 0x92, 0x1e, - 0x49, 0x23, 0xe9, 0xf3, 0xac, 0xcc, 0x34, 0xd8, 0x68, 0x90, 0x6a, 0x4e, 0x06, 0x2a, 0x2c, 0x48, - 0x24, 0xac, 0x9c, 0x16, 0xeb, 0xe3, 0xbb, 0xb7, 0x20, 0xe2, 0xd4, 0x61, 0xb8, 0x7b, 0x74, 0xc7, - 0xe8, 0x11, 0x81, 0x70, 0x76, 0xb0, 0x47, 0x5c, 0x52, 0x32, 0x86, 0xdf, 0x35, 0x0e, 0xaf, 0x2c, - 0x7a, 0x83, 0x2c, 0xdd, 0xed, 0x05, 0x13, 0xe8, 0xb9, 0xc5, 0x4b, 0xe0, 0xd9, 0xc7, 0xeb, 0x86, - 0x22, 0x5d, 0xbb, 0xf0, 0x0e, 0x21, 0xc0, 0xce, 0xed, 0xdb, 0x10, 0xf5, 0xfb, 0x49, 0xd8, 0x58, - 0x59, 0x93, 0x78, 0x65, 0xbd, 0x98, 0xa7, 0xb9, 0x11, 0xbc, 0x7f, 0x67, 0x31, 0x65, 0x4b, 0xd7, - 0x6e, 0xb8, 0x9c, 0x57, 0x02, 0x4b, 0x42, 0xa6, 0x9f, 0xff, 0x30, 0x44, 0x87, 0x87, 0xa2, 0x9e, - 0xe6, 0x7b, 0x73, 0xb2, 0xce, 0x6b, 0x59, 0x53, 0x81, 0xb1, 0x0f, 0xcd, 0xc5, 0xe0, 0xc0, 0x61, - 0xb8, 0x9c, 0x98, 0x80, 0xcb, 0x49, 0x97, 0x85, 0x40, 0x95, 0xf6, 0xc1, 0x89, 0xb2, 0x09, 0x22, - 0x55, 0x14, 0x17, 0x91, 0xc1, 0xea, 0x04, 0xda, 0xdd, 0x58, 0x93, 0xa5, 0x68, 0x67, 0x61, 0xfa, - 0x84, 0x89, 0x60, 0x45, 0x7e, 0x7b, 0x92, 0xd1, 0xce, 0xc9, 0x48, 0x45, 0x02, 0x69, 0x8f, 0xb8, - 0x39, 0x3b, 0xa1, 0xbb, 0xb3, 0x3d, 0xdc, 0x5c, 0xc8, 0x02, 0xb0, 0x9d, 0x13, 0x0a, 0x0a, 0xf2, - 0x10, 0x38, 0x6a, 0x1c, 0x66, 0x3e, 0x4c, 0x23, 0xa8, 0x15, 0xca, 0x47, 0xda, 0x08, 0x35, 0xf6, - 0xbd, 0x43, 0x4e, 0xc2, 0x96, 0x74, 0x3f, 0x5e, 0x49, 0x5b, 0xc3, 0xfb, 0xe8, 0xb0, 0x33, 0x76, - 0xdc, 0x3d, 0xd7, 0x64, 0xa0, 0xa8, 0xb5, 0x2c, 0x5a, 0xc1, 0x23, 0xa4, 0xf4, 0xd8, 0x49, 0xe4, - 0x16, 0x16, 0x63, 0xef, 0x9e, 0x9d, 0xb0, 0xb6, 0x73, 0xc4, 0xd0, 0x11, 0xbe, 0x18, 0x33, 0x7e, - 0x3c, 0xec, 0x1d, 0xed, 0x71, 0x81, 0xa6, 0x9c, 0x9f, 0x76, 0xec, 0xa4, 0x59, 0x45, 0x7d, 0xc9, - 0x2f, 0x90, 0xcf, 0x58, 0xd7, 0x72, 0x1c, 0x56, 0x57, 0x5b, 0x4d, 0x8b, 0x73, 0x8d, 0xd8, 0x45, - 0x99, 0x93, 0x99, 0x16, 0x1b, 0x5a, 0x94, 0x2d, 0xe9, 0x59, 0x4e, 0xf2, 0xe6, 0x39, 0x39, 0x57, - 0x89, 0x20, 0x36, 0xf0, 0x1b, 0x33, 0x09, 0x56, 0x15, 0xa4, 0xaa, 0x40, 0x46, 0x0a, 0xeb, 0xad, - 0x7b, 0x60, 0xfc, 0x8c, 0x07, 0x11, 0x38, 0x7c, 0xa4, 0x56, 0x49, 0x1d, 0xfb, 0xda, 0x21, 0x04, - 0x98, 0x3a, 0x6d, 0x06, 0x22, 0x49, 0xd3, 0x20, 0xf4, 0xe4, 0x09, 0x41, 0x00, 0x6d, 0x79, 0x16, - 0x36, 0xa9, 0x74, 0x2e, 0xf8, 0x04, 0x32, 0xa3, 0xce, 0xc2, 0xaa, 0xab, 0x17, 0x66, 0x3d, 0xf5, - 0x12, 0xa9, 0x0f, 0x79, 0x22, 0x23, 0xe5, 0x32, 0xa2, 0xce, 0xfd, 0x2e, 0xb4, 0x12, 0xb8, 0x17, - 0x9b, 0x6b, 0x58, 0x05, 0xac, 0xa5, 0xa0, 0x83, 0x7a, 0x75, 0xf7, 0xa7, 0x11, 0x60, 0x2e, 0x6e, - 0xb3, 0x7b, 0xf7, 0xe9, 0x8f, 0x3b, 0xc8, 0xec, 0x92, 0x03, 0x11, 0xce, 0x82, 0xe4, 0x24, 0x39, - 0xbc, 0x24, 0x3f, 0x0b, 0xf6, 0x16, 0x75, 0xb0, 0xe3, 0xc3, 0x18, 0x9f, 0xc6, 0xa8, 0x2c, 0x47, - 0x12, 0x72, 0xcb, 0x48, 0xcf, 0x20, 0x02, 0xd9, 0x8a, 0x11, 0xa9, 0x3d, 0xa2, 0x3a, 0x92, 0x04, - 0x1d, 0x32, 0x05, 0x31, 0x40, 0xa5, 0xb4, 0x2d, 0xfc, 0xe2, 0x93, 0x0f, 0x49, 0x3d, 0xa9, 0x1a, - 0x73, 0x9f, 0x7e, 0x09, 0x3e, 0xde, 0x5e, 0x60, 0xed, 0xa1, 0x6f, 0xbe, 0x5c, 0x83, 0x2b, 0xa9, - 0x97, 0xd0, 0xd3, 0x7f, 0x14, 0x3c, 0x7d, 0xfd, 0x68, 0x0e, 0xcf, 0x40, 0x49, 0x51, 0x11, 0xcc, - 0x69, 0x4e, 0x67, 0xfe, 0x8d, 0xda, 0x26, 0x8b, 0x06, 0xe5, 0xfc, 0x60, 0x42, 0x68, 0x7a, 0x3f, - 0x2f, 0xc8, 0xea, 0x85, 0x44, 0x3d, 0x32, 0xf2, 0xc9, 0x2e, 0x96, 0x17, 0x99, 0xcc, 0x09, 0x7a, - 0xe4, 0x61, 0xd8, 0x92, 0x68, 0xbc, 0xb9, 0xb9, 0x05, 0xad, 0x0f, 0x16, 0x48, 0x4b, 0x8c, 0x47, - 0x2e, 0xed, 0xbe, 0xd8, 0x06, 0x10, 0x13, 0x93, 0x91, 0xcd, 0xd2, 0x27, 0xa5, 0xc5, 0x25, 0x74, - 0x42, 0x56, 0xe1, 0xf6, 0xdb, 0xfd, 0x95, 0xdd, 0x57, 0x47, 0x22, 0x9f, 0xeb, 0xea, 0x30, 0x02, - 0x70, 0x65, 0x8c, 0xb0, 0xa8, 0xf3, 0x91, 0xd8, 0xf2, 0xd5, 0x3a, 0x74, 0x71, 0xb0, 0x15, 0xbb, - 0x90, 0x22, 0x42, 0x76, 0x17, 0xaf, 0x41, 0x70, 0xa6, 0x9e, 0x5b, 0x4d, 0xd2, 0x99, 0xe5, 0x64, - 0x34, 0x46, 0xb6, 0x8a, 0xc3, 0x88, 0x16, 0x38, 0xe7, 0xcc, 0xe4, 0x64, 0x91, 0x4d, 0xb5, 0x4f, - 0xf3, 0x5f, 0x43, 0x04, 0x46, 0x36, 0x1b, 0xa3, 0x49, 0xf9, 0x23, 0x12, 0x36, 0xa4, 0x83, 0x66, - 0x47, 0x82, 0xe5, 0x3c, 0xd2, 0xb8, 0xac, 0x2c, 0xd2, 0xf1, 0xc9, 0xa5, 0x38, 0x1b, 0x92, 0x92, - 0x67, 0xd1, 0x67, 0x3e, 0x65, 0xf3, 0xd4, 0xc4, 0xd4, 0x7b, 0xe6, 0xd9, 0x67, 0x30, 0x63, 0x06, - 0xe9, 0xbd, 0x75, 0xf0, 0xdc, 0x2f, 0xc3, 0xd0, 0x21, 0x53, 0x90, 0x5c, 0x19, 0xf7, 0xbc, 0x00, - 0xd2, 0xd8, 0xf2, 0x5f, 0xbd, 0x81, 0x6c, 0xaa, 0x97, 0x22, 0x34, 0xe4, 0x0c, 0x19, 0xdc, 0x3f, - 0x48, 0xe6, 0xb7, 0x92, 0x61, 0xe1, 0x4a, 0x22, 0xd5, 0x36, 0x76, 0x84, 0xb0, 0x7a, 0xf5, 0x1a, - 0xa1, 0xe9, 0xf4, 0x9c, 0x57, 0xfd, 0x4a, 0xe8, 0x97, 0x3b, 0xbc, 0xa6, 0x40, 0x65, 0x04, 0x70, - 0x02, 0xfa, 0x35, 0x90, 0x1e, 0x52, 0x83, 0x15, 0x59, 0x7c, 0xa3, 0x83, 0x94, 0x9b, 0xbb, 0xbb, - 0xd8, 0x5e, 0x72, 0x8f, 0xaf, 0xa6, 0xd3, 0x76, 0x35, 0xe9, 0x1c, 0xa9, 0x48, 0xdf, 0x88, 0x91, - 0xce, 0x32, 0xb7, 0x6c, 0xab, 0xac, 0x92, 0x76, 0x52, 0x0e, 0x34, 0x2d, 0x99, 0x0a, 0xf9, 0x0c, - 0x46, 0x87, 0x8e, 0x00, 0xae, 0xb0, 0x29, 0x77, 0x22, 0x38, 0x18, 0x61, 0x71, 0x17, 0x50, 0x55, - 0x4f, 0x6a, 0x40, 0x84, 0x14, 0xa2, 0x80, 0x1a, 0xeb, 0x9a, 0xd9, 0x86, 0x15, 0xb8, 0x18, 0xc7, - 0xe4, 0x15, 0x8e, 0x09, 0xa1, 0x38, 0xf2, 0x70, 0x38, 0xcf, 0xf5, 0xcc, 0x6a, 0x8e, 0x0e, 0xff, - 0x1d, 0xb9, 0xa4, 0xd0, 0xc8, 0x06, 0x0f, 0x2d, 0xa8, 0x97, 0xf3, 0x3a, 0x20, 0x0a, 0xa3, 0x44, - 0xd6, 0xb4, 0x1b, 0x72, 0xa2, 0xed, 0xe7, 0x8c, 0xa9, 0x93, 0x31, 0x93, 0x4e, 0xd3, 0x2c, 0x20, - 0xed, 0xe2, 0xe2, 0x62, 0x52, 0x02, 0x74, 0xe8, 0x08, 0x50, 0x90, 0xa6, 0xf7, 0xc2, 0xfa, 0x88, - 0xb5, 0xb5, 0xf5, 0x64, 0x49, 0x99, 0x50, 0xcd, 0xc8, 0xe7, 0x1f, 0x3b, 0x41, 0x07, 0x35, 0xf2, - 0x99, 0x02, 0x9a, 0x37, 0x75, 0x9c, 0x42, 0x04, 0x0a, 0xe5, 0x75, 0x81, 0xf2, 0xd0, 0x4a, 0x40, - 0x73, 0xbe, 0x25, 0x6a, 0xe9, 0xdd, 0x42, 0x50, 0x8c, 0xfd, 0x34, 0xdd, 0xd0, 0xf4, 0xc2, 0xd3, - 0x11, 0x13, 0xc4, 0x52, 0x65, 0x27, 0x90, 0xce, 0x22, 0x96, 0x37, 0x83, 0xbb, 0x29, 0x08, 0xc0, - 0x53, 0x02, 0x9f, 0x0f, 0xd8, 0xa2, 0x9b, 0x50, 0x9a, 0xd0, 0x10, 0xe0, 0x5a, 0x4f, 0x57, 0xb0, - 0xad, 0x8b, 0x33, 0x26, 0x8a, 0x48, 0x44, 0x44, 0xa0, 0x77, 0x6b, 0x95, 0x0a, 0x7f, 0xba, 0x67, - 0x92, 0x50, 0x89, 0xac, 0xa7, 0xc2, 0xb8, 0x87, 0x73, 0x38, 0x8b, 0xf8, 0x5b, 0x10, 0x21, 0xc4, - 0x30, 0x22, 0x7f, 0x58, 0x6c, 0x22, 0x02, 0xfc, 0x53, 0xe0, 0xe5, 0xe5, 0xad, 0x5b, 0x9e, 0x09, - 0x7c, 0x37, 0x09, 0x01, 0xd4, 0xc6, 0xce, 0xea, 0x6a, 0x1b, 0x50, 0x40, 0x9f, 0xc8, 0xa8, 0x22, - 0xc5, 0x6e, 0x81, 0x39, 0x0d, 0x42, 0xb8, 0x83, 0xcb, 0xc8, 0x23, 0xfc, 0x09, 0x0f, 0x8f, 0x14, - 0x4b, 0x9a, 0x52, 0x5c, 0x69, 0xae, 0xe7, 0x45, 0x95, 0x0f, 0x75, 0x15, 0xe5, 0xb5, 0xb4, 0x88, - 0x97, 0x22, 0x3f, 0x3f, 0x0f, 0xb5, 0xb4, 0xeb, 0xf2, 0xed, 0xef, 0x03, 0x57, 0x9a, 0x62, 0xb2, - 0x49, 0x37, 0xf5, 0x6a, 0x61, 0x09, 0x11, 0x88, 0xec, 0xf1, 0x91, 0xd6, 0x8b, 0x8a, 0xb4, 0x3a, - 0x79, 0xd4, 0xdd, 0x0c, 0xee, 0xa6, 0x20, 0x40, 0x2d, 0x69, 0xd0, 0x94, 0x14, 0x17, 0xc3, 0x8c, - 0x0e, 0x4a, 0x3c, 0x5d, 0xd8, 0xd2, 0xfc, 0xad, 0xee, 0xd9, 0x6a, 0x14, 0xf1, 0x3b, 0xd3, 0x80, - 0x9d, 0xe8, 0xf0, 0xe4, 0x11, 0x53, 0x15, 0xcd, 0xfb, 0x0d, 0x34, 0x72, 0x04, 0x7d, 0x34, 0x08, - 0x2d, 0x25, 0x36, 0xb7, 0x05, 0x1d, 0xc6, 0xe6, 0xcc, 0x0e, 0x42, 0xaf, 0xde, 0x9e, 0xe2, 0x8a, - 0x92, 0x17, 0xdc, 0x18, 0x92, 0x4c, 0x3d, 0x75, 0x2e, 0x02, 0x55, 0xbc, 0x00, 0x13, 0xfb, 0x59, - 0x8c, 0x08, 0x75, 0x91, 0x26, 0xfd, 0x7f, 0x53, 0x10, 0x20, 0x90, 0x58, 0xd1, 0x07, 0x8f, 0x9d, - 0xa0, 0xcb, 0x90, 0x22, 0xfa, 0xa4, 0x4a, 0x03, 0x8d, 0x80, 0x0a, 0x42, 0x30, 0xe1, 0x45, 0xee, - 0xf9, 0x02, 0x45, 0x72, 0xdf, 0x57, 0xe3, 0x4b, 0x8c, 0x00, 0x42, 0xa4, 0x9d, 0x1d, 0xed, 0x6c, - 0xcc, 0x79, 0x04, 0xa9, 0x39, 0x98, 0xb6, 0x36, 0x56, 0xa4, 0x4e, 0x5e, 0x8b, 0xe3, 0x27, 0x83, - 0x71, 0xf7, 0xb8, 0x71, 0x74, 0xb1, 0xe2, 0x84, 0xb4, 0xf4, 0x74, 0x84, 0x86, 0x45, 0x90, 0x96, - 0x75, 0x2d, 0x2a, 0x4b, 0xcb, 0x70, 0xfb, 0x9d, 0x81, 0xf0, 0xd4, 0xd8, 0x4a, 0x34, 0x29, 0xf6, - 0x19, 0x44, 0xea, 0x5d, 0x6a, 0xc8, 0x4c, 0xdc, 0x12, 0xb6, 0x78, 0xf9, 0xe5, 0xc6, 0x8d, 0xd8, - 0x4f, 0x26, 0x6c, 0xa9, 0x51, 0xc4, 0x2a, 0xb6, 0x16, 0x97, 0x34, 0xbc, 0xb0, 0x32, 0x0b, 0xe2, - 0xda, 0x1e, 0x88, 0x1b, 0xaa, 0x6e, 0xb2, 0x39, 0x19, 0xd2, 0x30, 0x63, 0x2d, 0x71, 0xe1, 0xd5, - 0x10, 0x88, 0x1e, 0x75, 0xc4, 0xe5, 0xac, 0x25, 0xb6, 0x34, 0xdf, 0xae, 0xd5, 0x13, 0x6b, 0x99, - 0x17, 0x6f, 0x3e, 0x00, 0xfb, 0xf9, 0xfb, 0xe3, 0x89, 0x27, 0xe6, 0x83, 0x4c, 0xc1, 0x89, 0x69, - 0xcb, 0xc4, 0x20, 0x8b, 0xea, 0x6f, 0x1a, 0x02, 0xdc, 0x0c, 0xc8, 0x30, 0x45, 0x1b, 0x68, 0x6b, - 0xd0, 0xe9, 0x4c, 0x89, 0x81, 0x4e, 0x02, 0x98, 0x12, 0xfb, 0x54, 0x77, 0x27, 0x01, 0xfe, 0x9b, - 0x09, 0xc0, 0x8c, 0xb8, 0xff, 0x76, 0x67, 0x92, 0x11, 0xc0, 0xd2, 0x0e, 0xcc, 0x98, 0x63, 0x76, - 0x00, 0x3f, 0xe5, 0x8f, 0x41, 0x1a, 0x43, 0x0c, 0x52, 0x33, 0x15, 0x1f, 0x02, 0xe0, 0xfc, 0xfa, - 0x3f, 0x52, 0xdc, 0x32, 0xa6, 0x28, 0x93, 0xa6, 0x35, 0xc9, 0x39, 0x80, 0x35, 0x3d, 0xe9, 0x43, - 0x3b, 0xe0, 0xef, 0x05, 0xd2, 0x37, 0x72, 0xc0, 0x9f, 0x10, 0x32, 0xd6, 0xf5, 0x24, 0x19, 0x22, - 0x52, 0xb4, 0x04, 0x29, 0x5c, 0x8a, 0xed, 0x26, 0xd9, 0xb6, 0x05, 0x7f, 0x7f, 0x8a, 0x1d, 0x29, - 0xab, 0x19, 0x5b, 0x9c, 0xc9, 0xd2, 0xb7, 0x68, 0x1b, 0x4a, 0xdf, 0x45, 0xd4, 0xe9, 0xa5, 0xfc, - 0x95, 0x12, 0xed, 0x8f, 0x5b, 0xf2, 0x05, 0x79, 0x52, 0x52, 0x92, 0x72, 0x7a, 0x65, 0xd1, 0xbe, - 0x5e, 0xbd, 0x7a, 0x35, 0x09, 0x14, 0x7d, 0x3a, 0x09, 0xfc, 0xd1, 0x34, 0xd9, 0xf1, 0xc9, 0x97, - 0x4c, 0x30, 0x0b, 0x66, 0x99, 0x1c, 0x76, 0xbd, 0x27, 0xf3, 0x78, 0x52, 0x53, 0x53, 0x41, 0xda, - 0x7d, 0xe2, 0x62, 0x85, 0xd3, 0x33, 0x11, 0x49, 0xbd, 0x51, 0x64, 0x65, 0xa2, 0x30, 0x61, 0x0d, - 0x39, 0xb6, 0xfd, 0x9e, 0x90, 0x90, 0x00, 0xd6, 0xcb, 0xe4, 0x3c, 0x6c, 0x61, 0x7f, 0xc8, 0x90, - 0x21, 0xc4, 0x1b, 0xf2, 0x32, 0x94, 0x45, 0x27, 0x9c, 0xdb, 0xcf, 0x79, 0x49, 0x99, 0x8f, 0xc4, - 0x60, 0xaa, 0x44, 0xfb, 0xc9, 0x8a, 0x33, 0xd9, 0x03, 0xeb, 0xa1, 0x93, 0xae, 0x45, 0x1e, 0x3e, - 0x88, 0x35, 0xe7, 0xe6, 0xce, 0x9d, 0xcb, 0x27, 0x9c, 0x46, 0x3f, 0xd9, 0x6c, 0xf4, 0xaa, 0x55, - 0xab, 0x1a, 0xc5, 0x71, 0x7a, 0x52, 0x30, 0x6d, 0x54, 0x2c, 0x01, 0xd9, 0x64, 0x5a, 0x7d, 0x7d, - 0x51, 0xfd, 0x8c, 0xac, 0x89, 0x48, 0xca, 0xac, 0x4d, 0xe6, 0x6d, 0xaa, 0x6d, 0xac, 0x86, 0xac, - 0xef, 0x48, 0x87, 0x5a, 0xd8, 0xda, 0x6e, 0x2a, 0xbd, 0x76, 0x18, 0xe9, 0x77, 0x4b, 0x07, 0x0e, - 0x1c, 0xd0, 0xcf, 0x2e, 0x34, 0x22, 0x89, 0x75, 0x7d, 0xdd, 0x36, 0xb0, 0xed, 0xee, 0xaf, 0xbe, - 0xfa, 0xaa, 0x51, 0x7e, 0x43, 0x01, 0xdc, 0x6b, 0x5b, 0xe4, 0xb4, 0x75, 0xaf, 0xb5, 0x2d, 0xac, - 0x73, 0x66, 0x56, 0xa4, 0x95, 0x81, 0x60, 0x3d, 0x53, 0x6d, 0x55, 0x65, 0x43, 0x85, 0xcb, 0x4a, - 0xb8, 0x9c, 0xaf, 0x39, 0x02, 0xb0, 0xd2, 0x2e, 0x4d, 0x59, 0x4a, 0xf9, 0xd4, 0xcb, 0xc4, 0x17, - 0x4b, 0xe5, 0x72, 0xa9, 0x27, 0x4b, 0xde, 0xde, 0xde, 0x4a, 0x3c, 0x97, 0x27, 0x2b, 0xf6, 0xca, - 0x69, 0xe8, 0xe3, 0xc2, 0x4a, 0x3c, 0xad, 0x17, 0xd2, 0xe9, 0xd3, 0xa7, 0xe5, 0x28, 0xe5, 0xc9, - 0x6a, 0xa9, 0xb2, 0x72, 0x31, 0x97, 0xb1, 0x70, 0xe1, 0x42, 0x25, 0x8e, 0xf5, 0x75, 0x65, 0xf8, - 0xf8, 0xf9, 0xfe, 0xfb, 0xef, 0x2b, 0x71, 0xf2, 0x0b, 0x13, 0x8d, 0xcb, 0x96, 0xd3, 0x8d, 0x1a, - 0x35, 0x4a, 0x8e, 0x6a, 0xf6, 0xd9, 0x62, 0x02, 0x70, 0x2f, 0xd4, 0xee, 0xc1, 0x6c, 0x02, 0x9f, - 0x1d, 0x4d, 0x05, 0x8a, 0x42, 0x30, 0xcd, 0xcb, 0x52, 0x53, 0x3a, 0xe1, 0x4d, 0xb5, 0xa0, 0xa5, - 0x04, 0xe0, 0xaf, 0xbe, 0xc9, 0x40, 0xf1, 0x33, 0x25, 0x25, 0xa5, 0x51, 0x71, 0xc5, 0xc5, 0xc5, - 0x3a, 0x69, 0xf4, 0x09, 0x30, 0x6e, 0xdc, 0x38, 0x9d, 0x78, 0xed, 0xf2, 0x0c, 0xbd, 0xcb, 0x96, - 0xe9, 0x49, 0xa8, 0x4c, 0xe2, 0x51, 0x21, 0xa7, 0xfb, 0xcb, 0x5f, 0xfe, 0xd2, 0xa8, 0x7e, 0x39, - 0x40, 0x7f, 0x36, 0x60, 0x5d, 0xe2, 0xeb, 0xb9, 0x16, 0xef, 0x82, 0x78, 0xa7, 0x41, 0x05, 0x92, - 0xd9, 0x4d, 0x77, 0x6a, 0x0b, 0xc0, 0x9f, 0x47, 0xdf, 0xb6, 0x6d, 0x1b, 0x5d, 0x68, 0xdf, 0x2e, - 0x16, 0x41, 0xde, 0xd1, 0xf0, 0x9c, 0xc8, 0x26, 0x1a, 0xda, 0xd3, 0xe9, 0xcf, 0xcb, 0x11, 0x11, - 0x11, 0x8d, 0x8a, 0xe7, 0x76, 0x35, 0xe7, 0xe8, 0x03, 0x78, 0x4a, 0x34, 0xaf, 0x4f, 0xbc, 0xa6, - 0x11, 0x62, 0x9a, 0xfd, 0xc9, 0x7a, 0xfb, 0xfc, 0x79, 0xee, 0x11, 0x23, 0x46, 0x28, 0xf9, 0xe9, - 0x5b, 0x0b, 0x42, 0x28, 0x4c, 0x09, 0xd0, 0x7a, 0xd1, 0x36, 0x2f, 0xc1, 0x97, 0xfe, 0xcc, 0x73, - 0xba, 0xae, 0xbb, 0x1e, 0x85, 0xf4, 0xe3, 0xb3, 0xb2, 0xb2, 0x74, 0x7a, 0x04, 0x55, 0x20, 0x3e, - 0x4e, 0xcc, 0x73, 0xac, 0x21, 0xc7, 0xa3, 0x62, 0xd6, 0xac, 0x59, 0xe2, 0x93, 0x84, 0xb4, 0x78, - 0x4b, 0xfc, 0xe3, 0xb9, 0x92, 0xf3, 0xf2, 0x8f, 0xe7, 0x56, 0x39, 0x9c, 0x08, 0x2a, 0xcc, 0x4e, - 0x68, 0x97, 0xa5, 0x3f, 0x05, 0xf0, 0x34, 0xf4, 0xdc, 0x73, 0xcf, 0x49, 0x2f, 0xbe, 0xf8, 0xa2, - 0xe4, 0xe9, 0xe9, 0xa9, 0x94, 0x23, 0x97, 0x47, 0x8b, 0xaa, 0xb4, 0x75, 0xeb, 0x56, 0xed, 0x22, - 0xa4, 0xa7, 0x9f, 0x7e, 0x5a, 0x27, 0x1d, 0x7f, 0xcb, 0x98, 0xdb, 0xc4, 0x1f, 0x99, 0x60, 0xab, - 0x12, 0xac, 0xae, 0x2f, 0xe7, 0xe7, 0x27, 0xa7, 0x97, 0x1d, 0x2d, 0xb4, 0xe2, 0x5b, 0x0e, 0xda, - 0xf1, 0xbc, 0x06, 0xb2, 0xf5, 0x88, 0x37, 0xdf, 0x7c, 0x53, 0xe2, 0xe9, 0x46, 0x3b, 0x8e, 0xcb, - 0xbe, 0x9e, 0xa6, 0xbd, 0x5c, 0x76, 0x8b, 0xa7, 0x20, 0x39, 0x03, 0x3f, 0x13, 0x13, 0x13, 0x25, - 0x32, 0x1e, 0x25, 0x2a, 0x65, 0x64, 0x34, 0x87, 0x7c, 0x4e, 0x4f, 0xbb, 0x0e, 0xf1, 0xe1, 0x09, - 0xda, 0xf1, 0xe8, 0x34, 0x54, 0xbb, 0xd1, 0xf2, 0x3b, 0x8d, 0x24, 0xf1, 0xb1, 0x49, 0xce, 0xa7, - 0xed, 0xe8, 0x43, 0x77, 0xd2, 0xb2, 0x65, 0xcb, 0x74, 0xe6, 0x69, 0xce, 0xc3, 0x84, 0x3b, 0x7a, - 0xf4, 0xa8, 0x98, 0x97, 0xe5, 0x39, 0x98, 0xbf, 0xe6, 0xb1, 0x7a, 0xf5, 0x6a, 0xed, 0xec, 0xca, - 0xfb, 0xae, 0x5d, 0xbb, 0x0c, 0x2e, 0xc6, 0x6c, 0x47, 0xe4, 0xd5, 0x57, 0x5f, 0x95, 0x64, 0x63, - 0x11, 0x4a, 0x26, 0xcd, 0x0b, 0x77, 0x24, 0x26, 0x18, 0xcd, 0x02, 0x8d, 0xe0, 0xe0, 0xf5, 0xe3, - 0xf9, 0xe7, 0x9f, 0x97, 0xe4, 0x0f, 0x7a, 0xe8, 0xe7, 0x35, 0xe4, 0x6f, 0xd1, 0x36, 0x94, 0x00, - 0xed, 0x74, 0x37, 0x08, 0x03, 0x2d, 0x5e, 0x03, 0x6e, 0x50, 0xfd, 0xff, 0xf5, 0xc5, 0x76, 0x12, - 0xc0, 0xc4, 0x5d, 0xa0, 0x93, 0x00, 0x9d, 0x04, 0x30, 0x31, 0x06, 0x4c, 0x5c, 0x7d, 0xe7, 0x08, - 0xe8, 0x24, 0x80, 0x89, 0x31, 0x60, 0xe2, 0xea, 0x3b, 0x47, 0x40, 0x27, 0x01, 0x4c, 0x8c, 0x01, - 0x13, 0x57, 0xff, 0xff, 0x2d, 0xb1, 0x75, 0xfd, 0xe9, 0xfe, 0xa1, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXXMLIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x30, 0x39, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x9d, - 0x3c, 0x78, 0xe3, 0x00, 0x00, 0x05, 0x7c, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x58, 0x59, - 0x4c, 0x1b, 0x57, 0x14, 0xc5, 0x0b, 0xbb, 0xc1, 0x26, 0xa2, 0x31, 0x56, 0x58, 0x4c, 0xb1, 0x1b, - 0x37, 0x15, 0x8e, 0x42, 0x05, 0x94, 0x25, 0x88, 0x25, 0x6c, 0x05, 0x52, 0x14, 0x0a, 0xfd, 0xa8, - 0x08, 0x1f, 0x91, 0xe0, 0x83, 0x02, 0xa2, 0x2a, 0x6a, 0xfb, 0xd3, 0x82, 0x00, 0x15, 0x3e, 0x8a, - 0x8a, 0x10, 0x42, 0x42, 0x4a, 0xbf, 0x10, 0x12, 0x84, 0x06, 0xd5, 0x12, 0x15, 0x5b, 0x49, 0x0a, - 0x51, 0x31, 0x34, 0xdd, 0x00, 0xa5, 0xb5, 0x4d, 0x42, 0x83, 0xa1, 0x24, 0x0a, 0xc4, 0x94, 0x60, - 0x03, 0xb6, 0xb1, 0x7b, 0x9d, 0x57, 0xdc, 0x67, 0x9b, 0x24, 0xe3, 0x19, 0x3b, 0x08, 0x69, 0x46, - 0x23, 0xfb, 0xbe, 0xf3, 0xee, 0xbd, 0xef, 0xdc, 0x7b, 0xdf, 0x32, 0x33, 0x0c, 0xb3, 0xd9, 0xec, - 0x71, 0x9c, 0x2f, 0xe6, 0x71, 0x26, 0x6f, 0xe1, 0x4e, 0x07, 0x70, 0xd4, 0x15, 0xa4, 0x2b, 0x40, - 0x57, 0x80, 0x62, 0x06, 0xe8, 0x29, 0x44, 0x31, 0x81, 0x94, 0xcd, 0xe9, 0x0a, 0x50, 0x4e, 0x21, - 0x45, 0x07, 0x74, 0x05, 0x28, 0x26, 0x90, 0xb2, 0x39, 0x5d, 0x81, 0xc3, 0x52, 0xa8, 0xff, 0x67, - 0xdb, 0x11, 0x36, 0xea, 0x76, 0x3d, 0x4c, 0xae, 0x7f, 0xf2, 0x75, 0x71, 0x05, 0x36, 0x15, 0xcb, - 0xb7, 0x9b, 0xbe, 0x1e, 0x2e, 0xfe, 0xd4, 0x31, 0x80, 0xf5, 0xdf, 0x94, 0xdf, 0x15, 0x7d, 0xac, - 0xec, 0x19, 0x36, 0x3c, 0xd1, 0x39, 0xf6, 0x92, 0x46, 0xd8, 0xa4, 0x2d, 0x6d, 0x0c, 0x4d, 0xe6, - 0xd5, 0x1f, 0x7e, 0x51, 0xf5, 0x8d, 0xad, 0xff, 0xae, 0x02, 0x9c, 0xe5, 0xed, 0x69, 0xd3, 0x7b, - 0xd0, 0xd0, 0x3d, 0xd8, 0x98, 0xeb, 0xbc, 0x76, 0xe7, 0xaa, 0x2c, 0x3c, 0x37, 0x41, 0x5c, 0x72, - 0x21, 0x40, 0x28, 0x38, 0xe8, 0x21, 0xff, 0x4f, 0x35, 0x00, 0xc3, 0x96, 0x76, 0x49, 0x36, 0xb5, - 0xf8, 0xcd, 0x04, 0x90, 0x23, 0xc8, 0xc2, 0xb8, 0xbb, 0x77, 0x6f, 0xf0, 0x26, 0xdc, 0xfc, 0xb8, - 0x33, 0xa2, 0x92, 0x4c, 0x41, 0x92, 0x94, 0xa0, 0xe1, 0xa1, 0x6a, 0xe4, 0x03, 0xd8, 0x5a, 0xfa, - 0x7b, 0xb1, 0x7f, 0x7c, 0x79, 0x58, 0x0e, 0x84, 0x70, 0xd7, 0xbe, 0xc1, 0x3c, 0x61, 0x7e, 0x32, - 0x8e, 0x20, 0x99, 0x2b, 0x0a, 0x8b, 0xc8, 0x49, 0x58, 0xb9, 0xf9, 0xf3, 0xfe, 0xae, 0x1e, 0x21, - 0x0f, 0x67, 0xef, 0xc0, 0xcd, 0x09, 0xe3, 0x8b, 0xde, 0x4d, 0x07, 0x13, 0xb6, 0x9f, 0x8f, 0xa3, - 0xd5, 0x0b, 0x11, 0x86, 0xd3, 0xaf, 0x94, 0x66, 0xf3, 0xda, 0x8f, 0xf3, 0x8b, 0xfd, 0x63, 0x30, - 0x36, 0xee, 0x9d, 0xc9, 0x66, 0x0b, 0x92, 0xa5, 0xc2, 0xfc, 0xf3, 0x82, 0x84, 0x68, 0x0f, 0x26, - 0x03, 0xef, 0xc2, 0x65, 0xc3, 0xf6, 0x8e, 0x7a, 0x54, 0x0e, 0x45, 0xd3, 0x28, 0xee, 0xe3, 0xb8, - 0xa7, 0xbf, 0xaf, 0x30, 0x2f, 0x49, 0x54, 0x9c, 0xe1, 0x1f, 0x7a, 0x12, 0xc7, 0x5f, 0x28, 0x3b, - 0x1d, 0xc0, 0xad, 0x0f, 0xbf, 0x7a, 0x30, 0x3d, 0x8f, 0xfb, 0xe5, 0x46, 0x85, 0x42, 0xfe, 0x20, - 0xbb, 0x5e, 0x3c, 0x0e, 0x8e, 0x3f, 0x5f, 0xde, 0x54, 0x2e, 0x43, 0x18, 0x10, 0x8c, 0x1e, 0x5b, - 0xd3, 0x0c, 0x06, 0xe3, 0xcd, 0x4f, 0xca, 0x84, 0x17, 0xcf, 0x3f, 0xdf, 0x16, 0xef, 0x75, 0x7a, - 0x0a, 0xe9, 0x37, 0xff, 0xdf, 0x22, 0x4f, 0xa5, 0xc6, 0x48, 0x2e, 0xe7, 0x05, 0xbd, 0x2e, 0xc4, - 0x3d, 0x12, 0x94, 0x79, 0xaf, 0x85, 0x9f, 0xfb, 0xe8, 0xfd, 0xb3, 0x55, 0x25, 0x30, 0xa9, 0xfe, - 0xb8, 0x2a, 0x7b, 0xa2, 0x7e, 0x08, 0x86, 0x30, 0x1d, 0x76, 0x35, 0x5b, 0x04, 0x3d, 0x20, 0x35, - 0xa7, 0x03, 0xc0, 0xbd, 0xaf, 0xdd, 0x9a, 0x63, 0x30, 0x98, 0x91, 0x85, 0x29, 0xfc, 0xb8, 0x37, - 0x70, 0x9c, 0xa0, 0x6c, 0xda, 0x33, 0xa8, 0xbf, 0xff, 0x69, 0x49, 0x36, 0x89, 0xd8, 0x13, 0xb4, - 0xb2, 0x53, 0x73, 0x3a, 0x80, 0xc8, 0x77, 0x52, 0x20, 0x49, 0x68, 0xcf, 0x31, 0x19, 0x8d, 0x2b, - 0x37, 0x6e, 0xc3, 0xed, 0x2f, 0x08, 0x06, 0x1c, 0x26, 0xb1, 0x4f, 0x30, 0xcf, 0x6e, 0x80, 0x43, - 0x9b, 0x68, 0xfe, 0x2c, 0x8f, 0xc8, 0x0d, 0xdb, 0x36, 0x67, 0xc2, 0x2b, 0xe7, 0x4e, 0x3b, 0x9b, - 0x0b, 0xa7, 0xd7, 0x80, 0x85, 0x90, 0xed, 0xae, 0x6f, 0xa5, 0xc8, 0x64, 0xb3, 0x04, 0x89, 0x52, - 0x88, 0x24, 0xe4, 0xad, 0xc3, 0xd7, 0x31, 0x1c, 0xc6, 0xea, 0xd1, 0x99, 0x7b, 0xdf, 0x4e, 0x6a, - 0xfe, 0xfc, 0xcb, 0x6a, 0x05, 0x02, 0xd3, 0x93, 0x1d, 0x9e, 0x15, 0x2f, 0x2a, 0xb9, 0x00, 0xf3, - 0x0a, 0xc7, 0x89, 0xc8, 0xa4, 0x02, 0x38, 0x70, 0xbc, 0xa9, 0xb8, 0xaf, 0xea, 0x1b, 0x57, 0x8f, - 0xcf, 0x9a, 0x0c, 0xc6, 0x03, 0xcc, 0xf2, 0xcf, 0x09, 0x3d, 0x99, 0x73, 0xed, 0x0b, 0x1c, 0x01, - 0xf9, 0xf1, 0xc2, 0xdd, 0xc9, 0xaa, 0x2f, 0xed, 0xf6, 0x5c, 0x9f, 0x13, 0xdc, 0xa8, 0x4b, 0xa9, - 0xaf, 0x5e, 0x4a, 0xf5, 0x0e, 0x0a, 0xb4, 0xd3, 0x27, 0xd8, 0x74, 0x7a, 0x0a, 0xe1, 0x7e, 0x79, - 0xa7, 0x23, 0x62, 0x3f, 0xbb, 0x22, 0xfd, 0xa0, 0xf8, 0x2e, 0x1c, 0x4c, 0xd7, 0x6f, 0xec, 0x3e, - 0xfe, 0x6f, 0xfd, 0xed, 0x3c, 0xd2, 0xe0, 0x6a, 0x48, 0xd6, 0x6f, 0x69, 0x71, 0xf6, 0x41, 0x92, - 0x08, 0x71, 0x49, 0x66, 0x58, 0x66, 0x1c, 0x83, 0xcd, 0x72, 0x54, 0x26, 0x8e, 0x50, 0x0a, 0x00, - 0x0d, 0xe3, 0x7d, 0x22, 0xf0, 0xcc, 0x95, 0x8b, 0x92, 0xcb, 0x6f, 0xab, 0xc7, 0x66, 0xe1, 0x68, - 0xb3, 0xdb, 0xe0, 0xed, 0xa8, 0x30, 0x58, 0xcc, 0x53, 0x29, 0x31, 0xa2, 0xf7, 0x2e, 0x04, 0x9f, - 0x15, 0xdb, 0x75, 0x91, 0x6c, 0xc2, 0xce, 0xe5, 0xda, 0xeb, 0xd1, 0xaf, 0x8a, 0x99, 0xcf, 0xbb, - 0x1d, 0x7d, 0x02, 0x3e, 0xd7, 0xd1, 0xaf, 0x5d, 0x5b, 0x77, 0xec, 0xa2, 0x82, 0x50, 0x5a, 0x03, - 0x24, 0x73, 0xe6, 0x52, 0x33, 0x17, 0x3f, 0x4e, 0xbb, 0x94, 0x1b, 0x21, 0x67, 0x74, 0x00, 0x84, - 0xd2, 0xe4, 0x46, 0x25, 0xba, 0x02, 0x6e, 0x4c, 0x2e, 0x21, 0xd7, 0x74, 0x05, 0x08, 0xa5, 0xc9, - 0x8d, 0x4a, 0xc7, 0xbe, 0x02, 0x2e, 0x78, 0x94, 0x20, 0x9d, 0xde, 0xfd, 0xfd, 0x7d, 0x38, 0x83, - 0xc1, 0x9c, 0xcd, 0x26, 0x4f, 0xe3, 0xc8, 0x2a, 0x50, 0x5d, 0x5d, 0xed, 0xe5, 0xe5, 0xe5, 0xf9, - 0xf4, 0x6a, 0x6f, 0x6f, 0x27, 0x9d, 0x85, 0x23, 0x0b, 0x20, 0x32, 0x32, 0x32, 0x2a, 0x2a, 0xca, - 0xd7, 0xd7, 0x17, 0xa8, 0x6b, 0xb5, 0xda, 0xe3, 0x17, 0x40, 0x6d, 0x6d, 0xad, 0x52, 0xa9, 0xcc, - 0xc8, 0xc8, 0x20, 0x4d, 0x1d, 0x19, 0x92, 0xa9, 0xc0, 0xf4, 0xf4, 0x74, 0x7a, 0x7a, 0x7a, 0x7c, - 0x7c, 0x7c, 0x72, 0x72, 0xf2, 0xd4, 0xd4, 0xd4, 0xc8, 0xc8, 0x48, 0x62, 0x62, 0x22, 0x34, 0x8b, - 0x8a, 0x8a, 0x76, 0x76, 0x76, 0x64, 0x32, 0x59, 0x52, 0x52, 0x52, 0x5a, 0x5a, 0x5a, 0x67, 0x67, - 0x27, 0x9f, 0xcf, 0x17, 0x8b, 0xc5, 0xbd, 0xbd, 0xbd, 0x31, 0x31, 0x31, 0x21, 0x21, 0x21, 0xf5, - 0xf5, 0xf5, 0x7b, 0x7b, 0x36, 0x1f, 0x91, 0x28, 0xb2, 0xb7, 0x98, 0x93, 0x78, 0x94, 0x6d, 0x69, - 0x69, 0xb1, 0x0e, 0xdc, 0xd4, 0xd4, 0x54, 0x57, 0x57, 0x67, 0x6d, 0xaa, 0x54, 0xaa, 0xaa, 0xaa, - 0x2a, 0x6b, 0xd3, 0x51, 0x80, 0x60, 0xf0, 0x11, 0xf3, 0xf3, 0xf3, 0x41, 0xa7, 0xb9, 0xb9, 0x19, - 0x07, 0x9d, 0x92, 0xc9, 0x54, 0xa0, 0xa6, 0xa6, 0x66, 0x70, 0x70, 0x90, 0xc7, 0xb3, 0xbc, 0xbf, - 0x4b, 0xa5, 0x52, 0x89, 0x44, 0x02, 0x42, 0x6e, 0x6e, 0xee, 0xcc, 0xcc, 0x8c, 0x48, 0x24, 0x6a, - 0x6c, 0x6c, 0x84, 0x6a, 0x00, 0x52, 0x5a, 0x5a, 0x3a, 0x3e, 0x3e, 0x0e, 0x02, 0x5c, 0x43, 0x43, - 0x43, 0xe5, 0xe5, 0xe5, 0x20, 0xcc, 0xcf, 0xdb, 0x7c, 0x53, 0x7a, 0xda, 0x49, 0xe9, 0x87, 0xcc, - 0xfe, 0xe5, 0xe3, 0xe3, 0x53, 0x58, 0x58, 0xc8, 0xe5, 0x72, 0xb3, 0xb3, 0xb3, 0xcb, 0xca, 0xca, - 0x74, 0x3a, 0x5d, 0x74, 0x74, 0x74, 0x5f, 0x5f, 0x5f, 0x40, 0x40, 0x00, 0x70, 0x01, 0x1c, 0x66, - 0x0b, 0x08, 0x79, 0x79, 0x79, 0xb1, 0xb1, 0xb1, 0x20, 0xc0, 0x4e, 0x93, 0x95, 0x95, 0xb5, 0xb2, - 0xb2, 0x02, 0xb2, 0x46, 0x73, 0xc8, 0xdb, 0x26, 0xe0, 0xa4, 0x2f, 0x32, 0x15, 0x40, 0x83, 0xc1, - 0x2c, 0x6f, 0x68, 0x68, 0x00, 0x42, 0x30, 0xad, 0x3b, 0x3a, 0x3a, 0x10, 0x7b, 0x9c, 0x87, 0x9f, - 0x9f, 0x1f, 0x7c, 0x69, 0x03, 0x04, 0x02, 0x80, 0x9d, 0x1e, 0xc9, 0x26, 0x93, 0x09, 0xd7, 0xa1, - 0x2e, 0x93, 0x0f, 0x00, 0x32, 0xda, 0xd5, 0xd5, 0x05, 0xd5, 0x00, 0x12, 0x15, 0x15, 0x15, 0x1b, - 0x1b, 0x44, 0xbf, 0x4e, 0x53, 0x27, 0x8d, 0x7b, 0x20, 0x19, 0x00, 0xd0, 0xcd, 0xc9, 0xc9, 0x59, - 0x5d, 0x5d, 0x1d, 0x18, 0x18, 0xa8, 0xac, 0xac, 0x54, 0x28, 0x14, 0x05, 0x05, 0x05, 0xd6, 0xed, - 0x1c, 0x56, 0x21, 0x8c, 0x81, 0x7e, 0xf1, 0xc1, 0x70, 0x19, 0x4a, 0x61, 0x34, 0x1a, 0x91, 0x0e, - 0x2e, 0xe3, 0x3a, 0x84, 0x64, 0xa7, 0x96, 0x3c, 0x52, 0x86, 0xa5, 0x89, 0x12, 0x0f, 0xc7, 0x90, - 0x5c, 0x2e, 0x6f, 0x6d, 0x6d, 0x45, 0x23, 0x41, 0x73, 0x62, 0x62, 0xa2, 0xad, 0xad, 0x0d, 0xcd, - 0x96, 0xc0, 0xc0, 0xc0, 0x85, 0x85, 0x05, 0xd4, 0x05, 0x4b, 0xbc, 0xbb, 0xbb, 0x1b, 0x64, 0x16, - 0x8b, 0xd5, 0xd3, 0xd3, 0x03, 0x26, 0x8e, 0x8f, 0x0f, 0x1c, 0x0e, 0x67, 0x74, 0x74, 0xd4, 0x59, - 0x3e, 0x64, 0x2a, 0x00, 0xfc, 0xe0, 0x29, 0x00, 0xd8, 0x80, 0x00, 0x59, 0xd4, 0xeb, 0xf5, 0x88, - 0xb1, 0x15, 0x64, 0x32, 0x2d, 0x6e, 0x81, 0x22, 0x5c, 0xe8, 0xac, 0x05, 0x04, 0x2d, 0x12, 0x08, - 0x00, 0x28, 0x82, 0x3e, 0x32, 0x41, 0xe1, 0xa1, 0x5f, 0x47, 0x04, 0xef, 0x7d, 0x96, 0x4c, 0x7f, - 0x95, 0x78, 0x56, 0x66, 0x5e, 0x16, 0x4e, 0x66, 0x0a, 0xbd, 0x2c, 0x6e, 0x84, 0xc6, 0xa1, 0x03, - 0x20, 0x94, 0x26, 0x37, 0x2a, 0xd1, 0x15, 0x70, 0x63, 0x72, 0x09, 0xb9, 0xa6, 0x2b, 0x40, 0x28, - 0x4d, 0x6e, 0x54, 0xa2, 0x2b, 0xe0, 0xc6, 0xe4, 0x12, 0x72, 0x4d, 0x57, 0x80, 0x50, 0x9a, 0xdc, - 0xa8, 0xf4, 0x2f, 0x8a, 0xf9, 0x6c, 0x7c, 0x9d, 0x47, 0x95, 0x15, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXXMLIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0e, 0x6d, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x1d, 0x69, 0x74, 0x54, 0xd5, 0xf9, 0x9b, 0xcc, 0x64, 0x9f, 0xec, 0x54, 0x16, 0x13, 0xb6, 0x20, - 0x02, 0x0a, 0x28, 0x2a, 0x04, 0xb1, 0x2d, 0x50, 0x6c, 0x2d, 0x16, 0xb4, 0x28, 0x76, 0x53, 0xaa, - 0xb5, 0x96, 0x9e, 0x23, 0x15, 0x0a, 0x47, 0xa4, 0x2d, 0x82, 0x4b, 0xed, 0xb1, 0xd5, 0x42, 0x6b, - 0x51, 0xb1, 0x0b, 0xf0, 0xc3, 0x96, 0xd3, 0x5a, 0x2c, 0x16, 0x5a, 0x6c, 0xd5, 0x42, 0x85, 0xb0, - 0x06, 0x01, 0x29, 0x90, 0xb0, 0x19, 0x16, 0xc3, 0x96, 0xc9, 0x64, 0x9b, 0x2c, 0x93, 0x99, 0x79, - 0xfd, 0xbe, 0x1b, 0xef, 0xcd, 0xbc, 0x37, 0xf3, 0xde, 0xcc, 0x7b, 0x33, 0xef, 0x91, 0xe0, 0x7b, - 0xe7, 0x24, 0xef, 0xdb, 0xee, 0x77, 0xbf, 0xe5, 0x2e, 0x6f, 0xb9, 0xef, 0x8e, 0x43, 0xc2, 0x03, - 0x74, 0x1c, 0x29, 0x3a, 0x64, 0x99, 0x68, 0xe2, 0x05, 0x6a, 0xb7, 0x8d, 0x65, 0x9a, 0xa4, 0xa0, - 0x8f, 0x9d, 0x39, 0x2e, 0x2c, 0x21, 0x1f, 0xf8, 0x71, 0x69, 0xeb, 0x2d, 0x1c, 0x94, 0xd4, 0x60, - 0x07, 0x49, 0x88, 0xd2, 0x08, 0x84, 0xda, 0x6a, 0x20, 0x25, 0xa3, 0x5f, 0x38, 0x49, 0x06, 0x47, - 0x14, 0x90, 0x71, 0xa3, 0x20, 0x89, 0x3b, 0xad, 0x54, 0xea, 0x70, 0x38, 0x64, 0xa4, 0x88, 0x1a, - 0xb8, 0x00, 0x3f, 0xcb, 0xa4, 0x11, 0x31, 0xdf, 0x07, 0xf3, 0x6b, 0x88, 0x70, 0x5a, 0xe9, 0xa4, - 0x12, 0x97, 0x15, 0x08, 0xfa, 0x8e, 0x81, 0x14, 0x68, 0x60, 0x32, 0xde, 0x8a, 0xaf, 0x82, 0x67, - 0xfb, 0x6d, 0x4a, 0x79, 0x00, 0xde, 0x78, 0x3c, 0x3b, 0x26, 0x71, 0x50, 0x76, 0x6e, 0xad, 0xf9, - 0xb3, 0x0c, 0x17, 0x05, 0xc2, 0xa9, 0xbc, 0xe1, 0x79, 0x76, 0x7d, 0x39, 0x9c, 0xcc, 0xe0, 0xee, - 0x1e, 0x25, 0x1e, 0x92, 0x8a, 0x8a, 0x0a, 0x18, 0x36, 0x6c, 0x18, 0x47, 0x65, 0x67, 0xf3, 0x7d, - 0xd0, 0x5d, 0x83, 0xcc, 0xbe, 0x38, 0x10, 0x59, 0xcb, 0x88, 0x43, 0x5e, 0xb7, 0x88, 0xa1, 0x0a, - 0x22, 0x86, 0x36, 0xad, 0x6a, 0x23, 0x9a, 0xd6, 0x27, 0x04, 0x6a, 0x7d, 0xde, 0x0f, 0xbe, 0x11, - 0xc1, 0xe6, 0xad, 0x32, 0x9c, 0x41, 0x34, 0xdf, 0x47, 0xbf, 0x0e, 0x27, 0x09, 0x38, 0x6a, 0xd3, - 0xe6, 0x5c, 0x2a, 0xe8, 0xd9, 0xf9, 0x45, 0x8e, 0xca, 0xc6, 0x5a, 0x4e, 0x24, 0x99, 0xc6, 0x23, - 0x8b, 0x38, 0x1a, 0x71, 0xd6, 0xac, 0x20, 0x5c, 0xba, 0xae, 0xe2, 0x5e, 0x29, 0xd4, 0xe1, 0x0d, - 0x27, 0xc5, 0x05, 0x77, 0xef, 0x56, 0x54, 0x5d, 0x5d, 0x0d, 0x9b, 0x37, 0x6f, 0xd6, 0x4a, 0x71, - 0xd7, 0x78, 0x14, 0xcd, 0x5f, 0x2c, 0xc9, 0xc8, 0xd7, 0x5f, 0x7f, 0xbd, 0xf4, 0xec, 0xb3, 0xcf, - 0x4a, 0x03, 0x07, 0x0e, 0xa4, 0x69, 0x8d, 0xfd, 0x71, 0x79, 0x2e, 0xc3, 0x71, 0xe5, 0x59, 0x33, - 0x07, 0x54, 0x78, 0xf7, 0xee, 0xdd, 0x42, 0x29, 0x57, 0x7e, 0xed, 0xb5, 0xd7, 0x4a, 0x4f, 0x3d, - 0xf5, 0x94, 0x8c, 0xae, 0x54, 0xcc, 0xf1, 0xee, 0x9d, 0x03, 0xf4, 0x28, 0xe6, 0xd1, 0xf3, 0x3d, - 0x30, 0x34, 0x16, 0xc5, 0x8c, 0x4b, 0x98, 0xc0, 0xa7, 0xb0, 0x82, 0x40, 0xd3, 0x41, 0x68, 0x3e, - 0xba, 0x24, 0x2c, 0x08, 0x31, 0x40, 0xde, 0x21, 0xa2, 0x9d, 0x69, 0xa4, 0xc4, 0xb1, 0x5f, 0xc6, - 0x22, 0x1a, 0x3b, 0x42, 0xed, 0x6c, 0x74, 0xf5, 0x7b, 0x77, 0xca, 0xf8, 0x4a, 0x24, 0x6a, 0x4f, - 0x6e, 0xfd, 0xf8, 0x4f, 0x51, 0x87, 0x66, 0x2a, 0x5c, 0xbb, 0xad, 0x4c, 0xa6, 0xa3, 0xe1, 0xe0, - 0xa3, 0xaa, 0xb2, 0x24, 0x18, 0xb5, 0x02, 0xb2, 0xd2, 0x57, 0xfd, 0xb2, 0x4c, 0x11, 0x21, 0xc2, - 0x7a, 0x05, 0x87, 0x79, 0x5a, 0x3e, 0x5e, 0x41, 0xed, 0x44, 0xa3, 0x56, 0x40, 0xac, 0xe6, 0x13, - 0x2f, 0x46, 0x28, 0x54, 0x56, 0x50, 0x57, 0x71, 0x4f, 0x84, 0x8c, 0xb2, 0x16, 0xd5, 0x0a, 0xb8, - 0x60, 0x6d, 0xf9, 0xad, 0x0c, 0xac, 0x8d, 0x62, 0x61, 0x47, 0xd3, 0x61, 0x2e, 0xa6, 0x7a, 0x8e, - 0xd9, 0x0f, 0x8a, 0x6e, 0x2d, 0x67, 0xcd, 0x44, 0x0a, 0x05, 0x22, 0x9a, 0x8b, 0xcb, 0x3d, 0x3c, - 0x82, 0xa6, 0x24, 0xd8, 0x63, 0x91, 0x32, 0x22, 0x11, 0x78, 0xcc, 0x1c, 0x44, 0x94, 0x08, 0x23, - 0xc4, 0x9c, 0x8f, 0x51, 0x36, 0xa1, 0x0a, 0x36, 0x6e, 0xdc, 0x18, 0x56, 0x5d, 0x74, 0x50, 0xb5, - 0x82, 0x79, 0xf3, 0xe6, 0x41, 0x6e, 0x6e, 0x2e, 0xd0, 0x3d, 0xde, 0xd9, 0xb3, 0x67, 0xd9, 0x79, - 0xcc, 0x98, 0x31, 0x40, 0x74, 0x97, 0xcb, 0x15, 0x5d, 0x5b, 0x34, 0xaa, 0x6a, 0x03, 0x46, 0x86, - 0xdb, 0xed, 0x96, 0xe6, 0xce, 0x9d, 0xcb, 0x44, 0xb0, 0xac, 0xf4, 0xc6, 0x1b, 0x6f, 0x08, 0x98, - 0x80, 0xf9, 0xf3, 0xe7, 0x33, 0x5c, 0xeb, 0x9f, 0x6a, 0x47, 0x23, 0x85, 0xfc, 0x8f, 0xae, 0x22, - 0x78, 0x05, 0x9c, 0x96, 0x97, 0x97, 0x27, 0xf8, 0xa7, 0x4f, 0x9f, 0x56, 0xad, 0xc3, 0xee, 0x07, - 0x18, 0x31, 0xed, 0x43, 0xb5, 0x15, 0x69, 0x17, 0x8b, 0x9f, 0x6b, 0x7a, 0x0e, 0xe2, 0x37, 0xc5, - 0x98, 0xa4, 0xe9, 0x11, 0x32, 0x66, 0x56, 0xfc, 0xa5, 0x6c, 0x07, 0xe2, 0x8f, 0x95, 0x39, 0x92, - 0x96, 0x65, 0x20, 0xd4, 0x5e, 0x63, 0x8a, 0x07, 0x09, 0x3b, 0xd0, 0x54, 0xb5, 0x18, 0x62, 0x3d, - 0xb6, 0xf0, 0x94, 0x8f, 0x87, 0xba, 0x3d, 0x77, 0xcb, 0x1c, 0xa0, 0x32, 0x0d, 0x07, 0xbf, 0x2f, - 0xa3, 0x19, 0x41, 0x0c, 0x8d, 0x42, 0xde, 0x8a, 0xe9, 0x10, 0x6c, 0x3b, 0xcf, 0xea, 0x73, 0x97, - 0x2e, 0x84, 0x8c, 0xbe, 0xf7, 0xaa, 0xd6, 0xed, 0xad, 0xb8, 0x1b, 0x65, 0x6b, 0xa0, 0x68, 0xfc, - 0x16, 0x70, 0x38, 0xb3, 0x64, 0x72, 0x7e, 0xcf, 0x16, 0x68, 0x3c, 0xb2, 0x90, 0xd1, 0x52, 0x5c, - 0x39, 0x50, 0x58, 0xf6, 0x9e, 0x8c, 0x1f, 0x0f, 0x12, 0xb7, 0x03, 0x9e, 0xf2, 0x32, 0x9c, 0x57, - 0x43, 0x4c, 0x67, 0xd1, 0xb8, 0x4d, 0xe0, 0x48, 0x2d, 0x8a, 0xa9, 0xbf, 0xa9, 0xea, 0x27, 0xd0, - 0x7e, 0xe9, 0x1d, 0xc8, 0x1f, 0xfd, 0x7b, 0x70, 0xe5, 0x8c, 0xd2, 0x94, 0x97, 0x82, 0x2d, 0x50, - 0xb7, 0x73, 0x0a, 0xd6, 0xd1, 0x79, 0x6d, 0xda, 0xeb, 0xb6, 0xdd, 0x9a, 0xf2, 0x9c, 0x19, 0xb7, - 0x03, 0x54, 0x20, 0xd0, 0xf4, 0x3f, 0xa8, 0x3f, 0xf0, 0x1d, 0x5e, 0x16, 0x0a, 0xc6, 0xac, 0x05, - 0x67, 0x56, 0xa9, 0xc0, 0xc3, 0x81, 0xb6, 0x73, 0x7f, 0x01, 0xbc, 0xf4, 0x87, 0xec, 0x81, 0x73, - 0x20, 0xb3, 0x78, 0x56, 0x38, 0x4b, 0x06, 0x87, 0xfc, 0x97, 0xa0, 0x6e, 0xf7, 0x9d, 0x82, 0x96, - 0x3b, 0xe2, 0x05, 0x48, 0x2b, 0xfc, 0xbc, 0xc0, 0x63, 0x01, 0xba, 0x1c, 0x50, 0x2a, 0xf3, 0xee, - 0x99, 0x06, 0xc1, 0xf6, 0x0b, 0x8c, 0x9c, 0x3f, 0xea, 0x35, 0x70, 0xe5, 0xde, 0xc8, 0xe0, 0x40, - 0x73, 0x25, 0xd4, 0xef, 0x9f, 0x05, 0xe9, 0x45, 0x9f, 0x85, 0x9c, 0xe1, 0xbf, 0x54, 0x16, 0x83, - 0x90, 0xbf, 0x16, 0x8d, 0x9e, 0xca, 0xe8, 0x29, 0x2e, 0x37, 0x36, 0x9d, 0x77, 0x10, 0x76, 0x46, - 0xc8, 0xc5, 0x43, 0x48, 0xc8, 0x81, 0xa8, 0x15, 0x84, 0xda, 0xa1, 0x76, 0xfb, 0x67, 0x21, 0x25, - 0xad, 0x17, 0x14, 0x8e, 0xfd, 0x67, 0x54, 0x91, 0x64, 0x12, 0x93, 0xef, 0x00, 0x5a, 0xe7, 0xaf, - 0x7d, 0x0f, 0xd2, 0x7a, 0x7d, 0x21, 0x99, 0x76, 0xaa, 0xea, 0x32, 0xc5, 0x01, 0xd5, 0xda, 0x4c, - 0x60, 0x24, 0x3c, 0x0f, 0x98, 0x60, 0x93, 0x2e, 0x95, 0x3d, 0xde, 0x01, 0x1d, 0xb7, 0x6f, 0xba, - 0x02, 0x13, 0x53, 0x38, 0xfc, 0x8d, 0x21, 0xde, 0x70, 0xc5, 0x94, 0x57, 0x13, 0x30, 0x94, 0x81, - 0xb4, 0xb4, 0x34, 0x76, 0x1b, 0xeb, 0x74, 0x3a, 0x21, 0x10, 0x08, 0x30, 0x98, 0x0c, 0x5a, 0xbf, - 0x7e, 0x3d, 0x14, 0x15, 0x15, 0x31, 0x7c, 0xd6, 0xac, 0x59, 0xec, 0x3c, 0x63, 0xc6, 0x0c, 0xc1, - 0x7f, 0xff, 0xfd, 0xf7, 0x85, 0x1d, 0x64, 0x34, 0xde, 0x95, 0x0a, 0xdc, 0x30, 0xa0, 0x7a, 0xbb, - 0x19, 0x83, 0x71, 0xe1, 0xc2, 0x05, 0x76, 0xd7, 0x8a, 0x4e, 0x48, 0x23, 0x46, 0x8c, 0x90, 0x49, - 0xa3, 0x31, 0xd2, 0xb6, 0x6d, 0xdb, 0xd8, 0x6d, 0x34, 0xc1, 0x74, 0xf0, 0x3b, 0xdf, 0x70, 0x41, - 0xba, 0xad, 0xe6, 0xfc, 0x70, 0xba, 0x1e, 0xd8, 0x50, 0x06, 0x28, 0x5a, 0x43, 0x87, 0x0e, 0x85, - 0x9c, 0x9c, 0x1c, 0x38, 0x74, 0xe8, 0x10, 0x1c, 0x3e, 0x7c, 0x18, 0x16, 0x2f, 0x5e, 0x4c, 0x64, - 0x71, 0xa4, 0xa7, 0xa7, 0x0b, 0xd8, 0x4c, 0xc0, 0x1e, 0x46, 0xcd, 0x8c, 0x6e, 0x3c, 0xba, 0x0d, - 0x37, 0xa1, 0x78, 0x94, 0x5b, 0x21, 0x63, 0x3b, 0x60, 0x45, 0x94, 0xb5, 0xea, 0xb0, 0x3b, 0xb1, - 0x56, 0x74, 0xac, 0xe0, 0xd9, 0x7d, 0xc0, 0x8a, 0x28, 0x6b, 0xd5, 0x61, 0x67, 0x40, 0x2b, 0x3a, - 0x56, 0xf0, 0xec, 0x0c, 0x58, 0x11, 0x65, 0xad, 0x3a, 0xec, 0x0c, 0x68, 0x45, 0x87, 0xf3, 0x82, - 0xbe, 0x2a, 0x0e, 0x26, 0xfd, 0x6c, 0xc9, 0x4c, 0xcc, 0x1f, 0xfe, 0xc6, 0xfb, 0xb8, 0x50, 0x8f, - 0x97, 0x09, 0x35, 0x21, 0xa9, 0xc3, 0xc3, 0x9e, 0x4c, 0xb7, 0x9c, 0x7a, 0x55, 0xb5, 0xce, 0x50, - 0xfb, 0x39, 0xc6, 0x4b, 0xcd, 0xbb, 0x41, 0xc8, 0xb4, 0x5f, 0xfa, 0x17, 0x2b, 0x17, 0x6c, 0xad, - 0x16, 0x34, 0xa3, 0x80, 0xe1, 0x9b, 0xfa, 0x86, 0x0f, 0x1f, 0x86, 0x8e, 0xc6, 0x83, 0xac, 0x5e, - 0x5c, 0xfa, 0xa6, 0x5a, 0x7f, 0xfd, 0xbe, 0x6f, 0x31, 0x5e, 0xde, 0xc8, 0x95, 0x42, 0x26, 0xd8, - 0x7a, 0x8a, 0xc1, 0xde, 0xbd, 0xf7, 0x81, 0x33, 0xb3, 0x04, 0x0a, 0x6e, 0x5a, 0x27, 0x78, 0x7a, - 0x01, 0xdd, 0x4d, 0xc8, 0x5f, 0xb7, 0x15, 0x1a, 0x0f, 0x2f, 0x60, 0xf5, 0x74, 0x3e, 0x12, 0x7f, - 0x17, 0x61, 0xf9, 0xe2, 0xe5, 0x2e, 0x23, 0x42, 0x18, 0xe9, 0x32, 0xe8, 0x7c, 0xfe, 0xf9, 0x9f, - 0x2e, 0xf2, 0x27, 0x90, 0xec, 0x31, 0xfd, 0x90, 0x45, 0x90, 0xd1, 0x67, 0x46, 0x84, 0x4c, 0x2c, - 0x82, 0x0e, 0x07, 0x42, 0xe0, 0xd9, 0x31, 0x19, 0xe8, 0x31, 0x38, 0x1d, 0xf9, 0xa3, 0x7e, 0x87, - 0x0f, 0x73, 0x47, 0x6b, 0xea, 0x6f, 0xf8, 0xf0, 0xbb, 0x98, 0xa5, 0x0f, 0xa1, 0xf0, 0x96, 0xb7, - 0x20, 0x25, 0xbd, 0x6f, 0x54, 0x59, 0xca, 0x86, 0x77, 0xef, 0x4c, 0xc6, 0x73, 0x38, 0x5c, 0xf8, - 0x1e, 0x01, 0x1d, 0x4d, 0xc9, 0x88, 0x2a, 0x1b, 0x8d, 0x18, 0x57, 0x1f, 0x68, 0x39, 0xb5, 0x92, - 0x45, 0x92, 0x8c, 0x4f, 0xff, 0xcc, 0x97, 0x80, 0x3a, 0x63, 0x2c, 0xe3, 0xa9, 0x32, 0x32, 0x9e, - 0x0e, 0x35, 0xe3, 0x89, 0xe7, 0xcc, 0x1c, 0xc0, 0xf4, 0x65, 0x15, 0xdf, 0xcf, 0xde, 0x0d, 0xd4, - 0x6e, 0xff, 0x1c, 0x34, 0x55, 0x2e, 0x22, 0x56, 0x5c, 0x47, 0x5c, 0x0e, 0xa4, 0xa4, 0x5f, 0x25, - 0x94, 0xf9, 0x3d, 0x9b, 0x69, 0x4d, 0xbe, 0xc0, 0xd5, 0x80, 0x96, 0xea, 0xdf, 0x30, 0x56, 0xee, - 0xb0, 0x9f, 0xaa, 0x89, 0x84, 0xd1, 0x43, 0xd0, 0x76, 0xfe, 0x2d, 0x81, 0x3b, 0x33, 0xae, 0x16, - 0x70, 0x2c, 0x40, 0x47, 0x13, 0x02, 0x68, 0x38, 0xf0, 0x20, 0xe0, 0x52, 0x21, 0xa6, 0x33, 0x35, - 0x6f, 0x0c, 0x84, 0x77, 0x4c, 0x65, 0x45, 0xf1, 0x0e, 0x9d, 0xf4, 0x8e, 0xad, 0xfd, 0xd2, 0xbf, - 0x59, 0x71, 0x32, 0xbc, 0xe0, 0xe6, 0xbf, 0x29, 0x55, 0x69, 0xe2, 0xba, 0x1c, 0x20, 0x4d, 0x52, - 0xb0, 0x19, 0x5f, 0x05, 0xdd, 0x8e, 0xe9, 0x0e, 0x32, 0xc5, 0x39, 0xd7, 0x2c, 0x86, 0xf4, 0xde, - 0xd3, 0x65, 0x95, 0xf8, 0xeb, 0xfe, 0x8b, 0x1d, 0xfd, 0x71, 0xc8, 0xec, 0x37, 0x13, 0xb2, 0x07, - 0x3f, 0x2e, 0xe3, 0x71, 0xa4, 0xc3, 0xbb, 0x1d, 0x1a, 0x0e, 0xcd, 0xe3, 0x28, 0xf6, 0x93, 0x0d, - 0xd8, 0xd4, 0x7a, 0x0b, 0x3c, 0x5e, 0x40, 0xb7, 0x03, 0x5c, 0xb1, 0xbf, 0xf6, 0x5d, 0x68, 0xac, - 0xfc, 0x31, 0x43, 0xe9, 0xb1, 0x62, 0xd1, 0x84, 0x5d, 0x9c, 0xc5, 0xc6, 0x78, 0x42, 0xd4, 0x26, - 0x2e, 0x0f, 0xbe, 0x00, 0x91, 0xf0, 0x45, 0x08, 0x1d, 0xee, 0xc1, 0x0b, 0x20, 0xa3, 0xdf, 0xd7, - 0x18, 0x6c, 0xe8, 0x9f, 0x9e, 0xc7, 0x78, 0xd1, 0x64, 0x71, 0x48, 0x95, 0x02, 0x2d, 0xd5, 0x82, - 0x15, 0x6c, 0xbf, 0xc8, 0x96, 0xbb, 0x79, 0xf7, 0xdd, 0x2f, 0x68, 0x4a, 0x20, 0x14, 0x68, 0x96, - 0xea, 0xf7, 0x3f, 0xa8, 0x24, 0x1b, 0xc2, 0x0d, 0x67, 0x40, 0x2d, 0x5a, 0x75, 0xbb, 0x6e, 0x87, - 0x50, 0x47, 0x03, 0xf4, 0x9a, 0xb0, 0x1d, 0xa7, 0x07, 0xc3, 0xf3, 0xa4, 0x9a, 0xfa, 0x08, 0x7a, - 0x5c, 0xa3, 0x50, 0x44, 0x29, 0x0d, 0x02, 0x19, 0xef, 0x48, 0xc1, 0xe7, 0xa2, 0x16, 0x18, 0x4f, - 0x66, 0x24, 0x3d, 0x03, 0xb4, 0x14, 0x2b, 0xd4, 0x76, 0x06, 0xe7, 0xa2, 0xfe, 0x1a, 0x6e, 0x26, - 0x8f, 0x65, 0x82, 0x03, 0xc9, 0x33, 0x2e, 0x1e, 0x4d, 0x49, 0x6f, 0x42, 0xf1, 0x54, 0x9a, 0x4c, - 0x19, 0xdb, 0x81, 0x64, 0x46, 0xd3, 0x88, 0x2e, 0x3b, 0x03, 0x46, 0xa2, 0x96, 0xcc, 0x32, 0xe6, - 0xcf, 0x34, 0x2a, 0xd6, 0xf2, 0xa5, 0xc5, 0xf8, 0x82, 0x10, 0x7a, 0xf7, 0xd6, 0x7f, 0x0d, 0x24, - 0xd4, 0x1a, 0x9a, 0xbf, 0x13, 0x2c, 0x84, 0x2b, 0x8c, 0xd9, 0xdb, 0x49, 0x34, 0x42, 0xba, 0xe3, - 0x8e, 0x3b, 0x12, 0xd2, 0x76, 0x59, 0xfa, 0xc0, 0xf2, 0xe5, 0xcb, 0xf1, 0x6a, 0x96, 0x7c, 0x48, - 0xfc, 0xd0, 0xed, 0xc0, 0x86, 0x0d, 0x1b, 0xc4, 0x8b, 0xeb, 0x75, 0xeb, 0xd6, 0x41, 0x49, 0x49, - 0x09, 0xc3, 0x53, 0x53, 0x53, 0xa1, 0xa5, 0xa5, 0x85, 0xc1, 0xc3, 0x87, 0x0f, 0x17, 0x32, 0xfc, - 0x45, 0x37, 0xae, 0x86, 0x4e, 0xdc, 0xda, 0x68, 0x1a, 0xf4, 0xe6, 0xaf, 0xa6, 0xa6, 0x46, 0xc2, - 0x77, 0xc4, 0xac, 0x09, 0xe0, 0x67, 0x6b, 0xd2, 0xcc, 0x99, 0x33, 0x19, 0x3c, 0x67, 0xce, 0x1c, - 0xa6, 0x2a, 0x3f, 0x3f, 0x9f, 0xe1, 0xab, 0x56, 0xad, 0x62, 0x67, 0xac, 0x53, 0x7a, 0xe6, 0x99, - 0x67, 0x18, 0x1c, 0x0c, 0x06, 0x65, 0xd5, 0x11, 0x2f, 0xd1, 0x26, 0x44, 0xa9, 0x34, 0x74, 0x70, - 0x27, 0xc8, 0x08, 0x8f, 0xc7, 0x23, 0x74, 0x8c, 0x1d, 0x3b, 0x96, 0x19, 0x4b, 0x84, 0x70, 0x03, - 0x09, 0x3e, 0x7a, 0xf4, 0xa8, 0x90, 0x53, 0xf2, 0x65, 0x0c, 0x1d, 0x88, 0xee, 0x26, 0x84, 0x86, - 0xb0, 0x63, 0xf5, 0xea, 0xd5, 0x1c, 0x84, 0xc2, 0xc2, 0x42, 0x01, 0x2b, 0x01, 0xb3, 0xdf, 0xd8, - 0x1b, 0x72, 0x60, 0xcf, 0x9e, 0x3d, 0x30, 0x61, 0xc2, 0x04, 0xd8, 0xb7, 0x6f, 0x9f, 0x58, 0xdc, - 0xa1, 0x34, 0xdc, 0x32, 0x5c, 0x47, 0xb6, 0x98, 0xe8, 0xda, 0xb5, 0x6b, 0x59, 0xd3, 0x40, 0x03, - 0xa5, 0xb7, 0xdf, 0x7e, 0x5b, 0xc0, 0x84, 0x1f, 0x3f, 0x7e, 0x5c, 0xe0, 0x8f, 0x3d, 0xf6, 0x98, - 0x80, 0x1b, 0x1b, 0x1b, 0x05, 0x4c, 0x4a, 0x48, 0x36, 0xda, 0x9f, 0x5e, 0x5b, 0x48, 0xde, 0xbe, - 0x9c, 0xc6, 0x48, 0x5e, 0xd6, 0xc3, 0x50, 0x1f, 0xb8, 0xac, 0x16, 0x2b, 0x2a, 0xb7, 0x1d, 0x50, - 0x04, 0xc4, 0x72, 0xd4, 0xce, 0x80, 0xe5, 0x21, 0x57, 0x54, 0x68, 0x67, 0x40, 0x11, 0x10, 0xcb, - 0xd1, 0x1e, 0x3f, 0x91, 0x59, 0x1e, 0xb1, 0x24, 0x57, 0xd8, 0xe3, 0xbb, 0x40, 0x92, 0xe3, 0x61, - 0xb9, 0x3a, 0x3b, 0x01, 0x96, 0x87, 0x5c, 0x5e, 0xa1, 0x9d, 0x00, 0x79, 0x3c, 0x2c, 0xc7, 0xec, - 0x04, 0x58, 0x1e, 0x72, 0x79, 0x85, 0x76, 0x02, 0xe4, 0xf1, 0xb0, 0x1c, 0xb3, 0x13, 0x60, 0x79, - 0xc8, 0xe5, 0x15, 0xda, 0x09, 0x90, 0xc7, 0xc3, 0x72, 0xcc, 0x4e, 0x80, 0xe5, 0x21, 0x97, 0x57, - 0x78, 0xd9, 0x5e, 0x8d, 0xc9, 0xcd, 0x48, 0x0e, 0xd6, 0x70, 0xe0, 0x21, 0xa0, 0x6f, 0xb0, 0xd3, - 0x8a, 0x26, 0xe2, 0xc7, 0xe3, 0xf7, 0x83, 0xcb, 0x7d, 0x5d, 0x72, 0x14, 0x9b, 0xa8, 0xa5, 0x5b, - 0xf4, 0x80, 0x8e, 0xfa, 0x5d, 0xd0, 0x48, 0x6b, 0xb6, 0x24, 0xbf, 0x61, 0x57, 0x9b, 0x2a, 0x7f, - 0x84, 0x8b, 0xe0, 0x0e, 0xe1, 0x6b, 0x9a, 0x20, 0xb4, 0xe3, 0x67, 0xd8, 0x6a, 0x9b, 0x26, 0x35, - 0x1f, 0x5d, 0x0a, 0xed, 0x17, 0x63, 0xef, 0x88, 0x64, 0xd8, 0x10, 0x9d, 0x05, 0x2f, 0xd3, 0xa3, - 0x08, 0x09, 0x97, 0x26, 0xbe, 0x09, 0x2d, 0xd5, 0x2f, 0x03, 0x2e, 0xd9, 0x12, 0x26, 0x3b, 0x52, - 0x5c, 0x90, 0x7f, 0xc3, 0xeb, 0xb8, 0x3d, 0xc2, 0x60, 0x41, 0x8b, 0x07, 0xf0, 0x7d, 0xf4, 0x2b, - 0xc0, 0x7d, 0xdf, 0x84, 0x68, 0xee, 0xf0, 0x5f, 0xb0, 0x5e, 0x20, 0x08, 0x08, 0x48, 0x81, 0x46, - 0xf0, 0x7e, 0x70, 0x1f, 0xee, 0x42, 0x50, 0x27, 0xc8, 0x8e, 0x94, 0x54, 0xb6, 0xcd, 0x42, 0x56, - 0xc9, 0x43, 0xb8, 0xda, 0x28, 0x4d, 0xd0, 0xad, 0x04, 0xac, 0x4b, 0x00, 0xae, 0x2f, 0x6d, 0x39, - 0xfd, 0x5b, 0x0c, 0xd4, 0x5a, 0xd6, 0x4a, 0xc3, 0x9d, 0x74, 0xb9, 0x87, 0x81, 0x7b, 0xc8, 0x13, - 0x86, 0x86, 0x8c, 0xb6, 0x9a, 0xb5, 0xd0, 0x7c, 0x72, 0xb9, 0x50, 0xe7, 0x1e, 0x3c, 0x1f, 0x17, - 0x0e, 0x7e, 0x5d, 0xe0, 0x4a, 0x20, 0xd4, 0xf6, 0x31, 0xca, 0xbf, 0x00, 0xfe, 0x3a, 0x5c, 0x06, - 0xa7, 0x38, 0x68, 0x21, 0xaf, 0x7b, 0xf0, 0x0f, 0x71, 0xa3, 0x0f, 0xf5, 0xf7, 0x7c, 0x8a, 0x22, - 0x09, 0xa3, 0xa6, 0x26, 0x20, 0xe4, 0xbf, 0x08, 0x3e, 0xdc, 0xd0, 0xa3, 0x1d, 0xb7, 0x4d, 0x09, - 0x3f, 0x68, 0x65, 0x66, 0xfa, 0x55, 0x77, 0xe2, 0x46, 0x1f, 0x3f, 0x40, 0x67, 0x0b, 0xc2, 0x59, - 0xba, 0x60, 0x5a, 0x38, 0xdc, 0x78, 0xe4, 0x09, 0x51, 0x26, 0xf3, 0xea, 0x6f, 0x42, 0xf6, 0xa0, - 0xae, 0xe5, 0xa7, 0x82, 0xa1, 0x06, 0xe0, 0x6a, 0xcf, 0x96, 0x33, 0x7f, 0xc0, 0x46, 0xf1, 0x3a, - 0xae, 0xfc, 0x94, 0xef, 0xd0, 0x97, 0x9a, 0x3b, 0x12, 0xdc, 0xa5, 0x8b, 0xc0, 0x99, 0x7d, 0x8d, - 0x5a, 0xe9, 0xa4, 0xd0, 0x93, 0x9e, 0x80, 0x40, 0xf3, 0x11, 0x68, 0x3e, 0xfe, 0x33, 0x9c, 0x0c, - 0xe5, 0x1f, 0x9a, 0xa4, 0xb8, 0xb2, 0x21, 0xab, 0xff, 0xf7, 0xb0, 0x75, 0xde, 0x87, 0x86, 0x1b, - 0xdb, 0x78, 0x24, 0xdc, 0xe3, 0x40, 0xf3, 0x61, 0xdc, 0xf0, 0xe4, 0x41, 0x41, 0x4a, 0xef, 0x35, - 0x19, 0x72, 0x86, 0x3d, 0x2f, 0x70, 0x23, 0x00, 0x2d, 0xdf, 0xf5, 0x7d, 0xb4, 0x1c, 0x37, 0x58, - 0xb9, 0x24, 0x2b, 0xee, 0xcc, 0xe8, 0x83, 0x6b, 0x8e, 0x17, 0xe2, 0x2e, 0x2f, 0xb7, 0xc9, 0xe8, - 0xc9, 0x40, 0x92, 0x9a, 0x80, 0xfa, 0xfd, 0x0f, 0x44, 0x04, 0xde, 0x85, 0xe3, 0x79, 0xee, 0x88, - 0x17, 0x71, 0xdd, 0x65, 0x71, 0x32, 0xec, 0x65, 0x3a, 0xa8, 0x67, 0x79, 0x71, 0x87, 0x25, 0xbe, - 0x77, 0x4f, 0x6a, 0xce, 0x75, 0x90, 0x37, 0x7a, 0x75, 0xd2, 0xf4, 0x4b, 0x81, 0x7a, 0x68, 0xaa, - 0x5a, 0x02, 0xb8, 0x09, 0xa9, 0x4c, 0x27, 0xcd, 0x51, 0x45, 0xb7, 0x46, 0x0e, 0x5d, 0x32, 0x21, - 0x9d, 0x48, 0x52, 0x13, 0x40, 0x75, 0x4b, 0x1d, 0x75, 0xe0, 0xab, 0x5e, 0x81, 0x57, 0x1a, 0xff, - 0xa0, 0x85, 0x23, 0x32, 0x73, 0x9c, 0xb8, 0x1a, 0x3d, 0x7b, 0xd0, 0x5c, 0xdc, 0x28, 0x66, 0x8a, - 0x8c, 0xae, 0x0b, 0x09, 0xb5, 0xe2, 0x56, 0x3e, 0x5f, 0xc1, 0xc9, 0xbb, 0x89, 0x15, 0x23, 0x9d, - 0x05, 0xb7, 0xac, 0x47, 0x38, 0xb1, 0x5e, 0x15, 0x68, 0xdc, 0x87, 0xfb, 0x1f, 0xbd, 0x00, 0x01, - 0xdf, 0xf1, 0x08, 0x73, 0xd2, 0x0a, 0xca, 0xb0, 0x07, 0x2c, 0x60, 0x1f, 0x67, 0x44, 0x30, 0x13, - 0x24, 0x24, 0x3d, 0x01, 0x72, 0x7b, 0x24, 0x68, 0xbf, 0xf0, 0x77, 0x4c, 0xc8, 0x2b, 0xb8, 0xfe, - 0xdb, 0x2b, 0x63, 0x39, 0x1c, 0x4e, 0xb6, 0x15, 0x57, 0xd6, 0x80, 0xd9, 0xb8, 0xd5, 0x96, 0x5b, - 0xc6, 0x53, 0x47, 0x24, 0xfc, 0xbc, 0xe6, 0x1e, 0x08, 0xb6, 0x9e, 0x65, 0x22, 0x0e, 0x67, 0x26, - 0x7e, 0x66, 0xb0, 0x11, 0x57, 0x65, 0xe7, 0xa8, 0x17, 0x51, 0xe3, 0xe0, 0xce, 0x57, 0xad, 0x1f, - 0xff, 0x11, 0xe7, 0x80, 0x55, 0xf8, 0x09, 0x44, 0xab, 0x4c, 0xca, 0xe1, 0xcc, 0x80, 0xac, 0xe2, - 0x6f, 0xe3, 0x15, 0xd2, 0x03, 0xa6, 0x5f, 0x1d, 0x99, 0x9c, 0x00, 0x99, 0x5f, 0x10, 0x6c, 0x39, - 0x09, 0x3e, 0xba, 0x02, 0xa9, 0xdf, 0x2b, 0x67, 0x20, 0x96, 0x9a, 0x33, 0x02, 0xb2, 0x4b, 0x1f, - 0xd7, 0xbc, 0x12, 0xa2, 0x4d, 0xdc, 0x3a, 0x1a, 0x3e, 0x60, 0x65, 0x69, 0x22, 0x2f, 0xb8, 0xe9, - 0xaf, 0x38, 0xb4, 0x95, 0x44, 0xe8, 0x52, 0x23, 0x74, 0x5e, 0x01, 0x2d, 0xc3, 0x2b, 0xa0, 0xad, - 0x11, 0x22, 0xae, 0xec, 0x52, 0xd6, 0xca, 0x53, 0xf3, 0x6e, 0x8e, 0xe0, 0x99, 0x49, 0xb0, 0x34, - 0x01, 0x32, 0x47, 0xd8, 0x15, 0xc8, 0xea, 0x4f, 0xae, 0x40, 0x3a, 0x6f, 0xc0, 0x52, 0xf3, 0x6e, - 0xc4, 0xaf, 0x88, 0x5e, 0x93, 0x89, 0x71, 0x84, 0x6e, 0xa0, 0xda, 0x2e, 0x6e, 0xe2, 0x28, 0xca, - 0xbd, 0x0a, 0xa9, 0x79, 0x37, 0x09, 0x3c, 0x1e, 0xc0, 0x77, 0xe2, 0x79, 0x68, 0x3d, 0xf7, 0x26, - 0x13, 0x65, 0x57, 0x62, 0xbd, 0xa7, 0x41, 0xf6, 0x80, 0x47, 0x13, 0xba, 0x12, 0x8b, 0xa7, 0x5e, - 0x2d, 0x99, 0xcb, 0x97, 0x00, 0x85, 0x55, 0x5a, 0x3f, 0x0d, 0xd3, 0x72, 0xea, 0x15, 0x1c, 0x2a, - 0xd6, 0x88, 0x12, 0x39, 0x43, 0x97, 0xb2, 0xcb, 0x58, 0x41, 0xd0, 0x01, 0xd0, 0x87, 0xa8, 0x5a, - 0x1f, 0xe1, 0xe9, 0x50, 0x95, 0x14, 0xd1, 0x6e, 0x93, 0x00, 0x35, 0x6f, 0xda, 0xce, 0xaf, 0xc3, - 0xcb, 0xda, 0x9f, 0x0b, 0x76, 0x36, 0xce, 0x19, 0x99, 0x25, 0x0f, 0x0b, 0xbc, 0xa7, 0x03, 0xdd, - 0xe2, 0x59, 0x90, 0x7a, 0x10, 0x43, 0xb8, 0x58, 0xd9, 0x89, 0x57, 0x1f, 0x9d, 0x9f, 0x0e, 0x65, - 0xf4, 0xb9, 0xfb, 0x8a, 0x0a, 0x3e, 0xf9, 0xdd, 0xed, 0x7b, 0x80, 0x7a, 0x72, 0xae, 0x0c, 0x4e, - 0x37, 0xef, 0x01, 0x57, 0x46, 0x90, 0xb5, 0xbc, 0xb0, 0x13, 0xa0, 0x15, 0x1d, 0x0b, 0x78, 0x76, - 0x02, 0x2c, 0x08, 0xb2, 0x56, 0x15, 0x76, 0x02, 0xb4, 0xa2, 0x63, 0x01, 0xcf, 0x4e, 0x80, 0x05, - 0x41, 0xd6, 0xaa, 0xc2, 0x4e, 0x80, 0x56, 0x74, 0x2c, 0xe0, 0x7d, 0xaa, 0x12, 0xb0, 0x62, 0xc5, - 0x0a, 0xf1, 0x11, 0x24, 0x3d, 0x8a, 0xe0, 0x7f, 0x77, 0xdd, 0x75, 0x97, 0x05, 0xa1, 0x8e, 0x5e, - 0xc5, 0x15, 0xb5, 0x2a, 0x22, 0xba, 0x8b, 0x5d, 0xd4, 0x69, 0xd3, 0xa6, 0xb1, 0x5f, 0x16, 0x3a, - 0x71, 0xe2, 0x04, 0x1c, 0x38, 0x70, 0x00, 0x8e, 0x1d, 0x3b, 0xc6, 0x98, 0x7e, 0xbf, 0xf1, 0xc5, - 0x00, 0x5d, 0xda, 0x8d, 0x41, 0x96, 0xdd, 0x88, 0x35, 0x37, 0x37, 0xc3, 0xc9, 0x93, 0x27, 0x85, - 0x95, 0xf4, 0x95, 0x36, 0xff, 0x52, 0xbb, 0xa3, 0xa3, 0x03, 0x2a, 0x2b, 0x2b, 0xc5, 0xfb, 0x83, - 0x41, 0x83, 0x06, 0xb1, 0x1d, 0x93, 0x49, 0x98, 0x78, 0x55, 0x55, 0x55, 0x10, 0x0a, 0x85, 0x80, - 0xd3, 0xb7, 0x6e, 0xdd, 0x0a, 0x7b, 0xf7, 0xee, 0x85, 0xd2, 0xd2, 0x52, 0x98, 0x3a, 0x75, 0x2a, - 0xd0, 0xfe, 0xd6, 0xe5, 0xe5, 0xe5, 0x40, 0x3f, 0xab, 0x8a, 0x5f, 0xcb, 0xc2, 0xa4, 0x49, 0x93, - 0xa0, 0x7f, 0x7f, 0xed, 0x8d, 0x37, 0x16, 0x2c, 0x58, 0x00, 0xcb, 0x96, 0x2d, 0x63, 0xf6, 0xe0, - 0x17, 0xb3, 0xb0, 0x69, 0x53, 0xd7, 0x83, 0x3e, 0x61, 0xa4, 0x15, 0x80, 0x91, 0xcf, 0x13, 0xf5, - 0x96, 0x79, 0xfa, 0xe9, 0xa7, 0xa3, 0x7e, 0x1a, 0xf9, 0xe4, 0x93, 0x4f, 0x4a, 0xe7, 0xcf, 0x9f, - 0x8f, 0xca, 0x5b, 0xba, 0x74, 0xa9, 0x84, 0x2d, 0x34, 0x2a, 0x0f, 0xe3, 0x12, 0x93, 0x3e, 0x71, - 0xe2, 0x44, 0x4d, 0x33, 0xf9, 0x9e, 0xdc, 0xa4, 0x2b, 0xd1, 0x4f, 0x96, 0x35, 0x2b, 0x8a, 0xc1, - 0xb4, 0x64, 0x0e, 0x58, 0xb2, 0x64, 0x09, 0x6b, 0xdd, 0x5e, 0xaf, 0x17, 0x46, 0x8f, 0x1e, 0x2d, - 0xda, 0xd5, 0x99, 0x33, 0x67, 0x00, 0x7f, 0x04, 0x54, 0xfc, 0xc0, 0x58, 0x59, 0x59, 0x19, 0x50, - 0x4f, 0x41, 0x9b, 0x01, 0x7f, 0x04, 0x14, 0x86, 0x0c, 0x19, 0xc2, 0x60, 0xfc, 0x84, 0x5a, 0x94, - 0x79, 0xe9, 0xa5, 0x97, 0x18, 0x8d, 0xce, 0xfc, 0xe8, 0xd3, 0xa7, 0x0f, 0xa3, 0x51, 0x2f, 0xe1, - 0x1f, 0xb6, 0x6f, 0xd9, 0xb2, 0x05, 0x70, 0xf3, 0x74, 0x2e, 0xd2, 0x6d, 0xcf, 0x96, 0x24, 0x80, - 0x7b, 0x4f, 0xc3, 0xc3, 0xfe, 0xfd, 0xfb, 0xe1, 0xd4, 0xa9, 0x53, 0x50, 0x5c, 0x5c, 0x0c, 0x6b, - 0xd6, 0xac, 0x81, 0xe9, 0xd3, 0xa7, 0x03, 0x7d, 0xd2, 0x4d, 0xc9, 0xd8, 0xb1, 0x63, 0x07, 0x64, - 0x67, 0x67, 0x73, 0xf1, 0xa8, 0xe7, 0xf1, 0xe3, 0xc7, 0x33, 0x7a, 0xdf, 0xbe, 0x7d, 0x05, 0x7f, - 0xdc, 0xb8, 0x71, 0x0c, 0xa6, 0x49, 0x95, 0x92, 0xc1, 0x0f, 0xfc, 0x48, 0x99, 0x83, 0xdd, 0xf6, - 0x6c, 0x69, 0x02, 0x28, 0x0a, 0x3b, 0x77, 0xee, 0x84, 0x91, 0x23, 0x47, 0xb2, 0xc9, 0xb0, 0x5f, - 0xbf, 0x7e, 0x30, 0x60, 0xc0, 0x00, 0xf0, 0xf9, 0x7c, 0x6c, 0xeb, 0x86, 0x85, 0x0b, 0x17, 0x76, - 0xdb, 0x40, 0x99, 0x66, 0x58, 0x8c, 0x21, 0x2a, 0x29, 0x6c, 0xfa, 0x1d, 0x85, 0xc9, 0x93, 0x27, - 0x4b, 0xf8, 0xa3, 0x10, 0x62, 0xec, 0xc6, 0x96, 0x2c, 0xe1, 0x90, 0x24, 0xe1, 0x3e, 0x19, 0xd2, - 0x94, 0x29, 0x53, 0x04, 0x1d, 0x1d, 0x95, 0x70, 0x72, 0x95, 0x56, 0xae, 0x5c, 0x29, 0xe1, 0x90, - 0xc2, 0xb6, 0xa4, 0x08, 0x2f, 0x87, 0xbf, 0x5d, 0x2e, 0xe1, 0x8f, 0x44, 0x88, 0xdf, 0x5d, 0x20, - 0xf9, 0xcc, 0xcc, 0x4c, 0x69, 0xf6, 0xec, 0xd9, 0xcc, 0x56, 0xfe, 0x1b, 0x0c, 0x44, 0x1f, 0x35, - 0x6a, 0x94, 0x84, 0x7b, 0x12, 0x30, 0xfa, 0x73, 0xcf, 0x3d, 0x27, 0xe1, 0x5e, 0x1c, 0x12, 0xf6, - 0x3c, 0xf6, 0x47, 0x3f, 0x87, 0x48, 0x32, 0xf4, 0x97, 0x91, 0x91, 0x21, 0xe8, 0x54, 0xf7, 0x23, - 0x8f, 0x3c, 0x92, 0x14, 0xbf, 0xe3, 0x51, 0x62, 0xc9, 0x65, 0x28, 0x5d, 0xc9, 0xd0, 0xf8, 0x4f, - 0x67, 0x7e, 0x34, 0x34, 0x34, 0x00, 0xee, 0xe1, 0xc1, 0x50, 0xe2, 0x85, 0x1f, 0xf5, 0xf5, 0xf5, - 0x40, 0x7f, 0xe8, 0x00, 0x1b, 0xc7, 0xc3, 0xcb, 0x11, 0x9d, 0xe6, 0x09, 0x1a, 0x6a, 0xe8, 0x57, - 0x3e, 0xe8, 0x12, 0x92, 0xfe, 0x70, 0x32, 0x67, 0x2a, 0x68, 0x13, 0x14, 0xba, 0x6a, 0xa2, 0xa3, - 0xae, 0xae, 0x8e, 0xc9, 0x12, 0x8c, 0xdb, 0x72, 0xb0, 0x5e, 0xd7, 0xd4, 0xd4, 0xb9, 0x9a, 0x82, - 0x68, 0xfc, 0x68, 0x6b, 0x6b, 0x63, 0x3c, 0xc2, 0x49, 0xe7, 0xb9, 0x73, 0x9d, 0xdb, 0xb7, 0x72, - 0xbe, 0x99, 0x67, 0xcb, 0x2e, 0x43, 0xcd, 0x74, 0xa2, 0x27, 0xeb, 0xb6, 0x7c, 0x0e, 0xe8, 0xc9, - 0xc1, 0x32, 0xc3, 0x76, 0x3b, 0x01, 0x66, 0x44, 0x55, 0x87, 0x4e, 0x3b, 0x01, 0x3a, 0x82, 0x65, - 0x86, 0xa8, 0x9d, 0x00, 0x33, 0xa2, 0xaa, 0x43, 0xa7, 0x9d, 0x00, 0x1d, 0xc1, 0x32, 0x43, 0xd4, - 0x4e, 0x80, 0x19, 0x51, 0xd5, 0xa1, 0xd3, 0x4e, 0x80, 0x8e, 0x60, 0x99, 0x21, 0x6a, 0x27, 0xc0, - 0x8c, 0xa8, 0xea, 0xd0, 0xf9, 0x7f, 0xbe, 0xc9, 0xb9, 0x8c, 0x96, 0x81, 0xf7, 0x5a, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXBinaryIcon2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25, 0x0b, 0xe6, - 0x89, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x04, 0x24, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x2f, - 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x64, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x70, 0x75, 0x72, 0x6c, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x64, 0x63, 0x2f, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x31, 0x2e, 0x31, 0x2f, 0x22, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, - 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, - 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, - 0x74, 0x3e, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x36, 0x34, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, - 0x64, 0x66, 0x3a, 0x42, 0x61, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x63, 0x3a, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x35, 0x2d, 0x30, 0x32, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x31, 0x3a, 0x30, 0x32, 0x3a, 0x38, 0x31, 0x3c, 0x2f, 0x78, 0x6d, - 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x33, 0x2e, 0x33, 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xce, - 0xc3, 0x0a, 0xd6, 0x00, 0x00, 0x05, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x59, 0x6f, - 0x48, 0x64, 0x55, 0x14, 0x3f, 0x33, 0xe3, 0x8c, 0x63, 0xce, 0x44, 0x6e, 0x5b, 0xae, 0xd9, 0x22, - 0xa8, 0x59, 0xae, 0x08, 0x91, 0x9a, 0x1b, 0xea, 0x87, 0x30, 0xd1, 0x45, 0x03, 0x29, 0x58, 0x61, - 0x2b, 0xe9, 0x93, 0x89, 0x84, 0x44, 0x11, 0x51, 0x7d, 0x0b, 0x4a, 0x21, 0xb2, 0xed, 0x8b, 0xfa, - 0x29, 0xa8, 0x2c, 0xf1, 0x83, 0x4a, 0x1b, 0xad, 0x6c, 0x61, 0x05, 0x9b, 0xc9, 0x36, 0xba, 0x9b, - 0xe8, 0x1a, 0xa2, 0x28, 0xfe, 0xd7, 0x36, 0xf3, 0xcf, 0x6c, 0x3a, 0xce, 0x8c, 0x33, 0x9d, 0x3b, - 0xf7, 0xcd, 0x9d, 0xf7, 0xe6, 0xcd, 0xcc, 0xfb, 0x3b, 0xc4, 0xc2, 0xbb, 0x1f, 0xc6, 0x73, 0xcf, - 0xfd, 0x9d, 0xdf, 0xb9, 0xe7, 0x9c, 0xfb, 0xe7, 0x71, 0x35, 0x05, 0x83, 0x41, 0xb8, 0x97, 0x9b, - 0xf9, 0x5e, 0x9e, 0x3c, 0x99, 0xbb, 0x11, 0xc0, 0xff, 0x5d, 0x41, 0xa3, 0x02, 0x46, 0x05, 0x34, - 0x66, 0xc0, 0x58, 0x42, 0x1a, 0x13, 0xa8, 0xd9, 0x5c, 0x46, 0x05, 0x0e, 0xff, 0x82, 0xe0, 0x89, - 0x66, 0x47, 0x3c, 0x02, 0x5d, 0x09, 0x53, 0x78, 0xc4, 0x42, 0x71, 0x67, 0x16, 0x7e, 0x7a, 0x13, - 0xb6, 0x26, 0xe0, 0x68, 0x07, 0x52, 0xec, 0x70, 0xfa, 0x1c, 0x94, 0xbc, 0x01, 0x45, 0xaf, 0x08, - 0x41, 0xbc, 0x1e, 0x06, 0x39, 0xf0, 0x1c, 0x78, 0xdd, 0x60, 0x3f, 0x05, 0x17, 0x7f, 0xe0, 0x0d, - 0x84, 0x45, 0xa5, 0x84, 0xb3, 0x7d, 0x30, 0x71, 0x99, 0x18, 0x9f, 0x7f, 0x17, 0x0a, 0x5e, 0x0c, - 0xb3, 0x44, 0xff, 0x8d, 0x13, 0x00, 0x1a, 0x5f, 0x7b, 0x0d, 0x7c, 0x87, 0x1c, 0xdc, 0xef, 0x81, - 0xad, 0x9b, 0xf0, 0x7d, 0x33, 0x2c, 0xff, 0x08, 0x17, 0x3e, 0x07, 0x53, 0x2c, 0xab, 0xc5, 0xab, - 0xb0, 0xf2, 0x0b, 0xc1, 0xa7, 0x67, 0x72, 0x56, 0xfc, 0x3f, 0x8a, 0x09, 0x83, 0x30, 0xf9, 0x19, - 0x6c, 0x4d, 0x12, 0x8e, 0xc3, 0x3b, 0x7c, 0xa6, 0x28, 0x39, 0xd6, 0x12, 0x3a, 0xdc, 0x86, 0x6b, - 0x2d, 0xdc, 0xec, 0x6d, 0xe9, 0x90, 0xf3, 0x2c, 0x38, 0x1f, 0xe1, 0xcc, 0x66, 0xbe, 0x82, 0x99, - 0x2f, 0xa2, 0x28, 0x48, 0x77, 0x7d, 0x0c, 0xae, 0xbe, 0x1a, 0x43, 0x4f, 0x55, 0x4a, 0x09, 0x4f, - 0x3c, 0x84, 0x6d, 0x73, 0x22, 0x2e, 0x21, 0x6f, 0x20, 0x56, 0x2e, 0x7f, 0xff, 0x18, 0x7c, 0x47, - 0x04, 0xe3, 0xcc, 0x86, 0x97, 0xc7, 0xc1, 0x79, 0x96, 0xec, 0x81, 0x2b, 0x4d, 0x30, 0x37, 0x48, - 0x94, 0xe3, 0x1f, 0x42, 0x51, 0x33, 0x98, 0xad, 0x44, 0x9e, 0xfd, 0x1a, 0xb6, 0x27, 0x61, 0xfd, - 0x37, 0xd8, 0xb8, 0x41, 0xba, 0xf1, 0x9a, 0x4c, 0xc2, 0xbb, 0xeb, 0x70, 0xab, 0x1b, 0xdc, 0xab, - 0xb0, 0xf0, 0x1d, 0x78, 0xf6, 0xe2, 0x91, 0x45, 0xe9, 0x45, 0x15, 0x08, 0x78, 0xe1, 0x56, 0x0f, - 0x07, 0x2a, 0x7f, 0x87, 0xcc, 0x1e, 0x9b, 0xc9, 0x02, 0xd5, 0x97, 0xc1, 0x6c, 0x21, 0xf2, 0xde, - 0x12, 0x2c, 0x5c, 0x21, 0x02, 0xb6, 0xdb, 0x5f, 0x82, 0xeb, 0x53, 0x89, 0xd9, 0xcb, 0x27, 0x3c, - 0x58, 0x81, 0xf1, 0x8f, 0x00, 0x8b, 0x2c, 0x7b, 0xf6, 0x38, 0x05, 0x51, 0x00, 0xee, 0xb5, 0xc8, - 0xd2, 0xcf, 0xbd, 0x10, 0x9a, 0x66, 0xe8, 0xc7, 0xf1, 0x28, 0x3c, 0x54, 0xcc, 0x75, 0xff, 0x99, - 0x8b, 0xe8, 0x25, 0x25, 0xdd, 0x09, 0x85, 0x1e, 0x45, 0x4b, 0x08, 0xd3, 0x40, 0x1b, 0xe6, 0xfb, - 0x81, 0x3c, 0x01, 0xf8, 0xd4, 0xe3, 0xb0, 0xfd, 0x07, 0xd1, 0x30, 0xcc, 0xf3, 0xdf, 0x80, 0xff, - 0x98, 0xc3, 0xb8, 0x3e, 0x01, 0x57, 0x97, 0x00, 0x4f, 0x3b, 0x0c, 0x2c, 0x49, 0x78, 0xa6, 0x04, - 0xda, 0xd6, 0x23, 0x0c, 0xdd, 0xd9, 0x11, 0x39, 0xbe, 0x24, 0x0e, 0x60, 0x99, 0x03, 0xdb, 0xee, - 0xc7, 0xa5, 0x23, 0x30, 0xc4, 0xf3, 0x91, 0xb6, 0x83, 0x30, 0xc6, 0xfe, 0x60, 0x04, 0x60, 0x73, - 0x46, 0x64, 0xbe, 0xc4, 0xc0, 0x92, 0x84, 0x66, 0x1b, 0x38, 0xc2, 0xa7, 0x05, 0x9f, 0x21, 0xa1, - 0x2c, 0x5a, 0x42, 0x77, 0x37, 0x38, 0xbc, 0x59, 0x14, 0x1b, 0xd3, 0x30, 0x4c, 0x42, 0x6a, 0x6e, - 0x90, 0x81, 0x99, 0x39, 0xb3, 0x62, 0x1a, 0x86, 0x61, 0x43, 0xb2, 0x05, 0x51, 0x00, 0x16, 0x3b, - 0x67, 0x7b, 0xe2, 0x8d, 0x26, 0x61, 0x1a, 0x86, 0x89, 0x46, 0xc4, 0xea, 0x33, 0x30, 0x33, 0x67, - 0x28, 0xa6, 0x61, 0x18, 0x36, 0x24, 0x5b, 0x10, 0x05, 0x90, 0x8a, 0x2b, 0x27, 0xd4, 0x7c, 0xff, - 0x42, 0xd0, 0x2f, 0xe0, 0x39, 0x0e, 0x1f, 0x6d, 0x0c, 0x23, 0x18, 0x8e, 0xd3, 0x61, 0x60, 0xbd, - 0x08, 0x85, 0x7e, 0x44, 0x01, 0x64, 0x3c, 0xc6, 0x01, 0x02, 0x7e, 0x72, 0x62, 0xf2, 0xdb, 0xee, - 0x3c, 0xd7, 0x63, 0x18, 0xfe, 0x68, 0x3c, 0x99, 0x81, 0xf5, 0x22, 0x14, 0x3a, 0x12, 0x05, 0xf0, - 0xf0, 0x93, 0xc0, 0x96, 0xe6, 0xca, 0xcf, 0x11, 0x30, 0xde, 0xa6, 0x7f, 0xdf, 0xe6, 0xba, 0x67, - 0x4a, 0x23, 0x7a, 0x49, 0x49, 0x77, 0x42, 0xa1, 0x47, 0x51, 0x00, 0x78, 0x56, 0x9c, 0xbb, 0xc4, - 0x61, 0x6e, 0x74, 0x82, 0x3f, 0x74, 0x25, 0x63, 0x1f, 0x2f, 0x60, 0x7a, 0x62, 0xde, 0x77, 0x1a, - 0x9e, 0xb8, 0x28, 0x24, 0x49, 0xd8, 0xd3, 0x9d, 0x50, 0xe8, 0x4d, 0x74, 0xd4, 0xe0, 0xf0, 0x33, - 0xef, 0x93, 0x6f, 0x84, 0xc0, 0x09, 0x59, 0x42, 0x3d, 0x67, 0xc9, 0x74, 0xd7, 0xae, 0xc3, 0x9d, - 0x19, 0xce, 0xb0, 0xec, 0x2d, 0xb0, 0x3a, 0x84, 0x24, 0x52, 0x3d, 0xdd, 0x09, 0x79, 0x0e, 0x45, - 0x15, 0xc0, 0xb1, 0x8c, 0x02, 0x38, 0xff, 0x1e, 0x87, 0xc1, 0x6f, 0x69, 0xfc, 0xb2, 0x60, 0xb3, - 0xcf, 0x7a, 0x1a, 0x9e, 0x7a, 0x9d, 0x67, 0x2e, 0x4f, 0xd4, 0x9d, 0x90, 0xe7, 0x36, 0x56, 0x00, - 0x38, 0x5c, 0xf9, 0x01, 0xbc, 0xf0, 0x6d, 0xe4, 0x23, 0x14, 0x35, 0xd6, 0x34, 0x28, 0x7f, 0x1b, - 0x5e, 0xfa, 0x55, 0x71, 0xfa, 0xa9, 0x33, 0xdd, 0x09, 0xc3, 0x31, 0x98, 0x24, 0x9e, 0x16, 0xf1, - 0x8a, 0xd9, 0xf9, 0x93, 0x7c, 0x96, 0xe2, 0x61, 0x82, 0x9f, 0x74, 0xda, 0x9b, 0xde, 0x84, 0x52, - 0x01, 0x68, 0x9f, 0x71, 0x92, 0x19, 0xe2, 0x2c, 0xa1, 0x24, 0x7b, 0xd5, 0x91, 0xde, 0x08, 0x40, - 0xc7, 0x64, 0xaa, 0xa2, 0x32, 0x2a, 0xa0, 0x2a, 0x6d, 0x3a, 0x1a, 0x19, 0x15, 0xd0, 0x31, 0x99, - 0xaa, 0xa8, 0x8c, 0x0a, 0xa8, 0x4a, 0x9b, 0x8e, 0x46, 0x6a, 0x2a, 0x70, 0x12, 0x6a, 0x92, 0x93, - 0xf0, 0xfb, 0xfd, 0x5d, 0x5d, 0x5d, 0x43, 0x43, 0x43, 0x92, 0x48, 0x4d, 0x00, 0xfc, 0x16, 0x52, - 0xd4, 0xaa, 0xaa, 0xaa, 0xd0, 0x9f, 0xc9, 0x64, 0x1a, 0x1d, 0x1d, 0x4d, 0x6c, 0x38, 0x37, 0x47, - 0x9e, 0x8f, 0x72, 0x73, 0x73, 0x13, 0xc3, 0x34, 0x8e, 0x2a, 0xae, 0x40, 0x41, 0x41, 0x41, 0x4a, - 0x4a, 0x0a, 0x7a, 0x3d, 0x38, 0x38, 0x48, 0x9c, 0x39, 0x9b, 0xcd, 0x96, 0x9a, 0x9a, 0x9a, 0x9d, - 0x2d, 0xeb, 0x79, 0x27, 0x31, 0x55, 0xa2, 0x51, 0x15, 0x09, 0xc0, 0xa4, 0x22, 0xe3, 0xf0, 0xf0, - 0xb0, 0xa4, 0xad, 0xcf, 0xe7, 0x93, 0xc4, 0x68, 0x04, 0x28, 0xae, 0x00, 0x4b, 0xc6, 0xc6, 0xc6, - 0x46, 0x7b, 0x7b, 0x7b, 0x75, 0x75, 0x75, 0x6b, 0x6b, 0xeb, 0xd8, 0xd8, 0x18, 0xd3, 0x53, 0xa1, - 0xb9, 0xb9, 0xb9, 0xbc, 0xbc, 0xbc, 0xa2, 0xa2, 0xa2, 0xb2, 0xb2, 0x72, 0x6f, 0x2f, 0xfc, 0x9c, - 0x01, 0xb0, 0xbb, 0xbb, 0xdb, 0xd8, 0xd8, 0x88, 0x43, 0x6d, 0x6d, 0x6d, 0x83, 0x83, 0x83, 0xc5, - 0xc5, 0xc5, 0xe9, 0xe9, 0xe9, 0x75, 0x75, 0x75, 0x9b, 0x9b, 0x9b, 0x51, 0x0c, 0x72, 0xbb, 0x2a, - 0x12, 0x40, 0x2b, 0x80, 0xdb, 0x80, 0xf9, 0xb0, 0x58, 0x2c, 0x3d, 0x3d, 0x3d, 0x8c, 0xca, 0xed, - 0x76, 0xe3, 0x32, 0x63, 0xa3, 0x4b, 0x4b, 0x4b, 0x6c, 0x68, 0x62, 0x82, 0x7b, 0x34, 0x77, 0x3a, - 0x9d, 0x7c, 0x4c, 0x53, 0x53, 0x13, 0xc3, 0x28, 0x12, 0x40, 0x11, 0x9a, 0x82, 0x69, 0x00, 0x38, - 0x69, 0x4c, 0x73, 0x77, 0x77, 0x77, 0x5e, 0x1e, 0x79, 0x42, 0x4d, 0x4b, 0x4b, 0x5b, 0x5e, 0x5e, - 0x66, 0x6c, 0xd3, 0xd3, 0xd3, 0x03, 0x03, 0x03, 0x34, 0x06, 0x7e, 0x00, 0x08, 0xe8, 0xeb, 0xeb, - 0xa3, 0xfa, 0xda, 0xda, 0x5a, 0x8c, 0xa7, 0xa5, 0xa5, 0x05, 0xbb, 0x58, 0x07, 0x66, 0xab, 0x48, - 0x50, 0x1f, 0x00, 0xcb, 0xd9, 0xfc, 0x3c, 0xf7, 0x5e, 0xd4, 0xd9, 0xd9, 0xc9, 0xf7, 0x7d, 0x74, - 0xc4, 0xbd, 0x68, 0x44, 0x05, 0x30, 0x35, 0x35, 0x45, 0x03, 0x70, 0xb9, 0x5c, 0x88, 0x9f, 0x9c, - 0x0c, 0xfd, 0x1b, 0x06, 0x60, 0x7f, 0x7f, 0x9f, 0x6f, 0x2e, 0x53, 0x56, 0xbf, 0x07, 0x1a, 0x1a, - 0x1a, 0xe8, 0x3c, 0xf2, 0xf3, 0xf3, 0x0b, 0x0b, 0x0b, 0x51, 0xa6, 0xe7, 0x26, 0x55, 0xca, 0xf9, - 0x2d, 0x29, 0x29, 0x41, 0x58, 0x4e, 0x4e, 0x0e, 0x05, 0x7b, 0x3c, 0x1e, 0x39, 0x56, 0x51, 0x18, - 0xf5, 0x01, 0x60, 0x5e, 0x29, 0x97, 0xd7, 0xeb, 0x5d, 0x5b, 0x5b, 0x43, 0xd9, 0x6e, 0x0f, 0xbf, - 0xab, 0x46, 0x39, 0x89, 0xd3, 0xa5, 0xbb, 0x88, 0xbf, 0x97, 0xe2, 0x00, 0x13, 0xa9, 0xd5, 0x07, - 0xd0, 0xdf, 0xdf, 0xbf, 0xba, 0xba, 0x8a, 0x85, 0xee, 0xed, 0xed, 0xc5, 0x5d, 0x8b, 0x4e, 0x4a, - 0x4b, 0x23, 0x2f, 0x76, 0x78, 0x59, 0xe3, 0x4d, 0x4c, 0x3d, 0xf3, 0x65, 0xd4, 0xa0, 0x09, 0xd5, - 0x53, 0x21, 0x10, 0x08, 0xf0, 0xbb, 0x54, 0x56, 0xf0, 0x2b, 0x73, 0xa9, 0x31, 0x58, 0x4d, 0x4d, - 0x0d, 0x63, 0xc7, 0xab, 0x8a, 0x6e, 0x68, 0xd4, 0x14, 0x15, 0x15, 0x61, 0x29, 0x28, 0xac, 0xac, - 0xac, 0x8c, 0x61, 0x98, 0x80, 0x2b, 0xed, 0xf8, 0xf8, 0x18, 0x37, 0x7a, 0x46, 0x46, 0x06, 0x55, - 0xa2, 0x06, 0x4f, 0xd8, 0xac, 0xac, 0x2c, 0xda, 0xcd, 0xcc, 0xcc, 0xc4, 0xcb, 0x91, 0x39, 0x92, - 0x29, 0x28, 0xae, 0x80, 0xd9, 0x4c, 0x4c, 0x1c, 0x0e, 0x47, 0x47, 0x47, 0x07, 0x26, 0x6f, 0x71, - 0x71, 0x11, 0xd7, 0x40, 0x7d, 0x7d, 0xfd, 0xc8, 0xc8, 0x88, 0xd5, 0x6a, 0xa5, 0x53, 0xa1, 0x18, - 0x2a, 0xb3, 0x5f, 0x54, 0xe2, 0x9c, 0xb0, 0x8b, 0x61, 0x53, 0x25, 0xde, 0xd3, 0xc8, 0xc0, 0xef, - 0x52, 0x00, 0x33, 0x91, 0x23, 0x68, 0x7a, 0x56, 0xc1, 0x6d, 0xb7, 0xb0, 0xb0, 0x80, 0xbb, 0x10, - 0x0f, 0x75, 0x39, 0xce, 0x92, 0x81, 0xd1, 0x14, 0x40, 0x32, 0x26, 0xa4, 0x94, 0x53, 0xf1, 0x12, - 0x52, 0xea, 0x20, 0xd9, 0x78, 0x23, 0x80, 0x64, 0x67, 0x58, 0x8a, 0xdf, 0xa8, 0x80, 0x54, 0x86, - 0x92, 0x3d, 0x6e, 0x54, 0x20, 0xd9, 0x19, 0x96, 0xe2, 0x37, 0x2a, 0x20, 0x95, 0xa1, 0x64, 0x8f, - 0x1b, 0x15, 0x48, 0x76, 0x86, 0xa5, 0xf8, 0xff, 0x03, 0xf5, 0x1a, 0x5a, 0xe0, 0xcf, 0xeb, 0xd5, - 0xa2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXBinaryIcon3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x01, 0x95, 0x9f, 0x47, - 0xae, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x60, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0xfb, 0x7d, 0x74, 0x00, 0x00, 0x0e, 0x68, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, - 0x5d, 0x09, 0x90, 0x15, 0xc5, 0x19, 0xfe, 0x39, 0xe4, 0x94, 0x1b, 0x24, 0xc8, 0x11, 0x8e, 0x04, - 0x90, 0x80, 0x18, 0x29, 0x54, 0x02, 0x05, 0x2b, 0x09, 0x87, 0x2b, 0x44, 0x70, 0x03, 0x16, 0xa9, - 0x84, 0xc2, 0x58, 0x20, 0x26, 0x9a, 0x22, 0xa1, 0xa2, 0x22, 0x11, 0x10, 0x22, 0x18, 0xc3, 0x12, - 0x23, 0x72, 0x54, 0x59, 0x31, 0x72, 0x48, 0x09, 0xca, 0x21, 0x97, 0x82, 0xc8, 0x11, 0x90, 0x2b, - 0x40, 0x10, 0x10, 0x50, 0x14, 0xd0, 0x05, 0x21, 0x28, 0xc7, 0x22, 0xb0, 0xdc, 0x93, 0xff, 0x9b, - 0x7e, 0x3d, 0xd3, 0x73, 0xbd, 0x37, 0x33, 0xef, 0xbd, 0x1d, 0x57, 0xe7, 0xaf, 0x7a, 0xd3, 0x7f, - 0xff, 0xfd, 0x1f, 0xdd, 0xfd, 0x77, 0xf7, 0xf4, 0xcc, 0x74, 0xf7, 0x2b, 0xa5, 0x31, 0x50, 0x00, - 0x28, 0x1d, 0x80, 0x57, 0x67, 0x4d, 0x43, 0xa0, 0xc5, 0x28, 0xa2, 0xae, 0x93, 0x84, 0x41, 0xe0, - 0x00, 0x84, 0x2a, 0xce, 0xa4, 0xb2, 0x7a, 0x82, 0xbc, 0xcc, 0x1b, 0x22, 0x31, 0x11, 0xde, 0x58, - 0x81, 0xa8, 0x57, 0x1b, 0x0b, 0xcd, 0xcc, 0xd2, 0xad, 0x0d, 0x88, 0x3a, 0x3e, 0x6f, 0x49, 0xa4, - 0xcb, 0x57, 0x89, 0x5e, 0xff, 0x8f, 0x85, 0x56, 0xea, 0x9b, 0x5c, 0x4b, 0x96, 0x9c, 0x12, 0x95, - 0x2a, 0x55, 0xca, 0x46, 0x11, 0x51, 0xb3, 0xd0, 0xb6, 0x64, 0xaf, 0x06, 0xe0, 0x29, 0x60, 0x93, - 0x37, 0xa2, 0xdf, 0xf8, 0x5a, 0xea, 0x3c, 0x51, 0xb4, 0x9d, 0x99, 0x9b, 0x89, 0x0a, 0x8b, 0x44, - 0xbe, 0xdf, 0xd8, 0x6e, 0xd2, 0x98, 0x22, 0x0a, 0xbd, 0xef, 0xb8, 0x48, 0xfc, 0xdf, 0x59, 0xa2, - 0x8f, 0xc6, 0x0a, 0x7c, 0xc4, 0x42, 0x11, 0xfe, 0xf9, 0x2d, 0x93, 0x06, 0x0a, 0x9a, 0x86, 0x0e, - 0xcd, 0x9f, 0x96, 0x98, 0xa6, 0xcd, 0xd8, 0xe4, 0x49, 0x2b, 0xe6, 0x5a, 0xf2, 0x6a, 0x0e, 0xa2, - 0x30, 0xe2, 0xea, 0xf0, 0xb4, 0x2a, 0x04, 0x5c, 0x8d, 0x43, 0x24, 0xfb, 0x65, 0x08, 0x6c, 0x41, - 0x2d, 0x8f, 0x1f, 0xdc, 0x51, 0x66, 0x3f, 0x42, 0x41, 0x78, 0x9c, 0x06, 0x30, 0x94, 0xa9, 0xc3, - 0x97, 0xd4, 0x76, 0x37, 0xd3, 0xd1, 0x24, 0x25, 0x48, 0x1e, 0x39, 0xcc, 0x49, 0xba, 0x8d, 0xcf, - 0x6a, 0x60, 0xcf, 0x17, 0x44, 0x47, 0xcf, 0x88, 0xa6, 0xb9, 0xf9, 0x49, 0x73, 0x8c, 0x84, 0xf0, - 0x17, 0x4c, 0x97, 0xf0, 0xf0, 0x6b, 0x44, 0x35, 0x2a, 0x09, 0xbe, 0x5f, 0xdd, 0xe9, 0xcd, 0xc7, - 0xfc, 0x56, 0x03, 0xad, 0x6f, 0x96, 0x2a, 0xc4, 0xa0, 0xdc, 0xac, 0x8e, 0x19, 0x57, 0xb1, 0x17, - 0xfa, 0x13, 0x9d, 0xbe, 0x20, 0x28, 0xb3, 0xb7, 0x10, 0xfd, 0x9d, 0xe3, 0x1e, 0xf0, 0x6d, 0x74, - 0xb2, 0x52, 0xd4, 0x35, 0x6b, 0xd6, 0x28, 0x31, 0x81, 0x56, 0xac, 0x58, 0xd1, 0x41, 0x4b, 0x4a, - 0x30, 0xc7, 0x14, 0x27, 0xc6, 0x82, 0x5a, 0xdf, 0xbe, 0x7d, 0x71, 0xff, 0xd6, 0x13, 0x47, 0x8e, - 0x1c, 0x69, 0xe0, 0x20, 0x80, 0x3e, 0x7e, 0xfc, 0x78, 0x0b, 0xcd, 0xae, 0xc5, 0x1c, 0xbf, 0x6c, - 0x29, 0x05, 0x05, 0x05, 0xba, 0x20, 0x94, 0x70, 0xff, 0xd7, 0x53, 0x81, 0xcb, 0x1f, 0x08, 0xc0, - 0x77, 0xee, 0xdc, 0x99, 0xd4, 0x40, 0xc9, 0x77, 0x72, 0xc9, 0x2f, 0x81, 0xb5, 0x27, 0xb3, 0xd7, - 0x32, 0x0d, 0xdf, 0x46, 0x03, 0x72, 0x18, 0xfe, 0xd7, 0x46, 0x6b, 0x6d, 0xa9, 0xc3, 0xf2, 0x95, - 0x6b, 0xe6, 0x90, 0x5e, 0x70, 0xda, 0x9b, 0x8f, 0x53, 0xac, 0xb3, 0x54, 0x28, 0x79, 0x83, 0x67, - 0xaa, 0x98, 0x80, 0x02, 0x7f, 0xf0, 0x27, 0xd6, 0xa1, 0x58, 0xaa, 0x6a, 0xfd, 0x8c, 0x39, 0xdb, - 0x00, 0x1f, 0x66, 0x23, 0x6a, 0x06, 0x24, 0x1f, 0x87, 0x4e, 0x1f, 0x40, 0xb9, 0x0a, 0x10, 0x96, - 0xd3, 0x19, 0x95, 0x6e, 0xc7, 0x3d, 0xf8, 0x9c, 0x06, 0xec, 0x82, 0x69, 0xc6, 0x9d, 0x06, 0x16, - 0xee, 0xf4, 0xa7, 0xf2, 0xda, 0x75, 0x7f, 0x7c, 0xb6, 0x31, 0x4e, 0xd3, 0x30, 0x69, 0xc3, 0xef, - 0xdd, 0xbd, 0xd6, 0x24, 0x75, 0x32, 0x87, 0x14, 0xc9, 0x57, 0x58, 0x94, 0x94, 0x2f, 0x1e, 0x2a, - 0x52, 0xfa, 0xc1, 0xe9, 0xe4, 0x94, 0x22, 0xc1, 0x18, 0x3c, 0x0d, 0x6c, 0xdc, 0x68, 0xeb, 0xc9, - 0xac, 0x77, 0xf9, 0xf2, 0xe5, 0xc1, 0xb4, 0x83, 0xdb, 0xda, 0x04, 0xcc, 0xd8, 0xf0, 0xe1, 0xc3, - 0xcd, 0x48, 0x1a, 0x98, 0x67, 0x09, 0x60, 0x5c, 0xce, 0xc7, 0x0f, 0x1f, 0x3e, 0x8c, 0x28, 0xb5, - 0x6f, 0xdf, 0x5e, 0x0f, 0x71, 0xe9, 0xda, 0xb5, 0xab, 0x91, 0x6e, 0x10, 0x5d, 0x90, 0xa4, 0x06, - 0x38, 0xe3, 0x28, 0x21, 0x35, 0x69, 0xd2, 0x44, 0x17, 0x1d, 0x35, 0x8a, 0xc7, 0x9d, 0x04, 0x8c, - 0x18, 0x31, 0x42, 0x4f, 0x7b, 0xe8, 0xa1, 0x87, 0x24, 0xc9, 0x3d, 0xf4, 0x2a, 0x3d, 0x73, 0x5b, - 0x66, 0x10, 0xdd, 0xbb, 0x77, 0x37, 0xe2, 0xb3, 0x66, 0xcd, 0x32, 0x70, 0xc9, 0xe7, 0xa5, 0x27, - 0xee, 0x68, 0xee, 0xf5, 0xae, 0x50, 0x93, 0x3a, 0x59, 0xe1, 0x0b, 0x8d, 0x66, 0xdd, 0x07, 0xa1, - 0x73, 0xe6, 0x53, 0x30, 0xeb, 0x35, 0xe4, 0x33, 0x1f, 0xa1, 0xd9, 0xe2, 0x02, 0x84, 0xae, 0xba, - 0x0c, 0x09, 0xfa, 0xf3, 0x00, 0x9e, 0x87, 0x5f, 0xdd, 0x44, 0xb4, 0x6a, 0x5f, 0x6a, 0xb3, 0x78, - 0xfd, 0xf8, 0xe5, 0x39, 0xa2, 0xa2, 0x2b, 0xde, 0xbc, 0x9f, 0x7c, 0x49, 0xf4, 0x8f, 0xd5, 0x44, - 0x3b, 0x0b, 0xbc, 0x79, 0x64, 0x4a, 0x0a, 0x7d, 0xc9, 0x3b, 0xf1, 0x83, 0x33, 0x88, 0x36, 0x7e, - 0x2a, 0x54, 0x0d, 0xef, 0x46, 0xb4, 0xeb, 0x28, 0xd1, 0xbb, 0x7b, 0x45, 0x7c, 0xed, 0x70, 0xa2, - 0x7a, 0xd5, 0xa4, 0x19, 0x11, 0x3e, 0xc9, 0x2f, 0xc9, 0x16, 0xfe, 0x57, 0xe0, 0x23, 0x73, 0x89, - 0x06, 0xde, 0x65, 0x4d, 0x97, 0x53, 0xd7, 0x72, 0x3c, 0x1b, 0x1e, 0xf7, 0x73, 0xa2, 0x17, 0xde, - 0x23, 0x3a, 0x56, 0x28, 0x78, 0xdc, 0x66, 0xa6, 0xa9, 0xf4, 0xb1, 0xa4, 0x75, 0x5e, 0xad, 0x9a, - 0xbb, 0xca, 0x93, 0x42, 0x99, 0x79, 0x55, 0xf9, 0xea, 0x8f, 0x88, 0x1e, 0xe1, 0xd7, 0x20, 0x39, - 0xf9, 0xe6, 0x74, 0x58, 0x66, 0x4c, 0x95, 0xb7, 0xe3, 0x53, 0xd7, 0x99, 0x94, 0xdd, 0x89, 0x7b, - 0x62, 0x9f, 0xdb, 0x88, 0xfa, 0x4e, 0x23, 0xda, 0x7b, 0x8c, 0x28, 0x77, 0x32, 0xcf, 0x27, 0x1e, - 0x13, 0x3c, 0x7e, 0xf4, 0x25, 0xb4, 0x79, 0x17, 0x40, 0x66, 0xde, 0x34, 0x2b, 0xb0, 0x8e, 0xcd, - 0xec, 0x14, 0xb3, 0x20, 0x48, 0xf1, 0x32, 0xbe, 0x86, 0x0b, 0x0e, 0xb0, 0x7b, 0xad, 0xe3, 0x0f, - 0x44, 0x01, 0x3e, 0xe5, 0x66, 0x25, 0x41, 0xad, 0x30, 0x2f, 0x7d, 0x09, 0x5e, 0xef, 0x3e, 0xd0, - 0xf9, 0x87, 0x52, 0x9d, 0x35, 0x7c, 0xe7, 0x43, 0x6b, 0xdc, 0x6f, 0x2c, 0xb7, 0xb5, 0xe0, 0x94, - 0x4d, 0x46, 0xca, 0x49, 0x7d, 0xea, 0x3b, 0x2a, 0x99, 0xe6, 0x23, 0xf4, 0x2e, 0x00, 0x84, 0xef, - 0x4d, 0x7c, 0x3c, 0x40, 0x2d, 0xa0, 0xbd, 0xa2, 0x4f, 0x3c, 0x3e, 0x5f, 0xa8, 0xdd, 0x32, 0xc2, - 0x87, 0x7a, 0x85, 0x05, 0x8f, 0x79, 0x65, 0xcb, 0x08, 0x42, 0xcb, 0xd1, 0x44, 0x78, 0xb6, 0xbc, - 0x63, 0x02, 0x51, 0xc1, 0x29, 0x41, 0x9b, 0x3f, 0x54, 0x61, 0xf6, 0x8f, 0x26, 0xef, 0xc4, 0xaa, - 0x9e, 0xf7, 0xf6, 0x13, 0x35, 0xa8, 0xc1, 0x4d, 0xa4, 0xae, 0x4a, 0x0d, 0x87, 0x63, 0x84, 0x7a, - 0x7b, 0x0f, 0x51, 0x97, 0xe6, 0x44, 0xb5, 0x2a, 0x87, 0xd3, 0x91, 0x90, 0xf2, 0x5f, 0x80, 0xb4, - 0xcc, 0x64, 0x4f, 0x38, 0x79, 0x13, 0xca, 0x9e, 0xdd, 0x8c, 0x69, 0x8e, 0x0b, 0x90, 0xb1, 0xaa, - 0x0c, 0xa9, 0x28, 0xb0, 0x07, 0x8e, 0x1c, 0x39, 0xe2, 0xeb, 0x69, 0x0f, 0xf9, 0x19, 0x36, 0x6c, - 0x98, 0xe3, 0x2b, 0x4e, 0xc8, 0x7c, 0x7a, 0x8b, 0x79, 0x3d, 0xac, 0x25, 0xa3, 0xe3, 0x99, 0x99, - 0x35, 0x6a, 0xf9, 0xf9, 0xf9, 0x7a, 0x58, 0xa7, 0x4e, 0x1d, 0xed, 0xd0, 0xa1, 0x43, 0x16, 0x91, - 0x0a, 0x15, 0x2a, 0x18, 0x0f, 0x86, 0x96, 0x04, 0x8e, 0x40, 0x16, 0xbf, 0x05, 0x0b, 0x16, 0x18, - 0xf8, 0x8a, 0x15, 0x2b, 0xec, 0x6c, 0xbe, 0xe2, 0x9e, 0x0f, 0xf6, 0xc9, 0xa4, 0x65, 0x01, 0x0a, - 0x0b, 0x0b, 0x0d, 0x36, 0x64, 0x08, 0x99, 0x56, 0x61, 0xf1, 0xe2, 0xc5, 0x7a, 0x06, 0x55, 0x1a, - 0xf0, 0x95, 0x2b, 0x57, 0xea, 0x74, 0xfe, 0x5a, 0xa0, 0x27, 0xe5, 0xe5, 0xe5, 0xb9, 0xf2, 0xe9, - 0x89, 0x29, 0x2e, 0x81, 0x9b, 0x10, 0x67, 0xd4, 0x80, 0x09, 0x13, 0xf8, 0x46, 0xc4, 0xb0, 0x6a, - 0xd5, 0x2a, 0x3d, 0x6c, 0xd6, 0xcc, 0x65, 0x9a, 0xa1, 0xa7, 0xb8, 0x5f, 0x72, 0x72, 0x72, 0xf4, - 0x84, 0xea, 0xd5, 0xab, 0xbb, 0x33, 0xf8, 0xa0, 0xa6, 0x7d, 0x1f, 0xd8, 0xb4, 0x69, 0x13, 0xb5, - 0x68, 0xd1, 0x82, 0x6a, 0xd6, 0xac, 0xe9, 0xc3, 0x5c, 0xe6, 0x59, 0xd2, 0x2e, 0x40, 0xe6, 0xb3, - 0x14, 0x4c, 0x63, 0x5a, 0x4d, 0x28, 0x98, 0xa9, 0xec, 0x70, 0xc7, 0x05, 0xc8, 0x4e, 0xbd, 0xfa, - 0xd7, 0x1a, 0xf7, 0x01, 0xff, 0x75, 0x95, 0x1d, 0xce, 0xb8, 0x0f, 0x64, 0xa7, 0x5e, 0xfd, 0x6b, - 0x8d, 0x3d, 0xe0, 0xbf, 0xae, 0xb2, 0xc3, 0x19, 0x7b, 0x20, 0x3b, 0xf5, 0xea, 0x5f, 0xeb, 0x77, - 0xc4, 0x03, 0x9b, 0x0e, 0x12, 0x4d, 0x59, 0x4b, 0x74, 0xc4, 0xf6, 0xfd, 0xdf, 0xad, 0xa2, 0xf0, - 0x62, 0x17, 0x3f, 0x2f, 0xc0, 0x77, 0xec, 0xa5, 0xbb, 0xc5, 0xfa, 0xd3, 0xf3, 0x97, 0xbd, 0xb8, - 0x4c, 0x7a, 0x0a, 0x7d, 0xc9, 0xef, 0xc4, 0x78, 0x7b, 0xfc, 0xc0, 0xcb, 0xa6, 0x32, 0x60, 0x37, - 0xf0, 0xcb, 0xa9, 0x3d, 0xa3, 0xad, 0x34, 0x19, 0xc3, 0xc3, 0x16, 0x5e, 0x5a, 0x01, 0xd4, 0xd7, - 0x83, 0x82, 0xc2, 0x2f, 0x74, 0xf9, 0x53, 0xea, 0x6c, 0x65, 0x1d, 0x1b, 0xe8, 0x6d, 0xea, 0x13, - 0xbd, 0xf9, 0xb0, 0xe4, 0xb0, 0x86, 0xa9, 0xf4, 0x31, 0x77, 0xf2, 0x26, 0x24, 0x33, 0x7f, 0x4b, - 0x3d, 0xf1, 0x36, 0x19, 0xea, 0xb1, 0x22, 0xe3, 0xb6, 0xbf, 0x58, 0x0d, 0x21, 0xf6, 0x39, 0xbf, - 0x61, 0x93, 0x99, 0x77, 0xa6, 0x12, 0x6d, 0xff, 0xcc, 0xcc, 0x7c, 0xff, 0x76, 0x44, 0x0f, 0x77, - 0x16, 0x5c, 0xbb, 0xf9, 0x8d, 0xf7, 0xb8, 0x65, 0x4e, 0x89, 0x54, 0xfa, 0x12, 0x12, 0xde, 0x2f, - 0x77, 0xff, 0xba, 0xc2, 0x54, 0xba, 0xe8, 0x11, 0x81, 0xf7, 0x63, 0xc3, 0xc8, 0x64, 0x91, 0xe2, - 0xfa, 0xf3, 0x97, 0x88, 0x6e, 0x7f, 0xd6, 0xe4, 0xf5, 0xc2, 0x06, 0xf1, 0x6b, 0x49, 0x00, 0xde, - 0xb9, 0x8e, 0xbb, 0x4f, 0xe0, 0xdf, 0xaf, 0x45, 0xf4, 0x14, 0xbf, 0x92, 0xc7, 0x3a, 0xbc, 0xa7, - 0xef, 0x15, 0x34, 0xbf, 0xfa, 0x04, 0x77, 0x12, 0x0f, 0x40, 0x29, 0xe0, 0xbe, 0xb6, 0x22, 0xc4, - 0x55, 0x5d, 0x7b, 0xfc, 0x76, 0xc0, 0x97, 0xbc, 0xf8, 0x50, 0x01, 0x18, 0xd5, 0x4b, 0x84, 0xb8, - 0xe6, 0xfd, 0xd8, 0xc4, 0x43, 0x62, 0xde, 0x1e, 0x90, 0x06, 0xdb, 0xda, 0x96, 0xc9, 0x48, 0x43, - 0xbb, 0x8e, 0x10, 0xdd, 0xf3, 0x23, 0xa2, 0xca, 0xe5, 0xcd, 0xf6, 0xbe, 0xf5, 0x30, 0xd1, 0xaf, - 0x5f, 0x91, 0x1c, 0xee, 0x61, 0x43, 0x7e, 0xbf, 0xea, 0x06, 0xe8, 0xd0, 0x95, 0xcb, 0x05, 0xd6, - 0x97, 0xbc, 0x0f, 0xc0, 0x50, 0x05, 0x56, 0xea, 0x06, 0x27, 0x93, 0x8c, 0x34, 0x6e, 0xfc, 0xa9, - 0x68, 0xa7, 0xce, 0xa7, 0xe2, 0x70, 0x4d, 0x4f, 0x5d, 0x80, 0xaf, 0x2f, 0xba, 0x0a, 0x52, 0x9d, - 0x2a, 0xee, 0xf4, 0xb0, 0xd4, 0x3a, 0x37, 0x86, 0x92, 0xf4, 0x2e, 0x00, 0x36, 0x17, 0x00, 0xbc, - 0xbe, 0xd4, 0xb4, 0x6f, 0xac, 0x27, 0x07, 0xbe, 0x60, 0xd4, 0x71, 0x83, 0x0a, 0x37, 0xb8, 0x51, - 0x53, 0xd2, 0xbc, 0x0b, 0xf0, 0x1b, 0xfe, 0x20, 0x01, 0x58, 0xf7, 0xb1, 0x08, 0x71, 0x95, 0xab, - 0x77, 0x81, 0xe7, 0xf0, 0xbb, 0xfd, 0x20, 0x80, 0xbe, 0x02, 0xf8, 0xe3, 0x1b, 0x22, 0xc4, 0x75, - 0xe2, 0xbb, 0x26, 0x1e, 0x12, 0xf3, 0x2e, 0xc0, 0xef, 0x72, 0x4c, 0x95, 0x3f, 0x7b, 0x81, 0xe8, - 0xe5, 0x0d, 0x44, 0x77, 0x3d, 0x27, 0x68, 0x58, 0xe7, 0x1c, 0x14, 0x5e, 0x1f, 0x2c, 0x24, 0x30, - 0xbe, 0x0f, 0x7f, 0x93, 0xe8, 0xb9, 0x77, 0x58, 0xe7, 0x7a, 0x41, 0x7b, 0xac, 0x6b, 0x50, 0x6d, - 0x06, 0xbf, 0x77, 0x01, 0xc0, 0xf2, 0xde, 0x1f, 0x04, 0x23, 0x3e, 0x03, 0x4d, 0x5c, 0x29, 0xf0, - 0x6a, 0x15, 0x89, 0xb0, 0x90, 0x3b, 0x28, 0x34, 0xbf, 0x89, 0x68, 0xc4, 0x3d, 0x42, 0x6a, 0xe9, - 0x2e, 0xf1, 0x89, 0x09, 0xb1, 0x6e, 0xad, 0x88, 0x1e, 0xcd, 0x11, 0xf4, 0x10, 0xd7, 0xe4, 0x53, - 0x09, 0xa9, 0xf0, 0xc8, 0x19, 0xa2, 0x1d, 0x9f, 0x8b, 0x61, 0x13, 0x53, 0x89, 0x74, 0xe1, 0x03, - 0x1e, 0x82, 0xcf, 0xf1, 0x0d, 0xd0, 0xed, 0x8b, 0x67, 0x40, 0xdd, 0xfe, 0x0a, 0x10, 0x50, 0x69, - 0x71, 0xb2, 0x27, 0x6f, 0x42, 0xc5, 0x99, 0x93, 0x90, 0xb6, 0xe2, 0x02, 0x84, 0xac, 0xb8, 0x8c, - 0x89, 0xc5, 0x1e, 0xc8, 0x58, 0x55, 0x86, 0x54, 0x14, 0x7b, 0x20, 0x64, 0xc5, 0x65, 0x4c, 0x2c, - 0xb0, 0x07, 0x8a, 0x8a, 0x8a, 0x08, 0x5b, 0x79, 0x4e, 0x9e, 0x3c, 0x99, 0x32, 0x13, 0xf8, 0xec, - 0x34, 0x63, 0x46, 0xe2, 0x49, 0x2c, 0x25, 0x77, 0x48, 0x86, 0x14, 0x1f, 0x01, 0x1d, 0xc9, 0x6c, - 0x86, 0x9f, 0xdc, 0x49, 0xeb, 0xd1, 0xa3, 0x87, 0x23, 0xcd, 0x4e, 0x00, 0xdf, 0xe0, 0xc1, 0x83, - 0xed, 0xe4, 0x8c, 0xc6, 0xbd, 0x9f, 0xc8, 0x3c, 0x2a, 0x84, 0xad, 0xfb, 0xfe, 0x78, 0x0d, 0xde, - 0x6c, 0x43, 0xe0, 0x26, 0x24, 0x33, 0x74, 0xf9, 0xf2, 0x65, 0xaa, 0x57, 0xaf, 0x9e, 0x5e, 0x98, - 0xfb, 0xef, 0xbf, 0x5f, 0x92, 0xf5, 0x70, 0xd7, 0xae, 0x5d, 0x3a, 0x1d, 0xeb, 0xbb, 0xc1, 0xa3, - 0xc2, 0xc0, 0x81, 0x03, 0xf5, 0xb4, 0x3e, 0x7d, 0xfa, 0x10, 0x7f, 0x57, 0xd6, 0x71, 0xfe, 0x50, - 0xae, 0xb2, 0x04, 0xc3, 0xc3, 0xf8, 0x93, 0x2d, 0xe8, 0xcd, 0xa8, 0x61, 0xc3, 0x86, 0x5a, 0xdb, - 0xb6, 0x6d, 0x75, 0xbc, 0x72, 0xe5, 0xca, 0x86, 0xaa, 0x73, 0xe7, 0xce, 0x69, 0xbd, 0x7a, 0xf5, - 0xd2, 0xe9, 0xd5, 0xaa, 0x55, 0x33, 0xe8, 0x40, 0xf0, 0x45, 0x5e, 0xca, 0xb7, 0x6b, 0xd7, 0x4e, - 0x6b, 0xd3, 0xa6, 0x8d, 0x1e, 0x9f, 0x3d, 0x7b, 0xb6, 0x85, 0xcf, 0x6f, 0x24, 0xd4, 0x97, 0x7a, - 0x64, 0xa0, 0x46, 0x8d, 0x1a, 0x86, 0x8d, 0xdc, 0xdc, 0x5c, 0x3d, 0x13, 0x57, 0xaf, 0x5e, 0x35, - 0x68, 0x40, 0xc0, 0x67, 0x2f, 0x80, 0xa4, 0x23, 0x4d, 0x02, 0xf0, 0xb0, 0x7d, 0x25, 0x74, 0x13, - 0xea, 0xd0, 0xa1, 0x03, 0xdb, 0x15, 0xd0, 0xb3, 0x67, 0x4f, 0x1d, 0xd9, 0xba, 0x75, 0xab, 0x24, - 0x05, 0x0e, 0x2f, 0x5d, 0xe2, 0xe9, 0x75, 0x18, 0x90, 0xb5, 0x10, 0x24, 0x64, 0x3b, 0x7a, 0xed, - 0x4a, 0x99, 0xd2, 0xa5, 0x4b, 0x5b, 0xe2, 0x92, 0x0e, 0x3e, 0xbf, 0x1e, 0xe0, 0xbe, 0x21, 0xc5, - 0x02, 0x85, 0xa6, 0x1f, 0x7d, 0x8a, 0xc9, 0xcc, 0x37, 0x68, 0xd0, 0x40, 0xcf, 0xb4, 0x8c, 0x8f, - 0x1e, 0x3d, 0xda, 0xd0, 0x20, 0x69, 0xf6, 0x10, 0x0c, 0xad, 0x5a, 0xb5, 0x32, 0xe4, 0x78, 0x39, - 0x8e, 0x81, 0x83, 0x77, 0xc7, 0x8e, 0x1d, 0x86, 0x0e, 0xbf, 0x48, 0x5a, 0x0f, 0x34, 0x17, 0x2e, - 0x5c, 0xa0, 0x6d, 0xdb, 0xb6, 0x51, 0xe7, 0xce, 0x89, 0xf7, 0x9c, 0x9c, 0x8b, 0xe2, 0x86, 0xb4, - 0x0a, 0x50, 0xdc, 0x99, 0x75, 0xb3, 0x17, 0xba, 0x13, 0xbb, 0x29, 0x8b, 0x82, 0x16, 0x17, 0x20, - 0x8a, 0x5a, 0x57, 0x6d, 0xc6, 0x1e, 0x50, 0x6b, 0x23, 0x0a, 0x3c, 0xf6, 0x40, 0x14, 0xb5, 0xae, - 0xda, 0x2c, 0xf1, 0xf7, 0x01, 0xb5, 0x30, 0x25, 0x11, 0x2f, 0xf1, 0x5d, 0xa0, 0x24, 0x56, 0xba, - 0x9a, 0xe7, 0xd8, 0x01, 0x6a, 0x6d, 0x44, 0x80, 0xc7, 0x0e, 0x88, 0xa0, 0xd2, 0x55, 0x93, 0xb1, - 0x03, 0xd4, 0xda, 0x88, 0x00, 0x8f, 0x1d, 0x10, 0x41, 0xa5, 0xab, 0x26, 0x63, 0x07, 0xa8, 0xb5, - 0x11, 0x01, 0x1e, 0x3b, 0x20, 0x82, 0x4a, 0x57, 0x4d, 0xc6, 0x0e, 0x50, 0x6b, 0x23, 0x02, 0x3c, - 0xf0, 0x87, 0x19, 0x47, 0x1e, 0xcf, 0xf2, 0x42, 0xae, 0x91, 0x8b, 0x88, 0x56, 0x26, 0xce, 0x08, - 0xb0, 0x33, 0x60, 0x41, 0xe2, 0xa4, 0x7e, 0x44, 0x21, 0x37, 0x6a, 0xeb, 0xfb, 0xaf, 0xa7, 0xad, - 0x33, 0xb5, 0xba, 0x9d, 0x31, 0x60, 0xa6, 0x3a, 0xb1, 0x55, 0xfb, 0x45, 0xfe, 0xce, 0x5c, 0x70, - 0xa6, 0x61, 0xed, 0x22, 0xf6, 0x67, 0xe3, 0x9c, 0x83, 0xb2, 0x21, 0xdb, 0x22, 0xf6, 0x87, 0xa7, - 0x91, 0xbf, 0xf0, 0x0e, 0xf8, 0x8c, 0x57, 0x0e, 0xf5, 0x9e, 0x42, 0x74, 0x89, 0xf7, 0x64, 0x27, - 0x83, 0xcf, 0xf8, 0x1b, 0x66, 0xde, 0x74, 0xc1, 0xf1, 0x24, 0x7f, 0x3d, 0x40, 0x81, 0xfd, 0x02, - 0xd6, 0x71, 0xc9, 0xa5, 0x50, 0x7e, 0x65, 0x24, 0x1f, 0x4e, 0x4d, 0xc5, 0x51, 0xab, 0xc9, 0x00, - 0x5f, 0x5e, 0x5e, 0x79, 0x5f, 0xfc, 0xea, 0x56, 0xe5, 0xbd, 0xe5, 0x8f, 0x89, 0xb5, 0x92, 0xc9, - 0x64, 0xd4, 0xb4, 0x74, 0xf2, 0x97, 0xd0, 0x13, 0xce, 0x01, 0x07, 0x4e, 0xf0, 0x11, 0xc3, 0x2f, - 0xa9, 0x59, 0xe1, 0x35, 0xc8, 0x0d, 0xf9, 0xc8, 0x8f, 0x41, 0x44, 0x15, 0x95, 0x15, 0x7b, 0x2f, - 0xad, 0x25, 0x9a, 0xbc, 0xda, 0xe4, 0xc3, 0xda, 0x32, 0x9c, 0x43, 0x3b, 0xec, 0xa7, 0x26, 0x0d, - 0x18, 0xd6, 0x30, 0xe7, 0x73, 0x65, 0x63, 0x21, 0xde, 0x21, 0x76, 0xd8, 0x07, 0x05, 0xd6, 0xf4, - 0xa0, 0xb1, 0xdf, 0xcf, 0x25, 0x5a, 0xf1, 0xa1, 0x29, 0x85, 0x96, 0xfe, 0xe2, 0x03, 0x44, 0xdd, - 0x79, 0x49, 0x98, 0x04, 0x1c, 0xa9, 0xf0, 0xcb, 0x7f, 0x9a, 0x67, 0x85, 0xe2, 0xe8, 0xdb, 0x8e, - 0x7f, 0x23, 0x7a, 0xff, 0x4f, 0x4e, 0x27, 0x64, 0x3a, 0x7f, 0x32, 0x0f, 0x1c, 0x86, 0xeb, 0x77, - 0x4f, 0xf1, 0x90, 0xa3, 0x42, 0xd3, 0xda, 0x44, 0x73, 0x79, 0x21, 0x9f, 0x5a, 0xf9, 0x48, 0xc7, - 0xfa, 0xb7, 0xdf, 0xf2, 0x4f, 0x05, 0x74, 0x57, 0xfb, 0xd1, 0x7d, 0x58, 0x19, 0x8c, 0xa3, 0x19, - 0x16, 0xed, 0x4c, 0xbf, 0xf2, 0xff, 0x7d, 0xc0, 0x5a, 0xf9, 0xb0, 0x8d, 0x21, 0x50, 0xad, 0x7c, - 0xd0, 0x70, 0x28, 0x07, 0x5a, 0x3c, 0x8e, 0x46, 0x91, 0x80, 0x75, 0xe0, 0xcf, 0x2c, 0x95, 0x31, - 0x33, 0xcc, 0x64, 0xfe, 0x4c, 0xad, 0x3a, 0xa6, 0x58, 0xb7, 0xa5, 0x78, 0x45, 0x31, 0xf4, 0x60, - 0xa9, 0xb4, 0x0a, 0xbd, 0x6e, 0x55, 0x63, 0x56, 0xbc, 0x37, 0xa7, 0x4d, 0x5d, 0x6b, 0xa5, 0x2d, - 0xfe, 0x80, 0x48, 0x5d, 0xc9, 0x89, 0x65, 0xa4, 0x7b, 0xc7, 0x58, 0x79, 0x10, 0xdb, 0x7a, 0x98, - 0x68, 0xd0, 0xab, 0xc0, 0xfc, 0x03, 0x74, 0xab, 0x50, 0x86, 0xdb, 0x98, 0x3c, 0x48, 0x44, 0xa5, - 0x03, 0xc7, 0xfa, 0xda, 0x6e, 0xb7, 0x10, 0x2d, 0xdb, 0x6d, 0xa6, 0x2c, 0x61, 0xfc, 0xf9, 0x3c, - 0x33, 0x0e, 0x2c, 0x93, 0xf9, 0xb3, 0x6a, 0x4e, 0x72, 0x9e, 0x8d, 0x8d, 0xd1, 0x88, 0xda, 0x4f, - 0x43, 0x41, 0x02, 0xc6, 0x4f, 0x2f, 0xb8, 0x99, 0x5b, 0x9a, 0x1d, 0x8e, 0x73, 0xf7, 0xb7, 0x03, - 0x2a, 0xca, 0x0e, 0x6e, 0x34, 0x3b, 0x8f, 0x3d, 0x7e, 0x8c, 0x87, 0x12, 0x15, 0x52, 0xad, 0xea, - 0xb6, 0x1f, 0x4f, 0x73, 0xfd, 0x3a, 0xd1, 0x89, 0xaf, 0x89, 0x6e, 0xaa, 0xa2, 0x6a, 0x21, 0x72, - 0xcb, 0x8b, 0x1b, 0xcd, 0x2a, 0x95, 0x32, 0xe6, 0x52, 0xea, 0x14, 0x32, 0x65, 0x78, 0x3c, 0xb5, - 0x03, 0xc6, 0x48, 0x2f, 0x70, 0x4b, 0x2b, 0x1d, 0xdc, 0xac, 0x97, 0x7a, 0x07, 0xdd, 0x9e, 0x3f, - 0x37, 0xfb, 0xaa, 0x90, 0x5b, 0x7a, 0x69, 0x97, 0x32, 0xaa, 0x32, 0x19, 0xc4, 0x83, 0xd7, 0x44, - 0xfd, 0x1a, 0x4e, 0xf3, 0x87, 0xf9, 0xc6, 0xe9, 0x05, 0x6e, 0x69, 0xf5, 0xab, 0x7b, 0x71, 0xa7, - 0x4f, 0xb7, 0xeb, 0xc6, 0xc6, 0x0c, 0x2c, 0x6b, 0xf6, 0x02, 0x7b, 0xfe, 0x70, 0x4f, 0xa8, 0x1d, - 0x6e, 0xef, 0x82, 0x97, 0x89, 0x64, 0xf4, 0xe0, 0x0e, 0xc0, 0x90, 0xd2, 0xbe, 0xb1, 0x55, 0xe7, - 0x72, 0x1e, 0x37, 0xbd, 0xce, 0x65, 0x7d, 0xcb, 0x36, 0x26, 0x43, 0x12, 0x47, 0x69, 0x65, 0x0b, - 0xdc, 0x74, 0xdb, 0xef, 0x0b, 0xd2, 0x36, 0x66, 0x5d, 0xeb, 0x3f, 0x91, 0x31, 0x11, 0xba, 0xc9, - 0x5b, 0x39, 0x32, 0x1a, 0x0b, 0xee, 0x00, 0x98, 0xc7, 0x4d, 0x4a, 0xdd, 0x80, 0x85, 0x31, 0xb3, - 0xe7, 0x8b, 0x44, 0xd8, 0xf1, 0xa5, 0xc2, 0xd8, 0x65, 0x44, 0xb3, 0x36, 0xab, 0x14, 0x3e, 0xd0, - 0xaa, 0x87, 0x73, 0x7c, 0xb5, 0x72, 0xa4, 0x17, 0xbb, 0xb3, 0x09, 0xd1, 0x2f, 0x6e, 0xb7, 0xea, - 0xc0, 0xcc, 0xe6, 0x35, 0xdb, 0xca, 0x25, 0x6c, 0x20, 0xc0, 0x39, 0xf9, 0x18, 0xf3, 0x25, 0x54, - 0xaf, 0xc4, 0x9b, 0xc2, 0x12, 0xbb, 0xd7, 0x24, 0x2d, 0xcb, 0x61, 0xf0, 0x59, 0x10, 0x32, 0x84, - 0x5e, 0xf0, 0xfe, 0xe3, 0x7c, 0x62, 0xd8, 0x64, 0x73, 0x13, 0x0d, 0xf6, 0x91, 0xa4, 0xda, 0xbe, - 0x97, 0xcf, 0xd3, 0x41, 0xdb, 0x5f, 0x94, 0x64, 0xa5, 0x7c, 0xcf, 0xf6, 0x21, 0x7d, 0x4b, 0x95, - 0xfa, 0x84, 0x3a, 0x96, 0x9d, 0x80, 0x9f, 0x17, 0x34, 0xe7, 0x83, 0xc2, 0x16, 0x0c, 0x15, 0x1b, - 0x43, 0xbd, 0x78, 0xb2, 0x40, 0x0f, 0xe7, 0x00, 0x64, 0x04, 0x27, 0x91, 0x61, 0xdf, 0x0c, 0x4e, - 0xff, 0x9b, 0xb4, 0x8a, 0x9f, 0x03, 0xb6, 0xf1, 0x58, 0x7b, 0xd1, 0x9a, 0x45, 0x6c, 0x4d, 0xb9, - 0x83, 0x5b, 0xe4, 0x78, 0xae, 0x90, 0xef, 0x25, 0x99, 0x29, 0x59, 0xa5, 0x32, 0x13, 0xc3, 0xc3, - 0x1e, 0x7e, 0xf8, 0xc3, 0x06, 0xbc, 0x2a, 0xf9, 0x98, 0x1f, 0x1e, 0xd5, 0xd6, 0x0e, 0x2b, 0xb5, - 0x78, 0xac, 0x7f, 0x34, 0x87, 0x1f, 0xc8, 0xee, 0xc8, 0x8c, 0xcd, 0x10, 0x5a, 0xe2, 0x8f, 0xf2, - 0x21, 0x2a, 0x2d, 0x93, 0x22, 0xe1, 0xee, 0x01, 0x99, 0xcc, 0xc1, 0x77, 0x5c, 0x57, 0xec, 0x80, - 0x88, 0x1b, 0x40, 0xec, 0x80, 0xd8, 0x01, 0x11, 0xd7, 0x40, 0xc4, 0xe6, 0xe3, 0x1e, 0x10, 0x3b, - 0x20, 0xe2, 0x1a, 0x88, 0xd8, 0x7c, 0xdc, 0x03, 0x62, 0x07, 0x84, 0xaf, 0x81, 0x2b, 0x57, 0xae, - 0x10, 0x76, 0xba, 0x94, 0x64, 0xc8, 0x7a, 0x0f, 0xb8, 0x78, 0xf1, 0x22, 0xf1, 0xb6, 0x38, 0x63, - 0xf3, 0x21, 0x36, 0x20, 0xf6, 0xef, 0xdf, 0x3f, 0xed, 0x3a, 0xe3, 0x83, 0x71, 0xa9, 0x5c, 0xb9, - 0x72, 0xc4, 0x7b, 0x04, 0x69, 0xc8, 0x90, 0x21, 0x69, 0xeb, 0x8b, 0x4a, 0x41, 0xd6, 0x1d, 0x80, - 0x1d, 0x9d, 0x13, 0x27, 0x4e, 0xa4, 0x96, 0x2d, 0x5b, 0x1a, 0x65, 0x3c, 0x7b, 0xd6, 0xf6, 0xd1, - 0xc4, 0x48, 0xf1, 0x8f, 0xf0, 0x7f, 0xeb, 0xe8, 0x7f, 0xe2, 0x83, 0x3f, 0xf2, 0x01, 0x5e, 0x52, - 0x21, 0xfc, 0xbb, 0xa0, 0x00, 0x25, 0xc6, 0x3f, 0x1a, 0xed, 0xdb, 0xb7, 0x8f, 0xf6, 0xef, 0xdf, - 0xef, 0x90, 0x3a, 0x71, 0xe2, 0x04, 0x5d, 0xbb, 0x76, 0xcd, 0xb1, 0x2d, 0xd7, 0xc1, 0x98, 0x20, - 0xa0, 0x47, 0x1d, 0x38, 0x70, 0x40, 0xe7, 0x5f, 0xb4, 0x88, 0xdf, 0xf1, 0x30, 0xd4, 0xad, 0x9b, - 0xfa, 0xc4, 0x7d, 0x1c, 0xe8, 0x7d, 0xea, 0x14, 0xbf, 0x30, 0x64, 0x68, 0xdc, 0xb8, 0x31, 0x55, - 0xad, 0x5a, 0x55, 0x8f, 0x6f, 0xd9, 0xb2, 0x45, 0xcf, 0x5b, 0xd3, 0xa6, 0x4d, 0xa9, 0x53, 0xa7, - 0x4e, 0x54, 0xbb, 0x76, 0x6d, 0x9d, 0xa7, 0xd8, 0x2e, 0x7e, 0xb7, 0x24, 0xa6, 0xcb, 0x27, 0xcf, - 0xd2, 0xe6, 0x82, 0x59, 0xb6, 0x47, 0xda, 0xe3, 0x55, 0xaa, 0x54, 0xd1, 0xe6, 0xce, 0x9d, 0xeb, - 0x6a, 0x6e, 0xde, 0xbc, 0x79, 0xae, 0xb2, 0x6e, 0xfb, 0x49, 0x55, 0x05, 0xdc, 0xfb, 0x2c, 0x72, - 0x5c, 0xc9, 0x5a, 0x99, 0x32, 0x65, 0x2c, 0x34, 0x99, 0x0f, 0x76, 0xa6, 0xc6, 0xf7, 0x15, 0x55, - 0x3c, 0xab, 0x78, 0xe0, 0xbd, 0xaa, 0x61, 0x73, 0x63, 0x77, 0xc0, 0x80, 0x01, 0x03, 0x34, 0x6e, - 0xcd, 0x86, 0xba, 0x69, 0xd3, 0xa6, 0x59, 0x2a, 0xa4, 0x77, 0xef, 0xde, 0x46, 0x9a, 0x1b, 0x22, - 0x0f, 0x3d, 0x47, 0xc5, 0xa5, 0x72, 0x00, 0xe4, 0xe5, 0x61, 0xe8, 0xb2, 0xa2, 0xd5, 0xed, 0xd5, - 0xd7, 0xaf, 0x5f, 0xd7, 0xb8, 0x57, 0x18, 0xf6, 0xc7, 0x8c, 0x19, 0xe3, 0x66, 0x32, 0x2b, 0xb4, - 0xac, 0xdf, 0x03, 0xb8, 0xc0, 0x0e, 0xe8, 0xd6, 0xad, 0x1b, 0xcd, 0x99, 0x33, 0x87, 0xca, 0x97, - 0x4f, 0x1c, 0xaa, 0xc5, 0x1c, 0x43, 0x87, 0x0e, 0x25, 0x3e, 0x2a, 0xdf, 0xe0, 0x5d, 0xb2, 0x64, - 0x89, 0x3e, 0xd4, 0x18, 0x84, 0x0c, 0x23, 0xec, 0x70, 0x43, 0x23, 0x26, 0x06, 0xf8, 0x87, 0x39, - 0x09, 0x07, 0x0f, 0x1e, 0x94, 0x68, 0xd6, 0xc3, 0x48, 0x1c, 0xb0, 0x67, 0xcf, 0x1e, 0xc2, 0x91, - 0x0d, 0x76, 0xd8, 0xbe, 0x7d, 0xbb, 0x41, 0x42, 0xa5, 0xf8, 0x19, 0xdb, 0x0d, 0x81, 0x80, 0x08, - 0x0f, 0x41, 0x16, 0x09, 0xd8, 0x8b, 0x04, 0xb2, 0xd2, 0xaf, 0x6c, 0x4a, 0x79, 0x9a, 0xa8, 0x0f, - 0x13, 0x5c, 0x40, 0xa3, 0x9b, 0x03, 0xe7, 0x9b, 0x9e, 0xf6, 0xc4, 0x13, 0x4f, 0x68, 0x3c, 0x2d, - 0xb5, 0x8c, 0xc9, 0x5c, 0x19, 0xda, 0xea, 0xd5, 0xab, 0x2d, 0x5a, 0xe6, 0xcf, 0x9f, 0xaf, 0xf1, - 0x7f, 0x22, 0x6a, 0xd8, 0xa6, 0x8f, 0x1f, 0xc6, 0x71, 0xa9, 0x0f, 0xfc, 0x92, 0xde, 0xa8, 0x51, - 0x23, 0xfd, 0xb8, 0x8a, 0xe3, 0xc7, 0x8f, 0x1b, 0xf2, 0xd3, 0xa7, 0x4f, 0xd7, 0x70, 0xbc, 0x85, - 0xe4, 0x47, 0x88, 0xe3, 0x2a, 0x36, 0x6f, 0xde, 0xac, 0xf1, 0x04, 0x40, 0xeb, 0xd7, 0xaf, 0x9f, - 0x56, 0xa9, 0x52, 0x25, 0x23, 0x9d, 0xff, 0xcd, 0x59, 0xc3, 0xff, 0x35, 0xd8, 0x4f, 0x90, 0x30, - 0x14, 0x66, 0x10, 0x29, 0x96, 0x59, 0xd0, 0xd1, 0xa3, 0x47, 0x09, 0xe7, 0xdd, 0x00, 0xf0, 0x57, - 0xd5, 0xeb, 0xd7, 0xaf, 0xa7, 0x29, 0x53, 0xa6, 0xd0, 0xcc, 0x99, 0x33, 0x69, 0xc3, 0x86, 0x0d, - 0x3a, 0x1d, 0x17, 0x3e, 0xcb, 0x80, 0xa6, 0x4e, 0x9d, 0x4a, 0x5d, 0xba, 0x74, 0x31, 0x68, 0x12, - 0xc1, 0xd4, 0x15, 0x33, 0x99, 0x63, 0xc7, 0x8e, 0x49, 0x92, 0x11, 0x72, 0x7d, 0xe8, 0x69, 0x20, - 0xa0, 0x25, 0xd7, 0xaa, 0x55, 0xcb, 0xd2, 0xc3, 0xce, 0x9c, 0x39, 0x43, 0xe7, 0xcf, 0x9f, 0x37, - 0xf8, 0x81, 0x9c, 0x3e, 0x7d, 0x5a, 0x7f, 0x88, 0xe3, 0xf1, 0x9f, 0xbe, 0xfa, 0xea, 0x2b, 0xc2, - 0x43, 0x9d, 0x04, 0xe0, 0xa0, 0x21, 0xcd, 0xde, 0x53, 0x24, 0x4f, 0xa6, 0xc2, 0xf8, 0x8b, 0x58, - 0xa6, 0x6a, 0x32, 0xa4, 0x9e, 0x48, 0xee, 0x01, 0x21, 0xf3, 0xfa, 0xad, 0x14, 0x8b, 0x1d, 0x10, - 0xb1, 0x5b, 0x63, 0x07, 0xc4, 0x0e, 0x88, 0xb8, 0x06, 0x22, 0x36, 0x1f, 0xf7, 0x80, 0xd8, 0x01, - 0x11, 0xd7, 0x40, 0xc4, 0xe6, 0xe3, 0x1e, 0x10, 0x3b, 0x20, 0xe2, 0x1a, 0x88, 0xd8, 0xfc, 0xff, - 0x01, 0xdc, 0xb2, 0xfe, 0x66, 0x57, 0x2f, 0x5a, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, - 0x44, 0xae, 0x42, 0x60, 0x82 -}; - - -#pragma mark - 3D Explorer Icons - -static const u_int8_t FLEXToggle2DIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x3f, 0x5b, - 0x66, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x34, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xdf, 0xdc, 0x41, 0x00, 0x00, - 0x02, 0x1f, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x98, 0xcf, 0x2b, 0x44, 0x51, 0x14, 0xc7, - 0x3d, 0xbf, 0x86, 0x92, 0x8d, 0x3f, 0x60, 0xc4, 0xc2, 0xd6, 0x8f, 0xb2, 0x40, 0x2c, 0xc9, 0x46, - 0xcd, 0x82, 0x94, 0x7f, 0x40, 0x52, 0xca, 0x4a, 0x12, 0x4a, 0x76, 0xca, 0x42, 0xc9, 0xc6, 0xc6, - 0x02, 0x0b, 0x25, 0x8b, 0xd9, 0x48, 0xc6, 0xc6, 0x0e, 0x65, 0x37, 0x7e, 0x65, 0x83, 0x0d, 0x2b, - 0xbf, 0xc2, 0x68, 0x7c, 0x8e, 0x86, 0x5e, 0xd7, 0x79, 0x79, 0xca, 0xdc, 0xa1, 0xee, 0xa9, 0x6f, - 0xf7, 0x9e, 0x73, 0xcf, 0x7d, 0xe7, 0x7b, 0xce, 0xbb, 0xef, 0xbe, 0xfb, 0x5e, 0x5e, 0x1e, 0x92, - 0x4e, 0xa7, 0x63, 0x60, 0x1d, 0xac, 0x82, 0x26, 0xb1, 0xfd, 0x57, 0xf1, 0x48, 0xa0, 0x07, 0xf2, - 0x2b, 0xbe, 0x04, 0x52, 0xf4, 0x1b, 0x3d, 0xcf, 0x3b, 0xf0, 0xd9, 0x24, 0xe9, 0x32, 0xf4, 0x29, - 0xd0, 0x01, 0xf2, 0xfd, 0x63, 0x59, 0xec, 0xa7, 0xb9, 0x76, 0x02, 0x8c, 0xc2, 0xe7, 0x3a, 0x54, - 0x1c, 0x88, 0x6e, 0x02, 0x53, 0x66, 0xcd, 0xc9, 0x38, 0xf4, 0x9b, 0x4e, 0x16, 0xf5, 0x09, 0x93, - 0x4f, 0x90, 0x2e, 0x95, 0x7e, 0x51, 0x06, 0x35, 0xdb, 0x83, 0xe2, 0x67, 0xcb, 0x14, 0x3a, 0xb6, - 0x2c, 0xb9, 0x76, 0x58, 0xc5, 0xc1, 0xc7, 0x32, 0xba, 0xa7, 0x5f, 0xcf, 0x2d, 0x3e, 0xf2, 0xb3, - 0xc5, 0x2f, 0x82, 0x3e, 0x04, 0x72, 0xb1, 0xe4, 0x66, 0xe0, 0x73, 0xeb, 0xe7, 0x13, 0xd4, 0xf7, - 0x64, 0x00, 0xb2, 0xcd, 0x34, 0x7d, 0xe0, 0x09, 0xcc, 0x33, 0x39, 0x49, 0xeb, 0xc4, 0x55, 0xc0, - 0x55, 0xc0, 0x55, 0xc0, 0x55, 0xe0, 0xcf, 0x55, 0xe0, 0x7d, 0xdb, 0xd6, 0x58, 0xb1, 0x95, 0x17, - 0x61, 0x6f, 0x03, 0xc5, 0x20, 0xc1, 0x56, 0x1e, 0xfa, 0xe5, 0xa6, 0x5d, 0xcf, 0x96, 0x4d, 0x4d, - 0x88, 0x64, 0xca, 0x21, 0xb0, 0x03, 0x6a, 0x33, 0x44, 0xce, 0x68, 0x5b, 0x49, 0xea, 0x22, 0xa3, - 0x7f, 0x36, 0xf8, 0x46, 0x51, 0xba, 0x80, 0xbc, 0x78, 0x6d, 0xc9, 0x1e, 0x81, 0xb6, 0xe1, 0x23, - 0x67, 0xbd, 0xef, 0x05, 0x92, 0xe3, 0xc0, 0x94, 0x05, 0x73, 0x26, 0x0e, 0x51, 0x90, 0x32, 0x1d, - 0x2d, 0xe9, 0x23, 0x26, 0x1f, 0xd1, 0x3f, 0x8e, 0x3b, 0xe6, 0x58, 0x95, 0x69, 0x40, 0xaf, 0x56, - 0x6c, 0xf2, 0xa9, 0x51, 0xa0, 0xd8, 0x6d, 0x98, 0x5a, 0xb4, 0x20, 0x41, 0x09, 0x6d, 0x29, 0xce, - 0x9a, 0x6d, 0x03, 0xbf, 0x7d, 0xc5, 0x37, 0xdb, 0xa6, 0x1b, 0x02, 0xcc, 0x69, 0x41, 0x82, 0x9e, - 0x21, 0xb1, 0x4f, 0x83, 0x41, 0x20, 0x77, 0x60, 0x09, 0x0c, 0xb0, 0x66, 0xb5, 0x53, 0xb8, 0x9c, - 0x05, 0x2b, 0x19, 0xb7, 0xf9, 0x0c, 0x9d, 0xc3, 0x45, 0xce, 0x9d, 0x3f, 0x13, 0x88, 0xe6, 0x83, - 0xc2, 0x9f, 0xcd, 0x72, 0xde, 0xae, 0x02, 0xae, 0x02, 0xae, 0x02, 0xae, 0x02, 0xd9, 0xab, 0x80, - 0xfa, 0x1e, 0x0a, 0x0a, 0xc7, 0x16, 0xde, 0xcd, 0xd8, 0x24, 0xa8, 0x00, 0x6b, 0x60, 0x98, 0xf7, - 0x81, 0x7a, 0x68, 0xc5, 0xb7, 0x94, 0x71, 0x39, 0xd8, 0xda, 0x92, 0x3b, 0xb8, 0xbc, 0x86, 0x0e, - 0x06, 0xc1, 0x06, 0xf0, 0x0a, 0xfc, 0xf2, 0xe5, 0xff, 0x9d, 0x5c, 0x10, 0x87, 0x45, 0xf0, 0xec, - 0x77, 0xb4, 0xd0, 0xbf, 0x24, 0x86, 0xfc, 0x34, 0x0d, 0x27, 0x38, 0x8f, 0x29, 0xa4, 0x4e, 0xcd, - 0xd9, 0xf8, 0x48, 0xe2, 0xb9, 0x92, 0x64, 0xd0, 0x59, 0xce, 0xe4, 0x29, 0xfa, 0x95, 0x62, 0xd4, - 0x6c, 0x27, 0xf8, 0xa9, 0xcb, 0x50, 0x99, 0xff, 0xdb, 0xa6, 0xc3, 0xd0, 0xcf, 0x10, 0x25, 0x2f, - 0x21, 0xfa, 0x2e, 0xa8, 0xcb, 0xb0, 0x78, 0xa4, 0xed, 0x64, 0xdd, 0x26, 0x32, 0xfa, 0x67, 0x83, - 0x6f, 0x0d, 0x4a, 0x2f, 0x90, 0xff, 0xe1, 0xb6, 0xe4, 0x98, 0x40, 0xcb, 0xa1, 0x13, 0x12, 0x56, - 0x10, 0x8d, 0xd0, 0xc4, 0x80, 0x6c, 0x0a, 0x71, 0x92, 0x91, 0x0f, 0x3f, 0x27, 0xd9, 0xac, 0xc0, - 0x1b, 0xa1, 0x20, 0xca, 0x34, 0x04, 0xe9, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, - 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXToggle2DIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0xbf, 0x82, 0x4c, - 0xac, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xa7, 0x5a, 0xe9, 0x00, 0x00, - 0x03, 0x33, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, 0x9b, 0x4d, 0x88, 0x4e, 0x61, 0x14, 0xc7, - 0xe7, 0x1a, 0x5f, 0x65, 0xe3, 0x23, 0x8a, 0xed, 0x64, 0x61, 0x22, 0x5f, 0xc9, 0x57, 0xc8, 0x42, - 0x29, 0x0b, 0xe5, 0x63, 0x43, 0xd9, 0x20, 0x11, 0x29, 0x9b, 0xd9, 0xb3, 0xb0, 0xd5, 0xac, 0x24, - 0x42, 0xd9, 0x48, 0xb3, 0xf3, 0x11, 0x0d, 0x09, 0x35, 0x44, 0x61, 0x43, 0xde, 0xb1, 0x20, 0x29, - 0x43, 0xb2, 0x41, 0xa9, 0xe9, 0x7d, 0xfd, 0xce, 0x64, 0xa6, 0x3b, 0x6f, 0xf7, 0x39, 0xe7, 0xbe, - 0xf3, 0xbc, 0xf1, 0xdc, 0x9c, 0x53, 0xff, 0xee, 0xbd, 0xcf, 0xff, 0x39, 0xe7, 0x39, 0xe7, 0x7f, - 0xef, 0x7d, 0x6e, 0xf7, 0xb9, 0xef, 0x9b, 0x75, 0x60, 0x8d, 0x46, 0x63, 0x32, 0x9b, 0x3d, 0x60, - 0x35, 0xf8, 0x09, 0xfa, 0xb3, 0x2c, 0xbb, 0xcd, 0xd6, 0x2d, 0xa0, 0x40, 0x86, 0x68, 0xf3, 0xe0, - 0x6e, 0x81, 0x15, 0x4d, 0x7d, 0xae, 0x70, 0xbc, 0x0f, 0x01, 0x1b, 0x4d, 0xed, 0xe3, 0x0e, 0xf1, - 0x9f, 0x46, 0xc3, 0x32, 0x30, 0x73, 0x1c, 0x91, 0xe6, 0xc1, 0x0f, 0xd2, 0x7a, 0x4e, 0x4d, 0xb2, - 0x8d, 0x33, 0x0a, 0xef, 0x03, 0x21, 0x3b, 0xa6, 0x45, 0xc7, 0xa9, 0x0b, 0xbc, 0x0d, 0x39, 0x27, - 0xda, 0x3e, 0x44, 0x5e, 0x6b, 0xb4, 0xba, 0xca, 0x70, 0x72, 0xc5, 0xd5, 0xe9, 0x98, 0x05, 0x3a, - 0x3f, 0xe3, 0xec, 0xac, 0x0a, 0x70, 0x72, 0x8b, 0xf7, 0xc1, 0xed, 0x08, 0xf1, 0x09, 0xb7, 0xbf, - 0xa4, 0x2e, 0xb9, 0x4b, 0x26, 0x6c, 0x93, 0xf0, 0x0c, 0x89, 0x26, 0x41, 0xbb, 0x8c, 0xc8, 0xdd, - 0x06, 0x9f, 0x2a, 0xbd, 0x88, 0x93, 0xae, 0xd5, 0x6d, 0xe6, 0x2d, 0xc2, 0x0d, 0x2b, 0xbd, 0x5e, - 0x29, 0x9c, 0x50, 0x03, 0x06, 0x9f, 0x2a, 0xfd, 0xd8, 0x9a, 0xbb, 0xad, 0xc4, 0x45, 0xb8, 0x73, - 0x4a, 0xa7, 0x5e, 0x85, 0x13, 0xaa, 0x07, 0xdc, 0x33, 0xfa, 0xa4, 0x46, 0xbf, 0x20, 0xa1, 0x03, - 0xb1, 0x49, 0xc9, 0x1c, 0x37, 0x83, 0x20, 0x97, 0xc1, 0xce, 0x5c, 0x30, 0xb9, 0x0a, 0x4f, 0x72, - 0x56, 0x4e, 0xe5, 0xda, 0x82, 0xbb, 0xc4, 0x98, 0x0d, 0x59, 0x85, 0xa7, 0xea, 0x77, 0x6a, 0xfa, - 0x1c, 0x2c, 0xa4, 0x05, 0x62, 0xec, 0x3e, 0xa7, 0x78, 0x79, 0xd2, 0x08, 0xe4, 0x51, 0x7d, 0x9f, - 0x01, 0x06, 0x5b, 0x88, 0xe3, 0x5d, 0x5d, 0x01, 0x57, 0xc0, 0x15, 0x70, 0x05, 0x5c, 0x01, 0x57, - 0xc0, 0x15, 0x70, 0x05, 0x5c, 0x01, 0x57, 0xc0, 0x15, 0xf8, 0xa3, 0x00, 0x6f, 0x17, 0x53, 0x5d, - 0x8c, 0x92, 0x0a, 0x20, 0x96, 0xbc, 0xcf, 0x1e, 0x05, 0x35, 0x50, 0x07, 0x1f, 0xc0, 0x69, 0x20, - 0x2b, 0xbf, 0xff, 0xad, 0x8d, 0xbd, 0xab, 0x86, 0x14, 0x40, 0x20, 0x59, 0x21, 0x29, 0x5a, 0x09, - 0xbe, 0x43, 0xfb, 0x56, 0x6d, 0x79, 0x06, 0xdf, 0x29, 0xf4, 0x39, 0x02, 0xd6, 0x82, 0x2a, 0x08, - 0xfd, 0x89, 0x3c, 0x2f, 0x51, 0xd3, 0x13, 0xb6, 0x13, 0x37, 0x0a, 0x5f, 0x0a, 0xe4, 0x2a, 0x0b, - 0xd9, 0x6e, 0x2d, 0x3a, 0x4e, 0xd7, 0x42, 0x8e, 0x09, 0xb7, 0x0f, 0x93, 0xdb, 0x3a, 0xad, 0x2e, - 0xe1, 0x64, 0x3d, 0x4e, 0xb3, 0x0d, 0x90, 0xda, 0x55, 0xb9, 0x29, 0xe4, 0xcc, 0xe0, 0xf2, 0x11, - 0x68, 0x57, 0x88, 0x4f, 0xb8, 0xbd, 0x93, 0xdc, 0x0e, 0x59, 0xf9, 0x59, 0xc2, 0x49, 0x10, 0xcd, - 0x34, 0x7f, 0x8d, 0xd3, 0x62, 0xa6, 0xc0, 0x69, 0x17, 0xcb, 0x48, 0x7e, 0x56, 0x71, 0x0f, 0x8d, - 0x2a, 0x1e, 0x85, 0x78, 0xe6, 0x09, 0x99, 0x2f, 0xae, 0x87, 0xf8, 0x84, 0xdb, 0xe5, 0x73, 0xe8, - 0x05, 0x2b, 0x3f, 0x53, 0x59, 0x6e, 0x39, 0x59, 0x5a, 0x3f, 0x58, 0x10, 0xe8, 0x01, 0x6d, 0x9b, - 0x11, 0x48, 0xbe, 0x92, 0x15, 0x1a, 0xbe, 0xd3, 0x21, 0x4e, 0x80, 0x2a, 0x3d, 0x1c, 0xce, 0x53, - 0x93, 0xd4, 0x16, 0x67, 0x14, 0xdf, 0x09, 0x7a, 0xc0, 0x47, 0x20, 0xf6, 0x15, 0xf4, 0x02, 0x59, - 0x72, 0x77, 0x2b, 0xa3, 0x00, 0x62, 0x55, 0xe1, 0xbb, 0x42, 0x99, 0x52, 0xbc, 0x8f, 0x2b, 0xe0, - 0x0a, 0xb8, 0x02, 0xae, 0x80, 0x2b, 0xe0, 0x0a, 0xb8, 0x02, 0xae, 0x80, 0x2b, 0xe0, 0x0a, 0xb4, - 0xa2, 0x80, 0xf9, 0xae, 0x5a, 0x26, 0x18, 0x6f, 0x14, 0x73, 0xe8, 0xb7, 0x11, 0xcc, 0x07, 0xf2, - 0x33, 0xaa, 0x01, 0xde, 0xf7, 0xd4, 0xdf, 0x0e, 0xd3, 0xa7, 0xd2, 0x16, 0x2d, 0x1c, 0xa2, 0xc9, - 0x9a, 0x9b, 0x2c, 0x04, 0xcc, 0xca, 0x29, 0x71, 0x97, 0xfd, 0xbd, 0x88, 0x37, 0x94, 0x6b, 0x2b, - 0xdc, 0xc5, 0x5f, 0x72, 0x98, 0x0b, 0xa2, 0x73, 0x29, 0x1c, 0xa0, 0x7d, 0x8d, 0x75, 0xea, 0xf9, - 0xd2, 0x96, 0x70, 0x14, 0xbd, 0x04, 0xfc, 0x02, 0x45, 0x76, 0xc3, 0x1a, 0x04, 0xa7, 0xc3, 0xe0, - 0x5b, 0x91, 0x73, 0xa2, 0x6d, 0xb2, 0xc0, 0xb1, 0x5f, 0xea, 0x8a, 0x3a, 0xcb, 0x04, 0x09, 0x2d, - 0x39, 0x8d, 0x6a, 0xd6, 0xcd, 0x59, 0x7a, 0x3d, 0x7a, 0x90, 0xdf, 0xe2, 0xbb, 0x92, 0xe3, 0xa7, - 0x20, 0x2a, 0x87, 0x7c, 0xcc, 0xbf, 0xb4, 0x2f, 0xcb, 0x68, 0xcb, 0xad, 0x85, 0x4c, 0x2b, 0x97, - 0xc5, 0x46, 0x07, 0x8d, 0xb7, 0x96, 0xe5, 0x8d, 0xd0, 0xff, 0x8c, 0x16, 0xcd, 0xd6, 0xc7, 0x0a, - 0xf7, 0xce, 0x48, 0xff, 0xbd, 0xc2, 0xd7, 0x14, 0x2e, 0x75, 0x6a, 0x30, 0x56, 0xb8, 0xab, 0x4a, - 0x85, 0x6f, 0xe0, 0xe4, 0x09, 0x5b, 0x68, 0xdc, 0xc2, 0x37, 0x21, 0xe4, 0xdf, 0x3b, 0x55, 0xb3, - 0x8b, 0xe4, 0xde, 0x1f, 0x3d, 0xbf, 0x30, 0x57, 0x9d, 0xa1, 0xf2, 0xe3, 0x4d, 0xd5, 0xcb, 0xd3, - 0x67, 0x1b, 0x03, 0xc8, 0x1c, 0xa6, 0x1a, 0xfe, 0x72, 0x3b, 0x2f, 0x04, 0xd1, 0xb9, 0xa8, 0x03, - 0xc5, 0x93, 0x32, 0xb7, 0xd5, 0xa8, 0x69, 0xe4, 0x2f, 0x0c, 0x6d, 0x49, 0x96, 0xe2, 0xb7, 0x10, - 0x74, 0x3b, 0x58, 0x00, 0xe4, 0x2a, 0x3b, 0xcb, 0x00, 0x6d, 0xf9, 0x75, 0x37, 0xb1, 0xdc, 0x5c, - 0x01, 0x57, 0xa0, 0xe3, 0x37, 0x24, 0xed, 0x51, 0x75, 0x62, 0x2b, 0x68, 0x57, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXToggle3DIcon2x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x67, 0x8e, 0xe8, - 0xa6, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x4a, 0x2a, 0x28, 0x00, 0x00, - 0x03, 0xc8, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xed, 0x99, 0x4b, 0x48, 0x55, 0x41, 0x18, 0xc7, - 0x3b, 0xa2, 0x62, 0x19, 0x16, 0xa6, 0x2d, 0xa4, 0x37, 0x62, 0x21, 0x51, 0x46, 0x90, 0x2d, 0x24, - 0x6a, 0x21, 0x2e, 0x5c, 0x45, 0x6e, 0x22, 0xdb, 0x18, 0xd5, 0x22, 0x03, 0x17, 0xad, 0x2c, 0x7b, - 0x50, 0x41, 0x04, 0xb6, 0xa9, 0x4d, 0x42, 0xf4, 0x2e, 0x89, 0x12, 0x8a, 0x5a, 0x64, 0x44, 0x2f, - 0x7a, 0xd0, 0x93, 0xca, 0x5c, 0x18, 0x24, 0xf4, 0xc2, 0xa4, 0x82, 0xa2, 0x0c, 0x33, 0xbb, 0xfd, - 0x3e, 0x61, 0x8e, 0xc7, 0x61, 0xc6, 0x73, 0xee, 0xbd, 0x73, 0x11, 0xc3, 0x0f, 0x7e, 0xdc, 0x99, - 0x6f, 0xe6, 0xfb, 0xbe, 0xff, 0x99, 0x33, 0x67, 0xee, 0xf1, 0xea, 0x8d, 0x73, 0x6c, 0xb1, 0x58, - 0x6c, 0x0a, 0x29, 0x2b, 0xa1, 0x10, 0x4e, 0x7a, 0x9e, 0xf7, 0xda, 0x71, 0x89, 0xe4, 0xd2, 0x21, - 0x70, 0x02, 0xec, 0x82, 0x1e, 0x50, 0xd6, 0x47, 0x23, 0x3f, 0xb9, 0xcc, 0x8e, 0xa2, 0x11, 0xe2, - 0xc1, 0x1a, 0x78, 0x07, 0x26, 0xab, 0x76, 0x54, 0x2a, 0xf1, 0x34, 0xa8, 0x5a, 0x02, 0xf7, 0x4c, - 0xea, 0xf0, 0xbd, 0x85, 0xd5, 0x89, 0x67, 0x77, 0x10, 0x89, 0x80, 0x02, 0x38, 0x0e, 0x7f, 0x41, - 0x37, 0xb9, 0xf5, 0x3b, 0x61, 0xbc, 0x83, 0x52, 0x89, 0xa5, 0xa0, 0x78, 0x16, 0x6c, 0x85, 0x1f, - 0x60, 0xb2, 0xb3, 0x38, 0xa7, 0x0f, 0x97, 0x9d, 0xf1, 0x0a, 0x38, 0x02, 0x4f, 0xa1, 0x01, 0xdc, - 0x5e, 0x10, 0x09, 0xab, 0xa0, 0x13, 0x4c, 0xf6, 0x04, 0x67, 0x59, 0x88, 0xc0, 0x62, 0xe6, 0xb4, - 0x1a, 0x82, 0xdd, 0x6c, 0x0f, 0x12, 0x97, 0xc0, 0x4d, 0x43, 0x01, 0x71, 0x75, 0xc1, 0x3a, 0x48, - 0xb3, 0x89, 0x64, 0x2c, 0x17, 0x0e, 0xc2, 0x1f, 0xd0, 0xad, 0x1f, 0x47, 0x9d, 0x2d, 0x36, 0x92, - 0x9f, 0x04, 0x53, 0xa1, 0x09, 0x24, 0x99, 0x6e, 0xbd, 0x38, 0xf6, 0x43, 0x8e, 0x2d, 0x19, 0x63, - 0xe9, 0x50, 0x0b, 0x5f, 0xc0, 0x64, 0xb7, 0x70, 0x96, 0xd8, 0xe2, 0x43, 0xfd, 0x04, 0x67, 0xc2, - 0x16, 0xf8, 0x06, 0x26, 0xbb, 0x84, 0x53, 0x0e, 0x73, 0xab, 0x31, 0x5e, 0x0e, 0x6d, 0xa6, 0x60, - 0x7c, 0x9d, 0x50, 0x65, 0x0d, 0x8e, 0x32, 0x40, 0x82, 0x4a, 0xe8, 0x00, 0x93, 0xbd, 0xc2, 0x59, - 0x3e, 0x5c, 0x1e, 0xc6, 0x0b, 0xe1, 0xa2, 0x29, 0x18, 0x9f, 0x3c, 0x80, 0xf2, 0x20, 0x66, 0x85, - 0xe4, 0x98, 0xc6, 0x9c, 0x46, 0x90, 0x7a, 0x72, 0xb1, 0x83, 0xe7, 0x30, 0x9d, 0x0c, 0x38, 0x0d, - 0x26, 0xfb, 0x8a, 0x73, 0x33, 0xa4, 0xdb, 0x0a, 0x30, 0x96, 0x03, 0xb2, 0x15, 0x64, 0x4b, 0xe8, - 0x26, 0x47, 0xd8, 0x09, 0x28, 0xb0, 0xc5, 0x8b, 0x9f, 0xf1, 0x6c, 0xd8, 0x0b, 0xbf, 0x20, 0x68, - 0x12, 0x3f, 0x77, 0x20, 0x96, 0x86, 0x1c, 0x13, 0xba, 0xc9, 0xe6, 0x3f, 0x04, 0xb9, 0xb6, 0x02, - 0x8c, 0xa5, 0x81, 0x3c, 0x4c, 0xf2, 0x50, 0x99, 0xec, 0x01, 0xce, 0x52, 0x5b, 0xbc, 0xf8, 0x19, - 0x97, 0x6f, 0xb6, 0xb5, 0xf0, 0x01, 0x6c, 0xd6, 0x30, 0x90, 0x83, 0x51, 0xfd, 0xa9, 0x7e, 0x88, - 0x6f, 0x7e, 0x48, 0x81, 0x32, 0xe6, 0xc8, 0xb1, 0x64, 0xb2, 0xf7, 0x38, 0xab, 0xc1, 0x0b, 0xc9, - 0x51, 0xca, 0x1c, 0xb9, 0x98, 0x30, 0x6b, 0x52, 0x42, 0x9f, 0x05, 0x66, 0xfe, 0xa4, 0x6d, 0x3d, - 0x84, 0x19, 0x9b, 0x01, 0xcd, 0x81, 0xf9, 0xc1, 0xa6, 0xdc, 0xb6, 0xdd, 0x90, 0x1d, 0x22, 0x50, - 0xbe, 0xd9, 0x64, 0x3b, 0xc8, 0x6d, 0x8d, 0x62, 0xcd, 0x4a, 0xe8, 0x8b, 0xc0, 0xec, 0x76, 0x53, - 0x11, 0xc6, 0x65, 0x1f, 0x6f, 0x83, 0xe0, 0xdb, 0x51, 0x20, 0x2c, 0x76, 0x8e, 0xce, 0x4c, 0x53, - 0xac, 0xf2, 0x31, 0x9e, 0x05, 0xf5, 0x20, 0x0f, 0x56, 0x3c, 0x66, 0x14, 0xda, 0xa6, 0x12, 0xab, - 0x4f, 0x32, 0x4e, 0x84, 0xfb, 0x96, 0xcc, 0x72, 0x37, 0x96, 0xa9, 0xb9, 0xb6, 0x4f, 0xe6, 0xac, - 0x82, 0x4e, 0x48, 0xc4, 0x9a, 0xad, 0xdf, 0x28, 0x5a, 0xc1, 0x1a, 0xfa, 0x4b, 0x35, 0x5f, 0x37, - 0xfd, 0x0d, 0xb0, 0x98, 0x97, 0xe3, 0xdb, 0xda, 0x98, 0xdf, 0x45, 0xd5, 0x42, 0xb8, 0x81, 0xe3, - 0x3c, 0xcc, 0xf2, 0x07, 0xe2, 0x6c, 0x58, 0x8f, 0x1c, 0x2d, 0xcf, 0x02, 0xad, 0x7f, 0x81, 0x7e, - 0x0d, 0x02, 0xbf, 0x6b, 0x7e, 0xbf, 0x8b, 0xb8, 0x3c, 0x3a, 0x7b, 0x60, 0x3d, 0x44, 0x5d, 0x10, - 0x3f, 0x5e, 0x6b, 0x78, 0x51, 0x85, 0xea, 0x0f, 0x47, 0xad, 0x4d, 0x24, 0x02, 0x33, 0x28, 0xb2, - 0x09, 0x76, 0xc0, 0x64, 0xad, 0x60, 0xc2, 0xdd, 0xa8, 0x42, 0xf5, 0x63, 0xe6, 0xb3, 0xa9, 0xa2, - 0xdc, 0x66, 0xfc, 0xa7, 0x60, 0xd8, 0xa3, 0xcd, 0x14, 0x1b, 0xe6, 0x8b, 0x2a, 0x34, 0x2c, 0x8f, - 0x1c, 0xdc, 0x8b, 0x98, 0x74, 0x07, 0xf4, 0xd5, 0x0f, 0x8d, 0x8d, 0x32, 0x21, 0xd9, 0xbd, 0x13, - 0xac, 0xd1, 0x98, 0x2a, 0x91, 0xe4, 0xf5, 0x9c, 0x08, 0x65, 0x35, 0x33, 0x49, 0xb6, 0x1c, 0x52, - 0x66, 0x4e, 0x84, 0xa2, 0x4e, 0xfe, 0x24, 0xd6, 0xf7, 0xb1, 0x53, 0xd1, 0xae, 0x84, 0xca, 0x8a, - 0xa6, 0xd4, 0x5c, 0x09, 0x4d, 0xa9, 0x48, 0x92, 0xbb, 0xd9, 0xa3, 0xa9, 0x56, 0x29, 0xf9, 0x47, - 0xcb, 0x8a, 0x8e, 0x09, 0x75, 0xbd, 0x1b, 0xc6, 0xf6, 0xa8, 0xeb, 0x15, 0xed, 0x1b, 0x2d, 0x0f, - 0x53, 0xb7, 0x12, 0xfa, 0xc6, 0xf5, 0x12, 0x38, 0xce, 0x77, 0x5d, 0x09, 0xbd, 0xea, 0x38, 0xb1, - 0xcb, 0x74, 0xd7, 0x48, 0x76, 0x45, 0x09, 0x6d, 0xa1, 0xa3, 0x56, 0xb5, 0xc7, 0x65, 0x95, 0x24, - 0x73, 0x1d, 0x26, 0x7e, 0x25, 0x2f, 0xe9, 0xfd, 0x03, 0xef, 0xa3, 0x34, 0x3e, 0xf1, 0x06, 0x54, - 0x8c, 0xb3, 0x08, 0x8c, 0x7f, 0x85, 0x26, 0x59, 0x30, 0xde, 0xf0, 0xc7, 0x04, 0xd4, 0xa1, 0xeb, - 0xae, 0x0a, 0xf4, 0x5f, 0x9c, 0x71, 0xf6, 0xe2, 0x7c, 0xa9, 0x06, 0xb4, 0xcf, 0x7e, 0xad, 0x9f, - 0xaa, 0x6e, 0x17, 0x89, 0xeb, 0xe1, 0x18, 0x7a, 0x62, 0xc1, 0x22, 0xea, 0xd6, 0x07, 0x7d, 0xa6, - 0xf6, 0x23, 0x93, 0xd3, 0xa1, 0x4f, 0x16, 0x69, 0x1f, 0x14, 0x21, 0xf0, 0xa8, 0x2e, 0x32, 0x72, - 0x1d, 0xb6, 0xc5, 0x3c, 0x08, 0x9a, 0x7f, 0x27, 0x24, 0x09, 0x03, 0xb3, 0x83, 0x83, 0x71, 0xb6, - 0x5b, 0x98, 0x3f, 0x27, 0xb2, 0x98, 0xb0, 0x89, 0x24, 0xdb, 0x0e, 0x1f, 0xa1, 0x15, 0x86, 0xdc, - 0x09, 0xfa, 0x89, 0x08, 0x7d, 0x4e, 0xdc, 0x8a, 0xb0, 0xba, 0x4e, 0xc7, 0xe3, 0x14, 0xda, 0xcd, - 0xfc, 0x8d, 0x30, 0xe4, 0x62, 0x9d, 0x0a, 0xb2, 0x25, 0xa3, 0x68, 0x3e, 0x84, 0xd9, 0x6f, 0x26, - 0x1c, 0x80, 0x49, 0xb6, 0x3c, 0x29, 0xf7, 0x53, 0x5c, 0x7e, 0xe3, 0xd4, 0x7f, 0x80, 0xc5, 0xe5, - 0xdb, 0x65, 0x5a, 0x72, 0xf4, 0x8d, 0xbc, 0x21, 0xe4, 0x8c, 0x2f, 0x6b, 0xb0, 0xd1, 0x4e, 0xb3, - 0x62, 0xe4, 0xd5, 0x05, 0x14, 0x20, 0x28, 0x0f, 0x64, 0xe5, 0xba, 0x40, 0x7e, 0x18, 0x96, 0xff, - 0x8f, 0x0e, 0x39, 0x1d, 0x02, 0xd3, 0xff, 0xdf, 0xe6, 0x3f, 0x87, 0x98, 0x3c, 0xc9, 0xe6, 0x6a, - 0x0b, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXToggle3DIcon3x[] = { - - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x48, 0x08, 0x06, 0x00, 0x00, 0x00, 0x41, 0x78, 0x2d, - 0xa6, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, - 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3f, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x17, 0xf4, 0xd7, 0x00, 0x00, - 0x05, 0xdb, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xed, 0x9b, 0x6b, 0x88, 0x55, 0x55, 0x14, 0xc7, - 0xe7, 0xaa, 0x4d, 0x0f, 0xad, 0xc8, 0xc0, 0x40, 0x8b, 0xc8, 0x9a, 0x84, 0x94, 0x6a, 0xb4, 0x82, - 0x0c, 0x7a, 0x9a, 0x45, 0x61, 0xfa, 0x41, 0xac, 0xc0, 0x40, 0x89, 0x04, 0x7b, 0x88, 0x69, 0x85, - 0x86, 0x0a, 0x12, 0x98, 0x1f, 0xb4, 0xec, 0x21, 0x41, 0xd6, 0x87, 0x1e, 0x16, 0x15, 0x22, 0x96, - 0x54, 0x16, 0x95, 0xd4, 0x60, 0x94, 0x20, 0x41, 0x25, 0x43, 0x06, 0x62, 0x08, 0x9a, 0x4c, 0x96, - 0xe2, 0xa3, 0xb2, 0x71, 0xfa, 0xfd, 0xc7, 0xee, 0x78, 0xef, 0x3d, 0x8f, 0xbd, 0xf7, 0x79, 0xec, - 0x73, 0x9a, 0x99, 0x05, 0x3f, 0xe6, 0x9c, 0xbd, 0xd7, 0x5e, 0x6b, 0xfd, 0xef, 0xde, 0xe7, 0x71, - 0xef, 0x39, 0x53, 0x69, 0x2a, 0xd0, 0xba, 0xba, 0xba, 0x4e, 0x23, 0xfd, 0x0d, 0x30, 0x02, 0xda, - 0x2b, 0x95, 0xca, 0x96, 0x02, 0xcb, 0xf1, 0x93, 0x5a, 0xa2, 0x61, 0x01, 0xec, 0x83, 0x5a, 0x7b, - 0x9f, 0x9d, 0x81, 0x7e, 0xaa, 0x28, 0x20, 0x0b, 0xe2, 0xa6, 0xc2, 0x4e, 0x88, 0xb2, 0xd9, 0x05, - 0x94, 0x95, 0x6f, 0x4a, 0x94, 0x5e, 0x09, 0x9b, 0xa3, 0x14, 0xd7, 0xb4, 0xbf, 0x93, 0x6f, 0x25, - 0x1e, 0xa3, 0x23, 0x6a, 0x18, 0xbc, 0x0c, 0x9d, 0x35, 0x02, 0xa3, 0x36, 0x7f, 0xa2, 0xe3, 0x36, - 0x8f, 0xe5, 0xe5, 0x93, 0x0a, 0x11, 0xcd, 0x30, 0x1f, 0x0e, 0x80, 0xc9, 0xe4, 0xf3, 0x18, 0x9c, - 0x92, 0x4f, 0x35, 0x1e, 0xa3, 0x22, 0x62, 0x12, 0x68, 0x16, 0x4d, 0xa6, 0xd5, 0xb0, 0x06, 0x86, - 0x79, 0x2c, 0x2f, 0x9f, 0x54, 0x88, 0x18, 0x0d, 0x9f, 0x80, 0x8d, 0x7d, 0x89, 0x53, 0xab, 0x6b, - 0x25, 0x8c, 0x69, 0x81, 0x3b, 0x61, 0x2c, 0x14, 0x7f, 0x65, 0xa0, 0x88, 0xa1, 0xf0, 0x02, 0xfc, - 0x03, 0x26, 0xdb, 0x85, 0xc3, 0xb4, 0x04, 0xa2, 0x27, 0x33, 0xee, 0x9b, 0x86, 0xe0, 0x5b, 0xd9, - 0x1f, 0xee, 0x1a, 0x2b, 0x13, 0x7f, 0x12, 0x0f, 0x82, 0x47, 0x60, 0x3f, 0x98, 0xec, 0x30, 0x0e, - 0x4b, 0xe0, 0x74, 0x97, 0xe4, 0xf8, 0x8f, 0x81, 0x4f, 0x21, 0xca, 0xde, 0x76, 0x89, 0x97, 0x89, - 0x2f, 0x95, 0x4c, 0x84, 0x1f, 0xa3, 0x2a, 0x6a, 0x68, 0x5f, 0xcb, 0xfe, 0xf9, 0x2e, 0x89, 0xf1, - 0x3f, 0x17, 0x56, 0x83, 0x69, 0x35, 0xed, 0x77, 0x89, 0x9b, 0xca, 0x97, 0x62, 0x2e, 0x85, 0x0f, - 0xc0, 0xc6, 0xb4, 0x2c, 0xc7, 0xbb, 0x24, 0xc4, 0x5f, 0xab, 0x69, 0x0e, 0xd8, 0xac, 0xa6, 0xbf, - 0xf1, 0x5b, 0x01, 0x15, 0x97, 0x1c, 0xce, 0xbe, 0x24, 0x38, 0x1b, 0x56, 0x82, 0x12, 0x9a, 0x6c, - 0x0f, 0x0e, 0x33, 0xc1, 0xa9, 0x28, 0xfc, 0x5d, 0x56, 0x93, 0x26, 0xa0, 0xc5, 0x59, 0x88, 0xcb, - 0x00, 0x12, 0x0c, 0x80, 0x59, 0xd0, 0x78, 0x1f, 0x4e, 0x53, 0xc0, 0xfe, 0xa4, 0x65, 0x39, 0x9c, - 0xe9, 0x98, 0x43, 0x67, 0x70, 0xdb, 0xd5, 0xb4, 0x1d, 0xdf, 0xfc, 0x6f, 0x84, 0x48, 0x72, 0x23, - 0x7c, 0x07, 0x36, 0xb6, 0x1e, 0xa7, 0x8b, 0x1d, 0x45, 0x6b, 0x35, 0x69, 0xd9, 0xda, 0xac, 0x26, - 0x1d, 0x06, 0x3a, 0xb9, 0x0e, 0x72, 0xc9, 0xe1, 0xec, 0x4b, 0x82, 0x8b, 0x60, 0x1d, 0xd8, 0xd8, - 0xf7, 0x38, 0xdd, 0xe2, 0x92, 0x04, 0x7f, 0xad, 0xa6, 0x07, 0xe0, 0x57, 0x30, 0x99, 0x4e, 0x78, - 0x2f, 0xc2, 0x50, 0x97, 0x1c, 0xf2, 0x65, 0xcc, 0x10, 0x98, 0x0b, 0x1b, 0xa1, 0x1d, 0x34, 0x41, - 0x13, 0x43, 0xe3, 0xd0, 0xa1, 0x93, 0xcd, 0x42, 0x38, 0x0a, 0x26, 0xeb, 0xc0, 0xe1, 0x21, 0x70, - 0xba, 0xd1, 0xc0, 0xff, 0x7a, 0xd8, 0x06, 0x36, 0xa6, 0x4b, 0xdc, 0x98, 0xd0, 0x62, 0x63, 0x1a, - 0x19, 0x73, 0x06, 0xe8, 0xb2, 0xfa, 0x3b, 0x34, 0xda, 0x31, 0x1a, 0xa6, 0xd4, 0x0d, 0xa7, 0x41, - 0x9f, 0xd2, 0x96, 0x46, 0xcf, 0x90, 0x7d, 0x0d, 0x7e, 0x1e, 0xce, 0xa9, 0x0b, 0x60, 0xd8, 0xc1, - 0xff, 0x42, 0x78, 0x17, 0x6c, 0x6c, 0x07, 0x4e, 0x93, 0x0d, 0x21, 0x43, 0xbb, 0x19, 0x77, 0x0f, - 0xfc, 0x62, 0x48, 0xf2, 0x43, 0xdd, 0x60, 0x9c, 0xdf, 0x34, 0x0c, 0x50, 0xf7, 0x26, 0xb8, 0xac, - 0x6e, 0xa0, 0x61, 0x07, 0xff, 0xc1, 0xf0, 0x14, 0xd8, 0xac, 0x26, 0x7d, 0xc1, 0x79, 0x1c, 0x9a, - 0x0d, 0x61, 0x03, 0xdd, 0x8c, 0x19, 0x07, 0x6d, 0x60, 0x6b, 0x63, 0xbb, 0x83, 0xe0, 0xad, 0x65, - 0x72, 0x24, 0x66, 0x94, 0x66, 0x62, 0x52, 0x20, 0x63, 0x4c, 0x03, 0xfe, 0x15, 0x98, 0x0e, 0xbb, - 0xc1, 0x64, 0xfa, 0x82, 0xf3, 0x0a, 0x9c, 0x17, 0x13, 0x32, 0xb4, 0x4b, 0x63, 0xe0, 0x55, 0x38, - 0x0e, 0x2e, 0x36, 0xb5, 0x3b, 0x20, 0x23, 0x46, 0xc5, 0x8c, 0x7a, 0x9a, 0x3e, 0xa7, 0x99, 0xc0, - 0xff, 0x1a, 0xf8, 0x3a, 0x26, 0x66, 0x6d, 0xd7, 0x57, 0xec, 0x9c, 0x98, 0x85, 0x50, 0x79, 0xe1, - 0x8d, 0x8c, 0x69, 0x86, 0x27, 0xe0, 0x20, 0x24, 0xb1, 0x39, 0x55, 0xf1, 0x57, 0x45, 0x8c, 0x7e, - 0x26, 0x3c, 0x75, 0x78, 0x2b, 0x31, 0x86, 0xc3, 0x6b, 0x60, 0x33, 0x0b, 0xbb, 0xf0, 0xbb, 0x3b, - 0x3c, 0x52, 0x7c, 0x2b, 0xe3, 0xee, 0x02, 0xad, 0xc6, 0x34, 0xb6, 0xa8, 0x7a, 0xcd, 0x3c, 0x35, - 0x22, 0x5d, 0x5b, 0x44, 0x7b, 0x5d, 0x33, 0x15, 0xe8, 0x57, 0xd8, 0x79, 0xf0, 0x24, 0x0c, 0xae, - 0xeb, 0x0c, 0xee, 0x1c, 0xa1, 0x69, 0x39, 0xac, 0xe0, 0xd7, 0xda, 0xa3, 0xc1, 0xee, 0xe8, 0x16, - 0xf2, 0x8c, 0xa6, 0xf7, 0x59, 0xb8, 0x35, 0xda, 0xcb, 0xbe, 0xa7, 0x2a, 0x3e, 0x6a, 0x44, 0x47, - 0x54, 0x47, 0xb5, 0x9d, 0x82, 0x6e, 0x62, 0x7b, 0x0d, 0xd8, 0xdc, 0xe0, 0xac, 0xc5, 0x6f, 0x01, - 0xa2, 0x77, 0x57, 0xc7, 0xdb, 0xfc, 0x25, 0x87, 0xae, 0xf1, 0x4b, 0x41, 0x3f, 0x6e, 0x3a, 0x5d, - 0x5a, 0xe3, 0xe2, 0x0f, 0x88, 0xeb, 0x34, 0xf5, 0x51, 0x94, 0x0a, 0xfa, 0x1c, 0x4c, 0xc2, 0xb7, - 0xe2, 0x33, 0x1e, 0xd1, 0xd3, 0x5d, 0x84, 0x13, 0x5f, 0xf7, 0x1d, 0x0f, 0x33, 0x76, 0x07, 0xe8, - 0x6f, 0x66, 0xc2, 0x89, 0xd5, 0x64, 0x9a, 0x79, 0xf9, 0x84, 0x1a, 0x45, 0xdd, 0x4b, 0xc7, 0x92, - 0xd0, 0xce, 0x93, 0x8d, 0x7b, 0xd8, 0x5c, 0x08, 0xaf, 0x23, 0xba, 0xeb, 0x64, 0xb3, 0x79, 0x8b, - 0xf8, 0x13, 0xf0, 0x5a, 0x05, 0x5a, 0xea, 0x79, 0x58, 0x25, 0xb1, 0x78, 0xaa, 0x99, 0x19, 0x53, - 0xd1, 0x5f, 0xf4, 0xe9, 0x64, 0xb9, 0x0c, 0xd1, 0x87, 0x62, 0xfc, 0x02, 0x5d, 0x88, 0xd6, 0x2a, - 0x5a, 0x09, 0x89, 0x6e, 0x72, 0x02, 0x01, 0x63, 0x1a, 0xd2, 0x88, 0x8f, 0xba, 0xed, 0xdc, 0x44, - 0xbe, 0xd9, 0x88, 0xde, 0x19, 0x93, 0x37, 0xd0, 0x85, 0x68, 0x7d, 0x13, 0x5c, 0x04, 0x73, 0xc1, - 0xe9, 0xd2, 0x1a, 0x08, 0x66, 0xd9, 0x90, 0x46, 0x7c, 0xd8, 0xd7, 0xd6, 0x6f, 0xc9, 0x7b, 0x07, - 0xc2, 0x8f, 0x5b, 0xe6, 0xd7, 0x97, 0x0f, 0x9d, 0x77, 0x66, 0xc0, 0x32, 0x70, 0xbe, 0xc9, 0x61, - 0x4c, 0x62, 0x4b, 0x23, 0x3e, 0xec, 0xb7, 0xb8, 0x36, 0x47, 0xe1, 0xd7, 0x51, 0xf9, 0x73, 0x30, - 0x2e, 0xb1, 0x82, 0xe4, 0x03, 0x53, 0x1d, 0xf3, 0x61, 0x69, 0x75, 0xac, 0x1b, 0x8d, 0xd9, 0x1e, - 0x82, 0x93, 0x4e, 0x66, 0xf7, 0x1b, 0x9d, 0x73, 0x74, 0x48, 0x33, 0xf3, 0x89, 0xca, 0x42, 0xf8, - 0x28, 0x06, 0x7e, 0x08, 0x23, 0x13, 0x05, 0xc8, 0x70, 0x50, 0xaa, 0xeb, 0xbc, 0x6b, 0x1d, 0x08, - 0xd7, 0xcd, 0xca, 0x46, 0x28, 0x5c, 0xb8, 0x6a, 0xf7, 0x2a, 0x9e, 0x7c, 0xf3, 0xe1, 0x12, 0x25, - 0x2e, 0x81, 0x55, 0x7c, 0x8b, 0xbf, 0xaf, 0x04, 0xa2, 0x7b, 0x4a, 0xf0, 0x26, 0x9e, 0x25, 0x7f, - 0x16, 0x59, 0x2f, 0xe8, 0xc9, 0x5c, 0x82, 0x0d, 0x6f, 0xe2, 0xd1, 0x5a, 0xba, 0x27, 0xb1, 0x3e, - 0xc5, 0x87, 0xdd, 0x14, 0x15, 0x39, 0xff, 0xde, 0x8f, 0xf9, 0x22, 0xc5, 0x06, 0x72, 0xfb, 0x9c, - 0xf9, 0x40, 0xf2, 0xa2, 0x1b, 0xfa, 0xc5, 0x17, 0x3d, 0x03, 0x05, 0xe5, 0xef, 0x3f, 0xe6, 0x0b, - 0xfa, 0xe0, 0x8b, 0x4f, 0xdb, 0x7f, 0xcc, 0x17, 0x3f, 0x07, 0x85, 0x54, 0xd0, 0x7f, 0xcc, 0x17, - 0xf2, 0xb1, 0x97, 0x21, 0x69, 0x5f, 0x3e, 0xe6, 0x3b, 0xfb, 0xb2, 0xf8, 0xdf, 0xfa, 0xb2, 0xf8, - 0xbd, 0x55, 0xf1, 0x07, 0xca, 0x70, 0x0c, 0x7a, 0xac, 0xe1, 0x18, 0xb9, 0xbe, 0xa8, 0x8a, 0x77, - 0x7a, 0xc0, 0xe0, 0xb1, 0xc8, 0xbc, 0x52, 0xad, 0xe3, 0x27, 0xf6, 0x13, 0xcb, 0x9e, 0x8d, 0xc3, - 0x64, 0xd9, 0x9c, 0x57, 0xa6, 0x92, 0xc5, 0x6d, 0xa7, 0x1e, 0x3d, 0xed, 0xad, 0xfb, 0x01, 0x73, - 0x31, 0xfb, 0x56, 0xbf, 0xbb, 0x6b, 0xe0, 0xff, 0xd4, 0xf4, 0x28, 0xed, 0x66, 0x26, 0xfb, 0x0f, - 0xd5, 0x5f, 0x5d, 0xf6, 0x4d, 0x34, 0xb4, 0xb1, 0x3f, 0x01, 0xd6, 0x83, 0xde, 0x56, 0xd2, 0x33, - 0xf7, 0xed, 0xd0, 0x1b, 0xac, 0x03, 0x11, 0xb3, 0xd0, 0x78, 0x3b, 0xe8, 0xc9, 0x71, 0xb7, 0xd5, - 0x3d, 0xb4, 0xf8, 0xef, 0x03, 0xd0, 0x87, 0xd0, 0x5b, 0x4c, 0x27, 0xb6, 0xd5, 0xb0, 0x14, 0x6d, - 0xdd, 0xb3, 0x5d, 0x2b, 0xac, 0x4e, 0x7c, 0x6d, 0x47, 0x2f, 0xd8, 0xfe, 0x08, 0x0d, 0xf3, 0x10, - 0xad, 0x63, 0x3c, 0xd4, 0x7a, 0x96, 0x7d, 0x68, 0x6f, 0x7c, 0xe3, 0xc1, 0xf8, 0xee, 0xc2, 0x7a, - 0x25, 0x56, 0x4f, 0x8a, 0x45, 0xa4, 0x70, 0x55, 0x97, 0x46, 0x7c, 0xd9, 0x2e, 0x8f, 0x5a, 0xd6, - 0x8f, 0xc2, 0xe5, 0x88, 0xd6, 0xac, 0x1b, 0x2d, 0x8d, 0xf8, 0x8f, 0x8d, 0xd1, 0xfd, 0x38, 0x74, - 0x92, 0xe6, 0x25, 0x68, 0x41, 0xf4, 0x2a, 0xd0, 0x71, 0x6e, 0x65, 0x69, 0xc4, 0xeb, 0x11, 0xf3, - 0x3e, 0xab, 0x2c, 0xf9, 0x39, 0x7d, 0x46, 0xe8, 0x56, 0x04, 0x3f, 0x08, 0x3a, 0xa3, 0xfb, 0x33, - 0x1e, 0x41, 0x8d, 0x84, 0x0d, 0xa0, 0x57, 0x4c, 0xdf, 0x83, 0x6b, 0xa3, 0xb2, 0xd3, 0xd7, 0x0a, - 0x59, 0xd9, 0xcf, 0x04, 0x9a, 0x12, 0x95, 0xab, 0x74, 0xed, 0x14, 0x9b, 0x85, 0x78, 0xbd, 0x6a, - 0xaa, 0x57, 0x4e, 0xbd, 0xbc, 0xb3, 0x93, 0xd9, 0x87, 0x48, 0xc1, 0x57, 0x40, 0x52, 0xd3, 0x8b, - 0xc9, 0x7a, 0xb9, 0xd8, 0xeb, 0x3b, 0x3b, 0x59, 0x8a, 0xd7, 0x7b, 0xb9, 0x49, 0x2c, 0xd1, 0x8b, - 0xc9, 0x99, 0x15, 0x9e, 0x45, 0x20, 0x54, 0x0f, 0x04, 0xcd, 0xa0, 0xad, 0xe9, 0xc5, 0xe4, 0x69, - 0x59, 0xe4, 0x2e, 0x45, 0x0c, 0xc4, 0xd8, 0xbc, 0x86, 0x7e, 0x08, 0xbf, 0xc5, 0x10, 0xf6, 0xb6, - 0x57, 0x29, 0x74, 0x24, 0x2a, 0x02, 0x41, 0x33, 0x20, 0xca, 0xf4, 0x9a, 0xfa, 0x1b, 0x30, 0x22, - 0x51, 0xf0, 0xb2, 0x0f, 0x42, 0x98, 0xfe, 0xfb, 0x42, 0xff, 0x22, 0x5a, 0x6b, 0xfa, 0x9f, 0x9d, - 0xb7, 0xa0, 0xd5, 0x77, 0xfd, 0x15, 0xdf, 0x09, 0x95, 0x0f, 0xa1, 0x7a, 0x99, 0xf8, 0x6a, 0xd8, - 0x0b, 0xdb, 0xb8, 0x41, 0x29, 0xfa, 0x66, 0x89, 0x32, 0xfa, 0x98, 0xfd, 0x0b, 0x55, 0xca, 0x1e, - 0xf8, 0x6a, 0x59, 0xc9, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82 -}; - -static const u_int8_t FLEXRangeSliderLeftHandle2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x50, 0x08, 0x06, 0x00, 0x00, 0x00, 0x56, 0x1d, 0x56, - 0xa7, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x02, 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87, - 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x34, 0xa0, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x7d, 0xa9, - 0x20, 0x00, 0x00, 0x01, 0x59, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, - 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, - 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, - 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, - 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, - 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, - 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, - 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, - 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, - 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, - 0x3e, 0x0a, 0x4c, 0xc2, 0x27, 0x59, 0x00, 0x00, 0x05, 0xdc, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, - 0xed, 0x9b, 0xbf, 0x4b, 0x64, 0x57, 0x14, 0xc7, 0x57, 0x67, 0xc6, 0xf9, 0xa1, 0x93, 0x15, 0xc6, - 0x8c, 0x1b, 0x62, 0x58, 0x90, 0x14, 0x59, 0x48, 0x0a, 0x2d, 0x22, 0x08, 0x01, 0x21, 0x76, 0x0a, - 0x81, 0x84, 0x80, 0xff, 0x40, 0xfe, 0x01, 0x6d, 0xad, 0x6c, 0x83, 0x18, 0xb0, 0x4c, 0xb0, 0xd9, - 0x40, 0x8a, 0x14, 0x82, 0xa9, 0x84, 0x04, 0x41, 0x48, 0x2c, 0xc4, 0xc2, 0x22, 0x5b, 0x98, 0x42, - 0x2c, 0x8c, 0x18, 0x2d, 0x74, 0x57, 0x9c, 0xd1, 0x71, 0xc6, 0xdc, 0xef, 0xb8, 0x5f, 0x39, 0x39, - 0xb9, 0xef, 0xd7, 0x38, 0xf3, 0xbc, 0xee, 0xce, 0x85, 0xeb, 0x39, 0xf7, 0xdc, 0x73, 0xcf, 0x39, - 0x9f, 0x77, 0x9e, 0x6f, 0x5c, 0xde, 0xec, 0xa3, 0x47, 0x6f, 0xd8, 0xe8, 0x68, 0x01, 0x4f, 0x2b, - 0x62, 0x86, 0x2e, 0xb3, 0x19, 0xc9, 0x1b, 0x8d, 0xd1, 0xe8, 0x39, 0xc2, 0x5d, 0x53, 0x91, 0xb2, - 0xd1, 0xa0, 0x61, 0xce, 0x85, 0xf1, 0x91, 0xb5, 0x34, 0x45, 0x8f, 0x9a, 0x34, 0xc8, 0xdf, 0xb6, - 0x6f, 0xb3, 0xe9, 0xe2, 0xc3, 0xf8, 0xf0, 0x8c, 0xb5, 0x33, 0xaf, 0x37, 0xaf, 0xa3, 0x04, 0xf2, - 0xf2, 0xd5, 0x76, 0xb9, 0x4e, 0x9a, 0x44, 0x98, 0xb0, 0x61, 0x26, 0xcc, 0x6c, 0xf6, 0x90, 0x80, - 0x52, 0xf7, 0xcd, 0xc3, 0x82, 0xb4, 0xec, 0x34, 0xa7, 0x38, 0x51, 0x2c, 0x66, 0xca, 0xcc, 0xee, - 0xd1, 0xd1, 0xd1, 0xe2, 0xf6, 0xf6, 0xf6, 0x57, 0x27, 0x27, 0x27, 0xdf, 0x97, 0x4a, 0xa5, 0xf5, - 0xcb, 0xcb, 0xcb, 0xbf, 0x6a, 0xb5, 0xda, 0xab, 0xeb, 0x16, 0x0f, 0x93, 0x3b, 0x70, 0x68, 0x08, - 0xac, 0x09, 0x01, 0x29, 0x41, 0xf2, 0x8b, 0x8b, 0x8b, 0x1f, 0x19, 0x88, 0x1f, 0xaa, 0xd5, 0xea, - 0xcb, 0x16, 0xd7, 0x6e, 0x0d, 0x1f, 0x44, 0xe3, 0x07, 0x43, 0x10, 0xdc, 0x52, 0x99, 0xb1, 0xb1, - 0xb1, 0x27, 0x87, 0x87, 0x87, 0xdf, 0x9a, 0x2e, 0x9c, 0x59, 0x33, 0xc5, 0x64, 0xf4, 0x03, 0x0a, - 0x82, 0xe1, 0xef, 0x47, 0xf7, 0xc2, 0xc2, 0xc2, 0xb3, 0xf3, 0xf3, 0xf3, 0xcd, 0x98, 0x6a, 0xf6, - 0x4d, 0xe3, 0x05, 0x14, 0x06, 0x06, 0xbf, 0x2b, 0xf9, 0xe5, 0xe5, 0xe5, 0xb1, 0x4a, 0xa5, 0xb2, - 0xef, 0x9b, 0x25, 0xc6, 0x4d, 0x1b, 0x50, 0x58, 0x98, 0xdc, 0xdc, 0xdc, 0xdc, 0x27, 0x17, 0x17, - 0x17, 0x7f, 0xc7, 0x58, 0x6f, 0x60, 0xaa, 0x30, 0x40, 0x7c, 0x00, 0xe0, 0x77, 0x06, 0xb7, 0x19, - 0x3a, 0x93, 0x1d, 0x1a, 0x1a, 0x7a, 0x7a, 0x76, 0x76, 0xb6, 0x15, 0x98, 0x21, 0x66, 0x07, 0x0d, - 0xa4, 0xbb, 0x63, 0x83, 0x49, 0x9b, 0x43, 0x7d, 0x7b, 0x7b, 0x7b, 0xdf, 0xc5, 0x5c, 0x6b, 0xa8, - 0x74, 0x28, 0x38, 0x68, 0x68, 0xc8, 0xae, 0x99, 0x99, 0x99, 0xa7, 0x03, 0x03, 0x03, 0xdf, 0x04, - 0x1d, 0x74, 0x61, 0x5f, 0x16, 0xaf, 0xbb, 0xd3, 0x65, 0x0a, 0xcc, 0x9a, 0xf9, 0x64, 0x7f, 0x7f, - 0xff, 0xc7, 0x50, 0x97, 0xeb, 0x1e, 0x9c, 0x64, 0x87, 0x00, 0xa3, 0x87, 0x04, 0x84, 0x9e, 0x1c, - 0x1c, 0x1c, 0x7c, 0xa7, 0xbf, 0xbf, 0xff, 0x0b, 0xed, 0xe8, 0xca, 0x5a, 0x02, 0xc9, 0x9a, 0x24, - 0x1c, 0xa1, 0xe0, 0x9b, 0x99, 0x9f, 0x9f, 0xff, 0x2c, 0x91, 0x48, 0xf4, 0x48, 0x67, 0x97, 0x74, - 0x2f, 0x20, 0xd4, 0x48, 0x10, 0xea, 0x78, 0xca, 0xe1, 0xe9, 0xf6, 0x39, 0x0c, 0xae, 0x0e, 0x1b, - 0x90, 0xad, 0x3b, 0xb0, 0x01, 0x28, 0x9d, 0xcf, 0xe7, 0x3f, 0x74, 0x15, 0x06, 0x75, 0x11, 0x48, - 0x42, 0xc0, 0xae, 0xbb, 0x03, 0xbf, 0xfa, 0xe7, 0x50, 0x26, 0x93, 0x29, 0xc2, 0xc1, 0xd5, 0x41, - 0x20, 0xaf, 0xfa, 0x08, 0xc6, 0x0e, 0xa5, 0xd2, 0xe9, 0xf4, 0xbb, 0x5e, 0xce, 0x2e, 0xd8, 0x35, - 0x90, 0xec, 0x94, 0xd6, 0xeb, 0x5d, 0x32, 0x0f, 0x84, 0x9c, 0x0b, 0x85, 0x7b, 0xd5, 0xa0, 0x81, - 0xe8, 0x47, 0x18, 0x48, 0x4c, 0xf8, 0x71, 0xd2, 0xc7, 0x49, 0x69, 0x03, 0x22, 0x0c, 0x0b, 0xe6, - 0x1a, 0xbe, 0xd4, 0xb9, 0xe7, 0x9c, 0xb4, 0x01, 0xb1, 0x48, 0x14, 0x4f, 0x00, 0xea, 0x5c, 0xd3, - 0xc7, 0x39, 0xe9, 0x07, 0xc4, 0x62, 0x9d, 0x87, 0x60, 0xa1, 0x90, 0x5e, 0x40, 0x1a, 0xe2, 0x8d, - 0xe8, 0x10, 0x21, 0xe4, 0x05, 0x70, 0x5e, 0xf7, 0xea, 0x90, 0x2c, 0x5c, 0x77, 0x4b, 0xee, 0x39, - 0xa7, 0x87, 0x01, 0x42, 0xd1, 0x84, 0xa2, 0x74, 0x0e, 0x84, 0x05, 0x49, 0xa0, 0xa0, 0x62, 0x83, - 0xf6, 0x19, 0xf3, 0x5e, 0xa5, 0x04, 0x62, 0x21, 0x0f, 0xa2, 0x70, 0x16, 0xab, 0xa5, 0x0d, 0x48, - 0xfb, 0x3c, 0xa8, 0x75, 0x1b, 0xc8, 0xf5, 0x76, 0xb5, 0x3b, 0xd4, 0xee, 0x50, 0xcc, 0x57, 0xa0, - 0x7d, 0xcb, 0xc5, 0x7c, 0xc1, 0x23, 0xa7, 0x6b, 0x77, 0x28, 0xf2, 0x25, 0x8b, 0xf9, 0x40, 0xbb, - 0x43, 0x31, 0x5f, 0xf0, 0xc8, 0xe9, 0xda, 0x1d, 0x32, 0xaf, 0xeb, 0xcf, 0x23, 0x5f, 0xb6, 0x18, - 0x0f, 0x44, 0xed, 0xd0, 0x75, 0xb9, 0x5c, 0x3e, 0x8e, 0xb1, 0xbe, 0xc8, 0xa9, 0x6c, 0x40, 0x5e, - 0x5f, 0x2f, 0x81, 0xbd, 0x66, 0x5e, 0xdf, 0x3f, 0x18, 0x20, 0x2f, 0x10, 0x5c, 0xa5, 0x3a, 0x0c, - 0x80, 0x8e, 0x8f, 0x8f, 0xf7, 0x60, 0x70, 0x75, 0xd8, 0x3a, 0x64, 0xab, 0x15, 0x40, 0x98, 0x57, - 0x6b, 0x6b, 0x6b, 0x7f, 0xd8, 0x1c, 0x5c, 0xb1, 0xf1, 0x9f, 0xdb, 0x52, 0x42, 0x07, 0xa8, 0x9c, - 0x78, 0x9d, 0x8f, 0xf7, 0xab, 0xbd, 0x7d, 0x7d, 0x7d, 0xef, 0x1d, 0x1c, 0x1c, 0xfc, 0x92, 0x4c, - 0x26, 0xbb, 0xcd, 0xda, 0xb9, 0xe1, 0xd7, 0x21, 0x76, 0x05, 0x45, 0xf3, 0x96, 0xbb, 0x32, 0xb7, - 0x5c, 0x79, 0x67, 0x67, 0xe7, 0x57, 0xe7, 0x48, 0x5e, 0x17, 0xe4, 0x05, 0x04, 0x00, 0x39, 0xb0, - 0xae, 0x9a, 0x59, 0x31, 0xb3, 0x34, 0x3d, 0x3d, 0xfd, 0xdc, 0x3c, 0xbe, 0x4b, 0xd2, 0xc1, 0x15, - 0xdd, 0x0b, 0x48, 0xd6, 0x47, 0xb8, 0x9a, 0x31, 0x5e, 0x99, 0x59, 0x59, 0x5d, 0x5d, 0xfd, 0x67, - 0x6b, 0x6b, 0xeb, 0x67, 0xe9, 0xe4, 0x8a, 0xee, 0x07, 0x04, 0x10, 0xc2, 0x40, 0x02, 0x08, 0x1d, - 0x2a, 0x9b, 0x59, 0x9a, 0x9c, 0x9c, 0xfc, 0xc9, 0xdc, 0x7e, 0x2f, 0x8c, 0xee, 0xd4, 0xb0, 0x01, - 0x11, 0x82, 0x85, 0x72, 0x0d, 0x89, 0xdb, 0xee, 0xd2, 0xcc, 0xd2, 0xd1, 0xd1, 0xd1, 0xcb, 0xa9, - 0xa9, 0xa9, 0x39, 0xf3, 0xb9, 0x74, 0x44, 0x47, 0x17, 0x24, 0x5e, 0x04, 0x63, 0xc8, 0xa7, 0xdc, - 0x8d, 0xe5, 0xbf, 0x36, 0xec, 0x4b, 0x1f, 0xe8, 0x89, 0xdd, 0xdd, 0xdd, 0xca, 0xe9, 0xe9, 0xe9, - 0x9f, 0xe6, 0xcb, 0x7f, 0x9f, 0xa6, 0x52, 0x29, 0x27, 0x9e, 0x7a, 0x1a, 0x08, 0x30, 0xb6, 0xe2, - 0x69, 0xd3, 0x50, 0x1d, 0x9b, 0x9b, 0x9b, 0xaf, 0x36, 0x36, 0x36, 0x7e, 0x9f, 0x98, 0x98, 0x78, - 0x96, 0xcb, 0xe5, 0xee, 0xfd, 0x85, 0xb2, 0x2c, 0x10, 0x30, 0x18, 0xb2, 0x78, 0xe8, 0xb8, 0x2d, - 0x39, 0x71, 0x01, 0xea, 0xaf, 0xf7, 0x8d, 0xc4, 0xe7, 0x52, 0xde, 0x4c, 0x74, 0x26, 0x57, 0x28, - 0x14, 0x1e, 0xaf, 0xac, 0xac, 0x7c, 0x3d, 0x32, 0x32, 0xf2, 0xa5, 0x79, 0xb1, 0x8c, 0xbd, 0x7b, - 0x19, 0xec, 0x10, 0x92, 0x7b, 0xc1, 0x71, 0x8f, 0xa0, 0x2c, 0x14, 0x0f, 0x09, 0x8e, 0x0e, 0xf3, - 0xcd, 0xdf, 0xea, 0xd2, 0xd2, 0xd2, 0x8b, 0xf5, 0xf5, 0xf5, 0xdf, 0x86, 0x87, 0x87, 0xbb, 0x0c, - 0xe0, 0xfb, 0x9d, 0x9d, 0x9d, 0xf8, 0xc2, 0x53, 0xac, 0x83, 0x10, 0x48, 0xaa, 0x75, 0x02, 0x40, - 0xb2, 0x43, 0x90, 0xb8, 0x08, 0x94, 0xf8, 0x32, 0x60, 0xc6, 0x4c, 0xbc, 0xea, 0xc7, 0x84, 0x0e, - 0x5b, 0xba, 0xb7, 0xb7, 0x37, 0x33, 0x3b, 0x3b, 0xfb, 0xf1, 0xf8, 0xf8, 0xf8, 0x48, 0xb1, 0x58, - 0xfc, 0xa0, 0xa7, 0xa7, 0xa7, 0x90, 0xcd, 0x66, 0x0b, 0xe6, 0x2f, 0x8c, 0x96, 0x76, 0x4f, 0x43, - 0x98, 0x5a, 0xea, 0x83, 0x76, 0xc2, 0x50, 0xda, 0xc0, 0x00, 0x80, 0x4e, 0x10, 0x0c, 0x5f, 0x10, - 0xc4, 0x9a, 0x5f, 0xb2, 0x85, 0xc4, 0x79, 0xc6, 0x30, 0xea, 0x9d, 0x86, 0x7c, 0xea, 0x42, 0xc7, - 0x9d, 0xc2, 0x79, 0x85, 0x64, 0xb6, 0x01, 0x47, 0x14, 0x80, 0x61, 0x0b, 0x80, 0x3d, 0xde, 0x72, - 0xf8, 0x6c, 0x62, 0x60, 0x7c, 0xf0, 0x02, 0x88, 0x9d, 0x02, 0x2c, 0xbb, 0x09, 0x29, 0x07, 0xe3, - 0x4b, 0x5b, 0x90, 0xce, 0x5a, 0xe0, 0x07, 0x9d, 0x79, 0x29, 0x2b, 0x12, 0x08, 0x46, 0x9d, 0x04, - 0x36, 0x0e, 0x1e, 0x42, 0x61, 0x84, 0xe1, 0x1e, 0x40, 0x60, 0xe3, 0x9f, 0x47, 0x17, 0x46, 0x07, - 0x0c, 0x26, 0x3b, 0x85, 0x73, 0x88, 0xcf, 0x1c, 0x94, 0xc6, 0x14, 0x69, 0xa0, 0x0e, 0xdb, 0x44, - 0xee, 0xaa, 0x04, 0xd2, 0x51, 0x71, 0x48, 0x26, 0xc5, 0x1a, 0x03, 0x52, 0x03, 0xd5, 0x37, 0xcc, - 0x0f, 0x74, 0x8b, 0x50, 0x88, 0xcd, 0xa7, 0x22, 0xe2, 0x00, 0x88, 0x50, 0x46, 0xbd, 0x1d, 0x32, - 0xc7, 0xad, 0xd1, 0x43, 0x91, 0x35, 0x40, 0xe7, 0x44, 0x3d, 0xf5, 0xe9, 0x07, 0xc4, 0x98, 0x0c, - 0xc2, 0x35, 0x0e, 0xea, 0x2e, 0x31, 0x30, 0xec, 0xd4, 0xe1, 0x47, 0x10, 0x16, 0x8d, 0x7d, 0x0e, - 0xda, 0xb8, 0x0e, 0x2b, 0x59, 0x8f, 0xcc, 0x03, 0xbd, 0x0e, 0x64, 0x0b, 0xaa, 0x6d, 0x5c, 0x43, - 0xca, 0xc9, 0xab, 0x0d, 0x1b, 0x74, 0xae, 0x29, 0xa5, 0x2f, 0x74, 0x0c, 0x2d, 0x6f, 0xac, 0xd1, - 0x7e, 0x6a, 0x20, 0x09, 0x56, 0x63, 0x02, 0x19, 0xd2, 0xcf, 0x86, 0x3d, 0x3d, 0x25, 0x80, 0xd4, - 0xb5, 0x1f, 0x72, 0xc8, 0xd8, 0x52, 0x97, 0xf9, 0x83, 0x74, 0x09, 0x04, 0x5f, 0x74, 0xe6, 0x16, - 0xca, 0x2b, 0xa8, 0xcd, 0x4e, 0x1b, 0x64, 0x23, 0x13, 0xc9, 0x19, 0x03, 0x3a, 0x86, 0x5e, 0xdf, - 0x58, 0xfd, 0x7f, 0x6a, 0x20, 0xc2, 0x40, 0x5a, 0x3b, 0xc4, 0x70, 0xb6, 0x64, 0xb4, 0x41, 0x6a, - 0x9d, 0x36, 0x2d, 0x11, 0x4f, 0xfa, 0xfa, 0xc5, 0xe7, 0x5e, 0x90, 0x94, 0x50, 0xd4, 0xeb, 0x9d, - 0x62, 0x22, 0xaf, 0x00, 0xb6, 0x7d, 0xda, 0xa4, 0xd4, 0xba, 0x5e, 0x23, 0x3e, 0x6d, 0xcc, 0xa5, - 0xd7, 0xb4, 0x87, 0x91, 0x84, 0xf8, 0x9f, 0x0c, 0x13, 0xd4, 0xe6, 0x23, 0x6d, 0xd4, 0x21, 0xa5, - 0x8e, 0xc2, 0xf4, 0x5a, 0xda, 0xa0, 0xdf, 0x75, 0x34, 0x04, 0x84, 0xa4, 0x2c, 0x4c, 0x17, 0x20, - 0xed, 0xd4, 0xb5, 0xb4, 0x9d, 0xa7, 0x8f, 0x8e, 0x17, 0x65, 0x4d, 0x18, 0x9e, 0xa9, 0xaf, 0xa3, - 0x04, 0xf6, 0xf2, 0xd5, 0x76, 0xb9, 0x96, 0xba, 0x0d, 0x8c, 0xc5, 0xdc, 0x45, 0x4a, 0xb0, 0x48, - 0xff, 0x4b, 0x32, 0x4c, 0x41, 0x1a, 0x20, 0xcc, 0x99, 0xb0, 0x3e, 0x84, 0x96, 0x00, 0xb4, 0x51, - 0x46, 0x06, 0xe2, 0x41, 0x5b, 0xe1, 0xdc, 0xa3, 0x0c, 0xe3, 0x43, 0xdf, 0xa6, 0xc9, 0x66, 0x24, - 0x6d, 0x34, 0x46, 0xa3, 0xe7, 0x08, 0x6f, 0xed, 0xd4, 0x5d, 0x83, 0x32, 0xb8, 0x94, 0xad, 0x88, - 0x29, 0xe3, 0xbf, 0x5d, 0xfa, 0xbf, 0x74, 0x7e, 0xdc, 0x6e, 0x66, 0x84, 0x09, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderLeftHandle3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x78, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5c, 0x89, 0xc4, - 0xad, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x02, 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87, - 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0xa0, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x54, 0xdc, - 0xcf, 0x00, 0x00, 0x01, 0x59, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, - 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, - 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, - 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, - 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, - 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, - 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, - 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, - 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, - 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, - 0x3e, 0x0a, 0x4c, 0xc2, 0x27, 0x59, 0x00, 0x00, 0x0a, 0x58, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, - 0xed, 0x9d, 0xcb, 0x8b, 0x14, 0xdb, 0x1d, 0xc7, 0x9d, 0x9e, 0xd6, 0x79, 0x39, 0xd7, 0xc7, 0x98, - 0x51, 0xc9, 0x20, 0x64, 0x20, 0x3e, 0x19, 0x2e, 0x04, 0x24, 0x8a, 0x49, 0x5c, 0x24, 0x17, 0x5c, - 0x19, 0xd0, 0x24, 0x0b, 0x73, 0x71, 0x97, 0x2c, 0xee, 0xee, 0x6e, 0x44, 0x70, 0x95, 0x85, 0x22, - 0x98, 0x6c, 0x62, 0xfe, 0x00, 0x11, 0x17, 0x6e, 0xcc, 0xc2, 0x08, 0xd9, 0xb8, 0x30, 0x0a, 0x77, - 0x61, 0xc4, 0xbb, 0x31, 0x66, 0x21, 0xa8, 0x38, 0x68, 0xcc, 0x42, 0x88, 0x13, 0x93, 0x8c, 0xce, - 0x2b, 0xe7, 0x53, 0xe3, 0x77, 0xee, 0xcf, 0xe3, 0x39, 0xd5, 0x55, 0xd5, 0xd3, 0xa3, 0x55, 0x5d, - 0x07, 0xce, 0xfc, 0x9e, 0xe7, 0xf5, 0xe9, 0x5f, 0x55, 0xf7, 0xb4, 0x4c, 0xb9, 0x6a, 0x55, 0xdd, - 0x6a, 0x02, 0x2b, 0x49, 0xa0, 0x67, 0x25, 0x17, 0x33, 0x6b, 0x7d, 0xa8, 0x75, 0xcd, 0x16, 0xda, - 0x53, 0x57, 0xea, 0x00, 0x2b, 0xb5, 0x4e, 0x7b, 0x34, 0x72, 0x8c, 0xee, 0xe4, 0x81, 0xda, 0x9d, - 0xbb, 0xdd, 0xf1, 0x39, 0x30, 0xe4, 0x4a, 0x5d, 0x20, 0xbb, 0x13, 0x9b, 0x2b, 0x32, 0x67, 0x91, - 0x31, 0x3a, 0x6d, 0x3b, 0x63, 0x35, 0x07, 0x32, 0x01, 0x62, 0x1d, 0x69, 0xfa, 0x72, 0x2d, 0xca, - 0x1a, 0x79, 0xe6, 0x6a, 0x95, 0xdb, 0x2a, 0x9e, 0x76, 0xa6, 0x4e, 0xc7, 0x96, 0xad, 0xe2, 0xf2, - 0x1c, 0x32, 0x96, 0x1b, 0xf2, 0x37, 0x1c, 0x01, 0xba, 0x62, 0x92, 0x9d, 0x06, 0x13, 0x9a, 0xff, - 0xbd, 0x6a, 0x6c, 0x77, 0x33, 0x59, 0xc6, 0xc7, 0x72, 0x7c, 0x7f, 0xd3, 0xed, 0xb8, 0xf7, 0x6d, - 0x27, 0x66, 0x7b, 0xe8, 0x30, 0x2b, 0xe9, 0xf3, 0xc1, 0x2d, 0xf8, 0x9b, 0xcf, 0xb3, 0x99, 0x2c, - 0x63, 0xfd, 0x1c, 0xdf, 0xa6, 0xa2, 0xd6, 0xb8, 0x0e, 0xb4, 0xc6, 0xe1, 0xc3, 0x87, 0x07, 0xce, - 0x9d, 0x3b, 0xf7, 0xa3, 0xcd, 0x9b, 0x37, 0xff, 0xb0, 0xaf, 0xaf, 0xef, 0xbb, 0xab, 0x57, 0xaf, - 0x1e, 0xef, 0xe9, 0xe9, 0xd9, 0xe0, 0xfa, 0x5a, 0xd7, 0xc9, 0x2b, 0x7d, 0x03, 0x40, 0x5a, 0xd7, - 0x65, 0x26, 0xa9, 0x4a, 0x42, 0x02, 0x69, 0xb5, 0xeb, 0x43, 0xae, 0xaf, 0x3f, 0x79, 0xf2, 0xe4, - 0xf8, 0xe3, 0xc7, 0x8f, 0xbf, 0x78, 0xf5, 0xea, 0xd5, 0xb5, 0xf9, 0xf9, 0xf9, 0xff, 0x2c, 0x94, - 0xa4, 0xb9, 0xbd, 0xe7, 0x6a, 0x69, 0xb0, 0x88, 0x09, 0x94, 0xa4, 0x0f, 0x0c, 0x68, 0x00, 0xdb, - 0x70, 0xe4, 0xc8, 0x91, 0xb1, 0xe7, 0xcf, 0x9f, 0x9f, 0x76, 0xb0, 0xa6, 0x4a, 0xc2, 0xea, 0x9d, - 0x6d, 0xe6, 0xa1, 0x56, 0x14, 0x1a, 0xb0, 0xe8, 0x7d, 0xae, 0xaf, 0xdb, 0xb2, 0x65, 0xcb, 0xb7, - 0x1e, 0x3d, 0x7a, 0xf4, 0xe5, 0xdc, 0xdc, 0xdc, 0x3f, 0xde, 0xd9, 0x49, 0xc9, 0x8c, 0xe5, 0x02, - 0xa7, 0x0a, 0x43, 0x86, 0xaa, 0x6c, 0xc0, 0xf9, 0x37, 0x9c, 0x3f, 0x7f, 0x7e, 0x62, 0x7a, 0x7a, - 0xfa, 0x6e, 0xc9, 0x18, 0x05, 0xb7, 0x9b, 0x15, 0x5c, 0x5a, 0xb5, 0x85, 0xa0, 0xa9, 0xca, 0x74, - 0x2f, 0x1b, 0xb9, 0x7e, 0xfd, 0xfa, 0xa1, 0xd9, 0xd9, 0xd9, 0xe7, 0xc1, 0x5d, 0x94, 0xd0, 0x09, - 0x90, 0x56, 0x2d, 0x2d, 0xc7, 0xc6, 0xa4, 0x5b, 0xc9, 0xe5, 0xd9, 0x7f, 0xff, 0xfe, 0xfd, 0x5f, - 0xec, 0xdc, 0xb9, 0xf3, 0x77, 0xee, 0x9d, 0xb1, 0xbf, 0xd5, 0x62, 0x65, 0x89, 0x53, 0x19, 0x69, - 0x4d, 0x10, 0x42, 0x39, 0x36, 0x26, 0x1d, 0x29, 0x9d, 0x8f, 0x0f, 0x83, 0xf7, 0xee, 0xdd, 0xfb, - 0xf9, 0xae, 0x5d, 0xbb, 0xfe, 0x10, 0x9a, 0xa0, 0xcc, 0x3e, 0x2e, 0xb3, 0x22, 0x4d, 0x70, 0x18, - 0x2b, 0xdd, 0x42, 0xe3, 0x05, 0x19, 0xba, 0x76, 0xed, 0xda, 0xde, 0xdd, 0xbb, 0x77, 0xff, 0xb6, - 0xc8, 0x02, 0x65, 0x1e, 0x23, 0x10, 0xbe, 0x8c, 0xdd, 0xd3, 0xb8, 0x9f, 0xd1, 0xb9, 0x1c, 0x37, - 0x9d, 0x3e, 0x7d, 0xfa, 0x7b, 0x55, 0xba, 0xa7, 0xf9, 0xb7, 0x61, 0x55, 0x4b, 0xe8, 0x05, 0x0e, - 0xc5, 0xac, 0x4f, 0x3a, 0x52, 0x3a, 0x50, 0x07, 0x36, 0x6e, 0xdc, 0x38, 0x3c, 0x39, 0x39, 0xf9, - 0xa7, 0xc1, 0xc1, 0xc1, 0x4f, 0x43, 0x13, 0x57, 0xc1, 0x17, 0xbb, 0x54, 0x05, 0x22, 0x76, 0x46, - 0xc5, 0x7d, 0x68, 0x5c, 0xa2, 0x83, 0x37, 0x6e, 0xdc, 0xf8, 0x65, 0x95, 0xa1, 0x01, 0x25, 0x06, - 0x2e, 0x04, 0x4c, 0xb0, 0x14, 0xb3, 0x36, 0x3a, 0x73, 0x0d, 0xee, 0xdf, 0xbf, 0xff, 0x13, 0xf7, - 0x66, 0xf0, 0xa5, 0x92, 0xaa, 0x2a, 0x43, 0xe0, 0x2c, 0x90, 0xd0, 0xb9, 0x6d, 0x1c, 0x5d, 0xd0, - 0xa8, 0xb6, 0xfe, 0x8b, 0x17, 0x2f, 0xfe, 0xaa, 0xd9, 0x6c, 0x8e, 0x86, 0x06, 0x56, 0xc9, 0x17, - 0x02, 0x17, 0x3a, 0x9f, 0x60, 0x59, 0x29, 0x68, 0x48, 0x7e, 0x5b, 0x18, 0x3c, 0x7a, 0xf4, 0xe8, - 0xa6, 0xf1, 0xf1, 0xf1, 0x5f, 0x87, 0x26, 0xa8, 0x9a, 0x2f, 0x0b, 0x38, 0xc1, 0xd2, 0xd9, 0x43, - 0x36, 0xe0, 0xfa, 0x4f, 0x9c, 0x38, 0xf1, 0x59, 0xa3, 0xd1, 0x58, 0xab, 0xc4, 0x2a, 0x4b, 0x1f, - 0x9c, 0x0f, 0xc5, 0x9e, 0xdd, 0xc6, 0xd0, 0xd5, 0x99, 0x83, 0xdf, 0x10, 0x9a, 0xae, 0xda, 0x3e, - 0xb3, 0x03, 0xaa, 0xac, 0xfb, 0xe0, 0x5a, 0x9d, 0x55, 0xb0, 0xc8, 0x43, 0x67, 0x3c, 0xd5, 0xb6, - 0x66, 0xcf, 0x9e, 0x3d, 0x6b, 0xdd, 0xc7, 0x90, 0x03, 0x4e, 0xef, 0x8a, 0xd6, 0x0a, 0x1c, 0x70, - 0x68, 0x92, 0x8b, 0xd6, 0x37, 0xb6, 0xc0, 0xf5, 0x9d, 0x3d, 0x7b, 0xf6, 0x07, 0xee, 0x32, 0xe5, - 0x5b, 0x90, 0xae, 0x68, 0xad, 0xc0, 0x59, 0x08, 0xaa, 0x36, 0x5f, 0xf2, 0x6e, 0xda, 0x74, 0x1f, - 0x41, 0xbe, 0x6f, 0x93, 0xab, 0xae, 0x5b, 0x70, 0xb1, 0xaa, 0xf2, 0xfd, 0x62, 0x82, 0x9f, 0xf1, - 0xfc, 0x9a, 0xd5, 0xbb, 0x6e, 0xdd, 0xba, 0xef, 0x28, 0xd0, 0x0d, 0xd2, 0x82, 0xcb, 0x73, 0x5e, - 0xa0, 0x09, 0x1c, 0xf7, 0xb8, 0xe6, 0xd0, 0xd0, 0xd0, 0xb6, 0x3c, 0x13, 0x94, 0x3d, 0x37, 0x2b, - 0x38, 0x81, 0x92, 0xe4, 0xdc, 0x02, 0xc7, 0xa5, 0xda, 0xeb, 0xfe, 0x45, 0xea, 0x93, 0xb2, 0xc3, - 0xc8, 0xb3, 0xff, 0xac, 0xe0, 0xec, 0x9c, 0x82, 0x27, 0x49, 0xc5, 0xb9, 0xf7, 0x85, 0x06, 0xff, - 0x08, 0xd3, 0x35, 0x2d, 0x06, 0x0e, 0x28, 0x34, 0xc9, 0x45, 0xeb, 0x5d, 0x9b, 0x18, 0xe3, 0xe9, - 0x3d, 0x0e, 0x1c, 0xf7, 0xba, 0xae, 0x69, 0x31, 0x70, 0x16, 0x80, 0x2a, 0xcb, 0x42, 0x14, 0x34, - 0xc5, 0xb2, 0xcc, 0x63, 0xe7, 0x2c, 0xbd, 0x5e, 0xe4, 0xc0, 0x16, 0x60, 0x52, 0x6d, 0x8e, 0x82, - 0xf5, 0x95, 0x1e, 0x4a, 0x96, 0x03, 0xe4, 0x05, 0x27, 0x40, 0xaa, 0x34, 0xc9, 0x2c, 0x6b, 0x55, - 0x2a, 0x27, 0x0d, 0x9c, 0x20, 0xe9, 0xc0, 0xb2, 0x25, 0xad, 0xdf, 0xf7, 0x29, 0x56, 0x59, 0x99, - 0x06, 0xce, 0x1e, 0xda, 0x07, 0xe3, 0xdb, 0x36, 0xb7, 0x2b, 0xf4, 0x10, 0x38, 0x0b, 0x05, 0xdd, - 0xb7, 0x05, 0x46, 0x31, 0x49, 0xf9, 0xbb, 0x42, 0x86, 0xc0, 0x75, 0xc5, 0xc1, 0xdb, 0x3d, 0x64, - 0x11, 0x70, 0xb6, 0x02, 0xdb, 0x5d, 0xbf, 0xb4, 0xe3, 0xf3, 0x80, 0xb3, 0xc0, 0xec, 0xe5, 0x69, - 0xf5, 0xd2, 0x82, 0xc8, 0xbb, 0xf1, 0x3c, 0xe0, 0x42, 0x73, 0x5b, 0x98, 0xa1, 0x78, 0x65, 0x7d, - 0xed, 0x82, 0xab, 0x2c, 0x98, 0x56, 0x07, 0xab, 0xc1, 0xb5, 0x22, 0x14, 0x89, 0xe7, 0x05, 0xd7, - 0xb5, 0x97, 0xa6, 0xcf, 0x2f, 0x06, 0xae, 0x06, 0xe4, 0x93, 0xf2, 0xec, 0x18, 0x38, 0x2f, 0xad, - 0x36, 0x7d, 0x02, 0x59, 0xc1, 0xd5, 0x15, 0xe8, 0x91, 0xcb, 0x0a, 0xce, 0x0e, 0x0b, 0x41, 0x0c, - 0xf9, 0xec, 0x98, 0xca, 0xe9, 0x45, 0xc0, 0x55, 0x0e, 0x42, 0x91, 0x03, 0xd5, 0xe0, 0x8a, 0x50, - 0x73, 0x63, 0x6a, 0x70, 0x35, 0xb8, 0x82, 0x04, 0x0a, 0x0e, 0xab, 0x2b, 0xae, 0x06, 0x57, 0x90, - 0x40, 0xc1, 0x61, 0x75, 0xc5, 0xd5, 0xe0, 0x0a, 0x12, 0x28, 0x38, 0xac, 0xae, 0xb8, 0x1a, 0x5c, - 0x41, 0x02, 0x05, 0x87, 0xd5, 0x15, 0x57, 0x83, 0x2b, 0x48, 0xa0, 0xe0, 0xb0, 0xba, 0xe2, 0x6a, - 0x70, 0x05, 0x09, 0x14, 0x1c, 0x56, 0x57, 0x5c, 0x0d, 0xae, 0x20, 0x81, 0x82, 0xc3, 0xea, 0x8a, - 0xab, 0xc1, 0x15, 0x24, 0x50, 0x70, 0xd8, 0x72, 0x54, 0x5c, 0xf2, 0xc0, 0x26, 0xf7, 0xc4, 0x9a, - 0x99, 0x82, 0x7b, 0x28, 0xe5, 0xb0, 0x22, 0xe0, 0xfc, 0x27, 0x5b, 0x71, 0xf0, 0x05, 0xf7, 0xe4, - 0x9a, 0xff, 0x96, 0x92, 0x40, 0xc1, 0x4d, 0x67, 0x05, 0x17, 0x82, 0xa5, 0x25, 0x93, 0xd8, 0x9b, - 0x37, 0x6f, 0xfe, 0x2d, 0x47, 0x37, 0xc8, 0xac, 0xe0, 0xd2, 0x58, 0xcc, 0x13, 0x74, 0x4f, 0xe3, - 0x9a, 0x4c, 0x4b, 0xaa, 0x5a, 0x2c, 0x06, 0x2e, 0xad, 0xc2, 0x2c, 0x03, 0xf2, 0x00, 0xb7, 0xf0, - 0xe2, 0xc5, 0x8b, 0x27, 0x36, 0x50, 0x75, 0x3d, 0x06, 0x2e, 0x76, 0x6e, 0x0b, 0x14, 0x5d, 0x7d, - 0xfe, 0xce, 0x9d, 0x3b, 0x5f, 0xc7, 0x06, 0x55, 0xd1, 0x6f, 0xff, 0x21, 0x59, 0xba, 0x95, 0xe8, - 0xea, 0x40, 0x46, 0x47, 0xd2, 0xf9, 0x1b, 0x2e, 0xfe, 0x32, 0x3a, 0x79, 0x80, 0xde, 0xb6, 0x6d, - 0xdb, 0x36, 0x3e, 0x7c, 0xf8, 0xf0, 0x6a, 0x6f, 0x6f, 0x6f, 0x65, 0x9e, 0x9f, 0xe4, 0xce, 0x16, - 0x6d, 0x79, 0x2b, 0xce, 0x4e, 0xb4, 0x54, 0x6d, 0xce, 0x39, 0xf7, 0xe4, 0xc9, 0x93, 0xe9, 0x67, - 0xcf, 0x9e, 0xfd, 0xd5, 0x26, 0x54, 0x59, 0x6f, 0x07, 0x1c, 0x5c, 0xb8, 0xbf, 0xd1, 0xf9, 0x0c, - 0xb7, 0xe0, 0x2e, 0xd7, 0xaf, 0x9c, 0xec, 0x8a, 0x96, 0x07, 0x9c, 0x7f, 0x7f, 0x4b, 0xde, 0x14, - 0x1c, 0x25, 0xe4, 0x1c, 0xfd, 0xcc, 0x99, 0x33, 0x5f, 0xb9, 0xe7, 0x29, 0x75, 0xc5, 0xe7, 0xb9, - 0x3c, 0xe0, 0x54, 0x49, 0x21, 0x80, 0x80, 0x9b, 0x76, 0x15, 0x37, 0x75, 0xfb, 0xf6, 0xed, 0xcb, - 0x4a, 0xac, 0xb2, 0x2c, 0x02, 0xce, 0xf2, 0x00, 0x62, 0x52, 0x6d, 0x4e, 0xce, 0xba, 0x3e, 0x73, - 0xec, 0xd8, 0xb1, 0x3f, 0xba, 0xc7, 0x39, 0xbe, 0xb0, 0x49, 0x55, 0xd4, 0xf9, 0x23, 0x5d, 0x35, - 0xbd, 0x9b, 0x62, 0xeb, 0x9d, 0xd4, 0xc6, 0x14, 0xb7, 0x31, 0xe9, 0xcc, 0xc3, 0xdf, 0xab, 0x36, - 0x5e, 0xbe, 0x7c, 0xd9, 0xd8, 0xb7, 0x6f, 0xdf, 0xff, 0xb6, 0x6f, 0xdf, 0xbe, 0x5f, 0x83, 0xab, - 0x28, 0x05, 0x83, 0xb3, 0xf9, 0xba, 0x6c, 0xc1, 0xa1, 0x3a, 0xd1, 0xad, 0x44, 0x4f, 0x9e, 0xa9, - 0xe4, 0x24, 0x8f, 0xce, 0xe0, 0xa3, 0xc9, 0xb0, 0x7b, 0xf8, 0xf1, 0xe0, 0xd3, 0xa7, 0x4f, 0x7f, - 0x3f, 0x32, 0x32, 0xb2, 0xc3, 0xd9, 0x95, 0x6c, 0x69, 0x97, 0xaa, 0xbd, 0x97, 0x71, 0x78, 0xd9, - 0x92, 0x02, 0xc2, 0x9b, 0x43, 0x72, 0x99, 0x3a, 0xc9, 0xbb, 0xeb, 0xf4, 0xeb, 0xd7, 0xaf, 0x67, - 0x8e, 0x1f, 0x3f, 0xfe, 0x9b, 0x2a, 0x5f, 0xb2, 0x69, 0x97, 0x2a, 0x60, 0x54, 0x6d, 0x92, 0xf2, - 0x49, 0xca, 0xcf, 0x0b, 0xa0, 0x4e, 0x05, 0xf6, 0x3c, 0x78, 0xf0, 0x60, 0xc6, 0x3d, 0x4c, 0xf4, - 0x6f, 0x07, 0x0f, 0x1e, 0xfc, 0xb1, 0xfb, 0xb3, 0x73, 0xbb, 0x0e, 0x63, 0x4b, 0xdf, 0xec, 0x81, - 0x80, 0xa0, 0x26, 0x5d, 0x60, 0xac, 0x24, 0x47, 0xb6, 0x74, 0x8d, 0x13, 0x3c, 0xe6, 0x6d, 0xdc, - 0xbc, 0x79, 0x73, 0xca, 0x3d, 0x8d, 0xf5, 0x9f, 0x13, 0x13, 0x13, 0x95, 0x7b, 0x74, 0x50, 0x16, - 0x70, 0x82, 0x22, 0x48, 0x21, 0xa8, 0xc4, 0x80, 0x26, 0xa0, 0x4b, 0xfa, 0x95, 0x2b, 0x57, 0x26, - 0x77, 0xec, 0xd8, 0xf1, 0xcc, 0x3d, 0x64, 0x74, 0x6f, 0x95, 0x2a, 0x2f, 0x06, 0x4e, 0x90, 0x24, - 0x05, 0xc4, 0xda, 0x56, 0xb7, 0x71, 0x41, 0x5b, 0x92, 0xc0, 0x73, 0x1f, 0x8c, 0xbf, 0x3e, 0x70, - 0xe0, 0xc0, 0x5e, 0xf7, 0x50, 0xbe, 0x41, 0x06, 0x96, 0xbd, 0xe5, 0x05, 0xa7, 0x6a, 0xe3, 0xdc, - 0x16, 0x96, 0xf5, 0x8b, 0x09, 0x3e, 0xc1, 0x5b, 0x75, 0xeb, 0xd6, 0xad, 0x7f, 0xdd, 0xbd, 0x7b, - 0xf7, 0x2f, 0x87, 0x0e, 0x1d, 0xda, 0xe3, 0x9e, 0x9f, 0xb9, 0x49, 0x49, 0x65, 0x95, 0xf6, 0xc0, - 0x56, 0xe7, 0x3c, 0xb2, 0xad, 0x44, 0xa7, 0x0b, 0x88, 0x95, 0xe8, 0x74, 0xde, 0x1c, 0xf4, 0xcd, - 0x09, 0xd5, 0xc5, 0xc7, 0x14, 0x1e, 0xa6, 0xcc, 0xe7, 0xbc, 0x01, 0xf7, 0x51, 0xa5, 0x79, 0xf9, - 0xf2, 0xe5, 0x9f, 0x38, 0x80, 0x9f, 0xf7, 0xf7, 0xf7, 0x8f, 0x38, 0x5f, 0x29, 0x9b, 0xa0, 0xb0, - 0x79, 0xab, 0x5b, 0x5b, 0x7e, 0xa4, 0xed, 0x16, 0x1a, 0x7e, 0x81, 0x43, 0x52, 0xc9, 0xc0, 0x4a, - 0x1e, 0xd9, 0xed, 0x24, 0x5f, 0x35, 0x09, 0x1e, 0x7a, 0x73, 0x6c, 0x6c, 0xac, 0xff, 0xd2, 0xa5, - 0x4b, 0x3f, 0x75, 0x97, 0xef, 0xcf, 0xca, 0x78, 0xf9, 0xda, 0x4b, 0xd5, 0x9d, 0x27, 0x15, 0x9e, - 0x85, 0x86, 0xae, 0x26, 0x5d, 0x71, 0xf9, 0x25, 0xf9, 0x9c, 0x67, 0x73, 0x92, 0x2f, 0x07, 0xa6, - 0xa6, 0xa6, 0xe6, 0x2e, 0x5c, 0xb8, 0xf0, 0xf7, 0xab, 0x57, 0xaf, 0xfe, 0x79, 0xfd, 0xfa, 0xf5, - 0x93, 0xc3, 0xc3, 0xc3, 0xf3, 0xae, 0x8f, 0xba, 0x37, 0x10, 0xaa, 0xf5, 0xa3, 0x6f, 0x3a, 0x90, - 0x36, 0x1a, 0xb3, 0xe5, 0x47, 0xda, 0xae, 0xaa, 0xc3, 0xa7, 0x8a, 0xb3, 0x3a, 0x2f, 0x0c, 0x97, - 0x28, 0x9d, 0x4a, 0xa3, 0x02, 0xe9, 0xd8, 0xc4, 0x80, 0x44, 0x25, 0x26, 0xf3, 0x6c, 0xdd, 0xba, - 0x75, 0xcd, 0xa9, 0x53, 0xa7, 0x3e, 0x75, 0x8f, 0xc4, 0x9d, 0x18, 0x1d, 0x1d, 0x1d, 0x73, 0x8f, - 0x56, 0xfb, 0xb6, 0xbb, 0xb4, 0xd7, 0xba, 0x8a, 0x1c, 0xf8, 0xd8, 0x1e, 0x41, 0xc4, 0x21, 0x6d, - 0xf3, 0x6d, 0x62, 0xf2, 0x21, 0xd5, 0xf1, 0x5b, 0x68, 0xf8, 0x65, 0xfb, 0x00, 0x81, 0xa3, 0x4b, - 0x17, 0x48, 0xba, 0x84, 0xf1, 0x2b, 0x46, 0x5c, 0x20, 0x35, 0x8f, 0x73, 0x2d, 0xad, 0x8d, 0xee, - 0x37, 0xed, 0xcb, 0xf7, 0x17, 0xb1, 0xf5, 0xdb, 0x90, 0x95, 0xbe, 0xce, 0x95, 0x42, 0xa7, 0xcd, - 0xb0, 0xf1, 0x3c, 0x4d, 0x93, 0xb1, 0x69, 0xe9, 0x8c, 0xb7, 0x36, 0x7e, 0x16, 0x00, 0x00, 0x3a, - 0xbf, 0x8e, 0x21, 0xe5, 0xd7, 0xb7, 0x29, 0xaa, 0x44, 0x55, 0x1f, 0xe0, 0xc8, 0x65, 0x2e, 0xba, - 0x7d, 0x01, 0x9c, 0x19, 0x84, 0x48, 0x5e, 0xbb, 0x8d, 0x7d, 0xa9, 0x49, 0xb7, 0x12, 0x9d, 0x9e, - 0xdc, 0x62, 0xde, 0xca, 0xf7, 0xc0, 0x91, 0x10, 0xdb, 0x8c, 0x8d, 0xa1, 0xdb, 0x66, 0x6d, 0xe9, - 0x48, 0x01, 0x04, 0x16, 0x0d, 0x9f, 0xc0, 0x01, 0x49, 0x5d, 0x95, 0x87, 0x14, 0x34, 0xa4, 0xba, - 0x53, 0xa3, 0xfb, 0x22, 0xb6, 0x5c, 0xcd, 0xee, 0x1d, 0xdd, 0x76, 0xd6, 0xe0, 0x3c, 0xc9, 0xfe, - 0xb3, 0x54, 0x1c, 0x83, 0x2d, 0x4c, 0xdf, 0x66, 0x42, 0x7c, 0x6a, 0xd2, 0x05, 0x4d, 0x92, 0x05, - 0xd1, 0x89, 0xd3, 0xb1, 0x01, 0xf7, 0xc6, 0x75, 0x5b, 0x75, 0x31, 0x78, 0x76, 0x0f, 0x6e, 0xc8, - 0xb2, 0x37, 0xed, 0x9b, 0x89, 0xb5, 0xc7, 0x90, 0xe4, 0x0c, 0xb3, 0xa1, 0xcd, 0x84, 0x7c, 0x4c, - 0x26, 0xbf, 0x95, 0xe8, 0xa1, 0xae, 0xfb, 0x14, 0xb1, 0x34, 0x9d, 0x98, 0xee, 0x6f, 0x48, 0x6b, - 0x6b, 0x5e, 0x7c, 0x34, 0x6c, 0x35, 0xab, 0xcb, 0xd7, 0x8e, 0xf4, 0xa1, 0x31, 0x57, 0x08, 0x9a, - 0x7c, 0xb3, 0xa1, 0x8a, 0x23, 0x98, 0xb6, 0x31, 0x1b, 0x47, 0x0f, 0x35, 0x55, 0x19, 0x31, 0x5f, - 0x17, 0x10, 0xc6, 0x12, 0xa3, 0x53, 0x7d, 0x00, 0xa2, 0x13, 0xb7, 0xd2, 0x99, 0x4b, 0x2f, 0x0e, - 0x7a, 0x27, 0x9b, 0xce, 0x83, 0x94, 0xce, 0xfe, 0x68, 0xf2, 0x21, 0xe7, 0x42, 0xe0, 0x92, 0xac, - 0xc0, 0x0f, 0x06, 0x58, 0xa0, 0xd6, 0x46, 0xf7, 0x5b, 0x0c, 0x98, 0xc0, 0x28, 0x5f, 0xf0, 0x04, - 0x34, 0x24, 0xc9, 0xb5, 0x6b, 0x6b, 0xec, 0x72, 0x4b, 0x7b, 0x0e, 0xf4, 0x50, 0x67, 0xbf, 0x0b, - 0x31, 0x70, 0x0c, 0x48, 0xdb, 0xa8, 0xe2, 0x48, 0x1a, 0xb9, 0xd2, 0x13, 0xc7, 0xdb, 0x1f, 0x2c, - 0x62, 0x41, 0xe8, 0xb2, 0xf3, 0xfd, 0xa4, 0x2b, 0x4f, 0xba, 0x95, 0xbe, 0x8e, 0xad, 0x96, 0xb6, - 0x4f, 0xe5, 0xb4, 0x92, 0x76, 0xef, 0xd2, 0x91, 0xbe, 0x9e, 0x40, 0xc3, 0x1f, 0x03, 0x17, 0x5b, - 0x88, 0x89, 0xb4, 0x51, 0xe9, 0x9a, 0x1c, 0xbf, 0xf4, 0xd8, 0x78, 0x1f, 0x98, 0x60, 0x69, 0xac, - 0xe6, 0x96, 0x5f, 0xf3, 0x29, 0x1e, 0x9b, 0x57, 0xe3, 0x62, 0xf1, 0x56, 0x7e, 0xad, 0x43, 0x9e, - 0x74, 0x2b, 0xd1, 0xdf, 0xe9, 0xad, 0x16, 0x8c, 0xc5, 0xad, 0x5f, 0x3a, 0xd2, 0xd7, 0xe5, 0x4b, - 0xf3, 0x2b, 0x87, 0x4d, 0xdb, 0x3c, 0x6b, 0xfb, 0x3a, 0xb6, 0x9a, 0xc6, 0xc8, 0x2e, 0x22, 0x05, - 0x89, 0xb1, 0xd2, 0xad, 0xb4, 0xd0, 0xc8, 0x99, 0xcf, 0x5b, 0x71, 0x0c, 0xa2, 0x31, 0x91, 0x36, - 0x2c, 0x5d, 0x0b, 0xe1, 0x97, 0x6e, 0x73, 0x95, 0x8f, 0x8f, 0xa6, 0x71, 0xf8, 0x15, 0x8b, 0x49, - 0xf2, 0x15, 0x43, 0xef, 0x64, 0xd3, 0xde, 0x43, 0x12, 0x5f, 0xd2, 0xb3, 0x6c, 0x26, 0x2d, 0xc7, - 0xc6, 0xa4, 0x5b, 0xe9, 0xeb, 0x69, 0x36, 0x30, 0x88, 0x2b, 0x47, 0x36, 0x92, 0x66, 0xfd, 0x8b, - 0x9e, 0xce, 0xfc, 0x14, 0x30, 0x66, 0x97, 0xbe, 0x04, 0xec, 0xed, 0x92, 0x99, 0xff, 0x7f, 0xd5, - 0xb4, 0x4d, 0xdb, 0x98, 0xf4, 0x90, 0xb4, 0x3e, 0xab, 0xb3, 0x17, 0x6c, 0xdf, 0x27, 0x3f, 0x92, - 0xa6, 0xf8, 0xa2, 0xd5, 0xd9, 0x9f, 0x16, 0x18, 0x2b, 0x59, 0x3b, 0xd1, 0xf3, 0x6c, 0x26, 0x2d, - 0xd7, 0xc6, 0x42, 0xba, 0x7c, 0x48, 0xab, 0xb3, 0xa9, 0x56, 0x36, 0x39, 0x34, 0xe5, 0x2d, 0x5a, - 0x9d, 0xfd, 0x29, 0x50, 0xac, 0x22, 0xdd, 0xca, 0xcc, 0x15, 0xc7, 0x04, 0xad, 0x36, 0xee, 0xc7, - 0x65, 0xc7, 0xa4, 0xe6, 0x54, 0x5c, 0xb6, 0x95, 0xe8, 0x34, 0x9b, 0xb3, 0xe8, 0x89, 0xff, 0xcc, - 0x93, 0xcb, 0x2c, 0x02, 0xe2, 0xcf, 0x68, 0xfd, 0xd2, 0x97, 0x64, 0xde, 0x45, 0x5a, 0xe5, 0xfb, - 0x71, 0x6b, 0x4b, 0x97, 0x64, 0xa3, 0xd2, 0x25, 0xad, 0xcf, 0xd7, 0xb1, 0xfd, 0x66, 0xc7, 0xf9, - 0xb1, 0xbc, 0xb6, 0xa0, 0xf8, 0xe3, 0xac, 0x5f, 0x7a, 0xae, 0x8a, 0xb3, 0x13, 0xb6, 0xda, 0xb0, - 0x1f, 0xb7, 0x76, 0x5e, 0x5d, 0xeb, 0xda, 0x71, 0xf2, 0x75, 0x52, 0x0a, 0x92, 0xd6, 0xb0, 0x76, - 0x61, 0x70, 0x4c, 0x96, 0xe5, 0x20, 0x7e, 0x4e, 0x9a, 0x9d, 0x16, 0xd3, 0xe6, 0x7d, 0xe9, 0x8f, - 0xf1, 0xe3, 0x79, 0x6c, 0x0b, 0xc6, 0x1f, 0xe7, 0xc7, 0xda, 0x02, 0xc7, 0xe4, 0x59, 0x36, 0x1e, - 0xcb, 0xf1, 0xfd, 0xbe, 0x9d, 0x75, 0x7e, 0xff, 0x90, 0x9d, 0xb0, 0xdf, 0x03, 0xc7, 0x57, 0x39, - 0xed, 0xb6, 0xd0, 0x81, 0x63, 0x73, 0xc6, 0x72, 0x63, 0xfe, 0xd8, 0x3c, 0x2b, 0xed, 0xf7, 0xc1, - 0x65, 0xaa, 0x98, 0xac, 0x9b, 0xcc, 0x73, 0xf8, 0x56, 0xb9, 0xad, 0xe2, 0x59, 0xf7, 0xd4, 0x89, - 0xbc, 0x04, 0x62, 0x27, 0x36, 0x58, 0x64, 0xce, 0x22, 0x63, 0x04, 0xa5, 0x9d, 0xb1, 0x9a, 0x03, - 0xf9, 0x5e, 0x55, 0xd9, 0xa0, 0xaf, 0x2f, 0xd7, 0xa2, 0xfe, 0xbc, 0xd8, 0xed, 0xce, 0xdd, 0xee, - 0xf8, 0xd0, 0x9e, 0x96, 0xc3, 0xd7, 0xb1, 0x8a, 0x0b, 0x6d, 0xee, 0x63, 0x85, 0x10, 0xda, 0x6b, - 0x26, 0xdf, 0x87, 0x3a, 0xd0, 0x87, 0x5a, 0x37, 0x13, 0x94, 0x3a, 0xa9, 0x26, 0xf0, 0xf1, 0x11, - 0xf8, 0x3f, 0x7a, 0xc4, 0x58, 0xcc, 0x89, 0xbc, 0xc8, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderRightHandle2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x50, 0x08, 0x06, 0x00, 0x00, 0x00, 0x56, 0x1d, 0x56, - 0xa7, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x02, 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87, - 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x34, 0xa0, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x7d, 0xa9, - 0x20, 0x00, 0x00, 0x01, 0x59, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, - 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, - 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, - 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, - 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, - 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, - 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, - 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, - 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, - 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, - 0x3e, 0x0a, 0x4c, 0xc2, 0x27, 0x59, 0x00, 0x00, 0x06, 0x18, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, - 0xed, 0x9a, 0xcf, 0x4b, 0x5c, 0x57, 0x14, 0xc7, 0x33, 0x31, 0x89, 0xb6, 0x89, 0x59, 0xb5, 0xb1, - 0x82, 0x50, 0x90, 0x2c, 0x92, 0x45, 0x16, 0x6e, 0x85, 0x10, 0x4b, 0xb6, 0xc6, 0x2e, 0x0a, 0xe2, - 0x3f, 0xd0, 0xb5, 0xa0, 0xae, 0xbb, 0x10, 0xb3, 0x2a, 0x62, 0xc0, 0x65, 0xb2, 0x4b, 0x20, 0x81, - 0x80, 0x7b, 0x41, 0x51, 0xba, 0x08, 0x48, 0x71, 0x21, 0x14, 0x17, 0x76, 0x25, 0xc5, 0xb6, 0xfe, - 0x18, 0xb0, 0xa9, 0x71, 0xe2, 0xef, 0x9e, 0xef, 0xf3, 0x7d, 0xaf, 0x67, 0xee, 0xbb, 0xef, 0xcd, - 0x7b, 0x33, 0x3a, 0x73, 0x5f, 0x99, 0x0b, 0xc7, 0x73, 0x7f, 0x9c, 0x77, 0xef, 0xf7, 0xf3, 0xce, - 0x7d, 0x77, 0x1e, 0xce, 0x5c, 0xbb, 0xf6, 0x3f, 0x2b, 0x05, 0xe1, 0x81, 0x35, 0xb2, 0x9c, 0x5d, - 0xe6, 0xe2, 0x49, 0x40, 0xb5, 0x82, 0x56, 0x2b, 0xb4, 0xda, 0xeb, 0x82, 0xfb, 0x02, 0xd1, 0xd7, - 0x2f, 0xf3, 0x0e, 0x65, 0x98, 0x2b, 0x8d, 0xf0, 0x34, 0x31, 0x65, 0x4b, 0x12, 0x28, 0x29, 0x1b, - 0x49, 0x63, 0x65, 0x93, 0x49, 0x23, 0x8d, 0x00, 0x57, 0x8c, 0xab, 0x4f, 0xcf, 0x5d, 0x69, 0xdc, - 0xc4, 0x42, 0xec, 0x5d, 0x31, 0x2d, 0x5a, 0xd7, 0x4d, 0x60, 0x8d, 0x95, 0x13, 0xb9, 0x1e, 0xa2, - 0x60, 0xc7, 0xa1, 0x89, 0x0b, 0x8a, 0x2d, 0xd6, 0x6e, 0xc7, 0xc5, 0xb1, 0xbf, 0xdc, 0x9f, 0x5d, - 0x71, 0x39, 0x3d, 0x3d, 0xfd, 0xf7, 0xf0, 0xf0, 0xf0, 0xf7, 0x52, 0xa9, 0xf4, 0xcb, 0xee, 0xee, - 0xee, 0xcb, 0x95, 0x95, 0x95, 0x1f, 0x7a, 0x7b, 0x7b, 0xef, 0x89, 0x8a, 0xdb, 0x62, 0x37, 0xc5, - 0x5a, 0x42, 0xc3, 0xd6, 0xa7, 0xe1, 0xa6, 0xba, 0x4c, 0xba, 0x2b, 0x94, 0x2b, 0xe6, 0x71, 0x4e, - 0x7f, 0x72, 0x72, 0xf2, 0x51, 0xe0, 0x5e, 0x4d, 0x4f, 0x4f, 0x3f, 0x10, 0x79, 0xed, 0x62, 0x59, - 0xc0, 0x92, 0x89, 0x9c, 0x2b, 0xd6, 0xa9, 0x53, 0xb2, 0xb7, 0xb7, 0xb9, 0xb9, 0xf9, 0x73, 0x5f, - 0x5f, 0xdf, 0x37, 0xa2, 0xb2, 0x4d, 0xec, 0x86, 0x98, 0x9d, 0xb1, 0x6c, 0x99, 0xaa, 0x93, 0xf6, - 0xc4, 0x65, 0xf6, 0xf7, 0xf7, 0x7f, 0x9d, 0x9a, 0x9a, 0x7a, 0x28, 0x30, 0xd8, 0x86, 0x80, 0x22, - 0x58, 0xd2, 0x16, 0x94, 0x30, 0x47, 0x49, 0x5c, 0xa9, 0x8e, 0x83, 0x47, 0x47, 0x47, 0x1b, 0x33, - 0x33, 0x33, 0x4f, 0x44, 0x22, 0xb7, 0x60, 0x75, 0x50, 0x75, 0xd4, 0x5c, 0x71, 0xa9, 0x83, 0x83, - 0x83, 0x3f, 0xc7, 0xc7, 0xc7, 0x1f, 0x09, 0xd4, 0x97, 0x62, 0x78, 0xae, 0xb2, 0x43, 0x55, 0x5c, - 0xa5, 0xce, 0x01, 0x7b, 0x7b, 0x7b, 0xcb, 0x3d, 0x3d, 0x3d, 0xdf, 0x0a, 0xcc, 0x17, 0x29, 0xa1, - 0x24, 0x4c, 0x95, 0x3a, 0xeb, 0x4d, 0xb5, 0xdc, 0xfa, 0xfa, 0xfa, 0x0b, 0x91, 0xf8, 0x95, 0x58, - 0xab, 0x58, 0x9a, 0x4c, 0x19, 0xa2, 0x46, 0xbd, 0xf6, 0x18, 0x01, 0xae, 0x4a, 0x57, 0x57, 0xd7, - 0x8f, 0xa3, 0xa3, 0xa3, 0xc8, 0xd2, 0x2d, 0x31, 0xfb, 0x94, 0x73, 0x5d, 0x72, 0xd1, 0x97, 0xea, - 0x96, 0x35, 0x20, 0x68, 0x63, 0x63, 0xe3, 0x8d, 0xa8, 0xc4, 0x71, 0x8e, 0xad, 0x07, 0xb0, 0xa4, - 0xe7, 0x49, 0x86, 0xcf, 0x8b, 0x97, 0x19, 0x82, 0xb4, 0x8e, 0x8e, 0x8e, 0xef, 0xbb, 0xbb, 0xbb, - 0xf1, 0x5a, 0x06, 0x90, 0x4a, 0x59, 0xc2, 0x78, 0x50, 0xbc, 0x05, 0x6a, 0x69, 0x69, 0xb9, 0x33, - 0x39, 0x39, 0xf9, 0x58, 0x54, 0xe2, 0x03, 0x17, 0x3a, 0x09, 0x15, 0x08, 0x0f, 0xdb, 0xac, 0x1b, - 0xef, 0x2d, 0x10, 0x14, 0xca, 0x69, 0xf7, 0x54, 0x1c, 0xb6, 0x1c, 0xde, 0x1e, 0x98, 0x05, 0x1b, - 0x4c, 0x86, 0x2e, 0x8a, 0xd7, 0x40, 0xed, 0xed, 0xed, 0xf7, 0x45, 0x2a, 0x4e, 0x3a, 0x02, 0xd9, - 0x30, 0x84, 0x34, 0x44, 0x5e, 0x03, 0xb5, 0xb5, 0xb5, 0xe1, 0xad, 0x5c, 0x1f, 0x06, 0x04, 0xb0, - 0xc1, 0x00, 0x14, 0x8c, 0x79, 0x0d, 0xd4, 0xda, 0xda, 0xfa, 0xb5, 0x08, 0xe5, 0x9b, 0x38, 0x21, - 0x08, 0x05, 0x88, 0x48, 0xf1, 0x1a, 0x48, 0x0e, 0x06, 0xbc, 0x02, 0x61, 0xbb, 0x41, 0xa7, 0x06, - 0x89, 0xab, 0x37, 0xec, 0xff, 0x09, 0x91, 0x3b, 0x9b, 0xd0, 0x01, 0x18, 0x1a, 0xb3, 0x84, 0x70, - 0x0d, 0x65, 0x2e, 0xf7, 0x3a, 0x43, 0xa1, 0x4a, 0x08, 0xa7, 0x4e, 0x1b, 0xc2, 0x6e, 0x9b, 0x40, - 0x43, 0xe8, 0x61, 0x05, 0xa2, 0x69, 0x90, 0xa7, 0xeb, 0x11, 0xb9, 0x24, 0x8f, 0x0c, 0x78, 0xda, - 0x11, 0xc9, 0x88, 0xad, 0x33, 0x0f, 0x40, 0xcc, 0x88, 0x0d, 0x63, 0xb7, 0x03, 0xb6, 0x3c, 0x00, - 0xd9, 0x49, 0x20, 0xa0, 0xdd, 0x9f, 0x4b, 0x20, 0x67, 0x56, 0x34, 0x59, 0x1e, 0x32, 0x44, 0x08, - 0x7a, 0xad, 0x3f, 0x52, 0xcf, 0x03, 0x10, 0x44, 0x57, 0x82, 0x31, 0xe3, 0x79, 0x01, 0x8a, 0x64, - 0x22, 0xec, 0x30, 0x20, 0x0c, 0xc8, 0x3b, 0x10, 0x39, 0x8c, 0x6f, 0x02, 0x99, 0x5b, 0xe1, 0x69, - 0xa5, 0x99, 0x21, 0x4f, 0x13, 0x63, 0x64, 0x35, 0x33, 0x64, 0x6e, 0x85, 0xa7, 0x95, 0x66, 0x86, - 0x3c, 0x4d, 0x8c, 0x91, 0xd5, 0xcc, 0x90, 0xb9, 0x15, 0x9e, 0x56, 0x9a, 0x19, 0xf2, 0x34, 0x31, - 0x46, 0x96, 0xd7, 0x19, 0x3a, 0x3e, 0x3e, 0xde, 0x37, 0x4a, 0x53, 0x56, 0xbc, 0x06, 0x92, 0xef, - 0x5c, 0x77, 0x84, 0x23, 0xee, 0x97, 0x25, 0x4e, 0x44, 0xaf, 0x81, 0xe4, 0xeb, 0x7e, 0x00, 0x9d, - 0x26, 0x40, 0x45, 0x60, 0xbd, 0x06, 0xda, 0xd9, 0xd9, 0x59, 0x0f, 0x81, 0x92, 0xa0, 0x90, 0x29, - 0x03, 0xe6, 0x35, 0xd0, 0xc2, 0xc2, 0xc2, 0x07, 0x11, 0x8b, 0x1f, 0x3b, 0x41, 0xb0, 0x11, 0x2d, - 0xf5, 0xd8, 0x52, 0xc0, 0xd7, 0xa7, 0xb1, 0xa3, 0x0d, 0x1c, 0x90, 0x03, 0xe1, 0x53, 0x67, 0x67, - 0xe7, 0x33, 0xc9, 0xd2, 0x5f, 0x22, 0x63, 0x57, 0xac, 0x24, 0x06, 0x38, 0x64, 0x4b, 0x9b, 0x86, - 0x3d, 0xf3, 0x36, 0x43, 0x6b, 0x6b, 0x6b, 0x73, 0x02, 0xf3, 0x59, 0x41, 0xf0, 0xc6, 0x6b, 0x00, - 0x19, 0x2e, 0x2f, 0x5e, 0x02, 0xc9, 0xaf, 0xb5, 0x4a, 0x23, 0x23, 0x23, 0xaf, 0x45, 0x2a, 0xb2, - 0x72, 0x24, 0xc6, 0xdf, 0xdb, 0x69, 0xf5, 0x04, 0xd4, 0x7d, 0x7e, 0xfe, 0xb3, 0x7e, 0x79, 0x79, - 0xf9, 0xfd, 0xec, 0xec, 0xec, 0x56, 0x08, 0xc3, 0x6d, 0x06, 0xe1, 0x4e, 0x08, 0x4d, 0xe4, 0x5d, - 0x86, 0x64, 0x9b, 0xad, 0xf6, 0xf7, 0xf7, 0xbf, 0x15, 0x91, 0xc8, 0x0e, 0xb6, 0x1c, 0x32, 0xa4, - 0x4f, 0xb9, 0xfc, 0x6c, 0x39, 0xf9, 0xdc, 0xd9, 0x1e, 0x1a, 0x1a, 0x1a, 0xdf, 0xde, 0xde, 0xfe, - 0x18, 0x02, 0x1d, 0x8a, 0xd7, 0xdb, 0xcd, 0xce, 0x90, 0xdd, 0xf6, 0x67, 0xcb, 0x01, 0x66, 0x6c, - 0x6c, 0xec, 0xa7, 0xf9, 0xf9, 0xf9, 0xbf, 0x43, 0x18, 0x64, 0x48, 0x03, 0x31, 0x33, 0x84, 0xa0, - 0x97, 0xb0, 0x8b, 0x82, 0x6f, 0x98, 0x1b, 0x5e, 0xb0, 0xcd, 0x06, 0x07, 0x07, 0x9f, 0xcb, 0xe7, - 0x0e, 0x8e, 0xe8, 0x4f, 0x62, 0x78, 0x87, 0x3b, 0x10, 0xd3, 0x9f, 0x41, 0x1a, 0x20, 0xae, 0x1e, - 0x7c, 0x65, 0x2e, 0xd7, 0x35, 0xa6, 0xe0, 0x34, 0x5b, 0x5a, 0x5a, 0x9a, 0x19, 0x18, 0x18, 0x78, - 0x5f, 0x2c, 0x16, 0xff, 0x11, 0x15, 0x00, 0x41, 0x66, 0x98, 0x1d, 0x3e, 0x3b, 0x00, 0xd0, 0x26, - 0x4d, 0x77, 0x69, 0x48, 0x86, 0xf0, 0xa1, 0xb9, 0xba, 0xba, 0xba, 0x30, 0x3c, 0x3c, 0xfc, 0x6e, - 0x71, 0x71, 0x11, 0xef, 0x6b, 0x78, 0xf8, 0x01, 0x81, 0xec, 0xc0, 0xd0, 0xc6, 0xb3, 0xe3, 0x02, - 0x92, 0x6e, 0x03, 0x87, 0x3a, 0x4b, 0x90, 0xb5, 0x2b, 0x07, 0x12, 0xf1, 0xf2, 0x0b, 0xe7, 0x52, - 0x51, 0x7e, 0xd8, 0x57, 0xdc, 0xda, 0xda, 0xfa, 0x63, 0x6e, 0x6e, 0x6e, 0x69, 0x62, 0x62, 0xe2, - 0x37, 0xf9, 0x55, 0x30, 0x44, 0x63, 0x5b, 0xe1, 0x14, 0x43, 0x1d, 0xd9, 0x81, 0xd9, 0x30, 0x71, - 0x50, 0x12, 0x1a, 0x3d, 0xc6, 0x6f, 0x14, 0x0a, 0x85, 0xef, 0x64, 0x00, 0x60, 0x38, 0xc2, 0x69, - 0xf8, 0xaf, 0x3e, 0xff, 0xb3, 0x4f, 0x2f, 0x5d, 0x55, 0x17, 0x2d, 0x0a, 0xcf, 0x05, 0x0d, 0x0f, - 0x3d, 0xa0, 0x08, 0x82, 0x36, 0x8f, 0x69, 0x5c, 0xa3, 0xaf, 0xe3, 0x73, 0xc3, 0xad, 0x27, 0xc3, - 0xd1, 0x02, 0x10, 0x4c, 0x86, 0x5f, 0x6b, 0x00, 0x06, 0xe2, 0xe9, 0x35, 0x88, 0xae, 0x4b, 0x48, - 0xaa, 0x42, 0x01, 0x0c, 0x86, 0x38, 0x6e, 0x23, 0x88, 0x66, 0x66, 0x00, 0x44, 0x10, 0x7e, 0x88, - 0x12, 0x84, 0x9e, 0x10, 0x7a, 0x4e, 0x5d, 0xe7, 0x1a, 0x41, 0x66, 0xf8, 0x00, 0xda, 0x3f, 0x10, - 0x02, 0x04, 0xcd, 0x5c, 0x90, 0xa1, 0xc2, 0x05, 0x29, 0x06, 0xe2, 0x98, 0x19, 0x02, 0xc1, 0xb3, - 0x0f, 0xe3, 0xb6, 0xe1, 0xda, 0x24, 0x28, 0x19, 0x0e, 0x0a, 0xd7, 0x0a, 0x80, 0x70, 0xba, 0x70, - 0xab, 0xe9, 0xec, 0x68, 0x98, 0x2c, 0x19, 0x32, 0x93, 0xab, 0xc5, 0x28, 0x14, 0x63, 0xc8, 0x12, - 0xcc, 0x95, 0x0d, 0xc6, 0xd1, 0x23, 0x9e, 0x26, 0x55, 0x53, 0xec, 0x35, 0xcc, 0x00, 0xb6, 0x1c, - 0x4e, 0x15, 0x02, 0x41, 0xb8, 0x86, 0x42, 0x60, 0x16, 0x18, 0xc4, 0xb3, 0xe8, 0x45, 0x21, 0x10, - 0x05, 0x7d, 0xa8, 0x53, 0x24, 0xeb, 0x1a, 0xc0, 0xae, 0x33, 0x96, 0x1e, 0xf3, 0xc4, 0x16, 0x00, - 0xe1, 0x4e, 0x69, 0x20, 0x66, 0x86, 0x20, 0xf4, 0xb1, 0x93, 0x24, 0x0c, 0x40, 0x04, 0x8a, 0xf6, - 0x14, 0x46, 0xef, 0x82, 0xc2, 0x18, 0xfb, 0x19, 0x07, 0x8f, 0x42, 0x7f, 0xde, 0xb2, 0xda, 0x00, - 0xc2, 0x85, 0x28, 0x08, 0x84, 0x78, 0xc0, 0xa1, 0x10, 0x84, 0xfe, 0xbc, 0x37, 0xfd, 0x5f, 0xbd, - 0x30, 0xeb, 0xf0, 0x2e, 0xd3, 0xe2, 0x75, 0x5d, 0xc7, 0x62, 0x65, 0xce, 0x13, 0xab, 0x42, 0x03, - 0x41, 0x38, 0x8c, 0x17, 0x11, 0x84, 0x3e, 0x76, 0x12, 0xc7, 0x00, 0xe7, 0xe0, 0x10, 0xdb, 0xf0, - 0xd5, 0x18, 0xe6, 0xe1, 0x1c, 0x9c, 0xd3, 0xd9, 0x47, 0x20, 0x04, 0xeb, 0xcc, 0x10, 0x82, 0x5e, - 0x4f, 0x92, 0xb6, 0xae, 0x05, 0xb0, 0xae, 0x3d, 0xea, 0x71, 0x86, 0x35, 0x38, 0xc6, 0x3a, 0xbc, - 0x2e, 0x9c, 0x4b, 0xf7, 0x05, 0xa7, 0x1c, 0x07, 0x70, 0xf2, 0x10, 0xc0, 0xf6, 0x65, 0x17, 0xa5, - 0x6c, 0x70, 0x5e, 0x86, 0xb3, 0x0d, 0x6f, 0xd7, 0xed, 0x36, 0xae, 0xd1, 0x7d, 0x9c, 0x83, 0x9e, - 0x63, 0x6c, 0x1b, 0xcf, 0x0c, 0xd9, 0x00, 0x6c, 0x9b, 0xc0, 0x1a, 0x2a, 0x7a, 0x71, 0xd6, 0x5d, - 0xde, 0xee, 0xc3, 0x92, 0xec, 0xd3, 0xcb, 0xbb, 0xfa, 0xcc, 0x38, 0x80, 0x10, 0x00, 0x03, 0x84, - 0x0e, 0xbe, 0x0c, 0x28, 0x3d, 0x9f, 0x4c, 0x5f, 0x36, 0x3f, 0xc7, 0x6c, 0x6f, 0xc7, 0xa1, 0xcd, - 0xc2, 0x58, 0xb6, 0x23, 0x1e, 0xa2, 0xf9, 0x86, 0xc0, 0xc1, 0xcb, 0x00, 0xe1, 0x5c, 0xf4, 0xb6, - 0x10, 0xdd, 0xd6, 0x75, 0xc4, 0xdb, 0xed, 0xb8, 0x39, 0xd8, 0x5f, 0xe6, 0x99, 0x21, 0xdd, 0x69, - 0x4f, 0x98, 0x05, 0xd0, 0xbe, 0x56, 0xcf, 0xcb, 0xba, 0x2b, 0xc6, 0xd5, 0xc7, 0x78, 0xf8, 0x4a, - 0xe3, 0x26, 0x16, 0x62, 0x79, 0xba, 0x99, 0xce, 0x3a, 0x55, 0xd2, 0x88, 0x4c, 0x13, 0x53, 0x26, - 0x17, 0xdb, 0x2d, 0xae, 0x64, 0xc9, 0x8c, 0x6b, 0x8e, 0xcc, 0x62, 0xc2, 0x49, 0xaa, 0xbd, 0x2e, - 0xb8, 0x1c, 0xa2, 0x6b, 0x15, 0xee, 0x82, 0xc9, 0xd2, 0x57, 0x13, 0x40, 0x96, 0x85, 0x72, 0x19, - 0xfb, 0x1f, 0xc1, 0xeb, 0xcc, 0x70, 0xd6, 0x0c, 0xd1, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderRightHandle3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x78, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5c, 0x89, 0xc4, - 0xad, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x44, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x02, 0x01, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87, - 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0xa0, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x54, 0xdc, - 0xcf, 0x00, 0x00, 0x01, 0x59, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, 0x6f, 0x6d, - 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, - 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, - 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x74, 0x61, - 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, 0x50, 0x20, - 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x72, - 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, - 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, 0x32, 0x32, - 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, 0x23, 0x22, - 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, 0x62, 0x6f, - 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, - 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, - 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, - 0x52, 0x44, 0x46, 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, - 0x3e, 0x0a, 0x4c, 0xc2, 0x27, 0x59, 0x00, 0x00, 0x0a, 0x85, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, - 0xed, 0x9c, 0xdf, 0xab, 0x55, 0x5b, 0x15, 0xc7, 0x3d, 0x76, 0xac, 0xae, 0x5e, 0xf2, 0x66, 0x3f, - 0x10, 0xcc, 0x20, 0xdf, 0xfc, 0x11, 0x41, 0x10, 0x17, 0xa9, 0x87, 0x5e, 0x82, 0x5e, 0xea, 0x41, - 0x5f, 0xc4, 0xd4, 0xb7, 0x7a, 0x88, 0x08, 0x2e, 0xa1, 0xf8, 0x24, 0x5c, 0x2e, 0x8a, 0x44, 0x0f, - 0x81, 0x7f, 0x41, 0x12, 0x78, 0xb1, 0x08, 0x12, 0x51, 0x1f, 0xa4, 0xa4, 0x30, 0xc9, 0xac, 0x38, - 0x84, 0x60, 0x04, 0xf9, 0x23, 0xf3, 0x57, 0x1c, 0x6f, 0xde, 0xce, 0x3d, 0xf7, 0x78, 0xfc, 0x71, - 0x1b, 0x9f, 0xb5, 0xf7, 0x77, 0x39, 0xf6, 0xdc, 0x73, 0xae, 0xbd, 0xf6, 0xda, 0xfb, 0x9c, 0xeb, - 0x5e, 0x6b, 0x4d, 0x98, 0x7b, 0xfc, 0x98, 0x63, 0xcc, 0x35, 0xe7, 0xe7, 0x8c, 0xb9, 0xd7, 0xde, - 0x47, 0xcf, 0x5a, 0xb1, 0xa2, 0x6d, 0x2d, 0x81, 0xe5, 0x24, 0x30, 0x65, 0x17, 0xa3, 0x4f, 0x7a, - 0xfb, 0x60, 0xb9, 0x37, 0x50, 0x17, 0x70, 0x21, 0xb7, 0x25, 0x07, 0xe9, 0xc1, 0xbd, 0xac, 0x95, - 0x37, 0x2a, 0x84, 0x51, 0xf3, 0xc3, 0x1f, 0x4a, 0x66, 0x03, 0x6b, 0x65, 0x74, 0x24, 0xed, 0x1c, - 0x17, 0xe0, 0x51, 0x36, 0x54, 0x25, 0xb7, 0x4a, 0x4e, 0x92, 0x82, 0x07, 0x37, 0x2e, 0x20, 0xc9, - 0x8b, 0x8d, 0x30, 0x30, 0x68, 0xd3, 0x83, 0xc6, 0xfd, 0xa5, 0x87, 0x89, 0xf5, 0x79, 0x3d, 0x3a, - 0xb0, 0x3e, 0xde, 0xe3, 0xe9, 0x18, 0x1f, 0x26, 0x44, 0x6d, 0x0c, 0xf9, 0xbc, 0xdb, 0xc3, 0x25, - 0x2a, 0xa6, 0xac, 0x3f, 0x8c, 0xc3, 0x4e, 0xcd, 0x11, 0x8b, 0xed, 0xf3, 0x4d, 0x9b, 0xe7, 0x63, - 0xd6, 0x43, 0x50, 0xa1, 0xdd, 0x97, 0xb8, 0x0c, 0x0e, 0x36, 0xe6, 0xfb, 0x33, 0xb3, 0xe9, 0x4f, - 0xad, 0xfb, 0xf5, 0x79, 0x00, 0x29, 0xbf, 0xa5, 0xf4, 0x35, 0x62, 0x7d, 0x6e, 0x5f, 0x40, 0x91, - 0x63, 0xea, 0x03, 0x6b, 0x45, 0x01, 0xcb, 0x3d, 0x66, 0xcb, 0x59, 0xb4, 0x3e, 0x67, 0xfd, 0x9d, - 0x27, 0x4f, 0x9e, 0xfc, 0xf3, 0xf1, 0xe3, 0xc7, 0xff, 0xb8, 0x7f, 0xff, 0xfe, 0xef, 0xf7, 0xef, - 0xdf, 0xff, 0xbb, 0x53, 0xa7, 0x4e, 0xbd, 0x6f, 0xeb, 0xa1, 0x0a, 0x81, 0xb7, 0xd8, 0xd5, 0x4d, - 0xe4, 0x2d, 0xdc, 0x4b, 0x68, 0xe7, 0x81, 0x4e, 0x29, 0x13, 0xe3, 0xc2, 0xbb, 0xaa, 0x2d, 0x70, - 0x22, 0xda, 0xf3, 0xe7, 0xcf, 0xdf, 0x9b, 0x9b, 0x9b, 0x3b, 0x7d, 0xe3, 0xc6, 0x8d, 0xef, 0x1f, - 0x3c, 0x78, 0x70, 0x93, 0x2d, 0xff, 0x35, 0xeb, 0x6b, 0xac, 0xaf, 0xb2, 0xce, 0xc9, 0xf9, 0x88, - 0xeb, 0xdc, 0xf0, 0x7c, 0xa7, 0xba, 0x8a, 0xba, 0x0d, 0x0f, 0xd9, 0x26, 0x82, 0x5a, 0xb0, 0x48, - 0x83, 0xf8, 0xee, 0xbd, 0x7b, 0xf7, 0x0e, 0xef, 0xd8, 0xb1, 0xe3, 0x73, 0xb6, 0xdd, 0x4f, 0x5a, - 0x07, 0x20, 0xf0, 0x96, 0x0f, 0x60, 0xb0, 0xa6, 0x89, 0x32, 0x9f, 0x3d, 0x7b, 0x76, 0xf7, 0xfa, - 0xf5, 0xeb, 0x6f, 0xac, 0x5f, 0xbf, 0xfe, 0x33, 0x06, 0x6d, 0xad, 0x75, 0xde, 0xaf, 0x43, 0x80, - 0xbe, 0xf2, 0xd0, 0x8b, 0x2a, 0x8f, 0xb1, 0x72, 0x6d, 0xa2, 0x48, 0x25, 0x16, 0xbb, 0xb0, 0xb0, - 0xf0, 0x97, 0x63, 0xc7, 0x8e, 0x7d, 0xd1, 0x76, 0x4c, 0xf5, 0xbd, 0x62, 0x3d, 0x84, 0xc7, 0x31, - 0xf6, 0x00, 0x8b, 0xe0, 0x59, 0x68, 0x89, 0x96, 0x58, 0xcb, 0xc4, 0xb9, 0x9f, 0x3e, 0x7d, 0x7a, - 0xef, 0xfc, 0xf9, 0xf3, 0xdf, 0xb4, 0x2d, 0x7f, 0xca, 0xba, 0x7f, 0xef, 0xf3, 0xc7, 0x77, 0x6c, - 0xf0, 0x5e, 0xba, 0xbb, 0x6a, 0x89, 0x9f, 0x75, 0x32, 0xc4, 0x7e, 0xda, 0x0b, 0xd7, 0xae, 0x5d, - 0xfb, 0xd1, 0x96, 0x2d, 0x5b, 0x4e, 0x5a, 0xd0, 0x82, 0xf5, 0xc7, 0xd6, 0x75, 0xd7, 0x0c, 0x25, - 0xf3, 0xc8, 0x87, 0x1e, 0xb6, 0xa2, 0xb1, 0x15, 0xb5, 0x02, 0xa7, 0x9d, 0x5f, 0xbd, 0x7a, 0xf5, - 0x07, 0xdb, 0xb6, 0x6d, 0xfb, 0x85, 0xd9, 0xef, 0x59, 0xe7, 0x63, 0x0b, 0x0d, 0x10, 0x82, 0x21, - 0x29, 0x3f, 0x32, 0xd6, 0x7c, 0x5c, 0xcf, 0x38, 0xa5, 0x5b, 0xbb, 0x66, 0x15, 0xf7, 0x93, 0xd3, - 0xa7, 0x4f, 0x7f, 0xc5, 0x36, 0xa6, 0xbb, 0x2d, 0x7b, 0xd4, 0xfb, 0x9a, 0x74, 0x24, 0xad, 0xfc, - 0x0d, 0xa1, 0x13, 0xdf, 0x79, 0x9d, 0xb8, 0x37, 0xb3, 0x92, 0x0b, 0xe6, 0x3d, 0xef, 0xf0, 0xe1, - 0xc3, 0x5f, 0xb6, 0x5d, 0x7e, 0xda, 0x3a, 0x5f, 0x2b, 0xf9, 0xbc, 0x17, 0x7e, 0xe6, 0x2b, 0xf3, - 0x9e, 0x67, 0x69, 0xfd, 0xad, 0x96, 0x47, 0x55, 0xdb, 0x9c, 0x9f, 0x9f, 0x9f, 0xd9, 0xb8, 0x71, - 0xe3, 0xb7, 0x1e, 0x3e, 0x7c, 0xf8, 0x3f, 0xf3, 0xe9, 0x5b, 0x07, 0xc3, 0xc3, 0x1c, 0xdb, 0xe8, - 0x71, 0xad, 0xe5, 0x51, 0x15, 0xb8, 0xd5, 0xab, 0x57, 0x7f, 0xe9, 0xc2, 0x85, 0x0b, 0xdf, 0x31, - 0x7b, 0xb5, 0x75, 0xee, 0xae, 0xda, 0x6f, 0xea, 0xd8, 0x2a, 0xd5, 0xcb, 0xe8, 0x51, 0xd6, 0x44, - 0x3e, 0xb0, 0x56, 0xfa, 0xe6, 0xcd, 0x9b, 0xdf, 0xd8, 0xbe, 0x7d, 0xfb, 0x27, 0x6c, 0x53, 0xc0, - 0x63, 0xbf, 0x1e, 0x84, 0xd7, 0xd9, 0x77, 0x68, 0xe3, 0x8b, 0xb6, 0xda, 0x83, 0x9b, 0x9e, 0x9e, - 0xfe, 0xec, 0xf1, 0xe3, 0xc7, 0xbf, 0x6b, 0xbb, 0xe7, 0x7d, 0x4e, 0x55, 0x07, 0x20, 0x0f, 0xc9, - 0xeb, 0x31, 0x50, 0x7d, 0xe3, 0xb5, 0x07, 0x07, 0x85, 0x4d, 0x9b, 0x36, 0x7d, 0x6f, 0xe7, 0xce, - 0x9d, 0xdc, 0x24, 0xa8, 0x3a, 0xbe, 0x45, 0x08, 0x9c, 0xa4, 0xb9, 0x72, 0x90, 0x7d, 0x90, 0x18, - 0x0c, 0x5b, 0x23, 0xc0, 0xad, 0x5c, 0xb9, 0xf2, 0xd5, 0x03, 0x07, 0x0e, 0x7c, 0xc3, 0x36, 0x4f, - 0xd5, 0x09, 0x9c, 0x67, 0x11, 0xc2, 0x0a, 0x6d, 0x1f, 0x9b, 0xe9, 0x8d, 0x00, 0xc7, 0x4e, 0xad, - 0xea, 0x00, 0xc7, 0x51, 0xe5, 0x17, 0x01, 0xec, 0x5b, 0xd5, 0xe6, 0x21, 0x79, 0xdd, 0x42, 0x7a, - 0x5a, 0xcf, 0x58, 0x63, 0xc0, 0xad, 0x5b, 0xb7, 0xee, 0xab, 0x5b, 0xb7, 0x6e, 0x7d, 0xd5, 0x50, - 0x7c, 0xd4, 0xba, 0xbe, 0xf4, 0x0b, 0x06, 0x52, 0x7a, 0x0f, 0xad, 0x94, 0xd1, 0x18, 0x70, 0x76, - 0x5c, 0x5f, 0x39, 0x7a, 0xf4, 0xe8, 0xd7, 0x0c, 0x04, 0x15, 0x27, 0x70, 0x70, 0x09, 0x81, 0xc9, - 0x96, 0x24, 0xa6, 0xaf, 0x35, 0x06, 0x1c, 0x3b, 0xb7, 0x8f, 0x26, 0xaf, 0x9b, 0xe0, 0xb8, 0xd2, - 0x01, 0x13, 0xeb, 0xe6, 0x1e, 0xdc, 0x1a, 0x05, 0x6e, 0xed, 0xda, 0xb5, 0x5f, 0x30, 0x24, 0x54, - 0x1b, 0x5f, 0xbd, 0xd8, 0x7b, 0xaa, 0xaa, 0xe4, 0x97, 0xb4, 0xd0, 0xac, 0xe5, 0x76, 0xa3, 0xc0, - 0xad, 0x59, 0xb3, 0xe6, 0xf3, 0xb6, 0x7d, 0xaa, 0x4d, 0x47, 0x15, 0x10, 0x39, 0x8c, 0x0c, 0x4d, - 0xc9, 0x17, 0x26, 0x69, 0x4c, 0x5b, 0xb5, 0x6a, 0x15, 0xdf, 0x20, 0x80, 0xc6, 0xbe, 0x7d, 0xc5, - 0x85, 0xf0, 0xa2, 0xdf, 0x4f, 0x3d, 0xa8, 0x46, 0x55, 0x9c, 0xdd, 0x20, 0xf8, 0x35, 0x13, 0x7b, - 0x06, 0x9e, 0xaa, 0x4d, 0xd2, 0x73, 0x19, 0xa8, 0x37, 0x0d, 0x1c, 0xef, 0x6d, 0x80, 0x62, 0xdf, - 0x74, 0x5f, 0x69, 0x5e, 0xb7, 0xa1, 0x7c, 0x2c, 0xf4, 0x33, 0x96, 0x25, 0x67, 0x4a, 0x83, 0x5e, - 0x04, 0x4c, 0x00, 0x3d, 0x18, 0x74, 0xf5, 0x42, 0x24, 0x8d, 0xaa, 0xb8, 0x2e, 0x09, 0x81, 0xf1, - 0x7b, 0xf7, 0xf0, 0x0a, 0x81, 0x69, 0xd0, 0x27, 0xcb, 0xd7, 0x04, 0x29, 0x78, 0x92, 0xec, 0x79, - 0x28, 0x78, 0x4d, 0x04, 0xe7, 0x61, 0xa9, 0x48, 0x04, 0x4d, 0x32, 0xf4, 0xcb, 0xce, 0x65, 0x13, - 0xc1, 0xe5, 0x9b, 0xef, 0x2a, 0xa5, 0x61, 0xf9, 0xc4, 0x26, 0x82, 0x53, 0xc5, 0x49, 0x8a, 0x87, - 0x07, 0x58, 0x34, 0x96, 0xc5, 0x37, 0x11, 0x9c, 0x40, 0x8d, 0x24, 0x5b, 0x70, 0x1d, 0x7c, 0xbe, - 0xda, 0x4a, 0x01, 0x6d, 0x22, 0x38, 0x7f, 0x0c, 0xbd, 0x0e, 0xb0, 0xd2, 0x00, 0x9b, 0x08, 0x4e, - 0x15, 0x55, 0x1a, 0x92, 0x12, 0xbc, 0x6c, 0x32, 0x38, 0xcf, 0x61, 0x68, 0xbd, 0x05, 0x37, 0x34, - 0xb2, 0x4e, 0x42, 0x0b, 0xee, 0x05, 0xb8, 0xa1, 0x8e, 0x6e, 0x0b, 0xee, 0x05, 0xb8, 0x94, 0x16, - 0x05, 0xda, 0x82, 0x4b, 0xe1, 0x1a, 0xe0, 0x6f, 0xc1, 0xf5, 0x03, 0x8a, 0x56, 0x58, 0x18, 0xd6, - 0x44, 0x70, 0x31, 0x30, 0x31, 0x5f, 0xc8, 0xaa, 0xc7, 0x6e, 0x22, 0xb8, 0x1e, 0x00, 0x55, 0x8d, - 0x16, 0x5c, 0x45, 0x72, 0x2d, 0xb8, 0x16, 0x5c, 0x45, 0x02, 0x15, 0xd3, 0xda, 0x8a, 0x6b, 0xc1, - 0x55, 0x24, 0x50, 0x31, 0xad, 0xad, 0xb8, 0x16, 0x5c, 0x45, 0x02, 0x15, 0xd3, 0xda, 0x8a, 0x6b, - 0xc1, 0x55, 0x24, 0x50, 0x31, 0xad, 0xad, 0xb8, 0x16, 0x5c, 0x45, 0x02, 0x15, 0xd3, 0xda, 0x8a, - 0x6b, 0xc1, 0x55, 0x24, 0x50, 0x31, 0xad, 0xad, 0xb8, 0x16, 0x5c, 0x45, 0x02, 0x15, 0xd3, 0xda, - 0x8a, 0x6b, 0xc1, 0x55, 0x24, 0x50, 0x31, 0xad, 0x51, 0x15, 0x67, 0x4f, 0xc8, 0x79, 0xd2, 0xe5, - 0x34, 0xf0, 0x7f, 0x95, 0x0f, 0xe2, 0xd9, 0x28, 0x70, 0xf6, 0x64, 0x9c, 0x79, 0x03, 0x12, 0x83, - 0x16, 0xf3, 0x15, 0xb2, 0x6b, 0x14, 0xb8, 0xc5, 0xc5, 0x45, 0xfe, 0x36, 0x9f, 0x56, 0x04, 0xaa, - 0x68, 0xac, 0x93, 0x6d, 0xaf, 0x8d, 0x02, 0x67, 0x4f, 0x03, 0xfb, 0x57, 0x77, 0xe7, 0x3c, 0x4a, - 0x6d, 0xa4, 0xd6, 0x28, 0x70, 0xb3, 0xb3, 0xb3, 0xb7, 0x8c, 0x16, 0x15, 0x05, 0xb8, 0x52, 0x95, - 0x95, 0x8a, 0x6b, 0x14, 0xb8, 0x2b, 0x57, 0xae, 0xfc, 0xd5, 0x41, 0x03, 0x9c, 0x87, 0xe7, 0x75, - 0x1b, 0x2a, 0x6e, 0xb5, 0x7e, 0xee, 0x88, 0xdf, 0xba, 0xdd, 0x18, 0x16, 0xec, 0xaf, 0xa4, 0xbf, - 0x7d, 0xeb, 0xd6, 0xad, 0x87, 0xe6, 0xff, 0xaf, 0x75, 0x1e, 0x1f, 0xc4, 0xb3, 0x97, 0x78, 0xfa, - 0x21, 0x15, 0xa8, 0x2a, 0x94, 0x14, 0x58, 0x01, 0xed, 0x91, 0x8d, 0xa9, 0xb8, 0x3b, 0x77, 0xee, - 0xfc, 0xc9, 0xa0, 0xf1, 0xa0, 0x2a, 0x9e, 0xb3, 0xe9, 0xe1, 0x98, 0x39, 0x7c, 0x6b, 0x0c, 0x38, - 0x3b, 0xa6, 0x7f, 0x30, 0x3c, 0x54, 0x0d, 0x9f, 0xe5, 0x54, 0x61, 0xc3, 0x13, 0xeb, 0x66, 0x34, - 0x02, 0x9c, 0x3d, 0x67, 0x69, 0xfe, 0xc8, 0x91, 0x23, 0x80, 0xd3, 0x93, 0x5d, 0x55, 0x71, 0x92, - 0x02, 0xa8, 0xe3, 0x28, 0x3b, 0x29, 0x1b, 0x01, 0xee, 0xf2, 0xe5, 0xcb, 0x6f, 0x5b, 0xc5, 0xbd, - 0x6b, 0x14, 0xc2, 0xa3, 0x2a, 0x30, 0xa5, 0x81, 0x29, 0xa1, 0xf6, 0xe0, 0xec, 0x31, 0x90, 0xb3, - 0xbb, 0x77, 0xef, 0xfe, 0x95, 0x6d, 0x98, 0x23, 0xca, 0x8d, 0x40, 0x55, 0x37, 0x34, 0x2c, 0x41, - 0x43, 0xd6, 0x1e, 0x9c, 0x3d, 0xfe, 0xf1, 0x67, 0x37, 0x6f, 0xde, 0xe4, 0xab, 0x16, 0x77, 0x50, - 0x3d, 0x80, 0xd9, 0xdf, 0x20, 0xe0, 0x40, 0xf3, 0x20, 0xd1, 0x43, 0x3b, 0x0b, 0xd2, 0x4b, 0xad, - 0x3f, 0x8e, 0xd8, 0x07, 0xde, 0xbf, 0x6f, 0xd8, 0xb0, 0xe1, 0x87, 0xf6, 0x10, 0x66, 0xc0, 0xf1, - 0x75, 0x8b, 0x8f, 0x20, 0x3c, 0x0e, 0x8d, 0x23, 0x9b, 0xfa, 0x18, 0xa2, 0xf7, 0x3d, 0x81, 0x8b, - 0x42, 0xac, 0x6d, 0xc5, 0x71, 0x44, 0xf7, 0xed, 0xdb, 0xf7, 0xa6, 0x41, 0xe3, 0x88, 0x0a, 0x94, - 0x8e, 0x2b, 0x70, 0x7c, 0xf3, 0x90, 0x62, 0x7e, 0xef, 0xcb, 0xf4, 0x5a, 0x82, 0xb3, 0x0f, 0xbb, - 0x8b, 0xf6, 0xb4, 0xc2, 0x37, 0xcf, 0x9c, 0x39, 0xf3, 0x1f, 0xdb, 0xa5, 0xa0, 0xf1, 0xac, 0x4c, - 0x7f, 0x44, 0x55, 0x49, 0x29, 0x68, 0x7d, 0xb0, 0xbc, 0xa3, 0x96, 0x47, 0xf5, 0xc4, 0x89, 0x13, - 0x3f, 0xb6, 0x1b, 0xc2, 0x6f, 0x6c, 0xa3, 0x1c, 0x4b, 0x8e, 0xa9, 0x3a, 0x36, 0x55, 0xe7, 0x01, - 0x52, 0x7d, 0xfe, 0x78, 0x7a, 0xa0, 0x31, 0xa8, 0x99, 0xaf, 0x56, 0x8f, 0xcf, 0xa0, 0xd2, 0x4e, - 0x9e, 0x3c, 0xf9, 0xd3, 0x2e, 0x34, 0x2a, 0x8d, 0xce, 0x4d, 0x81, 0x0e, 0x30, 0x41, 0x32, 0x35, - 0x6b, 0x82, 0x14, 0xda, 0x02, 0x26, 0x7f, 0x9f, 0xac, 0xcd, 0x51, 0xe5, 0x3d, 0xed, 0xd0, 0xa1, - 0x43, 0x07, 0x0c, 0xda, 0x6f, 0x6d, 0x97, 0x1c, 0x4b, 0x60, 0x21, 0xe9, 0xdc, 0x08, 0x74, 0x33, - 0x30, 0x35, 0xbb, 0x63, 0xc6, 0xa0, 0x31, 0xa6, 0x26, 0x78, 0x92, 0xf2, 0x67, 0xb2, 0x16, 0x15, - 0xc7, 0xdd, 0x73, 0xef, 0xde, 0xbd, 0x6f, 0x9d, 0x3d, 0x7b, 0x76, 0xd6, 0x76, 0xa5, 0x0a, 0x13, - 0x3c, 0x01, 0xf4, 0xc7, 0xd3, 0xc3, 0x08, 0x01, 0xf6, 0x00, 0x4a, 0x19, 0x13, 0x0d, 0x8e, 0x2a, - 0x3b, 0x77, 0xee, 0xdc, 0xcf, 0x77, 0xed, 0xda, 0x75, 0xde, 0xee, 0x9e, 0x54, 0x94, 0xde, 0xc3, - 0x04, 0x8d, 0xa3, 0x8a, 0x1e, 0x42, 0x13, 0x2c, 0x01, 0xf4, 0xb6, 0x7c, 0x29, 0x66, 0x99, 0x7f, - 0x22, 0xc1, 0xf1, 0xdd, 0xf3, 0xe2, 0xc5, 0x8b, 0xbf, 0xdc, 0xb3, 0x67, 0xcf, 0xaf, 0x6f, 0xdf, - 0xbe, 0xad, 0xbb, 0x26, 0x92, 0xf7, 0x31, 0x40, 0xa1, 0xcb, 0x06, 0x28, 0xe0, 0x3c, 0x1c, 0x33, - 0xf3, 0x0f, 0xb8, 0xa5, 0x40, 0x91, 0xe0, 0xdb, 0xc4, 0x80, 0xe3, 0xf7, 0x69, 0x06, 0xe9, 0xcf, - 0x97, 0x2e, 0x5d, 0xba, 0x6c, 0xcf, 0x81, 0xfb, 0xe3, 0xcc, 0xcc, 0xcc, 0x9c, 0x6d, 0x04, 0x28, - 0xc0, 0xa2, 0xa3, 0xeb, 0x98, 0xaa, 0xf2, 0xf0, 0x17, 0x55, 0x5b, 0x0a, 0x9a, 0xfc, 0x92, 0x36, - 0x4d, 0xd6, 0x72, 0xfb, 0xa5, 0x03, 0xc7, 0x3f, 0xe1, 0x59, 0x45, 0xbd, 0x6f, 0x47, 0x6f, 0xee, - 0xd1, 0xa3, 0x47, 0xff, 0x7e, 0xf0, 0xe0, 0xc1, 0x6d, 0x83, 0xf5, 0x37, 0xfb, 0x5c, 0x36, 0x73, - 0xf7, 0xee, 0x5d, 0xaa, 0x89, 0xc5, 0x73, 0x77, 0x44, 0x57, 0x35, 0x01, 0x48, 0xd0, 0x54, 0x69, - 0x82, 0x46, 0x7c, 0xac, 0x9b, 0x3b, 0xe9, 0x67, 0xac, 0xb0, 0x4d, 0x4f, 0x4d, 0x4d, 0x7d, 0xdd, - 0x22, 0x78, 0xe6, 0x10, 0x8d, 0xbb, 0x2c, 0x9d, 0x3f, 0xd1, 0xd1, 0x9f, 0xe9, 0x84, 0xba, 0x0d, - 0xe5, 0x63, 0xe8, 0xa3, 0xb6, 0xfc, 0xa7, 0x18, 0x99, 0x48, 0x63, 0x48, 0x60, 0x09, 0x14, 0x55, - 0x44, 0xc7, 0x56, 0xa5, 0x01, 0x52, 0x5d, 0xe3, 0xfe, 0xf3, 0x99, 0xd7, 0x05, 0xd2, 0x52, 0xf2, - 0x23, 0x8b, 0x4e, 0xf3, 0xd7, 0xec, 0x78, 0x22, 0xaf, 0x54, 0x1c, 0x3f, 0x19, 0x1a, 0xc0, 0x98, - 0xdc, 0x83, 0xf3, 0xf0, 0x88, 0x91, 0x1d, 0xea, 0xd8, 0x55, 0x9a, 0x16, 0xe9, 0x73, 0xe5, 0x43, - 0xb2, 0x1e, 0xbf, 0x61, 0x74, 0x41, 0x61, 0xdd, 0xea, 0x00, 0x93, 0xae, 0x71, 0xf2, 0x35, 0x87, - 0x74, 0x24, 0x2d, 0x65, 0x77, 0x46, 0x4b, 0xbc, 0x02, 0x8e, 0x8b, 0x72, 0x31, 0x1e, 0x0d, 0x06, - 0x34, 0x9a, 0xaa, 0xcc, 0x4b, 0xf9, 0xb3, 0x80, 0x25, 0x7c, 0x89, 0x6d, 0x4e, 0xf0, 0x54, 0x71, - 0x48, 0x81, 0x92, 0x64, 0x0f, 0x02, 0xcb, 0x1c, 0xca, 0xf1, 0x90, 0x52, 0xba, 0xb6, 0xa3, 0x6b, - 0xcb, 0xf6, 0xb2, 0x67, 0x0c, 0x70, 0xbc, 0x37, 0x20, 0xc3, 0x4a, 0xf3, 0xd0, 0xc6, 0x5d, 0x69, - 0x7e, 0x41, 0xa1, 0x1e, 0x6e, 0x4e, 0x00, 0x04, 0x0d, 0x40, 0xc0, 0x42, 0x7a, 0x1f, 0xb6, 0x72, - 0x95, 0x23, 0x29, 0xbf, 0xa4, 0x85, 0xf6, 0x34, 0xfc, 0xbe, 0x85, 0xb6, 0x1f, 0xcb, 0x74, 0x80, - 0x71, 0x07, 0x42, 0x86, 0xa0, 0xbc, 0x4d, 0xf0, 0x52, 0xc2, 0xf3, 0x0b, 0x95, 0xee, 0x37, 0x0d, - 0x14, 0x3a, 0x3e, 0xe9, 0xb2, 0x7d, 0x5c, 0x19, 0x9d, 0xf9, 0xc3, 0x6e, 0xae, 0xcc, 0xe7, 0x25, - 0x7a, 0xb2, 0x09, 0x5c, 0xf8, 0x04, 0x3f, 0x12, 0xc2, 0x63, 0x8b, 0xcf, 0xc3, 0xc3, 0x5e, 0x8a, - 0xa6, 0x4d, 0x31, 0xb7, 0x40, 0x78, 0x89, 0xae, 0xae, 0xd8, 0x50, 0x2a, 0x1e, 0xbf, 0xd7, 0xc3, - 0x38, 0xae, 0x41, 0xc3, 0x5f, 0xd4, 0xfa, 0xc6, 0x01, 0xc7, 0x51, 0x05, 0x48, 0xd1, 0x51, 0xd5, - 0xa4, 0xcb, 0x05, 0x8e, 0xeb, 0x85, 0x9b, 0xf4, 0x76, 0x38, 0x9e, 0x82, 0x93, 0xf2, 0x6b, 0x3f, - 0x21, 0x90, 0xd0, 0x56, 0x5c, 0x9f, 0x04, 0x1c, 0xef, 0x13, 0x00, 0x09, 0xe1, 0x11, 0x2c, 0xbf, - 0x74, 0x24, 0x6d, 0x1c, 0x00, 0x53, 0x8b, 0xf4, 0x7e, 0xe9, 0x5e, 0x86, 0x3a, 0xb6, 0x7a, 0x0a, - 0x94, 0xc6, 0xc3, 0x5c, 0xf6, 0x22, 0x1f, 0x7a, 0xac, 0x45, 0xc7, 0x01, 0xe7, 0x07, 0xb8, 0xb0, - 0x60, 0x21, 0x19, 0x13, 0x24, 0x49, 0x73, 0xe5, 0x3e, 0xf4, 0x2a, 0xcd, 0x5f, 0x33, 0x96, 0xef, - 0xc7, 0xd1, 0x65, 0x7b, 0x29, 0xff, 0x30, 0x92, 0x6b, 0x29, 0x5e, 0x3a, 0x92, 0xa6, 0xb9, 0x3b, - 0xd6, 0x80, 0x57, 0xc0, 0x01, 0x8b, 0x63, 0x4a, 0xa2, 0x87, 0x26, 0x50, 0xa1, 0xb4, 0xb0, 0x91, - 0xc1, 0x31, 0x47, 0x6a, 0xa1, 0xde, 0x2f, 0x3d, 0x26, 0xf1, 0xc5, 0xba, 0xe6, 0x0e, 0xc7, 0xbc, - 0x5f, 0x3a, 0x92, 0xa6, 0xf9, 0x3b, 0xd6, 0x8b, 0xd7, 0x94, 0x3f, 0xbb, 0x9b, 0x32, 0xa8, 0x4a, - 0x53, 0x0a, 0xbe, 0x10, 0x98, 0x6c, 0xc5, 0x2c, 0x95, 0xf4, 0x8b, 0x95, 0x1e, 0x93, 0xf8, 0xbc, - 0x5f, 0xb6, 0x24, 0xeb, 0x2b, 0xd2, 0xb5, 0x7e, 0xcd, 0x21, 0xbb, 0x94, 0xf4, 0x47, 0x95, 0x09, - 0x80, 0xa3, 0x2e, 0x5b, 0x13, 0x7f, 0x98, 0xe0, 0xd8, 0x0c, 0xeb, 0xd0, 0x5a, 0xbc, 0x0c, 0xfd, - 0x31, 0x5b, 0xf9, 0x5e, 0x86, 0x3a, 0xb6, 0x6f, 0xba, 0x86, 0xf7, 0xe5, 0xba, 0xc0, 0x11, 0x24, - 0x30, 0x5e, 0x97, 0x0f, 0x59, 0x38, 0x51, 0x3e, 0xe3, 0xe8, 0x8a, 0xbf, 0x4e, 0x4c, 0xc7, 0x27, - 0xbf, 0x97, 0x29, 0x9d, 0x15, 0xf9, 0x31, 0xad, 0x50, 0x3e, 0xd9, 0x5e, 0x16, 0x8d, 0x65, 0x71, - 0x7a, 0x8f, 0x13, 0x20, 0x12, 0x04, 0x49, 0x92, 0x40, 0x8d, 0x67, 0x49, 0x4b, 0xfc, 0x12, 0x2e, - 0x5a, 0x76, 0x19, 0x99, 0x8a, 0x61, 0xc9, 0x1a, 0x0b, 0xf5, 0x70, 0x3b, 0x3e, 0x2e, 0x1c, 0xcb, - 0x6d, 0x55, 0x9c, 0x26, 0x13, 0x2c, 0x49, 0xfc, 0x5e, 0xcf, 0x13, 0xbb, 0x7e, 0x6f, 0x0f, 0xd2, - 0x4b, 0x2d, 0xa8, 0x3b, 0x49, 0x18, 0x2b, 0x5b, 0x92, 0x30, 0xf4, 0xd0, 0x96, 0x3f, 0x26, 0xf1, - 0xd1, 0x7c, 0x4e, 0xc7, 0x53, 0xe1, 0xd5, 0x83, 0xf3, 0xe9, 0x4c, 0xae, 0x2a, 0x0b, 0x2f, 0x94, - 0xf2, 0xfb, 0xfc, 0xb2, 0x7a, 0x38, 0x77, 0x98, 0xe7, 0xc7, 0x63, 0x7a, 0x59, 0x9f, 0xe6, 0xf5, - 0xf1, 0xf2, 0x79, 0x39, 0x68, 0x3c, 0x8f, 0x0d, 0xc1, 0x91, 0x18, 0x82, 0x91, 0xad, 0xa4, 0xd2, - 0x93, 0x2b, 0x61, 0x48, 0x19, 0x9b, 0xdf, 0xfb, 0x86, 0xd5, 0xb9, 0xbc, 0xcf, 0x89, 0x2d, 0x67, - 0xd0, 0x78, 0x5f, 0x4e, 0x08, 0x4e, 0x17, 0xf1, 0xb0, 0xc2, 0x49, 0xfd, 0x58, 0xdf, 0x84, 0x43, - 0x3a, 0xc2, 0xb9, 0x63, 0xe9, 0x61, 0x8c, 0xb7, 0xbd, 0xae, 0xb5, 0xfb, 0x39, 0xc2, 0x71, 0x3f, - 0x26, 0xbd, 0x4c, 0x8c, 0x62, 0x73, 0x19, 0x03, 0x97, 0x0f, 0x26, 0x94, 0x4a, 0x17, 0x4a, 0xcc, - 0x35, 0xc8, 0x1d, 0xbb, 0x56, 0xe8, 0x0b, 0x6d, 0xcd, 0x99, 0xf2, 0x6b, 0x1c, 0x59, 0x26, 0xc6, - 0xc7, 0xe7, 0x3a, 0xe0, 0x68, 0x95, 0x27, 0xe8, 0xa4, 0x2f, 0xd9, 0x6b, 0x6a, 0x5d, 0xc3, 0xfa, - 0x63, 0x0b, 0x4c, 0xcd, 0x11, 0x8b, 0xed, 0xf3, 0xe9, 0xd7, 0x49, 0x0c, 0x8c, 0xf3, 0x08, 0xf6, - 0x5d, 0x68, 0x44, 0xc7, 0xa0, 0x4d, 0x0e, 0x1a, 0xf7, 0x97, 0x1f, 0x26, 0xd6, 0xe7, 0xf5, 0xe8, - 0x1e, 0x5c, 0xcf, 0x40, 0x81, 0x31, 0x2e, 0xc0, 0xa3, 0x6c, 0xa0, 0x4a, 0x6e, 0x95, 0x9c, 0x24, - 0x06, 0xc0, 0xa9, 0x8d, 0x0b, 0x88, 0xe6, 0x1b, 0x97, 0x1c, 0x75, 0xc3, 0xa3, 0xe6, 0x47, 0xf7, - 0x01, 0xac, 0x97, 0x15, 0x58, 0x74, 0xc1, 0x25, 0x9d, 0x4b, 0x02, 0xcb, 0x5f, 0x5b, 0x37, 0x07, - 0xef, 0x9b, 0x44, 0x7d, 0xc9, 0x41, 0x4d, 0x22, 0x94, 0x76, 0xcd, 0x75, 0x22, 0xf0, 0x7f, 0x3a, - 0xd5, 0x8c, 0xbe, 0x72, 0x32, 0xcf, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, - 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderTrack2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x08, 0x06, 0x00, 0x00, 0x00, 0x8e, 0x5f, 0x1f, - 0x96, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x47, 0x49, 0x44, 0x41, 0x54, 0x18, 0x19, 0x63, 0x3c, 0x75, 0xea, 0xac, - 0xc7, 0xbf, 0x7f, 0xff, 0x67, 0xff, 0xff, 0xcf, 0x20, 0xc3, 0x40, 0x01, 0x60, 0x64, 0x64, 0x78, - 0xc2, 0xc0, 0xc0, 0x9c, 0xce, 0x78, 0xe2, 0xc4, 0x99, 0x47, 0x40, 0xc3, 0x64, 0x29, 0x30, 0x0b, - 0xae, 0x15, 0x64, 0x28, 0x13, 0x90, 0xc7, 0x08, 0x17, 0xa1, 0x9c, 0xf1, 0x1f, 0x68, 0x20, 0xd0, - 0x99, 0x60, 0xe7, 0x52, 0x66, 0x1a, 0xd8, 0x75, 0x4c, 0x8c, 0x69, 0x00, 0xf4, 0x9d, 0x13, 0x90, - 0xe0, 0x80, 0xf3, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderTrack3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x06, 0x08, 0x06, 0x00, 0x00, 0x00, 0xd4, 0xb5, 0x2e, - 0x54, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x77, 0x49, 0x44, 0x41, 0x54, 0x28, 0x15, 0x63, 0x3c, 0x73, 0xe6, 0x0c, - 0xeb, 0x9f, 0x3f, 0x0c, 0x4d, 0x0c, 0x0c, 0x0c, 0xf1, 0xff, 0xff, 0x33, 0x48, 0x02, 0x69, 0x9a, - 0x01, 0x46, 0x46, 0x86, 0xe7, 0x0c, 0x0c, 0x8c, 0x4b, 0x78, 0x79, 0x39, 0x6a, 0x58, 0x40, 0x96, - 0x02, 0x2d, 0xac, 0xa0, 0x99, 0x6d, 0x48, 0x06, 0x43, 0x3c, 0xf6, 0xbf, 0xf4, 0xd3, 0xa7, 0x1f, - 0xff, 0x99, 0xfe, 0xff, 0x67, 0x8c, 0x43, 0x92, 0xa3, 0x0b, 0x93, 0x91, 0xf1, 0x7f, 0x2c, 0x13, - 0x90, 0x60, 0xa4, 0x8b, 0x6d, 0x48, 0x96, 0x00, 0x3d, 0x0b, 0xf6, 0xf1, 0x62, 0x24, 0x31, 0xba, - 0x30, 0x81, 0x9e, 0x5d, 0xc4, 0xc2, 0xc7, 0xc7, 0x51, 0xfb, 0xf9, 0xf3, 0x0f, 0xa0, 0xaf, 0xff, - 0xc7, 0xd0, 0x27, 0x71, 0x31, 0x2c, 0x64, 0x61, 0x61, 0xa8, 0x03, 0x00, 0xad, 0xe3, 0x2a, 0xed, - 0xfc, 0x71, 0x9f, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderFill2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x08, 0x06, 0x00, 0x00, 0x00, 0x8e, 0x5f, 0x1f, - 0x96, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x47, 0x49, 0x44, 0x41, 0x54, 0x18, 0x19, 0x63, 0x64, 0xa8, 0xf9, 0xef, - 0xc1, 0xf0, 0x8f, 0x61, 0x36, 0x03, 0x03, 0x83, 0x0c, 0x10, 0x53, 0x02, 0x9e, 0x30, 0x30, 0x31, - 0xa4, 0x33, 0x32, 0x54, 0xff, 0x7f, 0xc4, 0xf0, 0x9f, 0x41, 0x96, 0x12, 0x93, 0x90, 0xf4, 0x3e, - 0x61, 0x02, 0x1a, 0xc6, 0x88, 0x24, 0x40, 0x19, 0x93, 0x91, 0xe1, 0x3f, 0x13, 0xc8, 0x99, 0x40, - 0x53, 0x9e, 0x50, 0x66, 0x12, 0x58, 0xf7, 0x13, 0xa0, 0xd3, 0xd2, 0x00, 0xbe, 0xcf, 0x0d, 0xc0, - 0x10, 0xc9, 0x8a, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXRangeSliderFill3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x06, 0x08, 0x06, 0x00, 0x00, 0x00, 0xd4, 0xb5, 0x2e, - 0x54, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x6e, 0x49, 0x44, 0x41, 0x54, 0x28, 0x15, 0xbd, 0x92, 0xbb, 0x0d, 0x80, - 0x30, 0x0c, 0x05, 0xcf, 0x51, 0x32, 0x04, 0x0d, 0x93, 0xf1, 0x99, 0x02, 0x89, 0x02, 0x28, 0xd8, - 0x82, 0x92, 0xcf, 0x64, 0x34, 0x0c, 0x01, 0x92, 0x49, 0x28, 0xa2, 0x2c, 0x40, 0xdc, 0xf8, 0xc9, - 0x96, 0x7c, 0x3a, 0xc9, 0xc2, 0xa2, 0x8e, 0x93, 0x19, 0x68, 0x51, 0x0a, 0xdf, 0xff, 0x2b, 0xe1, - 0x42, 0x38, 0xb0, 0x0c, 0xf6, 0x83, 0x2a, 0xfd, 0x7f, 0xb4, 0xe4, 0x72, 0x10, 0x53, 0x3a, 0x6e, - 0xd4, 0xf8, 0xd0, 0x24, 0xab, 0x5c, 0xb1, 0x36, 0x5e, 0x5d, 0x72, 0xd1, 0x22, 0x47, 0x83, 0x31, - 0xec, 0x71, 0x90, 0x2b, 0x08, 0x9b, 0xc5, 0x31, 0xf2, 0x78, 0x6b, 0xa5, 0xca, 0xf2, 0x5c, 0xb0, - 0x52, 0x32, 0xbd, 0x8a, 0x37, 0x19, 0x0d, 0x36, 0x20, 0x19, 0x81, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - - -#pragma mark - Misc Icons - -static const u_int8_t FLEXCheckerPattern[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x03, 0x00, 0x00, 0x00, 0x6c, 0xbb, 0xce, - 0xa4, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x1a, 0x18, 0x18, 0xff, 0xff, 0xfd, 0x2c, 0xa7, 0x7c, 0x3f, - 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x80, 0x80, 0xa0, 0xa8, 0xd6, 0x53, 0x00, 0x00, - 0x00, 0x11, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0xfe, 0xc0, 0x80, 0x86, 0xfe, 0x30, - 0xa0, 0x21, 0x00, 0xcf, 0x3f, 0x0b, 0x9b, 0xd8, 0xd3, 0xac, 0x83, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXCheckerPattern2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x01, 0x03, 0x00, 0x00, 0x00, 0xda, 0xb9, 0xaf, - 0xbb, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, - 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x1a, 0x18, 0x18, 0xff, 0xff, 0xfd, 0x2c, 0xa7, 0x7c, 0x3f, - 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x80, 0x80, 0xa0, 0xa8, 0xd6, 0x53, 0x00, 0x00, - 0x00, 0x14, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0xe0, 0xff, 0xcf, 0x40, 0x0a, 0xfe, - 0xff, 0x81, 0x81, 0x14, 0x0c, 0x00, 0xbc, 0xcb, 0x23, 0xdd, 0xc8, 0xaf, 0xa2, 0x74, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXCheckerPattern3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x01, 0x20, 0x05, 0xc9, - 0x11, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, - 0x05, 0x00, 0x00, 0x00, 0x38, 0x65, 0x58, 0x49, 0x66, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x01, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x30, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0x4e, 0x36, 0x00, 0x00, 0x01, 0x16, 0x49, 0x44, 0x41, 0x54, 0x68, 0x05, 0xed, - 0x98, 0x51, 0x0e, 0xc2, 0x30, 0x0c, 0x43, 0x57, 0xae, 0x0c, 0x5c, 0x82, 0x8d, 0x33, 0x8f, 0x7d, - 0x6c, 0x51, 0x40, 0xb2, 0x88, 0x51, 0x2d, 0x56, 0xc9, 0xfb, 0xb2, 0x42, 0x9a, 0x34, 0xcf, 0x65, - 0x63, 0xb4, 0xe5, 0x31, 0xaf, 0xd3, 0x7e, 0x5d, 0xef, 0xb7, 0x43, 0x4e, 0x97, 0x50, 0x1f, 0x02, - 0x7e, 0xd0, 0xd6, 0xed, 0x3a, 0x92, 0x9f, 0xf3, 0x72, 0xc8, 0x5f, 0x4a, 0x9d, 0x7f, 0x57, 0x31, - 0xdd, 0x26, 0x32, 0xb7, 0x1c, 0x87, 0xa8, 0x72, 0x52, 0xd6, 0xf4, 0x82, 0x37, 0xe6, 0xb9, 0x52, - 0xe6, 0x9f, 0xe3, 0x74, 0x07, 0x7a, 0x41, 0xcb, 0xde, 0xe5, 0xd6, 0xff, 0xa3, 0x44, 0xcf, 0xa0, - 0x5f, 0x70, 0x42, 0xe3, 0xf4, 0x43, 0xd3, 0x1d, 0xe0, 0x59, 0xca, 0xe7, 0x2a, 0x6b, 0x74, 0xc6, - 0x72, 0x4e, 0xd6, 0xf4, 0x8e, 0xf2, 0xe2, 0x8a, 0x76, 0x83, 0xaf, 0x94, 0xe4, 0x88, 0xe0, 0x77, - 0x0d, 0x6d, 0x0d, 0xdd, 0x3c, 0x51, 0xbe, 0x7c, 0x02, 0x37, 0x40, 0xe8, 0x23, 0x2e, 0x47, 0xe4, - 0x7b, 0x51, 0xb0, 0x46, 0x42, 0xee, 0x81, 0x1b, 0x20, 0xf4, 0x11, 0x37, 0xa2, 0x40, 0x81, 0xc4, - 0xf8, 0x88, 0xfc, 0x44, 0x43, 0xde, 0x46, 0x7c, 0x7c, 0x93, 0x3d, 0x41, 0x98, 0x89, 0x84, 0x11, - 0x21, 0x32, 0x11, 0x97, 0x23, 0xa2, 0x7f, 0x17, 0xc5, 0xd6, 0x8a, 0x82, 0x7d, 0xa7, 0x2b, 0x96, - 0x8d, 0x34, 0x39, 0xa1, 0xe8, 0x24, 0x12, 0x1e, 0x40, 0x04, 0xb6, 0x5c, 0xd6, 0x0e, 0x94, 0x51, - 0x89, 0x12, 0xed, 0x80, 0x08, 0x6c, 0xb9, 0xac, 0x1d, 0x28, 0xa3, 0x12, 0x25, 0xda, 0x01, 0x11, - 0xd8, 0x72, 0x59, 0xfa, 0xbd, 0xac, 0x5c, 0x79, 0x4f, 0x64, 0xff, 0x99, 0x64, 0xeb, 0xfb, 0x08, - 0xb1, 0xc4, 0x7a, 0xe7, 0xdb, 0x81, 0xde, 0x44, 0xd9, 0x7a, 0x76, 0x80, 0x25, 0xd6, 0x3b, 0xdf, - 0x0e, 0xf4, 0x26, 0xca, 0xd6, 0xb3, 0x03, 0x2c, 0xb1, 0xde, 0xf9, 0xc3, 0x3b, 0xf0, 0x02, 0x0c, - 0xd8, 0x43, 0xeb, 0xbc, 0x94, 0xc3, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, - 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHierarchyIndentPattern[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0xf9, 0x3c, 0x0f, - 0xcd, 0x00, 0x00, 0x0a, 0x41, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0x9d, 0x96, 0x77, 0x54, 0x53, 0xd9, 0x16, 0x87, - 0xcf, 0xbd, 0x37, 0xbd, 0xd0, 0x12, 0x22, 0x20, 0x25, 0xf4, 0x1a, 0x7a, 0x09, 0x20, 0xd2, 0x3b, - 0x48, 0x15, 0x04, 0x51, 0x89, 0x49, 0x80, 0x50, 0x02, 0x86, 0x84, 0x26, 0x76, 0x44, 0x05, 0x46, - 0x14, 0x11, 0x29, 0x56, 0x64, 0x54, 0xc0, 0x01, 0x47, 0x87, 0x22, 0x63, 0x45, 0x14, 0x0b, 0x83, - 0x82, 0x62, 0xd7, 0x09, 0xf2, 0x10, 0x50, 0xc6, 0xc1, 0x51, 0x44, 0x45, 0xe5, 0xdd, 0x8c, 0x6b, - 0x09, 0xef, 0xad, 0x35, 0xf3, 0xde, 0x9a, 0xfd, 0xc7, 0x59, 0xdf, 0xd9, 0xe7, 0xb7, 0xd7, 0xd9, - 0x67, 0xef, 0x7d, 0xd7, 0xba, 0x00, 0x50, 0xfc, 0x82, 0x04, 0xc2, 0x74, 0x58, 0x01, 0x80, 0x34, - 0xa1, 0x58, 0x14, 0xee, 0xeb, 0xc1, 0x5c, 0x12, 0x13, 0xcb, 0xc4, 0xf7, 0x02, 0x18, 0x10, 0x01, - 0x0e, 0x58, 0x01, 0xc0, 0xe1, 0x66, 0x66, 0x04, 0x47, 0xf8, 0x44, 0x02, 0xd4, 0xfc, 0xbd, 0x3d, - 0x99, 0x99, 0xa8, 0x48, 0xc6, 0xb3, 0xf6, 0xee, 0x2e, 0x80, 0x64, 0xbb, 0xdb, 0x2c, 0xbf, 0x50, - 0x26, 0x73, 0xd6, 0xff, 0x7f, 0x91, 0x22, 0x37, 0x43, 0x24, 0x06, 0x00, 0x0a, 0x45, 0xd5, 0x36, - 0x3c, 0x7e, 0x26, 0x17, 0xe5, 0x02, 0x94, 0x53, 0xb3, 0xc5, 0x19, 0x32, 0xff, 0x04, 0xca, 0xf4, - 0x95, 0x29, 0x32, 0x86, 0x31, 0x32, 0x16, 0xa1, 0x09, 0xa2, 0xac, 0x22, 0xe3, 0xc4, 0xaf, 0x6c, - 0xf6, 0xa7, 0xe6, 0x2b, 0xbb, 0xc9, 0x98, 0x97, 0x26, 0xe4, 0xa1, 0x1a, 0x59, 0xce, 0x19, 0xbc, - 0x34, 0x9e, 0x8c, 0xbb, 0x50, 0xde, 0x9a, 0x25, 0xe1, 0xa3, 0x8c, 0x04, 0xa1, 0x5c, 0x98, 0x25, - 0xe0, 0x67, 0xa3, 0x7c, 0x07, 0x65, 0xbd, 0x54, 0x49, 0x9a, 0x00, 0xe5, 0xf7, 0x28, 0xd3, 0xd3, - 0xf8, 0x9c, 0x4c, 0x00, 0x30, 0x14, 0x99, 0x5f, 0xcc, 0xe7, 0x26, 0xa1, 0x6c, 0x89, 0x32, 0x45, - 0x14, 0x19, 0xee, 0x89, 0xf2, 0x02, 0x00, 0x08, 0x94, 0xc4, 0x39, 0xbc, 0x72, 0x0e, 0x8b, 0xf9, - 0x39, 0x68, 0x9e, 0x00, 0x78, 0xa6, 0x67, 0xe4, 0x8a, 0x04, 0x89, 0x49, 0x62, 0xa6, 0x11, 0xd7, - 0x98, 0x69, 0xe5, 0xe8, 0xc8, 0x66, 0xfa, 0xf1, 0xb3, 0x53, 0xf9, 0x62, 0x31, 0x2b, 0x94, 0xc3, - 0x4d, 0xe1, 0x88, 0x78, 0x4c, 0xcf, 0xf4, 0xb4, 0x0c, 0x8e, 0x30, 0x17, 0x80, 0xaf, 0x6f, 0x96, - 0x45, 0x01, 0x25, 0x59, 0x6d, 0x99, 0x68, 0x91, 0xed, 0xad, 0x1c, 0xed, 0xed, 0x59, 0xd6, 0xe6, - 0x68, 0xf9, 0xbf, 0xd9, 0xdf, 0x1e, 0x7e, 0x53, 0xfd, 0x3d, 0xc8, 0x7a, 0xfb, 0x55, 0xf1, 0x26, - 0xec, 0xcf, 0x9e, 0x41, 0x8c, 0x9e, 0x59, 0xdf, 0x6c, 0xec, 0xac, 0x2f, 0xbd, 0x16, 0x00, 0xf6, - 0x24, 0x5a, 0x9b, 0x1d, 0xb3, 0xbe, 0x95, 0x55, 0x00, 0xb4, 0x6d, 0x06, 0x40, 0xe5, 0xe1, 0xac, - 0x4f, 0xef, 0x20, 0x00, 0xf2, 0x05, 0x00, 0xb4, 0xde, 0x9c, 0xf3, 0x1e, 0x86, 0x6c, 0x5e, 0x92, - 0xc4, 0xe2, 0x0c, 0x27, 0x0b, 0x8b, 0xec, 0xec, 0x6c, 0x73, 0x01, 0x9f, 0x6b, 0x2e, 0x2b, 0xe8, - 0x37, 0xfb, 0x9f, 0x82, 0x6f, 0xca, 0xbf, 0x86, 0x39, 0xf7, 0x99, 0xcb, 0xee, 0xfb, 0x56, 0x3b, - 0xa6, 0x17, 0x3f, 0x81, 0x23, 0x49, 0x15, 0x33, 0x65, 0x45, 0xe5, 0xa6, 0xa7, 0xa6, 0x4b, 0x44, - 0xcc, 0xcc, 0x0c, 0x0e, 0x97, 0xcf, 0x64, 0xfd, 0xf7, 0x10, 0xff, 0xe3, 0xc0, 0x39, 0x69, 0xcd, - 0xc9, 0xc3, 0x2c, 0x9c, 0x9f, 0xc0, 0x17, 0xf1, 0x85, 0xe8, 0x55, 0x51, 0xe8, 0x94, 0x09, 0x84, - 0x89, 0x68, 0xbb, 0x85, 0x3c, 0x81, 0x58, 0x90, 0x2e, 0x64, 0x0a, 0x84, 0x7f, 0xd5, 0xe1, 0x7f, - 0x18, 0x36, 0x27, 0x07, 0x19, 0x7e, 0x9d, 0x6b, 0x14, 0x68, 0x75, 0x5f, 0x00, 0x7d, 0x85, 0x39, - 0x50, 0xb8, 0x49, 0x07, 0xc8, 0x6f, 0x3d, 0x00, 0x43, 0x23, 0x03, 0x24, 0x6e, 0x3f, 0x7a, 0x02, - 0x7d, 0xeb, 0x5b, 0x10, 0x31, 0x0a, 0xc8, 0xbe, 0xbc, 0x68, 0xad, 0x91, 0xaf, 0x73, 0x8f, 0x32, - 0x7a, 0xfe, 0xe7, 0xfa, 0x1f, 0x0b, 0x5c, 0x8a, 0x6e, 0xe1, 0x4c, 0x41, 0x22, 0x53, 0xe6, 0xf6, - 0x0c, 0x8f, 0x64, 0x72, 0x25, 0xa2, 0x2c, 0x19, 0xa3, 0xdf, 0x84, 0x6c, 0xc1, 0x02, 0x12, 0x90, - 0x07, 0x74, 0xa0, 0x0a, 0x34, 0x81, 0x2e, 0x30, 0x02, 0x2c, 0x60, 0x0d, 0x1c, 0x80, 0x33, 0x70, - 0x03, 0xde, 0x20, 0x00, 0x84, 0x80, 0x48, 0x10, 0x03, 0x96, 0x03, 0x2e, 0x48, 0x02, 0x69, 0x40, - 0x04, 0xb2, 0x41, 0x3e, 0xd8, 0x00, 0x0a, 0x41, 0x31, 0xd8, 0x01, 0x76, 0x83, 0x6a, 0x70, 0x00, - 0xd4, 0x81, 0x7a, 0xd0, 0x04, 0x4e, 0x82, 0x36, 0x70, 0x06, 0x5c, 0x04, 0x57, 0xc0, 0x0d, 0x70, - 0x0b, 0x0c, 0x80, 0x47, 0x40, 0x0a, 0x86, 0xc1, 0x4b, 0x30, 0x01, 0xde, 0x81, 0x69, 0x08, 0x82, - 0xf0, 0x10, 0x15, 0xa2, 0x41, 0xaa, 0x90, 0x16, 0xa4, 0x0f, 0x99, 0x42, 0xd6, 0x10, 0x1b, 0x5a, - 0x08, 0x79, 0x43, 0x41, 0x50, 0x38, 0x14, 0x03, 0xc5, 0x43, 0x89, 0x90, 0x10, 0x92, 0x40, 0xf9, - 0xd0, 0x26, 0xa8, 0x18, 0x2a, 0x83, 0xaa, 0xa1, 0x43, 0x50, 0x3d, 0xf4, 0x23, 0x74, 0x1a, 0xba, - 0x08, 0x5d, 0x83, 0xfa, 0xa0, 0x07, 0xd0, 0x20, 0x34, 0x06, 0xfd, 0x01, 0x7d, 0x84, 0x11, 0x98, - 0x02, 0xd3, 0x61, 0x0d, 0xd8, 0x00, 0xb6, 0x80, 0xd9, 0xb0, 0x3b, 0x1c, 0x08, 0x47, 0xc2, 0xcb, - 0xe0, 0x44, 0x78, 0x15, 0x9c, 0x07, 0x17, 0xc0, 0xdb, 0xe1, 0x4a, 0xb8, 0x16, 0x3e, 0x0e, 0xb7, - 0xc2, 0x17, 0xe1, 0x1b, 0xf0, 0x00, 0x2c, 0x85, 0x5f, 0xc2, 0x93, 0x08, 0x40, 0xc8, 0x08, 0x03, - 0xd1, 0x46, 0x58, 0x08, 0x1b, 0xf1, 0x44, 0x42, 0x90, 0x58, 0x24, 0x01, 0x11, 0x21, 0x6b, 0x91, - 0x22, 0xa4, 0x02, 0xa9, 0x45, 0x9a, 0x90, 0x0e, 0xa4, 0x1b, 0xb9, 0x8d, 0x48, 0x91, 0x71, 0xe4, - 0x03, 0x06, 0x87, 0xa1, 0x61, 0x98, 0x18, 0x16, 0xc6, 0x19, 0xe3, 0x87, 0x59, 0x8c, 0xe1, 0x62, - 0x56, 0x61, 0xd6, 0x62, 0x4a, 0x30, 0xd5, 0x98, 0x63, 0x98, 0x56, 0x4c, 0x17, 0xe6, 0x36, 0x66, - 0x10, 0x33, 0x81, 0xf9, 0x82, 0xa5, 0x62, 0xd5, 0xb1, 0xa6, 0x58, 0x27, 0xac, 0x3f, 0x76, 0x09, - 0x36, 0x11, 0x9b, 0x8d, 0x2d, 0xc4, 0x56, 0x60, 0x8f, 0x60, 0x5b, 0xb0, 0x97, 0xb1, 0x03, 0xd8, - 0x61, 0xec, 0x3b, 0x1c, 0x0e, 0xc7, 0xc0, 0x19, 0xe2, 0x1c, 0x70, 0x7e, 0xb8, 0x18, 0x5c, 0x32, - 0x6e, 0x35, 0xae, 0x04, 0xb7, 0x0f, 0xd7, 0x8c, 0xbb, 0x80, 0xeb, 0xc3, 0x0d, 0xe1, 0x26, 0xf1, - 0x78, 0xbc, 0x2a, 0xde, 0x14, 0xef, 0x82, 0x0f, 0xc1, 0x73, 0xf0, 0x62, 0x7c, 0x21, 0xbe, 0x0a, - 0x7f, 0x1c, 0x7f, 0x1e, 0xdf, 0x8f, 0x1f, 0xc6, 0xbf, 0x27, 0x90, 0x09, 0x5a, 0x04, 0x6b, 0x82, - 0x0f, 0x21, 0x96, 0x20, 0x24, 0x6c, 0x24, 0x54, 0x10, 0x1a, 0x08, 0xe7, 0x08, 0xfd, 0x84, 0x11, - 0xc2, 0x34, 0x51, 0x81, 0xa8, 0x4f, 0x74, 0x22, 0x86, 0x10, 0x79, 0xc4, 0x5c, 0x62, 0x29, 0xb1, - 0x8e, 0xd8, 0x41, 0xbc, 0x49, 0x1c, 0x26, 0x4e, 0x93, 0x14, 0x49, 0x86, 0x24, 0x17, 0x52, 0x24, - 0x29, 0x99, 0xb4, 0x81, 0x54, 0x49, 0x6a, 0x22, 0x5d, 0x26, 0x3d, 0x26, 0xbd, 0x21, 0x93, 0xc9, - 0x3a, 0x64, 0x47, 0x72, 0x18, 0x59, 0x40, 0x5e, 0x4f, 0xae, 0x24, 0x9f, 0x20, 0x5f, 0x25, 0x0f, - 0x92, 0x3f, 0x50, 0x94, 0x28, 0x26, 0x14, 0x4f, 0x4a, 0x1c, 0x45, 0x42, 0xd9, 0x4e, 0x39, 0x4a, - 0xb9, 0x40, 0x79, 0x40, 0x79, 0x43, 0xa5, 0x52, 0x0d, 0xa8, 0x6e, 0xd4, 0x58, 0xaa, 0x98, 0xba, - 0x9d, 0x5a, 0x4f, 0xbd, 0x44, 0x7d, 0x4a, 0x7d, 0x2f, 0x47, 0x93, 0x33, 0x97, 0xf3, 0x97, 0xe3, - 0xc9, 0xad, 0x93, 0xab, 0x91, 0x6b, 0x95, 0xeb, 0x97, 0x7b, 0x25, 0x4f, 0x94, 0xd7, 0x97, 0x77, - 0x97, 0x5f, 0x2e, 0x9f, 0x27, 0x5f, 0x21, 0x7f, 0x4a, 0xfe, 0xa6, 0xfc, 0xb8, 0x02, 0x51, 0xc1, - 0x40, 0xc1, 0x53, 0x81, 0xa3, 0xb0, 0x56, 0xa1, 0x46, 0xe1, 0xb4, 0xc2, 0x3d, 0x85, 0x49, 0x45, - 0x9a, 0xa2, 0x95, 0x62, 0x88, 0x62, 0x9a, 0x62, 0x89, 0x62, 0x83, 0xe2, 0x35, 0xc5, 0x51, 0x25, - 0xbc, 0x92, 0x81, 0x92, 0xb7, 0x12, 0x4f, 0xa9, 0x40, 0xe9, 0xb0, 0xd2, 0x25, 0xa5, 0x21, 0x1a, - 0x42, 0xd3, 0xa5, 0x79, 0xd2, 0xb8, 0xb4, 0x4d, 0xb4, 0x3a, 0xda, 0x65, 0xda, 0x30, 0x1d, 0x47, - 0x37, 0xa4, 0xfb, 0xd3, 0x93, 0xe9, 0xc5, 0xf4, 0x1f, 0xe8, 0xbd, 0xf4, 0x09, 0x65, 0x25, 0x65, - 0x5b, 0xe5, 0x28, 0xe5, 0x1c, 0xe5, 0x1a, 0xe5, 0xb3, 0xca, 0x52, 0x06, 0xc2, 0x30, 0x60, 0xf8, - 0x33, 0x52, 0x19, 0xa5, 0x8c, 0x93, 0x8c, 0xbb, 0x8c, 0x8f, 0xf3, 0x34, 0xe6, 0xb9, 0xcf, 0xe3, - 0xcf, 0xdb, 0x36, 0xaf, 0x69, 0x5e, 0xff, 0xbc, 0x29, 0x95, 0xf9, 0x2a, 0x6e, 0x2a, 0x7c, 0x95, - 0x22, 0x95, 0x66, 0x95, 0x01, 0x95, 0x8f, 0xaa, 0x4c, 0x55, 0x6f, 0xd5, 0x14, 0xd5, 0x9d, 0xaa, - 0x6d, 0xaa, 0x4f, 0xd4, 0x30, 0x6a, 0x26, 0x6a, 0x61, 0x6a, 0xd9, 0x6a, 0xfb, 0xd5, 0x2e, 0xab, - 0x8d, 0xcf, 0xa7, 0xcf, 0x77, 0x9e, 0xcf, 0x9d, 0x5f, 0x34, 0xff, 0xe4, 0xfc, 0x87, 0xea, 0xb0, - 0xba, 0x89, 0x7a, 0xb8, 0xfa, 0x6a, 0xf5, 0xc3, 0xea, 0x3d, 0xea, 0x93, 0x1a, 0x9a, 0x1a, 0xbe, - 0x1a, 0x19, 0x1a, 0x55, 0x1a, 0x97, 0x34, 0xc6, 0x35, 0x19, 0x9a, 0x6e, 0x9a, 0xc9, 0x9a, 0xe5, - 0x9a, 0xe7, 0x34, 0xc7, 0xb4, 0x68, 0x5a, 0x0b, 0xb5, 0x04, 0x5a, 0xe5, 0x5a, 0xe7, 0xb5, 0x5e, - 0x30, 0x95, 0x99, 0xee, 0xcc, 0x54, 0x66, 0x25, 0xb3, 0x8b, 0x39, 0xa1, 0xad, 0xae, 0xed, 0xa7, - 0x2d, 0xd1, 0x3e, 0xa4, 0xdd, 0xab, 0x3d, 0xad, 0x63, 0xa8, 0xb3, 0x58, 0x67, 0xa3, 0x4e, 0xb3, - 0xce, 0x13, 0x5d, 0x92, 0x2e, 0x5b, 0x37, 0x41, 0xb7, 0x5c, 0xb7, 0x53, 0x77, 0x42, 0x4f, 0x4b, - 0x2f, 0x58, 0x2f, 0x5f, 0xaf, 0x51, 0xef, 0xa1, 0x3e, 0x51, 0x9f, 0xad, 0x9f, 0xa4, 0xbf, 0x47, - 0xbf, 0x5b, 0x7f, 0xca, 0xc0, 0xd0, 0x20, 0xda, 0x60, 0x8b, 0x41, 0x9b, 0xc1, 0xa8, 0xa1, 0x8a, - 0xa1, 0xbf, 0x61, 0x9e, 0x61, 0xa3, 0xe1, 0x63, 0x23, 0xaa, 0x91, 0xab, 0xd1, 0x2a, 0xa3, 0x5a, - 0xa3, 0x3b, 0xc6, 0x38, 0x63, 0xb6, 0x71, 0x8a, 0xf1, 0x3e, 0xe3, 0x5b, 0x26, 0xb0, 0x89, 0x9d, - 0x49, 0x92, 0x49, 0x8d, 0xc9, 0x4d, 0x53, 0xd8, 0xd4, 0xde, 0x54, 0x60, 0xba, 0xcf, 0xb4, 0xcf, - 0x0c, 0x6b, 0xe6, 0x68, 0x26, 0x34, 0xab, 0x35, 0xbb, 0xc7, 0xa2, 0xb0, 0xdc, 0x59, 0x59, 0xac, - 0x46, 0xd6, 0xa0, 0x39, 0xc3, 0x3c, 0xc8, 0x7c, 0xa3, 0x79, 0x9b, 0xf9, 0x2b, 0x0b, 0x3d, 0x8b, - 0x58, 0x8b, 0x9d, 0x16, 0xdd, 0x16, 0x5f, 0x2c, 0xed, 0x2c, 0x53, 0x2d, 0xeb, 0x2c, 0x1f, 0x59, - 0x29, 0x59, 0x05, 0x58, 0x6d, 0xb4, 0xea, 0xb0, 0xfa, 0xc3, 0xda, 0xc4, 0x9a, 0x6b, 0x5d, 0x63, - 0x7d, 0xc7, 0x86, 0x6a, 0xe3, 0x63, 0xb3, 0xce, 0xa6, 0xdd, 0xe6, 0xb5, 0xad, 0xa9, 0x2d, 0xdf, - 0x76, 0xbf, 0xed, 0x7d, 0x3b, 0x9a, 0x5d, 0xb0, 0xdd, 0x16, 0xbb, 0x4e, 0xbb, 0xcf, 0xf6, 0x0e, - 0xf6, 0x22, 0xfb, 0x26, 0xfb, 0x31, 0x07, 0x3d, 0x87, 0x78, 0x87, 0xbd, 0x0e, 0xf7, 0xd8, 0x74, - 0x76, 0x28, 0xbb, 0x84, 0x7d, 0xd5, 0x11, 0xeb, 0xe8, 0xe1, 0xb8, 0xce, 0xf1, 0x8c, 0xe3, 0x07, - 0x27, 0x7b, 0x27, 0xb1, 0xd3, 0x49, 0xa7, 0xdf, 0x9d, 0x59, 0xce, 0x29, 0xce, 0x0d, 0xce, 0xa3, - 0x0b, 0x0c, 0x17, 0xf0, 0x17, 0xd4, 0x2d, 0x18, 0x72, 0xd1, 0x71, 0xe1, 0xb8, 0x1c, 0x72, 0x91, - 0x2e, 0x64, 0x2e, 0x8c, 0x5f, 0x78, 0x70, 0xa1, 0xd4, 0x55, 0xdb, 0x95, 0xe3, 0x5a, 0xeb, 0xfa, - 0xcc, 0x4d, 0xd7, 0x8d, 0xe7, 0x76, 0xc4, 0x6d, 0xc4, 0xdd, 0xd8, 0x3d, 0xd9, 0xfd, 0xb8, 0xfb, - 0x2b, 0x0f, 0x4b, 0x0f, 0x91, 0x47, 0x8b, 0xc7, 0x94, 0xa7, 0x93, 0xe7, 0x1a, 0xcf, 0x0b, 0x5e, - 0x88, 0x97, 0xaf, 0x57, 0x91, 0x57, 0xaf, 0xb7, 0x92, 0xf7, 0x62, 0xef, 0x6a, 0xef, 0xa7, 0x3e, - 0x3a, 0x3e, 0x89, 0x3e, 0x8d, 0x3e, 0x13, 0xbe, 0x76, 0xbe, 0xab, 0x7d, 0x2f, 0xf8, 0x61, 0xfd, - 0x02, 0xfd, 0x76, 0xfa, 0xdd, 0xf3, 0xd7, 0xf0, 0xe7, 0xfa, 0xd7, 0xfb, 0x4f, 0x04, 0x38, 0x04, - 0xac, 0x09, 0xe8, 0x0a, 0xa4, 0x04, 0x46, 0x04, 0x56, 0x07, 0x3e, 0x0b, 0x32, 0x09, 0x12, 0x05, - 0x75, 0x04, 0xc3, 0xc1, 0x01, 0xc1, 0xbb, 0x82, 0x1f, 0x2f, 0xd2, 0x5f, 0x24, 0x5c, 0xd4, 0x16, - 0x02, 0x42, 0xfc, 0x43, 0x76, 0x85, 0x3c, 0x09, 0x35, 0x0c, 0x5d, 0x15, 0xfa, 0x73, 0x18, 0x2e, - 0x2c, 0x34, 0xac, 0x26, 0xec, 0x79, 0xb8, 0x55, 0x78, 0x7e, 0x78, 0x77, 0x04, 0x2d, 0x62, 0x45, - 0x44, 0x43, 0xc4, 0xbb, 0x48, 0x8f, 0xc8, 0xd2, 0xc8, 0x47, 0x8b, 0x8d, 0x16, 0x4b, 0x16, 0x77, - 0x46, 0xc9, 0x47, 0xc5, 0x45, 0xd5, 0x47, 0x4d, 0x45, 0x7b, 0x45, 0x97, 0x45, 0x4b, 0x97, 0x58, - 0x2c, 0x59, 0xb3, 0xe4, 0x46, 0x8c, 0x5a, 0x8c, 0x20, 0xa6, 0x3d, 0x16, 0x1f, 0x1b, 0x15, 0x7b, - 0x24, 0x76, 0x72, 0xa9, 0xf7, 0xd2, 0xdd, 0x4b, 0x87, 0xe3, 0xec, 0xe2, 0x0a, 0xe3, 0xee, 0x2e, - 0x33, 0x5c, 0x96, 0xb3, 0xec, 0xda, 0x72, 0xb5, 0xe5, 0xa9, 0xcb, 0xcf, 0xae, 0x90, 0x5f, 0xc1, - 0x59, 0x71, 0x2a, 0x1e, 0x1b, 0x1f, 0x1d, 0xdf, 0x10, 0xff, 0x89, 0x13, 0xc2, 0xa9, 0xe5, 0x4c, - 0xae, 0xf4, 0x5f, 0xb9, 0x77, 0xe5, 0x04, 0xd7, 0x93, 0xbb, 0x87, 0xfb, 0x92, 0xe7, 0xc6, 0x2b, - 0xe7, 0x8d, 0xf1, 0x5d, 0xf8, 0x65, 0xfc, 0x91, 0x04, 0x97, 0x84, 0xb2, 0x84, 0xd1, 0x44, 0x97, - 0xc4, 0x5d, 0x89, 0x63, 0x49, 0xae, 0x49, 0x15, 0x49, 0xe3, 0x02, 0x4f, 0x41, 0xb5, 0xe0, 0x75, - 0xb2, 0x5f, 0xf2, 0x81, 0xe4, 0xa9, 0x94, 0x90, 0x94, 0xa3, 0x29, 0x33, 0xa9, 0xd1, 0xa9, 0xcd, - 0x69, 0x84, 0xb4, 0xf8, 0xb4, 0xd3, 0x42, 0x25, 0x61, 0x8a, 0xb0, 0x2b, 0x5d, 0x33, 0x3d, 0x27, - 0xbd, 0x2f, 0xc3, 0x34, 0xa3, 0x30, 0x43, 0xba, 0xca, 0x69, 0xd5, 0xee, 0x55, 0x13, 0xa2, 0x40, - 0xd1, 0x91, 0x4c, 0x28, 0x73, 0x59, 0x66, 0xbb, 0x98, 0x8e, 0xfe, 0x4c, 0xf5, 0x48, 0x8c, 0x24, - 0x9b, 0x25, 0x83, 0x59, 0x0b, 0xb3, 0x6a, 0xb2, 0xde, 0x67, 0x47, 0x65, 0x9f, 0xca, 0x51, 0xcc, - 0x11, 0xe6, 0xf4, 0xe4, 0x9a, 0xe4, 0x6e, 0xcb, 0x1d, 0xc9, 0xf3, 0xc9, 0xfb, 0x7e, 0x35, 0x66, - 0x35, 0x77, 0x75, 0x67, 0xbe, 0x76, 0xfe, 0x86, 0xfc, 0xc1, 0x35, 0xee, 0x6b, 0x0e, 0xad, 0x85, - 0xd6, 0xae, 0x5c, 0xdb, 0xb9, 0x4e, 0x77, 0x5d, 0xc1, 0xba, 0xe1, 0xf5, 0xbe, 0xeb, 0x8f, 0x6d, - 0x20, 0x6d, 0x48, 0xd9, 0xf0, 0xcb, 0x46, 0xcb, 0x8d, 0x65, 0x1b, 0xdf, 0x6e, 0x8a, 0xde, 0xd4, - 0x51, 0xa0, 0x51, 0xb0, 0xbe, 0x60, 0x68, 0xb3, 0xef, 0xe6, 0xc6, 0x42, 0xb9, 0x42, 0x51, 0xe1, - 0xbd, 0x2d, 0xce, 0x5b, 0x0e, 0x6c, 0xc5, 0x6c, 0x15, 0x6c, 0xed, 0xdd, 0x66, 0xb3, 0xad, 0x6a, - 0xdb, 0x97, 0x22, 0x5e, 0xd1, 0xf5, 0x62, 0xcb, 0xe2, 0x8a, 0xe2, 0x4f, 0x25, 0xdc, 0x92, 0xeb, - 0xdf, 0x59, 0x7d, 0x57, 0xf9, 0xdd, 0xcc, 0xf6, 0x84, 0xed, 0xbd, 0xa5, 0xf6, 0xa5, 0xfb, 0x77, - 0xe0, 0x76, 0x08, 0x77, 0xdc, 0xdd, 0xe9, 0xba, 0xf3, 0x58, 0x99, 0x62, 0x59, 0x5e, 0xd9, 0xd0, - 0xae, 0xe0, 0x5d, 0xad, 0xe5, 0xcc, 0xf2, 0xa2, 0xf2, 0xb7, 0xbb, 0x57, 0xec, 0xbe, 0x56, 0x61, - 0x5b, 0x71, 0x60, 0x0f, 0x69, 0x8f, 0x64, 0x8f, 0xb4, 0x32, 0xa8, 0xb2, 0xbd, 0x4a, 0xaf, 0x6a, - 0x47, 0xd5, 0xa7, 0xea, 0xa4, 0xea, 0x81, 0x1a, 0x8f, 0x9a, 0xe6, 0xbd, 0xea, 0x7b, 0xb7, 0xed, - 0x9d, 0xda, 0xc7, 0xdb, 0xd7, 0xbf, 0xdf, 0x6d, 0x7f, 0xd3, 0x01, 0x8d, 0x03, 0xc5, 0x07, 0x3e, - 0x1e, 0x14, 0x1c, 0xbc, 0x7f, 0xc8, 0xf7, 0x50, 0x6b, 0xad, 0x41, 0x6d, 0xc5, 0x61, 0xdc, 0xe1, - 0xac, 0xc3, 0xcf, 0xeb, 0xa2, 0xea, 0xba, 0xbf, 0x67, 0x7f, 0x5f, 0x7f, 0x44, 0xed, 0x48, 0xf1, - 0x91, 0xcf, 0x47, 0x85, 0x47, 0xa5, 0xc7, 0xc2, 0x8f, 0x75, 0xd5, 0x3b, 0xd4, 0xd7, 0x37, 0xa8, - 0x37, 0x94, 0x36, 0xc2, 0x8d, 0x92, 0xc6, 0xb1, 0xe3, 0x71, 0xc7, 0x6f, 0xfd, 0xe0, 0xf5, 0x43, - 0x7b, 0x13, 0xab, 0xe9, 0x50, 0x33, 0xa3, 0xb9, 0xf8, 0x04, 0x38, 0x21, 0x39, 0xf1, 0xe2, 0xc7, - 0xf8, 0x1f, 0xef, 0x9e, 0x0c, 0x3c, 0xd9, 0x79, 0x8a, 0x7d, 0xaa, 0xe9, 0x27, 0xfd, 0x9f, 0xf6, - 0xb6, 0xd0, 0x5a, 0x8a, 0x5a, 0xa1, 0xd6, 0xdc, 0xd6, 0x89, 0xb6, 0xa4, 0x36, 0x69, 0x7b, 0x4c, - 0x7b, 0xdf, 0xe9, 0x80, 0xd3, 0x9d, 0x1d, 0xce, 0x1d, 0x2d, 0x3f, 0x9b, 0xff, 0x7c, 0xf4, 0x8c, - 0xf6, 0x99, 0x9a, 0xb3, 0xca, 0x67, 0x4b, 0xcf, 0x91, 0xce, 0x15, 0x9c, 0x9b, 0x39, 0x9f, 0x77, - 0x7e, 0xf2, 0x42, 0xc6, 0x85, 0xf1, 0x8b, 0x89, 0x17, 0x87, 0x3a, 0x57, 0x74, 0x3e, 0xba, 0xb4, - 0xe4, 0xd2, 0x9d, 0xae, 0xb0, 0xae, 0xde, 0xcb, 0x81, 0x97, 0xaf, 0x5e, 0xf1, 0xb9, 0x72, 0xa9, - 0xdb, 0xbd, 0xfb, 0xfc, 0x55, 0x97, 0xab, 0x67, 0xae, 0x39, 0x5d, 0x3b, 0x7d, 0x9d, 0x7d, 0xbd, - 0xed, 0x86, 0xfd, 0x8d, 0xd6, 0x1e, 0xbb, 0x9e, 0x96, 0x5f, 0xec, 0x7e, 0x69, 0xe9, 0xb5, 0xef, - 0x6d, 0xbd, 0xe9, 0x70, 0xb3, 0xfd, 0x96, 0xe3, 0xad, 0x8e, 0xbe, 0x05, 0x7d, 0xe7, 0xfa, 0x5d, - 0xfb, 0x2f, 0xde, 0xf6, 0xba, 0x7d, 0xe5, 0x8e, 0xff, 0x9d, 0x1b, 0x03, 0x8b, 0x06, 0xfa, 0xee, - 0x2e, 0xbe, 0x7b, 0xff, 0x5e, 0xdc, 0x3d, 0xe9, 0x7d, 0xde, 0xfd, 0xd1, 0x07, 0xa9, 0x0f, 0x5e, - 0x3f, 0xcc, 0x7a, 0x38, 0xfd, 0x68, 0xfd, 0x63, 0xec, 0xe3, 0xa2, 0x27, 0x0a, 0x4f, 0x2a, 0x9e, - 0xaa, 0x3f, 0xad, 0xfd, 0xd5, 0xf8, 0xd7, 0x66, 0xa9, 0xbd, 0xf4, 0xec, 0xa0, 0xd7, 0x60, 0xcf, - 0xb3, 0x88, 0x67, 0x8f, 0x86, 0xb8, 0x43, 0x2f, 0xff, 0x95, 0xf9, 0xaf, 0x4f, 0xc3, 0x05, 0xcf, - 0xa9, 0xcf, 0x2b, 0x46, 0xb4, 0x46, 0xea, 0x47, 0xad, 0x47, 0xcf, 0x8c, 0xf9, 0x8c, 0xdd, 0x7a, - 0xb1, 0xf4, 0xc5, 0xf0, 0xcb, 0x8c, 0x97, 0xd3, 0xe3, 0x85, 0xbf, 0x29, 0xfe, 0xb6, 0xf7, 0x95, - 0xd1, 0xab, 0x9f, 0x7e, 0x77, 0xfb, 0xbd, 0x67, 0x62, 0xc9, 0xc4, 0xf0, 0x6b, 0xd1, 0xeb, 0x99, - 0x3f, 0x4a, 0xde, 0xa8, 0xbe, 0x39, 0xfa, 0xd6, 0xf6, 0x6d, 0xe7, 0x64, 0xe8, 0xe4, 0xd3, 0x77, - 0x69, 0xef, 0xa6, 0xa7, 0x8a, 0xde, 0xab, 0xbe, 0x3f, 0xf6, 0x81, 0xfd, 0xa1, 0xfb, 0x63, 0xf4, - 0xc7, 0x91, 0xe9, 0xec, 0x4f, 0xf8, 0x4f, 0x95, 0x9f, 0x8d, 0x3f, 0x77, 0x7c, 0x09, 0xfc, 0xf2, - 0x78, 0x26, 0x6d, 0x66, 0xe6, 0xdf, 0xf7, 0x84, 0xf3, 0xfb, 0x32, 0x3a, 0x59, 0x7e, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa4, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, - 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, - 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x35, 0x2d, 0x30, 0x32, 0x54, - 0x31, 0x31, 0x3a, 0x30, 0x35, 0x3a, 0x35, 0x35, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, - 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, - 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, - 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, - 0x69, 0x74, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, - 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, - 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x34, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, - 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0xc0, - 0x10, 0xf8, 0x70, 0x00, 0x00, 0x00, 0x10, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1d, 0x63, 0x60, 0x60, - 0x60, 0xf8, 0x0f, 0xc4, 0x70, 0x00, 0x00, 0x0d, 0x04, 0x01, 0x00, 0x65, 0x59, 0x09, 0xe8, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHierarchyIndentPattern2x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe3, 0x00, 0xef, - 0x43, 0x00, 0x00, 0x0a, 0x41, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0x9d, 0x96, 0x77, 0x54, 0x53, 0xd9, 0x16, 0x87, - 0xcf, 0xbd, 0x37, 0xbd, 0xd0, 0x12, 0x22, 0x20, 0x25, 0xf4, 0x1a, 0x7a, 0x09, 0x20, 0xd2, 0x3b, - 0x48, 0x15, 0x04, 0x51, 0x89, 0x49, 0x80, 0x50, 0x02, 0x86, 0x84, 0x26, 0x76, 0x44, 0x05, 0x46, - 0x14, 0x11, 0x29, 0x56, 0x64, 0x54, 0xc0, 0x01, 0x47, 0x87, 0x22, 0x63, 0x45, 0x14, 0x0b, 0x83, - 0x82, 0x62, 0xd7, 0x09, 0xf2, 0x10, 0x50, 0xc6, 0xc1, 0x51, 0x44, 0x45, 0xe5, 0xdd, 0x8c, 0x6b, - 0x09, 0xef, 0xad, 0x35, 0xf3, 0xde, 0x9a, 0xfd, 0xc7, 0x59, 0xdf, 0xd9, 0xe7, 0xb7, 0xd7, 0xd9, - 0x67, 0xef, 0x7d, 0xd7, 0xba, 0x00, 0x50, 0xfc, 0x82, 0x04, 0xc2, 0x74, 0x58, 0x01, 0x80, 0x34, - 0xa1, 0x58, 0x14, 0xee, 0xeb, 0xc1, 0x5c, 0x12, 0x13, 0xcb, 0xc4, 0xf7, 0x02, 0x18, 0x10, 0x01, - 0x0e, 0x58, 0x01, 0xc0, 0xe1, 0x66, 0x66, 0x04, 0x47, 0xf8, 0x44, 0x02, 0xd4, 0xfc, 0xbd, 0x3d, - 0x99, 0x99, 0xa8, 0x48, 0xc6, 0xb3, 0xf6, 0xee, 0x2e, 0x80, 0x64, 0xbb, 0xdb, 0x2c, 0xbf, 0x50, - 0x26, 0x73, 0xd6, 0xff, 0x7f, 0x91, 0x22, 0x37, 0x43, 0x24, 0x06, 0x00, 0x0a, 0x45, 0xd5, 0x36, - 0x3c, 0x7e, 0x26, 0x17, 0xe5, 0x02, 0x94, 0x53, 0xb3, 0xc5, 0x19, 0x32, 0xff, 0x04, 0xca, 0xf4, - 0x95, 0x29, 0x32, 0x86, 0x31, 0x32, 0x16, 0xa1, 0x09, 0xa2, 0xac, 0x22, 0xe3, 0xc4, 0xaf, 0x6c, - 0xf6, 0xa7, 0xe6, 0x2b, 0xbb, 0xc9, 0x98, 0x97, 0x26, 0xe4, 0xa1, 0x1a, 0x59, 0xce, 0x19, 0xbc, - 0x34, 0x9e, 0x8c, 0xbb, 0x50, 0xde, 0x9a, 0x25, 0xe1, 0xa3, 0x8c, 0x04, 0xa1, 0x5c, 0x98, 0x25, - 0xe0, 0x67, 0xa3, 0x7c, 0x07, 0x65, 0xbd, 0x54, 0x49, 0x9a, 0x00, 0xe5, 0xf7, 0x28, 0xd3, 0xd3, - 0xf8, 0x9c, 0x4c, 0x00, 0x30, 0x14, 0x99, 0x5f, 0xcc, 0xe7, 0x26, 0xa1, 0x6c, 0x89, 0x32, 0x45, - 0x14, 0x19, 0xee, 0x89, 0xf2, 0x02, 0x00, 0x08, 0x94, 0xc4, 0x39, 0xbc, 0x72, 0x0e, 0x8b, 0xf9, - 0x39, 0x68, 0x9e, 0x00, 0x78, 0xa6, 0x67, 0xe4, 0x8a, 0x04, 0x89, 0x49, 0x62, 0xa6, 0x11, 0xd7, - 0x98, 0x69, 0xe5, 0xe8, 0xc8, 0x66, 0xfa, 0xf1, 0xb3, 0x53, 0xf9, 0x62, 0x31, 0x2b, 0x94, 0xc3, - 0x4d, 0xe1, 0x88, 0x78, 0x4c, 0xcf, 0xf4, 0xb4, 0x0c, 0x8e, 0x30, 0x17, 0x80, 0xaf, 0x6f, 0x96, - 0x45, 0x01, 0x25, 0x59, 0x6d, 0x99, 0x68, 0x91, 0xed, 0xad, 0x1c, 0xed, 0xed, 0x59, 0xd6, 0xe6, - 0x68, 0xf9, 0xbf, 0xd9, 0xdf, 0x1e, 0x7e, 0x53, 0xfd, 0x3d, 0xc8, 0x7a, 0xfb, 0x55, 0xf1, 0x26, - 0xec, 0xcf, 0x9e, 0x41, 0x8c, 0x9e, 0x59, 0xdf, 0x6c, 0xec, 0xac, 0x2f, 0xbd, 0x16, 0x00, 0xf6, - 0x24, 0x5a, 0x9b, 0x1d, 0xb3, 0xbe, 0x95, 0x55, 0x00, 0xb4, 0x6d, 0x06, 0x40, 0xe5, 0xe1, 0xac, - 0x4f, 0xef, 0x20, 0x00, 0xf2, 0x05, 0x00, 0xb4, 0xde, 0x9c, 0xf3, 0x1e, 0x86, 0x6c, 0x5e, 0x92, - 0xc4, 0xe2, 0x0c, 0x27, 0x0b, 0x8b, 0xec, 0xec, 0x6c, 0x73, 0x01, 0x9f, 0x6b, 0x2e, 0x2b, 0xe8, - 0x37, 0xfb, 0x9f, 0x82, 0x6f, 0xca, 0xbf, 0x86, 0x39, 0xf7, 0x99, 0xcb, 0xee, 0xfb, 0x56, 0x3b, - 0xa6, 0x17, 0x3f, 0x81, 0x23, 0x49, 0x15, 0x33, 0x65, 0x45, 0xe5, 0xa6, 0xa7, 0xa6, 0x4b, 0x44, - 0xcc, 0xcc, 0x0c, 0x0e, 0x97, 0xcf, 0x64, 0xfd, 0xf7, 0x10, 0xff, 0xe3, 0xc0, 0x39, 0x69, 0xcd, - 0xc9, 0xc3, 0x2c, 0x9c, 0x9f, 0xc0, 0x17, 0xf1, 0x85, 0xe8, 0x55, 0x51, 0xe8, 0x94, 0x09, 0x84, - 0x89, 0x68, 0xbb, 0x85, 0x3c, 0x81, 0x58, 0x90, 0x2e, 0x64, 0x0a, 0x84, 0x7f, 0xd5, 0xe1, 0x7f, - 0x18, 0x36, 0x27, 0x07, 0x19, 0x7e, 0x9d, 0x6b, 0x14, 0x68, 0x75, 0x5f, 0x00, 0x7d, 0x85, 0x39, - 0x50, 0xb8, 0x49, 0x07, 0xc8, 0x6f, 0x3d, 0x00, 0x43, 0x23, 0x03, 0x24, 0x6e, 0x3f, 0x7a, 0x02, - 0x7d, 0xeb, 0x5b, 0x10, 0x31, 0x0a, 0xc8, 0xbe, 0xbc, 0x68, 0xad, 0x91, 0xaf, 0x73, 0x8f, 0x32, - 0x7a, 0xfe, 0xe7, 0xfa, 0x1f, 0x0b, 0x5c, 0x8a, 0x6e, 0xe1, 0x4c, 0x41, 0x22, 0x53, 0xe6, 0xf6, - 0x0c, 0x8f, 0x64, 0x72, 0x25, 0xa2, 0x2c, 0x19, 0xa3, 0xdf, 0x84, 0x6c, 0xc1, 0x02, 0x12, 0x90, - 0x07, 0x74, 0xa0, 0x0a, 0x34, 0x81, 0x2e, 0x30, 0x02, 0x2c, 0x60, 0x0d, 0x1c, 0x80, 0x33, 0x70, - 0x03, 0xde, 0x20, 0x00, 0x84, 0x80, 0x48, 0x10, 0x03, 0x96, 0x03, 0x2e, 0x48, 0x02, 0x69, 0x40, - 0x04, 0xb2, 0x41, 0x3e, 0xd8, 0x00, 0x0a, 0x41, 0x31, 0xd8, 0x01, 0x76, 0x83, 0x6a, 0x70, 0x00, - 0xd4, 0x81, 0x7a, 0xd0, 0x04, 0x4e, 0x82, 0x36, 0x70, 0x06, 0x5c, 0x04, 0x57, 0xc0, 0x0d, 0x70, - 0x0b, 0x0c, 0x80, 0x47, 0x40, 0x0a, 0x86, 0xc1, 0x4b, 0x30, 0x01, 0xde, 0x81, 0x69, 0x08, 0x82, - 0xf0, 0x10, 0x15, 0xa2, 0x41, 0xaa, 0x90, 0x16, 0xa4, 0x0f, 0x99, 0x42, 0xd6, 0x10, 0x1b, 0x5a, - 0x08, 0x79, 0x43, 0x41, 0x50, 0x38, 0x14, 0x03, 0xc5, 0x43, 0x89, 0x90, 0x10, 0x92, 0x40, 0xf9, - 0xd0, 0x26, 0xa8, 0x18, 0x2a, 0x83, 0xaa, 0xa1, 0x43, 0x50, 0x3d, 0xf4, 0x23, 0x74, 0x1a, 0xba, - 0x08, 0x5d, 0x83, 0xfa, 0xa0, 0x07, 0xd0, 0x20, 0x34, 0x06, 0xfd, 0x01, 0x7d, 0x84, 0x11, 0x98, - 0x02, 0xd3, 0x61, 0x0d, 0xd8, 0x00, 0xb6, 0x80, 0xd9, 0xb0, 0x3b, 0x1c, 0x08, 0x47, 0xc2, 0xcb, - 0xe0, 0x44, 0x78, 0x15, 0x9c, 0x07, 0x17, 0xc0, 0xdb, 0xe1, 0x4a, 0xb8, 0x16, 0x3e, 0x0e, 0xb7, - 0xc2, 0x17, 0xe1, 0x1b, 0xf0, 0x00, 0x2c, 0x85, 0x5f, 0xc2, 0x93, 0x08, 0x40, 0xc8, 0x08, 0x03, - 0xd1, 0x46, 0x58, 0x08, 0x1b, 0xf1, 0x44, 0x42, 0x90, 0x58, 0x24, 0x01, 0x11, 0x21, 0x6b, 0x91, - 0x22, 0xa4, 0x02, 0xa9, 0x45, 0x9a, 0x90, 0x0e, 0xa4, 0x1b, 0xb9, 0x8d, 0x48, 0x91, 0x71, 0xe4, - 0x03, 0x06, 0x87, 0xa1, 0x61, 0x98, 0x18, 0x16, 0xc6, 0x19, 0xe3, 0x87, 0x59, 0x8c, 0xe1, 0x62, - 0x56, 0x61, 0xd6, 0x62, 0x4a, 0x30, 0xd5, 0x98, 0x63, 0x98, 0x56, 0x4c, 0x17, 0xe6, 0x36, 0x66, - 0x10, 0x33, 0x81, 0xf9, 0x82, 0xa5, 0x62, 0xd5, 0xb1, 0xa6, 0x58, 0x27, 0xac, 0x3f, 0x76, 0x09, - 0x36, 0x11, 0x9b, 0x8d, 0x2d, 0xc4, 0x56, 0x60, 0x8f, 0x60, 0x5b, 0xb0, 0x97, 0xb1, 0x03, 0xd8, - 0x61, 0xec, 0x3b, 0x1c, 0x0e, 0xc7, 0xc0, 0x19, 0xe2, 0x1c, 0x70, 0x7e, 0xb8, 0x18, 0x5c, 0x32, - 0x6e, 0x35, 0xae, 0x04, 0xb7, 0x0f, 0xd7, 0x8c, 0xbb, 0x80, 0xeb, 0xc3, 0x0d, 0xe1, 0x26, 0xf1, - 0x78, 0xbc, 0x2a, 0xde, 0x14, 0xef, 0x82, 0x0f, 0xc1, 0x73, 0xf0, 0x62, 0x7c, 0x21, 0xbe, 0x0a, - 0x7f, 0x1c, 0x7f, 0x1e, 0xdf, 0x8f, 0x1f, 0xc6, 0xbf, 0x27, 0x90, 0x09, 0x5a, 0x04, 0x6b, 0x82, - 0x0f, 0x21, 0x96, 0x20, 0x24, 0x6c, 0x24, 0x54, 0x10, 0x1a, 0x08, 0xe7, 0x08, 0xfd, 0x84, 0x11, - 0xc2, 0x34, 0x51, 0x81, 0xa8, 0x4f, 0x74, 0x22, 0x86, 0x10, 0x79, 0xc4, 0x5c, 0x62, 0x29, 0xb1, - 0x8e, 0xd8, 0x41, 0xbc, 0x49, 0x1c, 0x26, 0x4e, 0x93, 0x14, 0x49, 0x86, 0x24, 0x17, 0x52, 0x24, - 0x29, 0x99, 0xb4, 0x81, 0x54, 0x49, 0x6a, 0x22, 0x5d, 0x26, 0x3d, 0x26, 0xbd, 0x21, 0x93, 0xc9, - 0x3a, 0x64, 0x47, 0x72, 0x18, 0x59, 0x40, 0x5e, 0x4f, 0xae, 0x24, 0x9f, 0x20, 0x5f, 0x25, 0x0f, - 0x92, 0x3f, 0x50, 0x94, 0x28, 0x26, 0x14, 0x4f, 0x4a, 0x1c, 0x45, 0x42, 0xd9, 0x4e, 0x39, 0x4a, - 0xb9, 0x40, 0x79, 0x40, 0x79, 0x43, 0xa5, 0x52, 0x0d, 0xa8, 0x6e, 0xd4, 0x58, 0xaa, 0x98, 0xba, - 0x9d, 0x5a, 0x4f, 0xbd, 0x44, 0x7d, 0x4a, 0x7d, 0x2f, 0x47, 0x93, 0x33, 0x97, 0xf3, 0x97, 0xe3, - 0xc9, 0xad, 0x93, 0xab, 0x91, 0x6b, 0x95, 0xeb, 0x97, 0x7b, 0x25, 0x4f, 0x94, 0xd7, 0x97, 0x77, - 0x97, 0x5f, 0x2e, 0x9f, 0x27, 0x5f, 0x21, 0x7f, 0x4a, 0xfe, 0xa6, 0xfc, 0xb8, 0x02, 0x51, 0xc1, - 0x40, 0xc1, 0x53, 0x81, 0xa3, 0xb0, 0x56, 0xa1, 0x46, 0xe1, 0xb4, 0xc2, 0x3d, 0x85, 0x49, 0x45, - 0x9a, 0xa2, 0x95, 0x62, 0x88, 0x62, 0x9a, 0x62, 0x89, 0x62, 0x83, 0xe2, 0x35, 0xc5, 0x51, 0x25, - 0xbc, 0x92, 0x81, 0x92, 0xb7, 0x12, 0x4f, 0xa9, 0x40, 0xe9, 0xb0, 0xd2, 0x25, 0xa5, 0x21, 0x1a, - 0x42, 0xd3, 0xa5, 0x79, 0xd2, 0xb8, 0xb4, 0x4d, 0xb4, 0x3a, 0xda, 0x65, 0xda, 0x30, 0x1d, 0x47, - 0x37, 0xa4, 0xfb, 0xd3, 0x93, 0xe9, 0xc5, 0xf4, 0x1f, 0xe8, 0xbd, 0xf4, 0x09, 0x65, 0x25, 0x65, - 0x5b, 0xe5, 0x28, 0xe5, 0x1c, 0xe5, 0x1a, 0xe5, 0xb3, 0xca, 0x52, 0x06, 0xc2, 0x30, 0x60, 0xf8, - 0x33, 0x52, 0x19, 0xa5, 0x8c, 0x93, 0x8c, 0xbb, 0x8c, 0x8f, 0xf3, 0x34, 0xe6, 0xb9, 0xcf, 0xe3, - 0xcf, 0xdb, 0x36, 0xaf, 0x69, 0x5e, 0xff, 0xbc, 0x29, 0x95, 0xf9, 0x2a, 0x6e, 0x2a, 0x7c, 0x95, - 0x22, 0x95, 0x66, 0x95, 0x01, 0x95, 0x8f, 0xaa, 0x4c, 0x55, 0x6f, 0xd5, 0x14, 0xd5, 0x9d, 0xaa, - 0x6d, 0xaa, 0x4f, 0xd4, 0x30, 0x6a, 0x26, 0x6a, 0x61, 0x6a, 0xd9, 0x6a, 0xfb, 0xd5, 0x2e, 0xab, - 0x8d, 0xcf, 0xa7, 0xcf, 0x77, 0x9e, 0xcf, 0x9d, 0x5f, 0x34, 0xff, 0xe4, 0xfc, 0x87, 0xea, 0xb0, - 0xba, 0x89, 0x7a, 0xb8, 0xfa, 0x6a, 0xf5, 0xc3, 0xea, 0x3d, 0xea, 0x93, 0x1a, 0x9a, 0x1a, 0xbe, - 0x1a, 0x19, 0x1a, 0x55, 0x1a, 0x97, 0x34, 0xc6, 0x35, 0x19, 0x9a, 0x6e, 0x9a, 0xc9, 0x9a, 0xe5, - 0x9a, 0xe7, 0x34, 0xc7, 0xb4, 0x68, 0x5a, 0x0b, 0xb5, 0x04, 0x5a, 0xe5, 0x5a, 0xe7, 0xb5, 0x5e, - 0x30, 0x95, 0x99, 0xee, 0xcc, 0x54, 0x66, 0x25, 0xb3, 0x8b, 0x39, 0xa1, 0xad, 0xae, 0xed, 0xa7, - 0x2d, 0xd1, 0x3e, 0xa4, 0xdd, 0xab, 0x3d, 0xad, 0x63, 0xa8, 0xb3, 0x58, 0x67, 0xa3, 0x4e, 0xb3, - 0xce, 0x13, 0x5d, 0x92, 0x2e, 0x5b, 0x37, 0x41, 0xb7, 0x5c, 0xb7, 0x53, 0x77, 0x42, 0x4f, 0x4b, - 0x2f, 0x58, 0x2f, 0x5f, 0xaf, 0x51, 0xef, 0xa1, 0x3e, 0x51, 0x9f, 0xad, 0x9f, 0xa4, 0xbf, 0x47, - 0xbf, 0x5b, 0x7f, 0xca, 0xc0, 0xd0, 0x20, 0xda, 0x60, 0x8b, 0x41, 0x9b, 0xc1, 0xa8, 0xa1, 0x8a, - 0xa1, 0xbf, 0x61, 0x9e, 0x61, 0xa3, 0xe1, 0x63, 0x23, 0xaa, 0x91, 0xab, 0xd1, 0x2a, 0xa3, 0x5a, - 0xa3, 0x3b, 0xc6, 0x38, 0x63, 0xb6, 0x71, 0x8a, 0xf1, 0x3e, 0xe3, 0x5b, 0x26, 0xb0, 0x89, 0x9d, - 0x49, 0x92, 0x49, 0x8d, 0xc9, 0x4d, 0x53, 0xd8, 0xd4, 0xde, 0x54, 0x60, 0xba, 0xcf, 0xb4, 0xcf, - 0x0c, 0x6b, 0xe6, 0x68, 0x26, 0x34, 0xab, 0x35, 0xbb, 0xc7, 0xa2, 0xb0, 0xdc, 0x59, 0x59, 0xac, - 0x46, 0xd6, 0xa0, 0x39, 0xc3, 0x3c, 0xc8, 0x7c, 0xa3, 0x79, 0x9b, 0xf9, 0x2b, 0x0b, 0x3d, 0x8b, - 0x58, 0x8b, 0x9d, 0x16, 0xdd, 0x16, 0x5f, 0x2c, 0xed, 0x2c, 0x53, 0x2d, 0xeb, 0x2c, 0x1f, 0x59, - 0x29, 0x59, 0x05, 0x58, 0x6d, 0xb4, 0xea, 0xb0, 0xfa, 0xc3, 0xda, 0xc4, 0x9a, 0x6b, 0x5d, 0x63, - 0x7d, 0xc7, 0x86, 0x6a, 0xe3, 0x63, 0xb3, 0xce, 0xa6, 0xdd, 0xe6, 0xb5, 0xad, 0xa9, 0x2d, 0xdf, - 0x76, 0xbf, 0xed, 0x7d, 0x3b, 0x9a, 0x5d, 0xb0, 0xdd, 0x16, 0xbb, 0x4e, 0xbb, 0xcf, 0xf6, 0x0e, - 0xf6, 0x22, 0xfb, 0x26, 0xfb, 0x31, 0x07, 0x3d, 0x87, 0x78, 0x87, 0xbd, 0x0e, 0xf7, 0xd8, 0x74, - 0x76, 0x28, 0xbb, 0x84, 0x7d, 0xd5, 0x11, 0xeb, 0xe8, 0xe1, 0xb8, 0xce, 0xf1, 0x8c, 0xe3, 0x07, - 0x27, 0x7b, 0x27, 0xb1, 0xd3, 0x49, 0xa7, 0xdf, 0x9d, 0x59, 0xce, 0x29, 0xce, 0x0d, 0xce, 0xa3, - 0x0b, 0x0c, 0x17, 0xf0, 0x17, 0xd4, 0x2d, 0x18, 0x72, 0xd1, 0x71, 0xe1, 0xb8, 0x1c, 0x72, 0x91, - 0x2e, 0x64, 0x2e, 0x8c, 0x5f, 0x78, 0x70, 0xa1, 0xd4, 0x55, 0xdb, 0x95, 0xe3, 0x5a, 0xeb, 0xfa, - 0xcc, 0x4d, 0xd7, 0x8d, 0xe7, 0x76, 0xc4, 0x6d, 0xc4, 0xdd, 0xd8, 0x3d, 0xd9, 0xfd, 0xb8, 0xfb, - 0x2b, 0x0f, 0x4b, 0x0f, 0x91, 0x47, 0x8b, 0xc7, 0x94, 0xa7, 0x93, 0xe7, 0x1a, 0xcf, 0x0b, 0x5e, - 0x88, 0x97, 0xaf, 0x57, 0x91, 0x57, 0xaf, 0xb7, 0x92, 0xf7, 0x62, 0xef, 0x6a, 0xef, 0xa7, 0x3e, - 0x3a, 0x3e, 0x89, 0x3e, 0x8d, 0x3e, 0x13, 0xbe, 0x76, 0xbe, 0xab, 0x7d, 0x2f, 0xf8, 0x61, 0xfd, - 0x02, 0xfd, 0x76, 0xfa, 0xdd, 0xf3, 0xd7, 0xf0, 0xe7, 0xfa, 0xd7, 0xfb, 0x4f, 0x04, 0x38, 0x04, - 0xac, 0x09, 0xe8, 0x0a, 0xa4, 0x04, 0x46, 0x04, 0x56, 0x07, 0x3e, 0x0b, 0x32, 0x09, 0x12, 0x05, - 0x75, 0x04, 0xc3, 0xc1, 0x01, 0xc1, 0xbb, 0x82, 0x1f, 0x2f, 0xd2, 0x5f, 0x24, 0x5c, 0xd4, 0x16, - 0x02, 0x42, 0xfc, 0x43, 0x76, 0x85, 0x3c, 0x09, 0x35, 0x0c, 0x5d, 0x15, 0xfa, 0x73, 0x18, 0x2e, - 0x2c, 0x34, 0xac, 0x26, 0xec, 0x79, 0xb8, 0x55, 0x78, 0x7e, 0x78, 0x77, 0x04, 0x2d, 0x62, 0x45, - 0x44, 0x43, 0xc4, 0xbb, 0x48, 0x8f, 0xc8, 0xd2, 0xc8, 0x47, 0x8b, 0x8d, 0x16, 0x4b, 0x16, 0x77, - 0x46, 0xc9, 0x47, 0xc5, 0x45, 0xd5, 0x47, 0x4d, 0x45, 0x7b, 0x45, 0x97, 0x45, 0x4b, 0x97, 0x58, - 0x2c, 0x59, 0xb3, 0xe4, 0x46, 0x8c, 0x5a, 0x8c, 0x20, 0xa6, 0x3d, 0x16, 0x1f, 0x1b, 0x15, 0x7b, - 0x24, 0x76, 0x72, 0xa9, 0xf7, 0xd2, 0xdd, 0x4b, 0x87, 0xe3, 0xec, 0xe2, 0x0a, 0xe3, 0xee, 0x2e, - 0x33, 0x5c, 0x96, 0xb3, 0xec, 0xda, 0x72, 0xb5, 0xe5, 0xa9, 0xcb, 0xcf, 0xae, 0x90, 0x5f, 0xc1, - 0x59, 0x71, 0x2a, 0x1e, 0x1b, 0x1f, 0x1d, 0xdf, 0x10, 0xff, 0x89, 0x13, 0xc2, 0xa9, 0xe5, 0x4c, - 0xae, 0xf4, 0x5f, 0xb9, 0x77, 0xe5, 0x04, 0xd7, 0x93, 0xbb, 0x87, 0xfb, 0x92, 0xe7, 0xc6, 0x2b, - 0xe7, 0x8d, 0xf1, 0x5d, 0xf8, 0x65, 0xfc, 0x91, 0x04, 0x97, 0x84, 0xb2, 0x84, 0xd1, 0x44, 0x97, - 0xc4, 0x5d, 0x89, 0x63, 0x49, 0xae, 0x49, 0x15, 0x49, 0xe3, 0x02, 0x4f, 0x41, 0xb5, 0xe0, 0x75, - 0xb2, 0x5f, 0xf2, 0x81, 0xe4, 0xa9, 0x94, 0x90, 0x94, 0xa3, 0x29, 0x33, 0xa9, 0xd1, 0xa9, 0xcd, - 0x69, 0x84, 0xb4, 0xf8, 0xb4, 0xd3, 0x42, 0x25, 0x61, 0x8a, 0xb0, 0x2b, 0x5d, 0x33, 0x3d, 0x27, - 0xbd, 0x2f, 0xc3, 0x34, 0xa3, 0x30, 0x43, 0xba, 0xca, 0x69, 0xd5, 0xee, 0x55, 0x13, 0xa2, 0x40, - 0xd1, 0x91, 0x4c, 0x28, 0x73, 0x59, 0x66, 0xbb, 0x98, 0x8e, 0xfe, 0x4c, 0xf5, 0x48, 0x8c, 0x24, - 0x9b, 0x25, 0x83, 0x59, 0x0b, 0xb3, 0x6a, 0xb2, 0xde, 0x67, 0x47, 0x65, 0x9f, 0xca, 0x51, 0xcc, - 0x11, 0xe6, 0xf4, 0xe4, 0x9a, 0xe4, 0x6e, 0xcb, 0x1d, 0xc9, 0xf3, 0xc9, 0xfb, 0x7e, 0x35, 0x66, - 0x35, 0x77, 0x75, 0x67, 0xbe, 0x76, 0xfe, 0x86, 0xfc, 0xc1, 0x35, 0xee, 0x6b, 0x0e, 0xad, 0x85, - 0xd6, 0xae, 0x5c, 0xdb, 0xb9, 0x4e, 0x77, 0x5d, 0xc1, 0xba, 0xe1, 0xf5, 0xbe, 0xeb, 0x8f, 0x6d, - 0x20, 0x6d, 0x48, 0xd9, 0xf0, 0xcb, 0x46, 0xcb, 0x8d, 0x65, 0x1b, 0xdf, 0x6e, 0x8a, 0xde, 0xd4, - 0x51, 0xa0, 0x51, 0xb0, 0xbe, 0x60, 0x68, 0xb3, 0xef, 0xe6, 0xc6, 0x42, 0xb9, 0x42, 0x51, 0xe1, - 0xbd, 0x2d, 0xce, 0x5b, 0x0e, 0x6c, 0xc5, 0x6c, 0x15, 0x6c, 0xed, 0xdd, 0x66, 0xb3, 0xad, 0x6a, - 0xdb, 0x97, 0x22, 0x5e, 0xd1, 0xf5, 0x62, 0xcb, 0xe2, 0x8a, 0xe2, 0x4f, 0x25, 0xdc, 0x92, 0xeb, - 0xdf, 0x59, 0x7d, 0x57, 0xf9, 0xdd, 0xcc, 0xf6, 0x84, 0xed, 0xbd, 0xa5, 0xf6, 0xa5, 0xfb, 0x77, - 0xe0, 0x76, 0x08, 0x77, 0xdc, 0xdd, 0xe9, 0xba, 0xf3, 0x58, 0x99, 0x62, 0x59, 0x5e, 0xd9, 0xd0, - 0xae, 0xe0, 0x5d, 0xad, 0xe5, 0xcc, 0xf2, 0xa2, 0xf2, 0xb7, 0xbb, 0x57, 0xec, 0xbe, 0x56, 0x61, - 0x5b, 0x71, 0x60, 0x0f, 0x69, 0x8f, 0x64, 0x8f, 0xb4, 0x32, 0xa8, 0xb2, 0xbd, 0x4a, 0xaf, 0x6a, - 0x47, 0xd5, 0xa7, 0xea, 0xa4, 0xea, 0x81, 0x1a, 0x8f, 0x9a, 0xe6, 0xbd, 0xea, 0x7b, 0xb7, 0xed, - 0x9d, 0xda, 0xc7, 0xdb, 0xd7, 0xbf, 0xdf, 0x6d, 0x7f, 0xd3, 0x01, 0x8d, 0x03, 0xc5, 0x07, 0x3e, - 0x1e, 0x14, 0x1c, 0xbc, 0x7f, 0xc8, 0xf7, 0x50, 0x6b, 0xad, 0x41, 0x6d, 0xc5, 0x61, 0xdc, 0xe1, - 0xac, 0xc3, 0xcf, 0xeb, 0xa2, 0xea, 0xba, 0xbf, 0x67, 0x7f, 0x5f, 0x7f, 0x44, 0xed, 0x48, 0xf1, - 0x91, 0xcf, 0x47, 0x85, 0x47, 0xa5, 0xc7, 0xc2, 0x8f, 0x75, 0xd5, 0x3b, 0xd4, 0xd7, 0x37, 0xa8, - 0x37, 0x94, 0x36, 0xc2, 0x8d, 0x92, 0xc6, 0xb1, 0xe3, 0x71, 0xc7, 0x6f, 0xfd, 0xe0, 0xf5, 0x43, - 0x7b, 0x13, 0xab, 0xe9, 0x50, 0x33, 0xa3, 0xb9, 0xf8, 0x04, 0x38, 0x21, 0x39, 0xf1, 0xe2, 0xc7, - 0xf8, 0x1f, 0xef, 0x9e, 0x0c, 0x3c, 0xd9, 0x79, 0x8a, 0x7d, 0xaa, 0xe9, 0x27, 0xfd, 0x9f, 0xf6, - 0xb6, 0xd0, 0x5a, 0x8a, 0x5a, 0xa1, 0xd6, 0xdc, 0xd6, 0x89, 0xb6, 0xa4, 0x36, 0x69, 0x7b, 0x4c, - 0x7b, 0xdf, 0xe9, 0x80, 0xd3, 0x9d, 0x1d, 0xce, 0x1d, 0x2d, 0x3f, 0x9b, 0xff, 0x7c, 0xf4, 0x8c, - 0xf6, 0x99, 0x9a, 0xb3, 0xca, 0x67, 0x4b, 0xcf, 0x91, 0xce, 0x15, 0x9c, 0x9b, 0x39, 0x9f, 0x77, - 0x7e, 0xf2, 0x42, 0xc6, 0x85, 0xf1, 0x8b, 0x89, 0x17, 0x87, 0x3a, 0x57, 0x74, 0x3e, 0xba, 0xb4, - 0xe4, 0xd2, 0x9d, 0xae, 0xb0, 0xae, 0xde, 0xcb, 0x81, 0x97, 0xaf, 0x5e, 0xf1, 0xb9, 0x72, 0xa9, - 0xdb, 0xbd, 0xfb, 0xfc, 0x55, 0x97, 0xab, 0x67, 0xae, 0x39, 0x5d, 0x3b, 0x7d, 0x9d, 0x7d, 0xbd, - 0xed, 0x86, 0xfd, 0x8d, 0xd6, 0x1e, 0xbb, 0x9e, 0x96, 0x5f, 0xec, 0x7e, 0x69, 0xe9, 0xb5, 0xef, - 0x6d, 0xbd, 0xe9, 0x70, 0xb3, 0xfd, 0x96, 0xe3, 0xad, 0x8e, 0xbe, 0x05, 0x7d, 0xe7, 0xfa, 0x5d, - 0xfb, 0x2f, 0xde, 0xf6, 0xba, 0x7d, 0xe5, 0x8e, 0xff, 0x9d, 0x1b, 0x03, 0x8b, 0x06, 0xfa, 0xee, - 0x2e, 0xbe, 0x7b, 0xff, 0x5e, 0xdc, 0x3d, 0xe9, 0x7d, 0xde, 0xfd, 0xd1, 0x07, 0xa9, 0x0f, 0x5e, - 0x3f, 0xcc, 0x7a, 0x38, 0xfd, 0x68, 0xfd, 0x63, 0xec, 0xe3, 0xa2, 0x27, 0x0a, 0x4f, 0x2a, 0x9e, - 0xaa, 0x3f, 0xad, 0xfd, 0xd5, 0xf8, 0xd7, 0x66, 0xa9, 0xbd, 0xf4, 0xec, 0xa0, 0xd7, 0x60, 0xcf, - 0xb3, 0x88, 0x67, 0x8f, 0x86, 0xb8, 0x43, 0x2f, 0xff, 0x95, 0xf9, 0xaf, 0x4f, 0xc3, 0x05, 0xcf, - 0xa9, 0xcf, 0x2b, 0x46, 0xb4, 0x46, 0xea, 0x47, 0xad, 0x47, 0xcf, 0x8c, 0xf9, 0x8c, 0xdd, 0x7a, - 0xb1, 0xf4, 0xc5, 0xf0, 0xcb, 0x8c, 0x97, 0xd3, 0xe3, 0x85, 0xbf, 0x29, 0xfe, 0xb6, 0xf7, 0x95, - 0xd1, 0xab, 0x9f, 0x7e, 0x77, 0xfb, 0xbd, 0x67, 0x62, 0xc9, 0xc4, 0xf0, 0x6b, 0xd1, 0xeb, 0x99, - 0x3f, 0x4a, 0xde, 0xa8, 0xbe, 0x39, 0xfa, 0xd6, 0xf6, 0x6d, 0xe7, 0x64, 0xe8, 0xe4, 0xd3, 0x77, - 0x69, 0xef, 0xa6, 0xa7, 0x8a, 0xde, 0xab, 0xbe, 0x3f, 0xf6, 0x81, 0xfd, 0xa1, 0xfb, 0x63, 0xf4, - 0xc7, 0x91, 0xe9, 0xec, 0x4f, 0xf8, 0x4f, 0x95, 0x9f, 0x8d, 0x3f, 0x77, 0x7c, 0x09, 0xfc, 0xf2, - 0x78, 0x26, 0x6d, 0x66, 0xe6, 0xdf, 0xf7, 0x84, 0xf3, 0xfb, 0x32, 0x3a, 0x59, 0x7e, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa4, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, - 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, - 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x35, 0x2d, 0x30, 0x32, 0x54, - 0x31, 0x31, 0x3a, 0x30, 0x35, 0x3a, 0x30, 0x36, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, - 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, - 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, - 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, - 0x69, 0x74, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, - 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, - 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x38, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, - 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x90, - 0x7a, 0xe1, 0x8d, 0x00, 0x00, 0x00, 0x12, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1d, 0x63, 0x60, 0x60, - 0x60, 0xf8, 0x0f, 0xc5, 0x40, 0x0a, 0x13, 0x00, 0x00, 0x35, 0xeb, 0x01, 0xff, 0x0f, 0x5e, 0xbc, - 0xf4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -static const u_int8_t FLEXHierarchyIndentPattern3x[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe3, 0x00, 0xef, - 0x43, 0x00, 0x00, 0x0a, 0x41, 0x69, 0x43, 0x43, 0x50, 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x48, 0x0d, 0x9d, 0x96, 0x77, 0x54, 0x53, 0xd9, 0x16, 0x87, - 0xcf, 0xbd, 0x37, 0xbd, 0xd0, 0x12, 0x22, 0x20, 0x25, 0xf4, 0x1a, 0x7a, 0x09, 0x20, 0xd2, 0x3b, - 0x48, 0x15, 0x04, 0x51, 0x89, 0x49, 0x80, 0x50, 0x02, 0x86, 0x84, 0x26, 0x76, 0x44, 0x05, 0x46, - 0x14, 0x11, 0x29, 0x56, 0x64, 0x54, 0xc0, 0x01, 0x47, 0x87, 0x22, 0x63, 0x45, 0x14, 0x0b, 0x83, - 0x82, 0x62, 0xd7, 0x09, 0xf2, 0x10, 0x50, 0xc6, 0xc1, 0x51, 0x44, 0x45, 0xe5, 0xdd, 0x8c, 0x6b, - 0x09, 0xef, 0xad, 0x35, 0xf3, 0xde, 0x9a, 0xfd, 0xc7, 0x59, 0xdf, 0xd9, 0xe7, 0xb7, 0xd7, 0xd9, - 0x67, 0xef, 0x7d, 0xd7, 0xba, 0x00, 0x50, 0xfc, 0x82, 0x04, 0xc2, 0x74, 0x58, 0x01, 0x80, 0x34, - 0xa1, 0x58, 0x14, 0xee, 0xeb, 0xc1, 0x5c, 0x12, 0x13, 0xcb, 0xc4, 0xf7, 0x02, 0x18, 0x10, 0x01, - 0x0e, 0x58, 0x01, 0xc0, 0xe1, 0x66, 0x66, 0x04, 0x47, 0xf8, 0x44, 0x02, 0xd4, 0xfc, 0xbd, 0x3d, - 0x99, 0x99, 0xa8, 0x48, 0xc6, 0xb3, 0xf6, 0xee, 0x2e, 0x80, 0x64, 0xbb, 0xdb, 0x2c, 0xbf, 0x50, - 0x26, 0x73, 0xd6, 0xff, 0x7f, 0x91, 0x22, 0x37, 0x43, 0x24, 0x06, 0x00, 0x0a, 0x45, 0xd5, 0x36, - 0x3c, 0x7e, 0x26, 0x17, 0xe5, 0x02, 0x94, 0x53, 0xb3, 0xc5, 0x19, 0x32, 0xff, 0x04, 0xca, 0xf4, - 0x95, 0x29, 0x32, 0x86, 0x31, 0x32, 0x16, 0xa1, 0x09, 0xa2, 0xac, 0x22, 0xe3, 0xc4, 0xaf, 0x6c, - 0xf6, 0xa7, 0xe6, 0x2b, 0xbb, 0xc9, 0x98, 0x97, 0x26, 0xe4, 0xa1, 0x1a, 0x59, 0xce, 0x19, 0xbc, - 0x34, 0x9e, 0x8c, 0xbb, 0x50, 0xde, 0x9a, 0x25, 0xe1, 0xa3, 0x8c, 0x04, 0xa1, 0x5c, 0x98, 0x25, - 0xe0, 0x67, 0xa3, 0x7c, 0x07, 0x65, 0xbd, 0x54, 0x49, 0x9a, 0x00, 0xe5, 0xf7, 0x28, 0xd3, 0xd3, - 0xf8, 0x9c, 0x4c, 0x00, 0x30, 0x14, 0x99, 0x5f, 0xcc, 0xe7, 0x26, 0xa1, 0x6c, 0x89, 0x32, 0x45, - 0x14, 0x19, 0xee, 0x89, 0xf2, 0x02, 0x00, 0x08, 0x94, 0xc4, 0x39, 0xbc, 0x72, 0x0e, 0x8b, 0xf9, - 0x39, 0x68, 0x9e, 0x00, 0x78, 0xa6, 0x67, 0xe4, 0x8a, 0x04, 0x89, 0x49, 0x62, 0xa6, 0x11, 0xd7, - 0x98, 0x69, 0xe5, 0xe8, 0xc8, 0x66, 0xfa, 0xf1, 0xb3, 0x53, 0xf9, 0x62, 0x31, 0x2b, 0x94, 0xc3, - 0x4d, 0xe1, 0x88, 0x78, 0x4c, 0xcf, 0xf4, 0xb4, 0x0c, 0x8e, 0x30, 0x17, 0x80, 0xaf, 0x6f, 0x96, - 0x45, 0x01, 0x25, 0x59, 0x6d, 0x99, 0x68, 0x91, 0xed, 0xad, 0x1c, 0xed, 0xed, 0x59, 0xd6, 0xe6, - 0x68, 0xf9, 0xbf, 0xd9, 0xdf, 0x1e, 0x7e, 0x53, 0xfd, 0x3d, 0xc8, 0x7a, 0xfb, 0x55, 0xf1, 0x26, - 0xec, 0xcf, 0x9e, 0x41, 0x8c, 0x9e, 0x59, 0xdf, 0x6c, 0xec, 0xac, 0x2f, 0xbd, 0x16, 0x00, 0xf6, - 0x24, 0x5a, 0x9b, 0x1d, 0xb3, 0xbe, 0x95, 0x55, 0x00, 0xb4, 0x6d, 0x06, 0x40, 0xe5, 0xe1, 0xac, - 0x4f, 0xef, 0x20, 0x00, 0xf2, 0x05, 0x00, 0xb4, 0xde, 0x9c, 0xf3, 0x1e, 0x86, 0x6c, 0x5e, 0x92, - 0xc4, 0xe2, 0x0c, 0x27, 0x0b, 0x8b, 0xec, 0xec, 0x6c, 0x73, 0x01, 0x9f, 0x6b, 0x2e, 0x2b, 0xe8, - 0x37, 0xfb, 0x9f, 0x82, 0x6f, 0xca, 0xbf, 0x86, 0x39, 0xf7, 0x99, 0xcb, 0xee, 0xfb, 0x56, 0x3b, - 0xa6, 0x17, 0x3f, 0x81, 0x23, 0x49, 0x15, 0x33, 0x65, 0x45, 0xe5, 0xa6, 0xa7, 0xa6, 0x4b, 0x44, - 0xcc, 0xcc, 0x0c, 0x0e, 0x97, 0xcf, 0x64, 0xfd, 0xf7, 0x10, 0xff, 0xe3, 0xc0, 0x39, 0x69, 0xcd, - 0xc9, 0xc3, 0x2c, 0x9c, 0x9f, 0xc0, 0x17, 0xf1, 0x85, 0xe8, 0x55, 0x51, 0xe8, 0x94, 0x09, 0x84, - 0x89, 0x68, 0xbb, 0x85, 0x3c, 0x81, 0x58, 0x90, 0x2e, 0x64, 0x0a, 0x84, 0x7f, 0xd5, 0xe1, 0x7f, - 0x18, 0x36, 0x27, 0x07, 0x19, 0x7e, 0x9d, 0x6b, 0x14, 0x68, 0x75, 0x5f, 0x00, 0x7d, 0x85, 0x39, - 0x50, 0xb8, 0x49, 0x07, 0xc8, 0x6f, 0x3d, 0x00, 0x43, 0x23, 0x03, 0x24, 0x6e, 0x3f, 0x7a, 0x02, - 0x7d, 0xeb, 0x5b, 0x10, 0x31, 0x0a, 0xc8, 0xbe, 0xbc, 0x68, 0xad, 0x91, 0xaf, 0x73, 0x8f, 0x32, - 0x7a, 0xfe, 0xe7, 0xfa, 0x1f, 0x0b, 0x5c, 0x8a, 0x6e, 0xe1, 0x4c, 0x41, 0x22, 0x53, 0xe6, 0xf6, - 0x0c, 0x8f, 0x64, 0x72, 0x25, 0xa2, 0x2c, 0x19, 0xa3, 0xdf, 0x84, 0x6c, 0xc1, 0x02, 0x12, 0x90, - 0x07, 0x74, 0xa0, 0x0a, 0x34, 0x81, 0x2e, 0x30, 0x02, 0x2c, 0x60, 0x0d, 0x1c, 0x80, 0x33, 0x70, - 0x03, 0xde, 0x20, 0x00, 0x84, 0x80, 0x48, 0x10, 0x03, 0x96, 0x03, 0x2e, 0x48, 0x02, 0x69, 0x40, - 0x04, 0xb2, 0x41, 0x3e, 0xd8, 0x00, 0x0a, 0x41, 0x31, 0xd8, 0x01, 0x76, 0x83, 0x6a, 0x70, 0x00, - 0xd4, 0x81, 0x7a, 0xd0, 0x04, 0x4e, 0x82, 0x36, 0x70, 0x06, 0x5c, 0x04, 0x57, 0xc0, 0x0d, 0x70, - 0x0b, 0x0c, 0x80, 0x47, 0x40, 0x0a, 0x86, 0xc1, 0x4b, 0x30, 0x01, 0xde, 0x81, 0x69, 0x08, 0x82, - 0xf0, 0x10, 0x15, 0xa2, 0x41, 0xaa, 0x90, 0x16, 0xa4, 0x0f, 0x99, 0x42, 0xd6, 0x10, 0x1b, 0x5a, - 0x08, 0x79, 0x43, 0x41, 0x50, 0x38, 0x14, 0x03, 0xc5, 0x43, 0x89, 0x90, 0x10, 0x92, 0x40, 0xf9, - 0xd0, 0x26, 0xa8, 0x18, 0x2a, 0x83, 0xaa, 0xa1, 0x43, 0x50, 0x3d, 0xf4, 0x23, 0x74, 0x1a, 0xba, - 0x08, 0x5d, 0x83, 0xfa, 0xa0, 0x07, 0xd0, 0x20, 0x34, 0x06, 0xfd, 0x01, 0x7d, 0x84, 0x11, 0x98, - 0x02, 0xd3, 0x61, 0x0d, 0xd8, 0x00, 0xb6, 0x80, 0xd9, 0xb0, 0x3b, 0x1c, 0x08, 0x47, 0xc2, 0xcb, - 0xe0, 0x44, 0x78, 0x15, 0x9c, 0x07, 0x17, 0xc0, 0xdb, 0xe1, 0x4a, 0xb8, 0x16, 0x3e, 0x0e, 0xb7, - 0xc2, 0x17, 0xe1, 0x1b, 0xf0, 0x00, 0x2c, 0x85, 0x5f, 0xc2, 0x93, 0x08, 0x40, 0xc8, 0x08, 0x03, - 0xd1, 0x46, 0x58, 0x08, 0x1b, 0xf1, 0x44, 0x42, 0x90, 0x58, 0x24, 0x01, 0x11, 0x21, 0x6b, 0x91, - 0x22, 0xa4, 0x02, 0xa9, 0x45, 0x9a, 0x90, 0x0e, 0xa4, 0x1b, 0xb9, 0x8d, 0x48, 0x91, 0x71, 0xe4, - 0x03, 0x06, 0x87, 0xa1, 0x61, 0x98, 0x18, 0x16, 0xc6, 0x19, 0xe3, 0x87, 0x59, 0x8c, 0xe1, 0x62, - 0x56, 0x61, 0xd6, 0x62, 0x4a, 0x30, 0xd5, 0x98, 0x63, 0x98, 0x56, 0x4c, 0x17, 0xe6, 0x36, 0x66, - 0x10, 0x33, 0x81, 0xf9, 0x82, 0xa5, 0x62, 0xd5, 0xb1, 0xa6, 0x58, 0x27, 0xac, 0x3f, 0x76, 0x09, - 0x36, 0x11, 0x9b, 0x8d, 0x2d, 0xc4, 0x56, 0x60, 0x8f, 0x60, 0x5b, 0xb0, 0x97, 0xb1, 0x03, 0xd8, - 0x61, 0xec, 0x3b, 0x1c, 0x0e, 0xc7, 0xc0, 0x19, 0xe2, 0x1c, 0x70, 0x7e, 0xb8, 0x18, 0x5c, 0x32, - 0x6e, 0x35, 0xae, 0x04, 0xb7, 0x0f, 0xd7, 0x8c, 0xbb, 0x80, 0xeb, 0xc3, 0x0d, 0xe1, 0x26, 0xf1, - 0x78, 0xbc, 0x2a, 0xde, 0x14, 0xef, 0x82, 0x0f, 0xc1, 0x73, 0xf0, 0x62, 0x7c, 0x21, 0xbe, 0x0a, - 0x7f, 0x1c, 0x7f, 0x1e, 0xdf, 0x8f, 0x1f, 0xc6, 0xbf, 0x27, 0x90, 0x09, 0x5a, 0x04, 0x6b, 0x82, - 0x0f, 0x21, 0x96, 0x20, 0x24, 0x6c, 0x24, 0x54, 0x10, 0x1a, 0x08, 0xe7, 0x08, 0xfd, 0x84, 0x11, - 0xc2, 0x34, 0x51, 0x81, 0xa8, 0x4f, 0x74, 0x22, 0x86, 0x10, 0x79, 0xc4, 0x5c, 0x62, 0x29, 0xb1, - 0x8e, 0xd8, 0x41, 0xbc, 0x49, 0x1c, 0x26, 0x4e, 0x93, 0x14, 0x49, 0x86, 0x24, 0x17, 0x52, 0x24, - 0x29, 0x99, 0xb4, 0x81, 0x54, 0x49, 0x6a, 0x22, 0x5d, 0x26, 0x3d, 0x26, 0xbd, 0x21, 0x93, 0xc9, - 0x3a, 0x64, 0x47, 0x72, 0x18, 0x59, 0x40, 0x5e, 0x4f, 0xae, 0x24, 0x9f, 0x20, 0x5f, 0x25, 0x0f, - 0x92, 0x3f, 0x50, 0x94, 0x28, 0x26, 0x14, 0x4f, 0x4a, 0x1c, 0x45, 0x42, 0xd9, 0x4e, 0x39, 0x4a, - 0xb9, 0x40, 0x79, 0x40, 0x79, 0x43, 0xa5, 0x52, 0x0d, 0xa8, 0x6e, 0xd4, 0x58, 0xaa, 0x98, 0xba, - 0x9d, 0x5a, 0x4f, 0xbd, 0x44, 0x7d, 0x4a, 0x7d, 0x2f, 0x47, 0x93, 0x33, 0x97, 0xf3, 0x97, 0xe3, - 0xc9, 0xad, 0x93, 0xab, 0x91, 0x6b, 0x95, 0xeb, 0x97, 0x7b, 0x25, 0x4f, 0x94, 0xd7, 0x97, 0x77, - 0x97, 0x5f, 0x2e, 0x9f, 0x27, 0x5f, 0x21, 0x7f, 0x4a, 0xfe, 0xa6, 0xfc, 0xb8, 0x02, 0x51, 0xc1, - 0x40, 0xc1, 0x53, 0x81, 0xa3, 0xb0, 0x56, 0xa1, 0x46, 0xe1, 0xb4, 0xc2, 0x3d, 0x85, 0x49, 0x45, - 0x9a, 0xa2, 0x95, 0x62, 0x88, 0x62, 0x9a, 0x62, 0x89, 0x62, 0x83, 0xe2, 0x35, 0xc5, 0x51, 0x25, - 0xbc, 0x92, 0x81, 0x92, 0xb7, 0x12, 0x4f, 0xa9, 0x40, 0xe9, 0xb0, 0xd2, 0x25, 0xa5, 0x21, 0x1a, - 0x42, 0xd3, 0xa5, 0x79, 0xd2, 0xb8, 0xb4, 0x4d, 0xb4, 0x3a, 0xda, 0x65, 0xda, 0x30, 0x1d, 0x47, - 0x37, 0xa4, 0xfb, 0xd3, 0x93, 0xe9, 0xc5, 0xf4, 0x1f, 0xe8, 0xbd, 0xf4, 0x09, 0x65, 0x25, 0x65, - 0x5b, 0xe5, 0x28, 0xe5, 0x1c, 0xe5, 0x1a, 0xe5, 0xb3, 0xca, 0x52, 0x06, 0xc2, 0x30, 0x60, 0xf8, - 0x33, 0x52, 0x19, 0xa5, 0x8c, 0x93, 0x8c, 0xbb, 0x8c, 0x8f, 0xf3, 0x34, 0xe6, 0xb9, 0xcf, 0xe3, - 0xcf, 0xdb, 0x36, 0xaf, 0x69, 0x5e, 0xff, 0xbc, 0x29, 0x95, 0xf9, 0x2a, 0x6e, 0x2a, 0x7c, 0x95, - 0x22, 0x95, 0x66, 0x95, 0x01, 0x95, 0x8f, 0xaa, 0x4c, 0x55, 0x6f, 0xd5, 0x14, 0xd5, 0x9d, 0xaa, - 0x6d, 0xaa, 0x4f, 0xd4, 0x30, 0x6a, 0x26, 0x6a, 0x61, 0x6a, 0xd9, 0x6a, 0xfb, 0xd5, 0x2e, 0xab, - 0x8d, 0xcf, 0xa7, 0xcf, 0x77, 0x9e, 0xcf, 0x9d, 0x5f, 0x34, 0xff, 0xe4, 0xfc, 0x87, 0xea, 0xb0, - 0xba, 0x89, 0x7a, 0xb8, 0xfa, 0x6a, 0xf5, 0xc3, 0xea, 0x3d, 0xea, 0x93, 0x1a, 0x9a, 0x1a, 0xbe, - 0x1a, 0x19, 0x1a, 0x55, 0x1a, 0x97, 0x34, 0xc6, 0x35, 0x19, 0x9a, 0x6e, 0x9a, 0xc9, 0x9a, 0xe5, - 0x9a, 0xe7, 0x34, 0xc7, 0xb4, 0x68, 0x5a, 0x0b, 0xb5, 0x04, 0x5a, 0xe5, 0x5a, 0xe7, 0xb5, 0x5e, - 0x30, 0x95, 0x99, 0xee, 0xcc, 0x54, 0x66, 0x25, 0xb3, 0x8b, 0x39, 0xa1, 0xad, 0xae, 0xed, 0xa7, - 0x2d, 0xd1, 0x3e, 0xa4, 0xdd, 0xab, 0x3d, 0xad, 0x63, 0xa8, 0xb3, 0x58, 0x67, 0xa3, 0x4e, 0xb3, - 0xce, 0x13, 0x5d, 0x92, 0x2e, 0x5b, 0x37, 0x41, 0xb7, 0x5c, 0xb7, 0x53, 0x77, 0x42, 0x4f, 0x4b, - 0x2f, 0x58, 0x2f, 0x5f, 0xaf, 0x51, 0xef, 0xa1, 0x3e, 0x51, 0x9f, 0xad, 0x9f, 0xa4, 0xbf, 0x47, - 0xbf, 0x5b, 0x7f, 0xca, 0xc0, 0xd0, 0x20, 0xda, 0x60, 0x8b, 0x41, 0x9b, 0xc1, 0xa8, 0xa1, 0x8a, - 0xa1, 0xbf, 0x61, 0x9e, 0x61, 0xa3, 0xe1, 0x63, 0x23, 0xaa, 0x91, 0xab, 0xd1, 0x2a, 0xa3, 0x5a, - 0xa3, 0x3b, 0xc6, 0x38, 0x63, 0xb6, 0x71, 0x8a, 0xf1, 0x3e, 0xe3, 0x5b, 0x26, 0xb0, 0x89, 0x9d, - 0x49, 0x92, 0x49, 0x8d, 0xc9, 0x4d, 0x53, 0xd8, 0xd4, 0xde, 0x54, 0x60, 0xba, 0xcf, 0xb4, 0xcf, - 0x0c, 0x6b, 0xe6, 0x68, 0x26, 0x34, 0xab, 0x35, 0xbb, 0xc7, 0xa2, 0xb0, 0xdc, 0x59, 0x59, 0xac, - 0x46, 0xd6, 0xa0, 0x39, 0xc3, 0x3c, 0xc8, 0x7c, 0xa3, 0x79, 0x9b, 0xf9, 0x2b, 0x0b, 0x3d, 0x8b, - 0x58, 0x8b, 0x9d, 0x16, 0xdd, 0x16, 0x5f, 0x2c, 0xed, 0x2c, 0x53, 0x2d, 0xeb, 0x2c, 0x1f, 0x59, - 0x29, 0x59, 0x05, 0x58, 0x6d, 0xb4, 0xea, 0xb0, 0xfa, 0xc3, 0xda, 0xc4, 0x9a, 0x6b, 0x5d, 0x63, - 0x7d, 0xc7, 0x86, 0x6a, 0xe3, 0x63, 0xb3, 0xce, 0xa6, 0xdd, 0xe6, 0xb5, 0xad, 0xa9, 0x2d, 0xdf, - 0x76, 0xbf, 0xed, 0x7d, 0x3b, 0x9a, 0x5d, 0xb0, 0xdd, 0x16, 0xbb, 0x4e, 0xbb, 0xcf, 0xf6, 0x0e, - 0xf6, 0x22, 0xfb, 0x26, 0xfb, 0x31, 0x07, 0x3d, 0x87, 0x78, 0x87, 0xbd, 0x0e, 0xf7, 0xd8, 0x74, - 0x76, 0x28, 0xbb, 0x84, 0x7d, 0xd5, 0x11, 0xeb, 0xe8, 0xe1, 0xb8, 0xce, 0xf1, 0x8c, 0xe3, 0x07, - 0x27, 0x7b, 0x27, 0xb1, 0xd3, 0x49, 0xa7, 0xdf, 0x9d, 0x59, 0xce, 0x29, 0xce, 0x0d, 0xce, 0xa3, - 0x0b, 0x0c, 0x17, 0xf0, 0x17, 0xd4, 0x2d, 0x18, 0x72, 0xd1, 0x71, 0xe1, 0xb8, 0x1c, 0x72, 0x91, - 0x2e, 0x64, 0x2e, 0x8c, 0x5f, 0x78, 0x70, 0xa1, 0xd4, 0x55, 0xdb, 0x95, 0xe3, 0x5a, 0xeb, 0xfa, - 0xcc, 0x4d, 0xd7, 0x8d, 0xe7, 0x76, 0xc4, 0x6d, 0xc4, 0xdd, 0xd8, 0x3d, 0xd9, 0xfd, 0xb8, 0xfb, - 0x2b, 0x0f, 0x4b, 0x0f, 0x91, 0x47, 0x8b, 0xc7, 0x94, 0xa7, 0x93, 0xe7, 0x1a, 0xcf, 0x0b, 0x5e, - 0x88, 0x97, 0xaf, 0x57, 0x91, 0x57, 0xaf, 0xb7, 0x92, 0xf7, 0x62, 0xef, 0x6a, 0xef, 0xa7, 0x3e, - 0x3a, 0x3e, 0x89, 0x3e, 0x8d, 0x3e, 0x13, 0xbe, 0x76, 0xbe, 0xab, 0x7d, 0x2f, 0xf8, 0x61, 0xfd, - 0x02, 0xfd, 0x76, 0xfa, 0xdd, 0xf3, 0xd7, 0xf0, 0xe7, 0xfa, 0xd7, 0xfb, 0x4f, 0x04, 0x38, 0x04, - 0xac, 0x09, 0xe8, 0x0a, 0xa4, 0x04, 0x46, 0x04, 0x56, 0x07, 0x3e, 0x0b, 0x32, 0x09, 0x12, 0x05, - 0x75, 0x04, 0xc3, 0xc1, 0x01, 0xc1, 0xbb, 0x82, 0x1f, 0x2f, 0xd2, 0x5f, 0x24, 0x5c, 0xd4, 0x16, - 0x02, 0x42, 0xfc, 0x43, 0x76, 0x85, 0x3c, 0x09, 0x35, 0x0c, 0x5d, 0x15, 0xfa, 0x73, 0x18, 0x2e, - 0x2c, 0x34, 0xac, 0x26, 0xec, 0x79, 0xb8, 0x55, 0x78, 0x7e, 0x78, 0x77, 0x04, 0x2d, 0x62, 0x45, - 0x44, 0x43, 0xc4, 0xbb, 0x48, 0x8f, 0xc8, 0xd2, 0xc8, 0x47, 0x8b, 0x8d, 0x16, 0x4b, 0x16, 0x77, - 0x46, 0xc9, 0x47, 0xc5, 0x45, 0xd5, 0x47, 0x4d, 0x45, 0x7b, 0x45, 0x97, 0x45, 0x4b, 0x97, 0x58, - 0x2c, 0x59, 0xb3, 0xe4, 0x46, 0x8c, 0x5a, 0x8c, 0x20, 0xa6, 0x3d, 0x16, 0x1f, 0x1b, 0x15, 0x7b, - 0x24, 0x76, 0x72, 0xa9, 0xf7, 0xd2, 0xdd, 0x4b, 0x87, 0xe3, 0xec, 0xe2, 0x0a, 0xe3, 0xee, 0x2e, - 0x33, 0x5c, 0x96, 0xb3, 0xec, 0xda, 0x72, 0xb5, 0xe5, 0xa9, 0xcb, 0xcf, 0xae, 0x90, 0x5f, 0xc1, - 0x59, 0x71, 0x2a, 0x1e, 0x1b, 0x1f, 0x1d, 0xdf, 0x10, 0xff, 0x89, 0x13, 0xc2, 0xa9, 0xe5, 0x4c, - 0xae, 0xf4, 0x5f, 0xb9, 0x77, 0xe5, 0x04, 0xd7, 0x93, 0xbb, 0x87, 0xfb, 0x92, 0xe7, 0xc6, 0x2b, - 0xe7, 0x8d, 0xf1, 0x5d, 0xf8, 0x65, 0xfc, 0x91, 0x04, 0x97, 0x84, 0xb2, 0x84, 0xd1, 0x44, 0x97, - 0xc4, 0x5d, 0x89, 0x63, 0x49, 0xae, 0x49, 0x15, 0x49, 0xe3, 0x02, 0x4f, 0x41, 0xb5, 0xe0, 0x75, - 0xb2, 0x5f, 0xf2, 0x81, 0xe4, 0xa9, 0x94, 0x90, 0x94, 0xa3, 0x29, 0x33, 0xa9, 0xd1, 0xa9, 0xcd, - 0x69, 0x84, 0xb4, 0xf8, 0xb4, 0xd3, 0x42, 0x25, 0x61, 0x8a, 0xb0, 0x2b, 0x5d, 0x33, 0x3d, 0x27, - 0xbd, 0x2f, 0xc3, 0x34, 0xa3, 0x30, 0x43, 0xba, 0xca, 0x69, 0xd5, 0xee, 0x55, 0x13, 0xa2, 0x40, - 0xd1, 0x91, 0x4c, 0x28, 0x73, 0x59, 0x66, 0xbb, 0x98, 0x8e, 0xfe, 0x4c, 0xf5, 0x48, 0x8c, 0x24, - 0x9b, 0x25, 0x83, 0x59, 0x0b, 0xb3, 0x6a, 0xb2, 0xde, 0x67, 0x47, 0x65, 0x9f, 0xca, 0x51, 0xcc, - 0x11, 0xe6, 0xf4, 0xe4, 0x9a, 0xe4, 0x6e, 0xcb, 0x1d, 0xc9, 0xf3, 0xc9, 0xfb, 0x7e, 0x35, 0x66, - 0x35, 0x77, 0x75, 0x67, 0xbe, 0x76, 0xfe, 0x86, 0xfc, 0xc1, 0x35, 0xee, 0x6b, 0x0e, 0xad, 0x85, - 0xd6, 0xae, 0x5c, 0xdb, 0xb9, 0x4e, 0x77, 0x5d, 0xc1, 0xba, 0xe1, 0xf5, 0xbe, 0xeb, 0x8f, 0x6d, - 0x20, 0x6d, 0x48, 0xd9, 0xf0, 0xcb, 0x46, 0xcb, 0x8d, 0x65, 0x1b, 0xdf, 0x6e, 0x8a, 0xde, 0xd4, - 0x51, 0xa0, 0x51, 0xb0, 0xbe, 0x60, 0x68, 0xb3, 0xef, 0xe6, 0xc6, 0x42, 0xb9, 0x42, 0x51, 0xe1, - 0xbd, 0x2d, 0xce, 0x5b, 0x0e, 0x6c, 0xc5, 0x6c, 0x15, 0x6c, 0xed, 0xdd, 0x66, 0xb3, 0xad, 0x6a, - 0xdb, 0x97, 0x22, 0x5e, 0xd1, 0xf5, 0x62, 0xcb, 0xe2, 0x8a, 0xe2, 0x4f, 0x25, 0xdc, 0x92, 0xeb, - 0xdf, 0x59, 0x7d, 0x57, 0xf9, 0xdd, 0xcc, 0xf6, 0x84, 0xed, 0xbd, 0xa5, 0xf6, 0xa5, 0xfb, 0x77, - 0xe0, 0x76, 0x08, 0x77, 0xdc, 0xdd, 0xe9, 0xba, 0xf3, 0x58, 0x99, 0x62, 0x59, 0x5e, 0xd9, 0xd0, - 0xae, 0xe0, 0x5d, 0xad, 0xe5, 0xcc, 0xf2, 0xa2, 0xf2, 0xb7, 0xbb, 0x57, 0xec, 0xbe, 0x56, 0x61, - 0x5b, 0x71, 0x60, 0x0f, 0x69, 0x8f, 0x64, 0x8f, 0xb4, 0x32, 0xa8, 0xb2, 0xbd, 0x4a, 0xaf, 0x6a, - 0x47, 0xd5, 0xa7, 0xea, 0xa4, 0xea, 0x81, 0x1a, 0x8f, 0x9a, 0xe6, 0xbd, 0xea, 0x7b, 0xb7, 0xed, - 0x9d, 0xda, 0xc7, 0xdb, 0xd7, 0xbf, 0xdf, 0x6d, 0x7f, 0xd3, 0x01, 0x8d, 0x03, 0xc5, 0x07, 0x3e, - 0x1e, 0x14, 0x1c, 0xbc, 0x7f, 0xc8, 0xf7, 0x50, 0x6b, 0xad, 0x41, 0x6d, 0xc5, 0x61, 0xdc, 0xe1, - 0xac, 0xc3, 0xcf, 0xeb, 0xa2, 0xea, 0xba, 0xbf, 0x67, 0x7f, 0x5f, 0x7f, 0x44, 0xed, 0x48, 0xf1, - 0x91, 0xcf, 0x47, 0x85, 0x47, 0xa5, 0xc7, 0xc2, 0x8f, 0x75, 0xd5, 0x3b, 0xd4, 0xd7, 0x37, 0xa8, - 0x37, 0x94, 0x36, 0xc2, 0x8d, 0x92, 0xc6, 0xb1, 0xe3, 0x71, 0xc7, 0x6f, 0xfd, 0xe0, 0xf5, 0x43, - 0x7b, 0x13, 0xab, 0xe9, 0x50, 0x33, 0xa3, 0xb9, 0xf8, 0x04, 0x38, 0x21, 0x39, 0xf1, 0xe2, 0xc7, - 0xf8, 0x1f, 0xef, 0x9e, 0x0c, 0x3c, 0xd9, 0x79, 0x8a, 0x7d, 0xaa, 0xe9, 0x27, 0xfd, 0x9f, 0xf6, - 0xb6, 0xd0, 0x5a, 0x8a, 0x5a, 0xa1, 0xd6, 0xdc, 0xd6, 0x89, 0xb6, 0xa4, 0x36, 0x69, 0x7b, 0x4c, - 0x7b, 0xdf, 0xe9, 0x80, 0xd3, 0x9d, 0x1d, 0xce, 0x1d, 0x2d, 0x3f, 0x9b, 0xff, 0x7c, 0xf4, 0x8c, - 0xf6, 0x99, 0x9a, 0xb3, 0xca, 0x67, 0x4b, 0xcf, 0x91, 0xce, 0x15, 0x9c, 0x9b, 0x39, 0x9f, 0x77, - 0x7e, 0xf2, 0x42, 0xc6, 0x85, 0xf1, 0x8b, 0x89, 0x17, 0x87, 0x3a, 0x57, 0x74, 0x3e, 0xba, 0xb4, - 0xe4, 0xd2, 0x9d, 0xae, 0xb0, 0xae, 0xde, 0xcb, 0x81, 0x97, 0xaf, 0x5e, 0xf1, 0xb9, 0x72, 0xa9, - 0xdb, 0xbd, 0xfb, 0xfc, 0x55, 0x97, 0xab, 0x67, 0xae, 0x39, 0x5d, 0x3b, 0x7d, 0x9d, 0x7d, 0xbd, - 0xed, 0x86, 0xfd, 0x8d, 0xd6, 0x1e, 0xbb, 0x9e, 0x96, 0x5f, 0xec, 0x7e, 0x69, 0xe9, 0xb5, 0xef, - 0x6d, 0xbd, 0xe9, 0x70, 0xb3, 0xfd, 0x96, 0xe3, 0xad, 0x8e, 0xbe, 0x05, 0x7d, 0xe7, 0xfa, 0x5d, - 0xfb, 0x2f, 0xde, 0xf6, 0xba, 0x7d, 0xe5, 0x8e, 0xff, 0x9d, 0x1b, 0x03, 0x8b, 0x06, 0xfa, 0xee, - 0x2e, 0xbe, 0x7b, 0xff, 0x5e, 0xdc, 0x3d, 0xe9, 0x7d, 0xde, 0xfd, 0xd1, 0x07, 0xa9, 0x0f, 0x5e, - 0x3f, 0xcc, 0x7a, 0x38, 0xfd, 0x68, 0xfd, 0x63, 0xec, 0xe3, 0xa2, 0x27, 0x0a, 0x4f, 0x2a, 0x9e, - 0xaa, 0x3f, 0xad, 0xfd, 0xd5, 0xf8, 0xd7, 0x66, 0xa9, 0xbd, 0xf4, 0xec, 0xa0, 0xd7, 0x60, 0xcf, - 0xb3, 0x88, 0x67, 0x8f, 0x86, 0xb8, 0x43, 0x2f, 0xff, 0x95, 0xf9, 0xaf, 0x4f, 0xc3, 0x05, 0xcf, - 0xa9, 0xcf, 0x2b, 0x46, 0xb4, 0x46, 0xea, 0x47, 0xad, 0x47, 0xcf, 0x8c, 0xf9, 0x8c, 0xdd, 0x7a, - 0xb1, 0xf4, 0xc5, 0xf0, 0xcb, 0x8c, 0x97, 0xd3, 0xe3, 0x85, 0xbf, 0x29, 0xfe, 0xb6, 0xf7, 0x95, - 0xd1, 0xab, 0x9f, 0x7e, 0x77, 0xfb, 0xbd, 0x67, 0x62, 0xc9, 0xc4, 0xf0, 0x6b, 0xd1, 0xeb, 0x99, - 0x3f, 0x4a, 0xde, 0xa8, 0xbe, 0x39, 0xfa, 0xd6, 0xf6, 0x6d, 0xe7, 0x64, 0xe8, 0xe4, 0xd3, 0x77, - 0x69, 0xef, 0xa6, 0xa7, 0x8a, 0xde, 0xab, 0xbe, 0x3f, 0xf6, 0x81, 0xfd, 0xa1, 0xfb, 0x63, 0xf4, - 0xc7, 0x91, 0xe9, 0xec, 0x4f, 0xf8, 0x4f, 0x95, 0x9f, 0x8d, 0x3f, 0x77, 0x7c, 0x09, 0xfc, 0xf2, - 0x78, 0x26, 0x6d, 0x66, 0xe6, 0xdf, 0xf7, 0x84, 0xf3, 0xfb, 0x32, 0x3a, 0x59, 0x7e, 0x00, 0x00, - 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, - 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x03, 0xa4, 0x69, 0x54, 0x58, 0x74, 0x58, 0x4d, 0x4c, 0x3a, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x78, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x78, 0x6d, 0x6c, 0x6e, - 0x73, 0x3a, 0x78, 0x3d, 0x22, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x3a, 0x6e, 0x73, 0x3a, 0x6d, 0x65, - 0x74, 0x61, 0x2f, 0x22, 0x20, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x74, 0x6b, 0x3d, 0x22, 0x58, 0x4d, - 0x50, 0x20, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x35, 0x2e, 0x34, 0x2e, 0x30, 0x22, 0x3e, 0x0a, 0x20, - 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, - 0x3a, 0x72, 0x64, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x31, 0x39, 0x39, 0x39, 0x2f, 0x30, 0x32, 0x2f, - 0x32, 0x32, 0x2d, 0x72, 0x64, 0x66, 0x2d, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x2d, 0x6e, 0x73, - 0x23, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x72, 0x64, 0x66, 0x3a, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x64, 0x66, 0x3a, 0x61, - 0x62, 0x6f, 0x75, 0x74, 0x3d, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x78, 0x6d, 0x70, 0x3d, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x61, 0x70, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x74, - 0x69, 0x66, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, - 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x2f, 0x31, 0x2e, - 0x30, 0x2f, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3a, 0x65, 0x78, 0x69, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6e, 0x73, 0x2e, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x78, 0x69, 0x66, 0x2f, 0x31, 0x2e, 0x30, 0x2f, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x44, 0x61, 0x74, 0x65, 0x3e, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x35, 0x2d, 0x30, 0x32, 0x54, - 0x31, 0x31, 0x3a, 0x30, 0x35, 0x3a, 0x30, 0x36, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x79, 0x44, 0x61, 0x74, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3c, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x33, - 0x2e, 0x31, 0x3c, 0x2f, 0x78, 0x6d, 0x70, 0x3a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x54, - 0x6f, 0x6f, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, - 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x4f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3e, - 0x35, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, - 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, - 0x69, 0x74, 0x3e, 0x31, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x59, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x66, 0x66, 0x3a, 0x58, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x37, 0x32, 0x3c, 0x2f, 0x74, 0x69, 0x66, 0x66, 0x3a, - 0x58, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, - 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x38, 0x3c, 0x2f, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x58, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, - 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x3e, 0x31, - 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x70, 0x61, 0x63, - 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x65, 0x78, 0x69, - 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x3e, 0x31, 0x3c, 0x2f, 0x65, 0x78, 0x69, 0x66, 0x3a, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x59, - 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x72, 0x64, 0x66, 0x3a, 0x52, 0x44, 0x46, - 0x3e, 0x0a, 0x3c, 0x2f, 0x78, 0x3a, 0x78, 0x6d, 0x70, 0x6d, 0x65, 0x74, 0x61, 0x3e, 0x0a, 0x90, - 0x7a, 0xe1, 0x8d, 0x00, 0x00, 0x00, 0x12, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1d, 0x63, 0x60, 0x60, - 0x60, 0xf8, 0x0f, 0xc5, 0x40, 0x0a, 0x13, 0x00, 0x00, 0x35, 0xeb, 0x01, 0xff, 0x0f, 0x5e, 0xbc, - 0xf4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - - -#pragma clang diagnostic pop - -@implementation FLEXResources - -#define FLEXImage(base) ( \ - (UIScreen.mainScreen.scale > 1.5) ? \ - ( (UIScreen.mainScreen.scale > 2.5) ? \ - [self imageWithBytesNoCopy:(void *)base##3x length:sizeof(base##3x) scale:3.0] : \ - [self imageWithBytesNoCopy:(void *)base##2x length:sizeof(base##2x) scale:2.0] \ - ) : \ - nil \ -) - -#define FLEXImageTemplate(base) ([FLEXImage(base) imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]) - -#define FLEXRetinaOnlyImage(base) ([self imageWithBytesNoCopy:(void *)(base) length:sizeof(base) scale:2.0]) - - -#pragma mark - FLEX Toolbar Icons - -+ (UIImage *)closeIcon { - return FLEXImageTemplate(FLEXCloseIcon); -} - -+ (UIImage *)dragHandle { - return FLEXImageTemplate(FLEXDragHandle); -} - -+ (UIImage *)globalsIcon { - return FLEXImageTemplate(FLEXGlobalsIcon); -} - -+ (UIImage *)hierarchyIcon { - return FLEXImageTemplate(FLEXHierarchyIcon); -} - -+ (UIImage *)recentIcon { - return FLEXImageTemplate(FLEXRecentTabIcon); -} - -+ (UIImage *)moveIcon { - return FLEXImageTemplate(FLEXMoveIcon); -} - -+ (UIImage *)selectIcon { - return FLEXImageTemplate(FLEXSelectIcon); -} - - -#pragma mark - Toolbar Icons - -+ (UIImage *)bookmarksIcon { - return FLEXImage(FLEXBookmarksIcon); -} - -+ (UIImage *)openTabsIcon { - return FLEXImage(FLEXOpenTabsIcon); -} - -+ (UIImage *)moreIcon { - return FLEXImage(FLEXMoreIcon); -} - -+ (UIImage *)gearIcon { - return FLEXImage(FLEXGearIcon); -} - -+ (UIImage *)scrollToBottomIcon { - return FLEXImage(FLEXCircleDownArrowIcon); -} - - -#pragma mark - Content Type Icons - -+ (UIImage *)jsonIcon { - return FLEXImage(FLEXJSONIcon); -} - -+ (UIImage *)textPlainIcon { - return FLEXImage(FLEXTextPlainIcon); -} - -+ (UIImage *)htmlIcon { - return FLEXImage(FLEXHTMLIcon); -} - -+ (UIImage *)audioIcon { - return FLEXImage(FLEXAudioIcon); -} - -+ (UIImage *)jsIcon { - return FLEXImage(FLEXJSIcon); -} - -+ (UIImage *)plistIcon { - return FLEXImage(FLEXPlistIcon); -} - -+ (UIImage *)textIcon { - return FLEXImage(FLEXTextIcon); -} - -+ (UIImage *)videoIcon { - return FLEXImage(FLEXVideoIcon); -} - -+ (UIImage *)xmlIcon { - return FLEXImage(FLEXXMLIcon); -} - -+ (UIImage *)binaryIcon { - return FLEXImage(FLEXBinaryIcon); -} - - -#pragma mark - 3D Explorer Icons - -+ (UIImage *)toggle2DIcon { - return FLEXImage(FLEXToggle2DIcon); -} - -+ (UIImage *)toggle3DIcon { - return FLEXImage(FLEXToggle3DIcon); -} - -+ (UIImage *)rangeSliderLeftHandle { - return FLEXImage(FLEXRangeSliderLeftHandle); -} - -+ (UIImage *)rangeSliderRightHandle { - return FLEXImage(FLEXRangeSliderRightHandle); -} - -+ (UIImage *)rangeSliderTrack { - UIEdgeInsets cap = UIEdgeInsetsMake(0, 5, 0, 4); - return [FLEXImage(FLEXRangeSliderTrack) resizableImageWithCapInsets:cap]; -} - -+ (UIImage *)rangeSliderFill { - UIEdgeInsets cap = UIEdgeInsetsMake(0, 5, 0, 4); - return [FLEXImage(FLEXRangeSliderFill) resizableImageWithCapInsets:cap]; -} - - -#pragma mark - Misc Icons - -+ (UIImage *)checkerPattern { - return FLEXImage(FLEXCheckerPattern); -} - -+ (UIColor *)checkerPatternColor { - return [UIColor colorWithPatternImage:FLEXResources.checkerPattern]; -} - -+ (UIImage *)hierarchyIndentPattern { - return FLEXImageTemplate(FLEXHierarchyIndentPattern); -} - - -#undef FLEXImage -#undef FLEXRetinaOnlyImage - - -#pragma mark - Helpers - -+ (UIImage *)imageWithBytesNoCopy:(void *)bytes length:(NSUInteger)length scale:(CGFloat)scale { - NSData *data = [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO]; - return [UIImage imageWithData:data scale:scale]; -} - -@end diff --git a/Tweaks/FLEX/Utility/FLEXUtility.h b/Tweaks/FLEX/Utility/FLEXUtility.h deleted file mode 100644 index adc4d70..0000000 --- a/Tweaks/FLEX/Utility/FLEXUtility.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// FLEXUtility.h -// Flipboard -// -// Created by Ryan Olson on 4/18/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import -#import -#import -#import -#import "FLEXTypeEncodingParser.h" -#import "FLEXAlert.h" -#import "NSArray+FLEX.h" -#import "UIFont+FLEX.h" -#import "FLEXMacros.h" - -@interface FLEXUtility : NSObject - -/// The key window of the app, if it is not a \c FLEXWindow. -/// If it is, then \c FLEXWindow.previousKeyWindow is returned. -@property (nonatomic, readonly, class) UIWindow *appKeyWindow; -/// @return the result of +[UIWindow allWindowsIncludingInternalWindows:onlyVisibleWindows:] -@property (nonatomic, readonly, class) NSArray *allWindows; -/// The first active \c UIWindowScene of the app. -@property (nonatomic, readonly, class) UIWindowScene *activeScene API_AVAILABLE(ios(13.0)); -/// @return top-most view controller of the given window -+ (UIViewController *)topViewControllerInWindow:(UIWindow *)window; - -+ (UIColor *)consistentRandomColorForObject:(id)object; -+ (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFrame; -+ (NSString *)stringForCGRect:(CGRect)rect; -+ (UIViewController *)viewControllerForView:(UIView *)view; -+ (UIViewController *)viewControllerForAncestralView:(UIView *)view; -+ (UIImage *)previewImageForView:(UIView *)view; -+ (UIImage *)previewImageForLayer:(CALayer *)layer; -+ (NSString *)detailDescriptionForView:(UIView *)view; -+ (UIImage *)circularImageWithColor:(UIColor *)color radius:(CGFloat)radius; -+ (UIColor *)hierarchyIndentPatternColor; -+ (NSString *)pointerToString:(void *)ptr; -+ (NSString *)addressOfObject:(id)object; -+ (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString; -+ (UIInterfaceOrientationMask)infoPlistSupportedInterfaceOrientationsMask; -+ (UIImage *)thumbnailedImageWithMaxPixelDimension:(NSInteger)dimension fromImageData:(NSData *)data; -+ (NSString *)stringFromRequestDuration:(NSTimeInterval)duration; -+ (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response; -+ (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response; -+ (NSArray *)itemsFromQueryString:(NSString *)query; -+ (NSString *)prettyJSONStringFromData:(NSData *)data; -+ (BOOL)isValidJSONData:(NSData *)data; -+ (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData; - -// Swizzling utilities - -+ (SEL)swizzledSelectorForSelector:(SEL)selector; -+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls; -+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)cls withBlock:(id)block swizzledSelector:(SEL)swizzledSelector; -+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock; - -@end diff --git a/Tweaks/FLEX/Utility/FLEXUtility.m b/Tweaks/FLEX/Utility/FLEXUtility.m deleted file mode 100644 index 59f4e8e..0000000 --- a/Tweaks/FLEX/Utility/FLEXUtility.m +++ /dev/null @@ -1,527 +0,0 @@ -// -// FLEXUtility.m -// Flipboard -// -// Created by Ryan Olson on 4/18/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXUtility.h" -#import "FLEXResources.h" -#import "FLEXWindow.h" -#import -#import -#import - -BOOL FLEXConstructorsShouldRun() { - #if FLEX_DISABLE_CTORS - return NO; - #else - static BOOL _FLEXConstructorsShouldRun_storage = YES; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *key = @"FLEX_SKIP_INIT"; - if (getenv(key.UTF8String) || [NSUserDefaults.standardUserDefaults boolForKey:key]) { - _FLEXConstructorsShouldRun_storage = NO; - } - }); - - return _FLEXConstructorsShouldRun_storage; - #endif -} - -@implementation FLEXUtility - -+ (UIWindow *)appKeyWindow { - // First, check UIApplication.keyWindow - FLEXWindow *window = (id)UIApplication.sharedApplication.keyWindow; - if (window) { - if ([window isKindOfClass:[FLEXWindow class]]) { - return window.previousKeyWindow; - } - - return window; - } - - // As of iOS 13, UIApplication.keyWindow does not return nil, - // so this is more of a safeguard against it returning nil in the future. - // - // Also, these are obviously not all FLEXWindows; FLEXWindow is used - // so we can call window.previousKeyWindow without an ugly cast - for (FLEXWindow *window in UIApplication.sharedApplication.windows) { - if (window.isKeyWindow) { - if ([window isKindOfClass:[FLEXWindow class]]) { - return window.previousKeyWindow; - } - - return window; - } - } - - return nil; -} - -+ (UIWindowScene *)activeScene { - for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { - // Look for an active UIWindowScene - if (scene.activationState == UISceneActivationStateForegroundActive && - [scene isKindOfClass:[UIWindowScene class]]) { - return (UIWindowScene *)scene; - } - } - - return nil; -} - -+ (UIViewController *)topViewControllerInWindow:(UIWindow *)window { - UIViewController *topViewController = window.rootViewController; - while (topViewController.presentedViewController) { - topViewController = topViewController.presentedViewController; - } - return topViewController; -} - -+ (UIColor *)consistentRandomColorForObject:(id)object { - CGFloat hue = (((NSUInteger)object >> 4) % 256) / 255.0; - return [UIColor colorWithHue:hue saturation:1.0 brightness:1.0 alpha:1.0]; -} - -+ (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFrame { - NSString *description = [[view class] description]; - - NSString *viewControllerDescription = [[[self viewControllerForView:view] class] description]; - if (viewControllerDescription.length > 0) { - description = [description stringByAppendingFormat:@" (%@)", viewControllerDescription]; - } - - if (includeFrame) { - description = [description stringByAppendingFormat:@" %@", [self stringForCGRect:view.frame]]; - } - - if (view.accessibilityLabel.length > 0) { - description = [description stringByAppendingFormat:@" · %@", view.accessibilityLabel]; - } - - return description; -} - -+ (NSString *)stringForCGRect:(CGRect)rect { - return [NSString stringWithFormat:@"{(%g, %g), (%g, %g)}", - rect.origin.x, rect.origin.y, rect.size.width, rect.size.height - ]; -} - -+ (UIViewController *)viewControllerForView:(UIView *)view { - NSString *viewDelegate = @"_viewDelegate"; - if ([view respondsToSelector:NSSelectorFromString(viewDelegate)]) { - return [view valueForKey:viewDelegate]; - } - - return nil; -} - -+ (UIViewController *)viewControllerForAncestralView:(UIView *)view { - NSString *_viewControllerForAncestor = @"_viewControllerForAncestor"; - if ([view respondsToSelector:NSSelectorFromString(_viewControllerForAncestor)]) { - return [view valueForKey:_viewControllerForAncestor]; - } - - return nil; -} - -+ (UIImage *)previewImageForView:(UIView *)view { - if (CGRectIsEmpty(view.bounds)) { - return [UIImage new]; - } - - CGSize viewSize = view.bounds.size; - UIGraphicsBeginImageContextWithOptions(viewSize, NO, 0.0); - [view drawViewHierarchyInRect:CGRectMake(0, 0, viewSize.width, viewSize.height) afterScreenUpdates:YES]; - UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return previewImage; -} - -+ (UIImage *)previewImageForLayer:(CALayer *)layer { - if (CGRectIsEmpty(layer.bounds)) { - return nil; - } - - UIGraphicsBeginImageContextWithOptions(layer.bounds.size, NO, 0.0); - CGContextRef imageContext = UIGraphicsGetCurrentContext(); - [layer renderInContext:imageContext]; - UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return previewImage; -} - -+ (NSString *)detailDescriptionForView:(UIView *)view { - return [NSString stringWithFormat:@"frame %@", [self stringForCGRect:view.frame]]; -} - -+ (UIImage *)circularImageWithColor:(UIColor *)color radius:(CGFloat)radius { - CGFloat diameter = radius * 2.0; - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), NO, 0.0); - CGContextRef imageContext = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(imageContext, color.CGColor); - CGContextFillEllipseInRect(imageContext, CGRectMake(0, 0, diameter, diameter)); - UIImage *circularImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return circularImage; -} - -+ (UIColor *)hierarchyIndentPatternColor { - static UIColor *patternColor = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - UIImage *indentationPatternImage = FLEXResources.hierarchyIndentPattern; - patternColor = [UIColor colorWithPatternImage:indentationPatternImage]; - if (@available(iOS 13.0, *)) { - // Create a dark mode version - UIGraphicsBeginImageContextWithOptions( - indentationPatternImage.size, NO, indentationPatternImage.scale - ); - [FLEXColor.iconColor set]; - [indentationPatternImage drawInRect:CGRectMake( - 0, 0, indentationPatternImage.size.width, indentationPatternImage.size.height - )]; - UIImage *darkModePatternImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - // Create dynamic color provider - patternColor = [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) { - return (traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight - ? [UIColor colorWithPatternImage:indentationPatternImage] - : [UIColor colorWithPatternImage:darkModePatternImage]); - }]; - } - }); - - return patternColor; -} - -+ (NSString *)applicationImageName { - return NSBundle.mainBundle.executablePath; -} - -+ (NSString *)applicationName { - return FLEXUtility.applicationImageName.lastPathComponent; -} - -+ (NSString *)pointerToString:(void *)ptr { - return [NSString stringWithFormat:@"%p", ptr]; -} - -+ (NSString *)addressOfObject:(id)object { - return [NSString stringWithFormat:@"%p", object]; -} - -+ (NSString *)stringByEscapingHTMLEntitiesInString:(NSString *)originalString { - static NSDictionary *escapingDictionary = nil; - static NSRegularExpression *regex = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - escapingDictionary = @{ @" " : @" ", - @">" : @">", - @"<" : @"<", - @"&" : @"&", - @"'" : @"'", - @"\"" : @""", - @"«" : @"«", - @"»" : @"»" - }; - regex = [NSRegularExpression regularExpressionWithPattern:@"(&|>|<|'|\"|«|»)" options:0 error:NULL]; - }); - - NSMutableString *mutableString = originalString.mutableCopy; - - NSArray *matches = [regex - matchesInString:mutableString options:0 range:NSMakeRange(0, mutableString.length) - ]; - for (NSTextCheckingResult *result in matches.reverseObjectEnumerator) { - NSString *foundString = [mutableString substringWithRange:result.range]; - NSString *replacementString = escapingDictionary[foundString]; - if (replacementString) { - [mutableString replaceCharactersInRange:result.range withString:replacementString]; - } - } - - return [mutableString copy]; -} - -+ (UIInterfaceOrientationMask)infoPlistSupportedInterfaceOrientationsMask { - NSArray *supportedOrientations = NSBundle.mainBundle.infoDictionary[@"UISupportedInterfaceOrientations"]; - UIInterfaceOrientationMask supportedOrientationsMask = 0; - if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"]) { - supportedOrientationsMask |= UIInterfaceOrientationMaskPortrait; - } - if ([supportedOrientations containsObject:@"UIInterfaceOrientationMaskLandscapeRight"]) { - supportedOrientationsMask |= UIInterfaceOrientationMaskLandscapeRight; - } - if ([supportedOrientations containsObject:@"UIInterfaceOrientationMaskPortraitUpsideDown"]) { - supportedOrientationsMask |= UIInterfaceOrientationMaskPortraitUpsideDown; - } - if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeLeft"]) { - supportedOrientationsMask |= UIInterfaceOrientationMaskLandscapeLeft; - } - return supportedOrientationsMask; -} - -+ (UIImage *)thumbnailedImageWithMaxPixelDimension:(NSInteger)dimension fromImageData:(NSData *)data { - UIImage *thumbnail = nil; - CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, 0); - if (imageSource) { - NSDictionary *options = @{ - (__bridge id)kCGImageSourceCreateThumbnailWithTransform : @YES, - (__bridge id)kCGImageSourceCreateThumbnailFromImageAlways : @YES, - (__bridge id)kCGImageSourceThumbnailMaxPixelSize : @(dimension) - }; - - CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex( - imageSource, 0, (__bridge CFDictionaryRef)options - ); - if (scaledImageRef) { - thumbnail = [UIImage imageWithCGImage:scaledImageRef]; - CFRelease(scaledImageRef); - } - CFRelease(imageSource); - } - return thumbnail; -} - -+ (NSString *)stringFromRequestDuration:(NSTimeInterval)duration { - NSString *string = @"0s"; - if (duration > 0.0) { - if (duration < 1.0) { - string = [NSString stringWithFormat:@"%dms", (int)(duration * 1000)]; - } else if (duration < 10.0) { - string = [NSString stringWithFormat:@"%.2fs", duration]; - } else { - string = [NSString stringWithFormat:@"%.1fs", duration]; - } - } - return string; -} - -+ (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response { - NSString *httpResponseString = nil; - if ([response isKindOfClass:[NSHTTPURLResponse class]]) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - NSString *statusCodeDescription = nil; - if (httpResponse.statusCode == 200) { - // Prefer OK to the default "no error" - statusCodeDescription = @"OK"; - } else { - statusCodeDescription = [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]; - } - httpResponseString = [NSString stringWithFormat:@"%ld %@", (long)httpResponse.statusCode, statusCodeDescription]; - } - return httpResponseString; -} - -+ (BOOL)isErrorStatusCodeFromURLResponse:(NSURLResponse *)response { - if ([response isKindOfClass:[NSHTTPURLResponse class]]) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - return httpResponse.statusCode >= 400; - } - - return NO; -} - -+ (NSArray *)itemsFromQueryString:(NSString *)query { - NSMutableArray *items = [NSMutableArray new]; - - // [a=1, b=2, c=3] - NSArray *queryComponents = [query componentsSeparatedByString:@"&"]; - for (NSString *keyValueString in queryComponents) { - // [a, 1] - NSArray *components = [keyValueString componentsSeparatedByString:@"="]; - if (components.count == 2) { - NSString *key = components.firstObject.stringByRemovingPercentEncoding; - NSString *value = components.lastObject.stringByRemovingPercentEncoding; - - [items addObject:[NSURLQueryItem queryItemWithName:key value:value]]; - } - } - - return items.copy; -} - -+ (NSString *)prettyJSONStringFromData:(NSData *)data { - NSString *prettyString = nil; - - id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; - if ([NSJSONSerialization isValidJSONObject:jsonObject]) { - // Thanks RaziPour1993 - prettyString = [[NSString alloc] - initWithData:[NSJSONSerialization - dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:NULL - ] - encoding:NSUTF8StringEncoding - ]; - // NSJSONSerialization escapes forward slashes. - // We want pretty json, so run through and unescape the slashes. - prettyString = [prettyString stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]; - } else { - prettyString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - } - - return prettyString; -} - -+ (BOOL)isValidJSONData:(NSData *)data { - return [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL] ? YES : NO; -} - -// Thanks to the following links for help with this method -// https://www.cocoanetics.com/2012/02/decompressing-files-into-memory/ -// https://github.com/nicklockwood/GZIP -+ (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData { - NSData *inflatedData = nil; - NSUInteger compressedDataLength = compressedData.length; - if (compressedDataLength > 0) { - z_stream stream; - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.avail_in = (uInt)compressedDataLength; - stream.next_in = (void *)compressedData.bytes; - stream.total_out = 0; - stream.avail_out = 0; - - NSMutableData *mutableData = [NSMutableData dataWithLength:compressedDataLength * 1.5]; - if (inflateInit2(&stream, 15 + 32) == Z_OK) { - int status = Z_OK; - while (status == Z_OK) { - if (stream.total_out >= mutableData.length) { - mutableData.length += compressedDataLength / 2; - } - stream.next_out = (uint8_t *)[mutableData mutableBytes] + stream.total_out; - stream.avail_out = (uInt)(mutableData.length - stream.total_out); - status = inflate(&stream, Z_SYNC_FLUSH); - } - if (inflateEnd(&stream) == Z_OK) { - if (status == Z_STREAM_END) { - mutableData.length = stream.total_out; - inflatedData = [mutableData copy]; - } - } - } - } - return inflatedData; -} - -+ (NSArray *)allWindows { - BOOL includeInternalWindows = YES; - BOOL onlyVisibleWindows = NO; - - // Obfuscating selector allWindowsIncludingInternalWindows:onlyVisibleWindows: - NSArray *allWindowsComponents = @[ - @"al", @"lWindo", @"wsIncl", @"udingInt", @"ernalWin", @"dows:o", @"nlyVisi", @"bleWin", @"dows:" - ]; - SEL allWindowsSelector = NSSelectorFromString([allWindowsComponents componentsJoinedByString:@""]); - - NSMethodSignature *methodSignature = [[UIWindow class] methodSignatureForSelector:allWindowsSelector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - - invocation.target = [UIWindow class]; - invocation.selector = allWindowsSelector; - [invocation setArgument:&includeInternalWindows atIndex:2]; - [invocation setArgument:&onlyVisibleWindows atIndex:3]; - [invocation invoke]; - - __unsafe_unretained NSArray *windows = nil; - [invocation getReturnValue:&windows]; - return windows; -} - -+ (UIAlertController *)alert:(NSString *)title message:(NSString *)message { - return [UIAlertController - alertControllerWithTitle:title - message:message - preferredStyle:UIAlertControllerStyleAlert - ]; -} - -+ (SEL)swizzledSelectorForSelector:(SEL)selector { - return NSSelectorFromString([NSString stringWithFormat: - @"_flex_swizzle_%x_%@", arc4random(), NSStringFromSelector(selector) - ]); -} - -+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls { - if ([cls instancesRespondToSelector:selector]) { - unsigned int numMethods = 0; - Method *methods = class_copyMethodList(cls, &numMethods); - - BOOL implementsSelector = NO; - for (int index = 0; index < numMethods; index++) { - SEL methodSelector = method_getName(methods[index]); - if (selector == methodSelector) { - implementsSelector = YES; - break; - } - } - - free(methods); - - if (!implementsSelector) { - return YES; - } - } - - return NO; -} - -+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector - onClass:(Class)class - withBlock:(id)block - swizzledSelector:(SEL)swizzledSelector { - // This method is only intended for swizzling methods that are know to exist on the class. - // Bail if that isn't the case. - Method originalMethod = class_getInstanceMethod(class, originalSelector); - if (!originalMethod) { - return; - } - - IMP implementation = imp_implementationWithBlock(block); - class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalMethod)); - Method newMethod = class_getInstanceMethod(class, swizzledSelector); - method_exchangeImplementations(originalMethod, newMethod); -} - -+ (void)replaceImplementationOfSelector:(SEL)selector - withSelector:(SEL)swizzledSelector - forClass:(Class)cls - withMethodDescription:(struct objc_method_description)methodDescription - implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock { - if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) { - return; - } - - IMP implementation = imp_implementationWithBlock((id)( - [cls instancesRespondToSelector:selector] ? implementationBlock : undefinedBlock) - ); - - Method oldMethod = class_getInstanceMethod(cls, selector); - const char *types = methodDescription.types; - if (oldMethod) { - if (!types) { - types = method_getTypeEncoding(oldMethod); - } - - class_addMethod(cls, swizzledSelector, implementation, types); - Method newMethod = class_getInstanceMethod(cls, swizzledSelector); - method_exchangeImplementations(oldMethod, newMethod); - } else { - if (!types) { - // Some protocol method descriptions don't have .types populated - // Set the return type to void and ignore arguments - types = "v@:"; - } - class_addMethod(cls, selector, implementation, types); - } -} - -@end diff --git a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardHelpViewController.h b/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardHelpViewController.h deleted file mode 100644 index 4fae64e..0000000 --- a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardHelpViewController.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FLEXKeyboardHelpViewController.h -// FLEX -// -// Created by Ryan Olson on 9/19/15. -// Copyright © 2015 f. All rights reserved. -// - -#import - -@interface FLEXKeyboardHelpViewController : UIViewController - -@end diff --git a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardHelpViewController.m b/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardHelpViewController.m deleted file mode 100644 index 66e9d7e..0000000 --- a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardHelpViewController.m +++ /dev/null @@ -1,42 +0,0 @@ -// -// FLEXKeyboardHelpViewController.m -// FLEX -// -// Created by Ryan Olson on 9/19/15. -// Copyright © 2015 f. All rights reserved. -// - -#import "FLEXKeyboardHelpViewController.h" -#import "FLEXKeyboardShortcutManager.h" - -@interface FLEXKeyboardHelpViewController () - -@property (nonatomic) UITextView *textView; - -@end - -@implementation FLEXKeyboardHelpViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.textView = [[UITextView alloc] initWithFrame:self.view.bounds]; - self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; - [self.view addSubview:self.textView]; -#if TARGET_OS_SIMULATOR - self.textView.text = FLEXKeyboardShortcutManager.sharedManager.keyboardShortcutsDescription; -#endif - self.textView.backgroundColor = UIColor.blackColor; - self.textView.textColor = UIColor.whiteColor; - self.textView.font = [UIFont boldSystemFontOfSize:14.0]; - self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque; - - self.title = @"Simulator Shortcuts"; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed:)]; -} - -- (void)donePressed:(id)sender { - [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.h b/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.h deleted file mode 100644 index 292f3d4..0000000 --- a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// FLEXKeyboardShortcutManager.h -// FLEX -// -// Created by Ryan Olson on 9/19/15. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXKeyboardShortcutManager : NSObject - -@property (nonatomic, readonly, class) FLEXKeyboardShortcutManager *sharedManager; - -/// @param key A single character string matching a key on the keyboard -/// @param modifiers Modifier keys such as shift, command, or alt/option -/// @param action The block to run on the main thread when the key & modifier combination is recognized. -/// @param description Shown the the keyboard shortcut help menu, which is accessed via the '?' key. -/// @param allowOverride Allow registering even if there's an existing action associated with that key/modifier. -- (void)registerSimulatorShortcutWithKey:(NSString *)key - modifiers:(UIKeyModifierFlags)modifiers - action:(dispatch_block_t)action - description:(NSString *)description - allowOverride:(BOOL)allowOverride; - -@property (nonatomic, getter=isEnabled) BOOL enabled; -@property (nonatomic, readonly) NSString *keyboardShortcutsDescription; - -@end diff --git a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.m b/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.m deleted file mode 100644 index 4263245..0000000 --- a/Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.m +++ /dev/null @@ -1,326 +0,0 @@ -// -// FLEXKeyboardShortcutManager.m -// FLEX -// -// Created by Ryan Olson on 9/19/15. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXKeyboardShortcutManager.h" -#import "FLEXUtility.h" -#import -#import - -#if TARGET_OS_SIMULATOR - -@interface UIEvent (UIPhysicalKeyboardEvent) - -@property (nonatomic) NSString *_modifiedInput; -@property (nonatomic) NSString *_unmodifiedInput; -@property (nonatomic) UIKeyModifierFlags _modifierFlags; -@property (nonatomic) BOOL _isKeyDown; -@property (nonatomic) long _keyCode; - -@end - -@interface FLEXKeyInput : NSObject - -@property (nonatomic, copy, readonly) NSString *key; -@property (nonatomic, readonly) UIKeyModifierFlags flags; -@property (nonatomic, copy, readonly) NSString *helpDescription; - -@end - -@implementation FLEXKeyInput - -- (BOOL)isEqual:(id)object { - BOOL isEqual = NO; - if ([object isKindOfClass:[FLEXKeyInput class]]) { - FLEXKeyInput *keyCommand = (FLEXKeyInput *)object; - BOOL equalKeys = self.key == keyCommand.key || [self.key isEqual:keyCommand.key]; - BOOL equalFlags = self.flags == keyCommand.flags; - isEqual = equalKeys && equalFlags; - } - return isEqual; -} - -- (NSUInteger)hash { - return self.key.hash ^ self.flags; -} - -- (id)copyWithZone:(NSZone *)zone { - return [[self class] keyInputForKey:self.key flags:self.flags helpDescription:self.helpDescription]; -} - -- (NSString *)description { - NSDictionary *keyMappings = @{ - UIKeyInputUpArrow : @"↑", - UIKeyInputDownArrow : @"↓", - UIKeyInputLeftArrow : @"←", - UIKeyInputRightArrow : @"→", - UIKeyInputEscape : @"␛", - @" " : @"␠" - }; - - NSString *prettyKey = nil; - if (self.key && keyMappings[self.key]) { - prettyKey = keyMappings[self.key]; - } else { - prettyKey = [self.key uppercaseString]; - } - - NSString *prettyFlags = @""; - if (self.flags & UIKeyModifierControl) { - prettyFlags = [prettyFlags stringByAppendingString:@"⌃"]; - } - if (self.flags & UIKeyModifierAlternate) { - prettyFlags = [prettyFlags stringByAppendingString:@"⌥"]; - } - if (self.flags & UIKeyModifierShift) { - prettyFlags = [prettyFlags stringByAppendingString:@"⇧"]; - } - if (self.flags & UIKeyModifierCommand) { - prettyFlags = [prettyFlags stringByAppendingString:@"⌘"]; - } - - // Fudging to get easy columns with tabs - if (prettyFlags.length < 2) { - prettyKey = [prettyKey stringByAppendingString:@"\t"]; - } - - return [NSString stringWithFormat:@"%@%@\t%@", prettyFlags, prettyKey, self.helpDescription]; -} - -+ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags { - return [self keyInputForKey:key flags:flags helpDescription:nil]; -} - -+ (instancetype)keyInputForKey:(NSString *)key - flags:(UIKeyModifierFlags)flags - helpDescription:(NSString *)helpDescription { - FLEXKeyInput *keyInput = [self new]; - if (keyInput) { - keyInput->_key = key; - keyInput->_flags = flags; - keyInput->_helpDescription = helpDescription; - } - return keyInput; -} - -@end - -@interface FLEXKeyboardShortcutManager () - -@property (nonatomic) NSMutableDictionary *actionsForKeyInputs; - -@property (nonatomic, getter=isPressingShift) BOOL pressingShift; -@property (nonatomic, getter=isPressingCommand) BOOL pressingCommand; -@property (nonatomic, getter=isPressingControl) BOOL pressingControl; - -@end - -@implementation FLEXKeyboardShortcutManager - -+ (instancetype)sharedManager { - static FLEXKeyboardShortcutManager *sharedManager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedManager = [self new]; - }); - return sharedManager; -} - -+ (void)load { - SEL originalKeyEventSelector = NSSelectorFromString(@"handleKeyUIEvent:"); - SEL swizzledKeyEventSelector = [FLEXUtility swizzledSelectorForSelector:originalKeyEventSelector]; - - void (^handleKeyUIEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) { - - [[[self class] sharedManager] handleKeyboardEvent:event]; - - ((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledKeyEventSelector, event); - }; - - [FLEXUtility replaceImplementationOfKnownSelector:originalKeyEventSelector - onClass:[UIApplication class] - withBlock:handleKeyUIEventSwizzleBlock - swizzledSelector:swizzledKeyEventSelector - ]; - - if ([[UITouch class] instancesRespondToSelector:@selector(maximumPossibleForce)]) { - SEL originalSendEventSelector = NSSelectorFromString(@"sendEvent:"); - SEL swizzledSendEventSelector = [FLEXUtility swizzledSelectorForSelector:originalSendEventSelector]; - - void (^sendEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) { - if (event.type == UIEventTypeTouches) { - FLEXKeyboardShortcutManager *keyboardManager = FLEXKeyboardShortcutManager.sharedManager; - NSInteger pressureLevel = 0; - if (keyboardManager.isPressingShift) { - pressureLevel++; - } - if (keyboardManager.isPressingCommand) { - pressureLevel++; - } - if (keyboardManager.isPressingControl) { - pressureLevel++; - } - if (pressureLevel > 0) { - if (@available(iOS 9.0, *)) { - for (UITouch *touch in [event allTouches]) { - double adjustedPressureLevel = pressureLevel * 20 * touch.maximumPossibleForce; - [touch setValue:@(adjustedPressureLevel) forKey:@"_pressure"]; - } - } - } - } - - ((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledSendEventSelector, event); - }; - - [FLEXUtility replaceImplementationOfKnownSelector:originalSendEventSelector - onClass:[UIApplication class] - withBlock:sendEventSwizzleBlock - swizzledSelector:swizzledSendEventSelector - ]; - - SEL originalSupportsTouchPressureSelector = NSSelectorFromString(@"_supportsForceTouch"); - SEL swizzledSupportsTouchPressureSelector = [FLEXUtility swizzledSelectorForSelector:originalSupportsTouchPressureSelector]; - - BOOL (^supportsTouchPressureSwizzleBlock)(UIDevice *) = ^BOOL(UIDevice *slf) { - return YES; - }; - - [FLEXUtility replaceImplementationOfKnownSelector:originalSupportsTouchPressureSelector - onClass:[UIDevice class] - withBlock:supportsTouchPressureSwizzleBlock - swizzledSelector:swizzledSupportsTouchPressureSelector - ]; - } -} - -- (instancetype)init { - self = [super init]; - - if (self) { - _actionsForKeyInputs = [NSMutableDictionary new]; - _enabled = YES; - } - - return self; -} - -- (void)registerSimulatorShortcutWithKey:(NSString *)key - modifiers:(UIKeyModifierFlags)modifiers - action:(dispatch_block_t)action - description:(NSString *)description - allowOverride:(BOOL)allowOverride { - FLEXKeyInput *keyInput = [FLEXKeyInput keyInputForKey:key flags:modifiers helpDescription:description]; - if (!allowOverride && self.actionsForKeyInputs[keyInput] != nil) { - return; - } else { - [self.actionsForKeyInputs setObject:action forKey:keyInput]; - } -} - -static const long kFLEXControlKeyCode = 0xe0; -static const long kFLEXShiftKeyCode = 0xe1; -static const long kFLEXCommandKeyCode = 0xe3; - -- (void)handleKeyboardEvent:(UIEvent *)event { - if (!self.enabled) { - return; - } - - NSString *modifiedInput = nil; - NSString *unmodifiedInput = nil; - UIKeyModifierFlags flags = 0; - BOOL isKeyDown = NO; - - if ([event respondsToSelector:@selector(_modifiedInput)]) { - modifiedInput = [event _modifiedInput]; - } - - if ([event respondsToSelector:@selector(_unmodifiedInput)]) { - unmodifiedInput = [event _unmodifiedInput]; - } - - if ([event respondsToSelector:@selector(_modifierFlags)]) { - flags = [event _modifierFlags]; - } - - if ([event respondsToSelector:@selector(_isKeyDown)]) { - isKeyDown = [event _isKeyDown]; - } - - BOOL interactionEnabled = !UIApplication.sharedApplication.isIgnoringInteractionEvents; - BOOL hasFirstResponder = NO; - if (isKeyDown && modifiedInput.length > 0 && interactionEnabled) { - UIResponder *firstResponder = nil; - for (UIWindow *window in FLEXUtility.allWindows) { - firstResponder = [window valueForKey:@"firstResponder"]; - if (firstResponder) { - hasFirstResponder = YES; - break; - } - } - - // Ignore key commands (except escape) when there's an active responder - if (firstResponder) { - if ([unmodifiedInput isEqual:UIKeyInputEscape]) { - [firstResponder resignFirstResponder]; - } - } else { - FLEXKeyInput *exactMatch = [FLEXKeyInput keyInputForKey:unmodifiedInput flags:flags]; - - dispatch_block_t actionBlock = self.actionsForKeyInputs[exactMatch]; - - if (!actionBlock) { - FLEXKeyInput *shiftMatch = [FLEXKeyInput - keyInputForKey:modifiedInput flags:flags&(~UIKeyModifierShift) - ]; - actionBlock = self.actionsForKeyInputs[shiftMatch]; - } - - if (!actionBlock) { - FLEXKeyInput *capitalMatch = [FLEXKeyInput - keyInputForKey:[unmodifiedInput uppercaseString] flags:flags - ]; - actionBlock = self.actionsForKeyInputs[capitalMatch]; - } - - if (actionBlock) { - actionBlock(); - } - } - } - - // Calling _keyCode on events from the simulator keyboard will crash. - // It is only safe to call _keyCode when there's not an active responder. - if (!hasFirstResponder && [event respondsToSelector:@selector(_keyCode)]) { - long keyCode = [event _keyCode]; - if (keyCode == kFLEXControlKeyCode) { - self.pressingControl = isKeyDown; - } else if (keyCode == kFLEXCommandKeyCode) { - self.pressingCommand = isKeyDown; - } else if (keyCode == kFLEXShiftKeyCode) { - self.pressingShift = isKeyDown; - } - } -} - -- (NSString *)keyboardShortcutsDescription { - NSMutableString *description = [NSMutableString new]; - NSArray *keyInputs = [self.actionsForKeyInputs.allKeys - sortedArrayUsingComparator:^NSComparisonResult(FLEXKeyInput *input1, FLEXKeyInput *input2) { - return [input1.key caseInsensitiveCompare:input2.key]; - } - ]; - for (FLEXKeyInput *keyInput in keyInputs) { - [description appendFormat:@"%@\n", keyInput]; - } - return [description copy]; -} - -@end - -#endif diff --git a/Tweaks/FLEX/Utility/Runtime/FLEXRuntimeUtility.h b/Tweaks/FLEX/Utility/Runtime/FLEXRuntimeUtility.h deleted file mode 100644 index 38d12a5..0000000 --- a/Tweaks/FLEX/Utility/Runtime/FLEXRuntimeUtility.h +++ /dev/null @@ -1,108 +0,0 @@ -// -// FLEXRuntimeUtility.h -// Flipboard -// -// Created by Ryan Olson on 6/8/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" - -#define PropertyKey(suffix) kFLEXPropertyAttributeKey##suffix : @"" -#define PropertyKeyGetter(getter) kFLEXPropertyAttributeKeyCustomGetter : NSStringFromSelector(@selector(getter)) -#define PropertyKeySetter(setter) kFLEXPropertyAttributeKeyCustomSetter : NSStringFromSelector(@selector(setter)) - -/// Takes: min iOS version, property name, target class, property type, and a list of attributes -#define FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, type, ...) ({ \ - if (@available(iOS iOS_atLeast, *)) { \ - NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithDictionary:@{ \ - kFLEXPropertyAttributeKeyTypeEncoding : @(type), \ - __VA_ARGS__ \ - }]; \ - [FLEXRuntimeUtility \ - tryAddPropertyWithName:#name \ - attributes:attrs \ - toClass:cls \ - ]; \ - } \ -}) - -/// Takes: min iOS version, property name, target class, property type, and a list of attributes -#define FLEXRuntimeUtilityTryAddNonatomicProperty(iOS_atLeast, name, cls, type, ...) \ - FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, @encode(type), PropertyKey(NonAtomic), __VA_ARGS__); -/// Takes: min iOS version, property name, target class, property type (class name), and a list of attributes -#define FLEXRuntimeUtilityTryAddObjectProperty(iOS_atLeast, name, cls, type, ...) \ - FLEXRuntimeUtilityTryAddProperty(iOS_atLeast, name, cls, FLEXEncodeClass(type), PropertyKey(NonAtomic), __VA_ARGS__); - -extern NSString * const FLEXRuntimeUtilityErrorDomain; - -typedef NS_ENUM(NSInteger, FLEXRuntimeUtilityErrorCode) { - // Start at a random value instead of 0 to avoid confusion with an absent code - FLEXRuntimeUtilityErrorCodeDoesNotRecognizeSelector = 0xbabe, - FLEXRuntimeUtilityErrorCodeInvocationFailed, - FLEXRuntimeUtilityErrorCodeArgumentTypeMismatch -}; - -@interface FLEXRuntimeUtility : NSObject - -// General Helpers -+ (BOOL)pointerIsValidObjcObject:(const void *)pointer; -/// Unwraps raw pointers to objects stored in NSValue, and re-boxes C strings into NSStrings. -+ (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXTypeEncoding *)returnType; -/// Some fields have a name in their encoded string (e.g. \"width\"d) -/// @return the offset to skip the field name, 0 if there is no name -+ (NSUInteger)fieldNameOffsetForTypeEncoding:(const FLEXTypeEncoding *)typeEncoding; -/// Given name "foo" and type "int" this would return "int foo", but -/// given name "foo" and type "T *" it would return "T *foo" -+ (NSString *)appendName:(NSString *)name toType:(NSString *)typeEncoding; - -/// @return The class hierarchy for the given object or class, -/// from the current class to the root-most class. -+ (NSArray *)classHierarchyOfObject:(id)objectOrClass; - -/// Used to describe an object in brief within an explorer row -+ (NSString *)summaryForObject:(id)value; -+ (NSString *)safeClassNameForObject:(id)object; -+ (NSString *)safeDescriptionForObject:(id)object; -+ (NSString *)safeDebugDescriptionForObject:(id)object; - -+ (BOOL)safeObject:(id)object isKindOfClass:(Class)cls; -+ (BOOL)safeObject:(id)object respondsToSelector:(SEL)sel; - -// Property Helpers -+ (BOOL)tryAddPropertyWithName:(const char *)name - attributes:(NSDictionary *)attributePairs - toClass:(__unsafe_unretained Class)theClass; -+ (NSArray *)allPropertyAttributeKeys; - -// Method Helpers -+ (NSArray *)prettyArgumentComponentsForMethod:(Method)method; - -// Method Calling/Field Editing -+ (id)performSelector:(SEL)selector onObject:(id)object; -+ (id)performSelector:(SEL)selector - onObject:(id)object - withArguments:(NSArray *)arguments - error:(NSError * __autoreleasing *)error; -+ (id)performSelector:(SEL)selector - onObject:(id)object - withArguments:(NSArray *)arguments - allowForwarding:(BOOL)mightForwardMsgSend - error:(NSError * __autoreleasing *)error; - -+ (NSString *)editableJSONStringForObject:(id)object; -+ (id)objectValueFromEditableJSONString:(NSString *)string; -+ (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString; -+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding - usingBlock:(void (^)(NSString *structName, - const char *fieldTypeEncoding, - NSString *prettyTypeEncoding, - NSUInteger fieldIndex, - NSUInteger fieldOffset))typeBlock; -+ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type; - -#pragma mark - Metadata Helpers - -+ (NSString *)readableTypeForEncoding:(NSString *)encodingString; - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/FLEXRuntimeUtility.m b/Tweaks/FLEX/Utility/Runtime/FLEXRuntimeUtility.m deleted file mode 100644 index b9cd77c..0000000 --- a/Tweaks/FLEX/Utility/Runtime/FLEXRuntimeUtility.m +++ /dev/null @@ -1,881 +0,0 @@ -// -// FLEXRuntimeUtility.m -// Flipboard -// -// Created by Ryan Olson on 6/8/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import "FLEXRuntimeUtility.h" -#import "FLEXObjcInternal.h" -#import "FLEXTypeEncodingParser.h" -#import "FLEXMethod.h" - -NSString * const FLEXRuntimeUtilityErrorDomain = @"FLEXRuntimeUtilityErrorDomain"; - -@implementation FLEXRuntimeUtility - -#pragma mark - General Helpers (Public) - -+ (BOOL)pointerIsValidObjcObject:(const void *)pointer { - return FLEXPointerIsValidObjcObject(pointer); -} - -+ (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXTypeEncoding *)returnType { - if (!returnedObjectOrNil) { - return nil; - } - - NSInteger i = 0; - if (returnType[i] == FLEXTypeEncodingConst) { - i++; - } - - BOOL returnsObjectOrClass = returnType[i] == FLEXTypeEncodingObjcObject || - returnType[i] == FLEXTypeEncodingObjcClass; - BOOL returnsVoidPointer = returnType[i] == FLEXTypeEncodingPointer && - returnType[i+1] == FLEXTypeEncodingVoid; - BOOL returnsCString = returnType[i] == FLEXTypeEncodingCString; - - // If we got back an NSValue and the return type is not an object, - // we check to see if the pointer is of a valid object. If not, - // we just display the NSValue. - if (!returnsObjectOrClass) { - // Skip NSNumber instances - if ([returnedObjectOrNil isKindOfClass:[NSNumber class]]) { - return returnedObjectOrNil; - } - - // Can only be NSValue since return type is not an object, - // so we bail if this doesn't add up - if (![returnedObjectOrNil isKindOfClass:[NSValue class]]) { - return returnedObjectOrNil; - } - - NSValue *value = (NSValue *)returnedObjectOrNil; - - if (returnsCString) { - // Wrap char * in NSString - const char *string = (const char *)value.pointerValue; - returnedObjectOrNil = string ? [NSString stringWithCString:string encoding:NSUTF8StringEncoding] : NULL; - } else if (returnsVoidPointer) { - // Cast valid objects disguised as void * to id - if ([FLEXRuntimeUtility pointerIsValidObjcObject:value.pointerValue]) { - returnedObjectOrNil = (__bridge id)value.pointerValue; - } - } - } - - return returnedObjectOrNil; -} - -+ (NSUInteger)fieldNameOffsetForTypeEncoding:(const FLEXTypeEncoding *)typeEncoding { - NSUInteger beginIndex = 0; - while (typeEncoding[beginIndex] == FLEXTypeEncodingQuote) { - NSUInteger endIndex = beginIndex + 1; - while (typeEncoding[endIndex] != FLEXTypeEncodingQuote) { - ++endIndex; - } - beginIndex = endIndex + 1; - } - return beginIndex; -} - -+ (NSArray *)classHierarchyOfObject:(id)objectOrClass { - NSMutableArray *superClasses = [NSMutableArray new]; - id cls = [objectOrClass class]; - do { - [superClasses addObject:cls]; - } while ((cls = [cls superclass])); - - return superClasses; -} - -+ (NSString *)safeClassNameForObject:(id)object { - // Don't assume that we have an NSObject subclass - if ([self safeObject:object respondsToSelector:@selector(class)]) { - return NSStringFromClass([object class]); - } - - return NSStringFromClass(object_getClass(object)); -} - -/// Could be nil -+ (NSString *)safeDescriptionForObject:(id)object { - // Don't assume that we have an NSObject subclass; not all objects respond to -description - if ([self safeObject:object respondsToSelector:@selector(description)]) { - @try { - return [object description]; - } @catch (NSException *exception) { - return nil; - } - } - - return nil; -} - -/// Never nil -+ (NSString *)safeDebugDescriptionForObject:(id)object { - NSString *description = nil; - - if ([self safeObject:object respondsToSelector:@selector(debugDescription)]) { - @try { - description = [object debugDescription]; - } @catch (NSException *exception) { } - } else { - description = [self safeDescriptionForObject:object]; - } - - if (!description.length) { - NSString *cls = NSStringFromClass(object_getClass(object)); - if (object_isClass(object)) { - description = [cls stringByAppendingString:@" class (no description)"]; - } else { - description = [cls stringByAppendingString:@" instance (no description)"]; - } - } - - return description; -} - -+ (NSString *)summaryForObject:(id)value { - NSString *description = nil; - - // Special case BOOL for better readability. - if ([self safeObject:value isKindOfClass:[NSValue class]]) { - const char *type = [value objCType]; - if (strcmp(type, @encode(BOOL)) == 0) { - BOOL boolValue = NO; - [value getValue:&boolValue]; - return boolValue ? @"YES" : @"NO"; - } else if (strcmp(type, @encode(SEL)) == 0) { - SEL selector = NULL; - [value getValue:&selector]; - return NSStringFromSelector(selector); - } - } - - @try { - // Single line display - replace newlines and tabs with spaces. - description = [[self safeDescriptionForObject:value] stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; - description = [description stringByReplacingOccurrencesOfString:@"\t" withString:@" "]; - } @catch (NSException *e) { - description = [@"Thrown: " stringByAppendingString:e.reason ?: @"(nil exception reason)"]; - } - - if (!description) { - description = @"nil"; - } - - return description; -} - -+ (BOOL)safeObject:(id)object isKindOfClass:(Class)cls { - static BOOL (*isKindOfClass)(id, SEL, Class) = nil; - static BOOL (*isKindOfClass_meta)(id, SEL, Class) = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - isKindOfClass = (BOOL(*)(id, SEL, Class))[NSObject instanceMethodForSelector:@selector(isKindOfClass:)]; - isKindOfClass_meta = (BOOL(*)(id, SEL, Class))[NSObject methodForSelector:@selector(isKindOfClass:)]; - }); - - BOOL isClass = object_isClass(object); - return (isClass ? isKindOfClass_meta : isKindOfClass)(object, @selector(isKindOfClass:), cls); -} - -+ (BOOL)safeObject:(id)object respondsToSelector:(SEL)sel { - // If we're given a class, we want to know if classes respond to this selector. - // Similarly, if we're given an instance, we want to know if instances respond. - BOOL isClass = object_isClass(object); - Class cls = isClass ? object : object_getClass(object); - // BOOL isMetaclass = class_isMetaClass(cls); - - if (isClass) { - // In theory, this should also work for metaclasses... - return class_getClassMethod(cls, sel) != nil; - } else { - return class_getInstanceMethod(cls, sel) != nil; - } -} - - -#pragma mark - Property Helpers (Public) - -+ (BOOL)tryAddPropertyWithName:(const char *)name - attributes:(NSDictionary *)attributePairs - toClass:(__unsafe_unretained Class)theClass { - objc_property_t property = class_getProperty(theClass, name); - if (!property) { - unsigned int totalAttributesCount = (unsigned int)attributePairs.count; - objc_property_attribute_t *attributes = malloc(sizeof(objc_property_attribute_t) * totalAttributesCount); - if (attributes) { - unsigned int attributeIndex = 0; - for (NSString *attributeName in attributePairs.allKeys) { - objc_property_attribute_t attribute; - attribute.name = attributeName.UTF8String; - attribute.value = attributePairs[attributeName].UTF8String; - attributes[attributeIndex++] = attribute; - } - - BOOL success = class_addProperty(theClass, name, attributes, totalAttributesCount); - free(attributes); - return success; - } else { - return NO; - } - } - - return YES; -} - -+ (NSArray *)allPropertyAttributeKeys { - static NSArray *allPropertyAttributeKeys = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - allPropertyAttributeKeys = @[ - kFLEXPropertyAttributeKeyTypeEncoding, - kFLEXPropertyAttributeKeyBackingIvarName, - kFLEXPropertyAttributeKeyReadOnly, - kFLEXPropertyAttributeKeyCopy, - kFLEXPropertyAttributeKeyRetain, - kFLEXPropertyAttributeKeyNonAtomic, - kFLEXPropertyAttributeKeyCustomGetter, - kFLEXPropertyAttributeKeyCustomSetter, - kFLEXPropertyAttributeKeyDynamic, - kFLEXPropertyAttributeKeyWeak, - kFLEXPropertyAttributeKeyGarbageCollectable, - kFLEXPropertyAttributeKeyOldStyleTypeEncoding, - ]; - }); - - return allPropertyAttributeKeys; -} - - -#pragma mark - Method Helpers (Public) - -+ (NSArray *)prettyArgumentComponentsForMethod:(Method)method { - NSMutableArray *components = [NSMutableArray new]; - - NSString *selectorName = NSStringFromSelector(method_getName(method)); - NSMutableArray *selectorComponents = [selectorName componentsSeparatedByString:@":"].mutableCopy; - - // this is a workaround cause method_getNumberOfArguments() returns wrong number for some methods - if (selectorComponents.count == 1) { - return @[]; - } - - if ([selectorComponents.lastObject isEqualToString:@""]) { - [selectorComponents removeLastObject]; - } - - for (unsigned int argIndex = 0; argIndex < selectorComponents.count; argIndex++) { - char *argType = method_copyArgumentType(method, argIndex + kFLEXNumberOfImplicitArgs); - NSString *readableArgType = (argType != NULL) ? [self readableTypeForEncoding:@(argType)] : nil; - free(argType); - NSString *prettyComponent = [NSString - stringWithFormat:@"%@:(%@) ", - selectorComponents[argIndex], - readableArgType - ]; - [components addObject:prettyComponent]; - } - - return components; -} - - -#pragma mark - Method Calling/Field Editing (Public) - -+ (id)performSelector:(SEL)selector onObject:(id)object { - return [self performSelector:selector onObject:object withArguments:@[] error:nil]; -} - -+ (id)performSelector:(SEL)selector - onObject:(id)object - withArguments:(NSArray *)arguments - error:(NSError * __autoreleasing *)error { - return [self performSelector:selector - onObject:object - withArguments:arguments - allowForwarding:NO - error:error - ]; -} - -+ (id)performSelector:(SEL)selector - onObject:(id)object - withArguments:(NSArray *)arguments - allowForwarding:(BOOL)mightForwardMsgSend - error:(NSError * __autoreleasing *)error { - static dispatch_once_t onceToken; - static SEL stdStringExclusion = nil; - dispatch_once(&onceToken, ^{ - stdStringExclusion = NSSelectorFromString(@"stdString"); - }); - - // Bail if the object won't respond to this selector - if (mightForwardMsgSend || ![self safeObject:object respondsToSelector:selector]) { - if (error) { - NSString *msg = [NSString - stringWithFormat:@"This object does not respond to the selector %@", - NSStringFromSelector(selector) - ]; - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : msg }; - *error = [NSError - errorWithDomain:FLEXRuntimeUtilityErrorDomain - code:FLEXRuntimeUtilityErrorCodeDoesNotRecognizeSelector - userInfo:userInfo - ]; - } - - return nil; - } - - // It is important to use object_getClass and not -class here, as - // object_getClass will return a different result for class objects - Class cls = object_getClass(object); - NSMethodSignature *methodSignature = [FLEXMethod selector:selector class:cls].signature; - if (!methodSignature) { - // Unsupported type encoding - return nil; - } - - // Probably an unsupported type encoding, like bitfields. - // In the future, we could calculate the return length - // on our own. For now, we abort. - // - // For future reference, the code here will get the true type encoding. - // NSMethodSignature will convert {?=b8b4b1b1b18[8S]} to {?} - // - // returnType = method_getTypeEncoding(class_getInstanceMethod([object class], selector)); - if (!methodSignature.methodReturnLength && - methodSignature.methodReturnType[0] != FLEXTypeEncodingVoid) { - return nil; - } - - // Build the invocation - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:object]; - [invocation retainArguments]; - - // Always self and _cmd - NSUInteger numberOfArguments = methodSignature.numberOfArguments; - for (NSUInteger argumentIndex = kFLEXNumberOfImplicitArgs; argumentIndex < numberOfArguments; argumentIndex++) { - NSUInteger argumentsArrayIndex = argumentIndex - kFLEXNumberOfImplicitArgs; - id argumentObject = arguments.count > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil; - - // NSNull in the arguments array can be passed as a placeholder to indicate nil. - // We only need to set the argument if it will be non-nil. - if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) { - const char *typeEncodingCString = [methodSignature getArgumentTypeAtIndex:argumentIndex]; - if (typeEncodingCString[0] == FLEXTypeEncodingObjcObject || - typeEncodingCString[0] == FLEXTypeEncodingObjcClass || - [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) { - // Object - [invocation setArgument:&argumentObject atIndex:argumentIndex]; - } else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0 && - [argumentObject isKindOfClass:[UIColor class]]) { - // Bridging UIColor to CGColorRef - CGColorRef colorRef = [argumentObject CGColor]; - [invocation setArgument:&colorRef atIndex:argumentIndex]; - } else if ([argumentObject isKindOfClass:[NSValue class]]) { - // Primitive boxed in NSValue - NSValue *argumentValue = (NSValue *)argumentObject; - - // Ensure that the type encoding on the NSValue matches the type encoding of the argument in the method signature - if (strcmp([argumentValue objCType], typeEncodingCString) != 0) { - if (error) { - NSString *msg = [NSString - stringWithFormat:@"Type encoding mismatch for argument at index %lu. " - "Value type: %s; Method argument type: %s.", - (unsigned long)argumentsArrayIndex, argumentValue.objCType, typeEncodingCString - ]; - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : msg }; - *error = [NSError - errorWithDomain:FLEXRuntimeUtilityErrorDomain - code:FLEXRuntimeUtilityErrorCodeArgumentTypeMismatch - userInfo:userInfo - ]; - } - return nil; - } - - @try { - NSUInteger bufferSize = 0; - FLEXGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL); - - if (bufferSize > 0) { - void *buffer = alloca(bufferSize); - [argumentValue getValue:buffer]; - [invocation setArgument:buffer atIndex:argumentIndex]; - } - } @catch (NSException *exception) { } - } - } - } - - // Try to invoke the invocation but guard against an exception being thrown. - id returnObject = nil; - @try { - [invocation invoke]; - - // Retrieve the return value and box if necessary. - const char *returnType = methodSignature.methodReturnType; - - if (returnType[0] == FLEXTypeEncodingObjcObject || returnType[0] == FLEXTypeEncodingObjcClass) { - // Return value is an object. - __unsafe_unretained id objectReturnedFromMethod = nil; - [invocation getReturnValue:&objectReturnedFromMethod]; - returnObject = objectReturnedFromMethod; - } else if (returnType[0] != FLEXTypeEncodingVoid) { - NSAssert(methodSignature.methodReturnLength, @"Memory corruption lies ahead"); - - if (returnType[0] == FLEXTypeEncodingStructBegin) { - if (selector == stdStringExclusion && [object isKindOfClass:[NSString class]]) { - // stdString is a C++ object and we will crash if we try to access it - if (error) { - *error = [NSError - errorWithDomain:FLEXRuntimeUtilityErrorDomain - code:FLEXRuntimeUtilityErrorCodeInvocationFailed - userInfo:@{ NSLocalizedDescriptionKey : @"Skipping -[NSString stdString]" } - ]; - } - - return nil; - } - } - - // Will use arbitrary buffer for return value and box it. - void *returnValue = malloc(methodSignature.methodReturnLength); - [invocation getReturnValue:returnValue]; - returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType]; - free(returnValue); - } - } @catch (NSException *exception) { - // Bummer... - if (error) { - // "… on " / "… on instance of " - NSString *class = NSStringFromClass([object class]); - NSString *calledOn = object == [object class] ? class : [@"an instance of " stringByAppendingString:class]; - - NSString *message = [NSString - stringWithFormat:@"Exception '%@' thrown while performing selector '%@' on %@.\nReason:\n\n%@", - exception.name, NSStringFromSelector(selector), calledOn, exception.reason - ]; - - *error = [NSError - errorWithDomain:FLEXRuntimeUtilityErrorDomain - code:FLEXRuntimeUtilityErrorCodeInvocationFailed - userInfo:@{ NSLocalizedDescriptionKey : message } - ]; - } - } - - return returnObject; -} - -+ (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding { - // See https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html -#define CASE(cftype, foundationClass) \ - if (strcmp(typeEncoding, @encode(cftype)) == 0) { \ - return [value isKindOfClass:[foundationClass class]]; \ - } - - CASE(CFArrayRef, NSArray); - CASE(CFAttributedStringRef, NSAttributedString); - CASE(CFCalendarRef, NSCalendar); - CASE(CFCharacterSetRef, NSCharacterSet); - CASE(CFDataRef, NSData); - CASE(CFDateRef, NSDate); - CASE(CFDictionaryRef, NSDictionary); - CASE(CFErrorRef, NSError); - CASE(CFLocaleRef, NSLocale); - CASE(CFMutableArrayRef, NSMutableArray); - CASE(CFMutableAttributedStringRef, NSMutableAttributedString); - CASE(CFMutableCharacterSetRef, NSMutableCharacterSet); - CASE(CFMutableDataRef, NSMutableData); - CASE(CFMutableDictionaryRef, NSMutableDictionary); - CASE(CFMutableSetRef, NSMutableSet); - CASE(CFMutableStringRef, NSMutableString); - CASE(CFNumberRef, NSNumber); - CASE(CFReadStreamRef, NSInputStream); - CASE(CFRunLoopTimerRef, NSTimer); - CASE(CFSetRef, NSSet); - CASE(CFStringRef, NSString); - CASE(CFTimeZoneRef, NSTimeZone); - CASE(CFURLRef, NSURL); - CASE(CFWriteStreamRef, NSOutputStream); - -#undef CASE - - return NO; -} - -+ (NSString *)editableJSONStringForObject:(id)object { - NSString *editableDescription = nil; - - if (object) { - // This is a hack to use JSON serialization for our editable objects. - // NSJSONSerialization doesn't allow writing fragments - the top level object must be an array or dictionary. - // We always wrap the object inside an array and then strip the outer square braces off the final string. - NSArray *wrappedObject = @[object]; - if ([NSJSONSerialization isValidJSONObject:wrappedObject]) { - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:wrappedObject options:0 error:NULL]; - NSString *wrappedDescription = [NSString stringWithUTF8String:jsonData.bytes]; - editableDescription = [wrappedDescription substringWithRange:NSMakeRange(1, wrappedDescription.length - 2)]; - } - } - - return editableDescription; -} - -+ (id)objectValueFromEditableJSONString:(NSString *)string { - id value = nil; - // nil for empty string/whitespace - if ([string stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet].length) { - value = [NSJSONSerialization - JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding] - options:NSJSONReadingAllowFragments - error:NULL - ]; - } - return value; -} - -+ (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString { - NSNumberFormatter *formatter = [NSNumberFormatter new]; - [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; - NSNumber *number = [formatter numberFromString:inputString]; - - // Is the type encoding longer than one character? - if (strlen(typeEncoding) > 1) { - NSString *type = @(typeEncoding); - - // Is it NSDecimalNumber or NSNumber? - if ([type isEqualToString:@FLEXEncodeClass(NSDecimalNumber)]) { - return [NSDecimalNumber decimalNumberWithString:inputString]; - } else if ([type isEqualToString:@FLEXEncodeClass(NSNumber)]) { - return number; - } - - return nil; - } - - // Type encoding is one character, switch on the type - FLEXTypeEncoding type = typeEncoding[0]; - uint8_t value[32]; - void *bufferStart = &value[0]; - - // Make sure we box the number with the correct type encoding - // so it can be properly unboxed later via getValue: - switch (type) { - case FLEXTypeEncodingChar: - *(char *)bufferStart = number.charValue; break; - case FLEXTypeEncodingInt: - *(int *)bufferStart = number.intValue; break; - case FLEXTypeEncodingShort: - *(short *)bufferStart = number.shortValue; break; - case FLEXTypeEncodingLong: - *(long *)bufferStart = number.longValue; break; - case FLEXTypeEncodingLongLong: - *(long long *)bufferStart = number.longLongValue; break; - case FLEXTypeEncodingUnsignedChar: - *(unsigned char *)bufferStart = number.unsignedCharValue; break; - case FLEXTypeEncodingUnsignedInt: - *(unsigned int *)bufferStart = number.unsignedIntValue; break; - case FLEXTypeEncodingUnsignedShort: - *(unsigned short *)bufferStart = number.unsignedShortValue; break; - case FLEXTypeEncodingUnsignedLong: - *(unsigned long *)bufferStart = number.unsignedLongValue; break; - case FLEXTypeEncodingUnsignedLongLong: - *(unsigned long long *)bufferStart = number.unsignedLongLongValue; break; - case FLEXTypeEncodingFloat: - *(float *)bufferStart = number.floatValue; break; - case FLEXTypeEncodingDouble: - *(double *)bufferStart = number.doubleValue; break; - - case FLEXTypeEncodingLongDouble: - // NSNumber does not support long double - default: - return nil; - } - - return [NSValue value:value withObjCType:typeEncoding]; -} - -+ (void)enumerateTypesInStructEncoding:(const char *)structEncoding - usingBlock:(void (^)(NSString *structName, - const char *fieldTypeEncoding, - NSString *prettyTypeEncoding, - NSUInteger fieldIndex, - NSUInteger fieldOffset))typeBlock { - if (structEncoding && structEncoding[0] == FLEXTypeEncodingStructBegin) { - const char *equals = strchr(structEncoding, '='); - if (equals) { - const char *nameStart = structEncoding + 1; - NSString *structName = [@(structEncoding) - substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart) - ]; - - NSUInteger fieldAlignment = 0, structSize = 0; - if (FLEXGetSizeAndAlignment(structEncoding, &structSize, &fieldAlignment)) { - NSUInteger runningFieldIndex = 0; - NSUInteger runningFieldOffset = 0; - const char *typeStart = equals + 1; - - while (*typeStart != FLEXTypeEncodingStructEnd) { - NSUInteger fieldSize = 0; - // If the struct type encoding was successfully handled by - // FLEXGetSizeAndAlignment above, we *should* be ok with the field here. - const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL); - NSString *typeEncoding = [@(structEncoding) - substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart) - ]; - - // Padding to keep proper alignment. __attribute((packed)) structs - // will break here. The type encoding is no different for packed structs, - // so it's not clear there's anything we can do for those. - const NSUInteger currentSizeSum = runningFieldOffset % fieldAlignment; - if (currentSizeSum != 0 && currentSizeSum + fieldSize > fieldAlignment) { - runningFieldOffset += fieldAlignment - currentSizeSum; - } - - typeBlock( - structName, - typeEncoding.UTF8String, - [self readableTypeForEncoding:typeEncoding], - runningFieldIndex, - runningFieldOffset - ); - runningFieldOffset += fieldSize; - runningFieldIndex++; - typeStart = nextTypeStart; - } - } - } - } -} - - -#pragma mark - Metadata Helpers - -+ (NSDictionary *)attributesForProperty:(objc_property_t)property { - NSString *attributes = @(property_getAttributes(property) ?: ""); - // Thanks to MAObjcRuntime for inspiration here. - NSArray *attributePairs = [attributes componentsSeparatedByString:@","]; - NSMutableDictionary *attributesDictionary = [NSMutableDictionary new]; - for (NSString *attributePair in attributePairs) { - attributesDictionary[[attributePair substringToIndex:1]] = [attributePair substringFromIndex:1]; - } - return attributesDictionary; -} - -+ (NSString *)appendName:(NSString *)name toType:(NSString *)type { - if (!type.length) { - type = @"(?)"; - } - - NSString *combined = nil; - if ([type characterAtIndex:type.length - 1] == FLEXTypeEncodingCString) { - combined = [type stringByAppendingString:name]; - } else { - combined = [type stringByAppendingFormat:@" %@", name]; - } - return combined; -} - -+ (NSString *)readableTypeForEncoding:(NSString *)encodingString { - if (!encodingString.length) { - return @"?"; - } - - // See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html - // class-dump has a much nicer and much more complete implementation for this task, but it is distributed under GPLv2 :/ - // See https://github.com/nygard/class-dump/blob/master/Source/CDType.m - // Warning: this method uses multiple middle returns and macros to cut down on boilerplate. - // The use of macros here was inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html - const char *encodingCString = encodingString.UTF8String; - - // Some fields have a name, such as {Size=\"width\"d\"height\"d}, we need to extract the name out and recursive - const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:encodingCString]; - if (fieldNameOffset > 0) { - // According to https://github.com/nygard/class-dump/commit/33fb5ed221810685f57c192e1ce8ab6054949a7c, - // there are some consecutive quoted strings, so use `_` to concatenate the names. - NSString *const fieldNamesString = [encodingString substringWithRange:NSMakeRange(0, fieldNameOffset)]; - NSArray *const fieldNames = [fieldNamesString - componentsSeparatedByString:[NSString stringWithFormat:@"%c", FLEXTypeEncodingQuote] - ]; - NSMutableString *finalFieldNamesString = [NSMutableString new]; - for (NSString *const fieldName in fieldNames) { - if (fieldName.length > 0) { - if (finalFieldNamesString.length > 0) { - [finalFieldNamesString appendString:@"_"]; - } - [finalFieldNamesString appendString:fieldName]; - } - } - NSString *const recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:fieldNameOffset]]; - return [NSString stringWithFormat:@"%@ %@", recursiveType, finalFieldNamesString]; - } - - // Objects - if (encodingCString[0] == FLEXTypeEncodingObjcObject) { - NSString *class = [encodingString substringFromIndex:1]; - class = [class stringByReplacingOccurrencesOfString:@"\"" withString:@""]; - if (class.length == 0 || (class.length == 1 && [class characterAtIndex:0] == FLEXTypeEncodingUnknown)) { - class = @"id"; - } else { - class = [class stringByAppendingString:@" *"]; - } - return class; - } - - // Qualifier Prefixes - // Do this first since some of the direct translations (i.e. Method) contain a prefix. -#define RECURSIVE_TRANSLATE(prefix, formatString) \ - if (encodingCString[0] == prefix) { \ - NSString *recursiveType = [self readableTypeForEncoding:[encodingString substringFromIndex:1]]; \ - return [NSString stringWithFormat:formatString, recursiveType]; \ - } - - // If there's a qualifier prefix on the encoding, translate it and then - // recursively call this method with the rest of the encoding string. - RECURSIVE_TRANSLATE('^', @"%@ *"); - RECURSIVE_TRANSLATE('r', @"const %@"); - RECURSIVE_TRANSLATE('n', @"in %@"); - RECURSIVE_TRANSLATE('N', @"inout %@"); - RECURSIVE_TRANSLATE('o', @"out %@"); - RECURSIVE_TRANSLATE('O', @"bycopy %@"); - RECURSIVE_TRANSLATE('R', @"byref %@"); - RECURSIVE_TRANSLATE('V', @"oneway %@"); - RECURSIVE_TRANSLATE('b', @"bitfield(%@)"); - -#undef RECURSIVE_TRANSLATE - - // C Types -#define TRANSLATE(ctype) \ - if (strcmp(encodingCString, @encode(ctype)) == 0) { \ - return (NSString *)CFSTR(#ctype); \ - } - - // Order matters here since some of the cocoa types are typedefed to c types. - // We can't recover the exact mapping, but we choose to prefer the cocoa types. - // This is not an exhaustive list, but it covers the most common types - TRANSLATE(CGRect); - TRANSLATE(CGPoint); - TRANSLATE(CGSize); - TRANSLATE(CGVector); - TRANSLATE(UIEdgeInsets); - if (@available(iOS 11.0, *)) { - TRANSLATE(NSDirectionalEdgeInsets); - } - TRANSLATE(UIOffset); - TRANSLATE(NSRange); - TRANSLATE(CGAffineTransform); - TRANSLATE(CATransform3D); - TRANSLATE(CGColorRef); - TRANSLATE(CGPathRef); - TRANSLATE(CGContextRef); - TRANSLATE(NSInteger); - TRANSLATE(NSUInteger); - TRANSLATE(CGFloat); - TRANSLATE(BOOL); - TRANSLATE(int); - TRANSLATE(short); - TRANSLATE(long); - TRANSLATE(long long); - TRANSLATE(unsigned char); - TRANSLATE(unsigned int); - TRANSLATE(unsigned short); - TRANSLATE(unsigned long); - TRANSLATE(unsigned long long); - TRANSLATE(float); - TRANSLATE(double); - TRANSLATE(long double); - TRANSLATE(char *); - TRANSLATE(Class); - TRANSLATE(objc_property_t); - TRANSLATE(Ivar); - TRANSLATE(Method); - TRANSLATE(Category); - TRANSLATE(NSZone *); - TRANSLATE(SEL); - TRANSLATE(void); - -#undef TRANSLATE - - // For structs, we only use the name of the structs - if (encodingCString[0] == FLEXTypeEncodingStructBegin) { - // Special case: std::string - if ([encodingString hasPrefix:@"{basic_string d) - const NSUInteger fieldNameOffset = [FLEXRuntimeUtility fieldNameOffsetForTypeEncoding:type]; - if (fieldNameOffset > 0) { - return [self valueForPrimitivePointer:pointer objCType:type + fieldNameOffset]; - } - - // CASE macro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html -#define CASE(ctype, selectorpart) \ - if (strcmp(type, @encode(ctype)) == 0) { \ - return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \ - } - - CASE(BOOL, Bool); - CASE(unsigned char, UnsignedChar); - CASE(short, Short); - CASE(unsigned short, UnsignedShort); - CASE(int, Int); - CASE(unsigned int, UnsignedInt); - CASE(long, Long); - CASE(unsigned long, UnsignedLong); - CASE(long long, LongLong); - CASE(unsigned long long, UnsignedLongLong); - CASE(float, Float); - CASE(double, Double); - CASE(long double, Double); - -#undef CASE - - NSValue *value = nil; - if (FLEXGetSizeAndAlignment(type, nil, nil)) { - @try { - value = [NSValue valueWithBytes:pointer objCType:type]; - } @catch (NSException *exception) { - // Certain type encodings are not supported by valueWithBytes:objCType:. - // Just fail silently if an exception is thrown. - } - } - - return value; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.h b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.h deleted file mode 100644 index d5e0ddc..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// FLEXObjcInternal.h -// FLEX -// -// Created by Tanner Bennett on 11/1/18. -// - -#import - -#ifdef __cplusplus -extern "C" { -#endif - -// The macros below are copied straight from -// objc-internal.h, objc-private.h, objc-object.h, and objc-config.h with -// as few modifications as possible. Changes are noted in boxed comments. -// https://opensource.apple.com/source/objc4/objc4-723/ -// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-internal.h.auto.html -// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-object.h.auto.html - -///////////////////// -// objc-internal.h // -///////////////////// - -#if __LP64__ -#define OBJC_HAVE_TAGGED_POINTERS 1 -#endif - -#if OBJC_HAVE_TAGGED_POINTERS - -#if TARGET_OS_OSX && __x86_64__ -// 64-bit Mac - tag bit is LSB -# define OBJC_MSB_TAGGED_POINTERS 0 -#else -// Everything else - tag bit is MSB -# define OBJC_MSB_TAGGED_POINTERS 1 -#endif - -#if OBJC_MSB_TAGGED_POINTERS -# define _OBJC_TAG_MASK (1UL<<63) -# define _OBJC_TAG_EXT_MASK (0xfUL<<60) -#else -# define _OBJC_TAG_MASK 1UL -# define _OBJC_TAG_EXT_MASK 0xfUL -#endif - -#endif // OBJC_HAVE_TAGGED_POINTERS - -////////////////////////////////////// -// originally _objc_isTaggedPointer // -////////////////////////////////////// -NS_INLINE BOOL flex_isTaggedPointer(const void *ptr) { - #if OBJC_HAVE_TAGGED_POINTERS - return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK; - #else - return NO; - #endif -} - -#define FLEXPointerIsTaggedPointer(obj) flex_isTaggedPointer((__bridge void *)obj) - -BOOL FLEXPointerIsReadable(const void * ptr); - -/// @brief Assumes memory is valid and readable. -/// @discussion objc-internal.h, objc-private.h, and objc-config.h -/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/ -/// https://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py -/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/ -BOOL FLEXPointerIsValidObjcObject(const void * ptr); - -#ifdef __cplusplus -} -#endif diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.mm b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.mm deleted file mode 100644 index ff17dcf..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.mm +++ /dev/null @@ -1,196 +0,0 @@ -// -// FLEXObjcInternal.mm -// FLEX -// -// Created by Tanner Bennett on 11/1/18. -// - -/* - * Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import "FLEXObjcInternal.h" -#import -// For malloc_size -#import -// For vm_region_64 -#include - -#if __arm64e__ -#include -#endif - -#define ALWAYS_INLINE inline __attribute__((always_inline)) -#define NEVER_INLINE inline __attribute__((noinline)) - -// The macros below are copied straight from -// objc-internal.h, objc-private.h, objc-object.h, and objc-config.h with -// as few modifications as possible. Changes are noted in boxed comments. -// https://opensource.apple.com/source/objc4/objc4-723/ -// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-internal.h.auto.html -// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-object.h.auto.html - -///////////////////// -// objc-internal.h // -///////////////////// - -#if OBJC_HAVE_TAGGED_POINTERS - -/////////////////// -// objc-object.h // -/////////////////// - -//////////////////////////////////////////////// -// originally objc_object::isExtTaggedPointer // -//////////////////////////////////////////////// -NS_INLINE BOOL flex_isExtTaggedPointer(const void *ptr) { - return ((uintptr_t)ptr & _OBJC_TAG_EXT_MASK) == _OBJC_TAG_EXT_MASK; -} - -#endif // OBJC_HAVE_TAGGED_POINTERS - -///////////////////////////////////// -// FLEXObjectInternal // -// No Apple code beyond this point // -///////////////////////////////////// - -extern "C" { - -BOOL FLEXPointerIsReadable(const void *inPtr) { - kern_return_t error = KERN_SUCCESS; - - vm_size_t vmsize; -#if __arm64e__ - // On arm64e, we need to strip the PAC from the pointer so the adress is readable - vm_address_t address = (vm_address_t)ptrauth_strip(inPtr, ptrauth_key_function_pointer); -#else - vm_address_t address = (vm_address_t)inPtr; -#endif - vm_region_basic_info_data_t info; - mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64; - memory_object_name_t object; - - error = vm_region_64( - mach_task_self(), - &address, - &vmsize, - VM_REGION_BASIC_INFO, - (vm_region_info_t)&info, - &info_count, - &object - ); - - if (error != KERN_SUCCESS) { - // vm_region/vm_region_64 returned an error - return NO; - } else if (!(BOOL)(info.protection & VM_PROT_READ)) { - return NO; - } - -#if __arm64e__ - address = (vm_address_t)ptrauth_strip(inPtr, ptrauth_key_function_pointer); -#else - address = (vm_address_t)inPtr; -#endif - - // Read the memory - vm_size_t size = 0; - char buf[sizeof(uintptr_t)]; - error = vm_read_overwrite(mach_task_self(), address, sizeof(uintptr_t), (vm_address_t)buf, &size); - if (error != KERN_SUCCESS) { - // vm_read_overwrite returned an error - return NO; - } - - return YES; -} - -/// Accepts addresses that may or may not be readable. -/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/ -BOOL FLEXPointerIsValidObjcObject(const void *ptr) { - uintptr_t pointer = (uintptr_t)ptr; - - if (!ptr) { - return NO; - } - -#if OBJC_HAVE_TAGGED_POINTERS - // Tagged pointers have 0x1 set, no other valid pointers do - // objc-internal.h -> _objc_isTaggedPointer() - if (flex_isTaggedPointer(ptr) || flex_isExtTaggedPointer(ptr)) { - return YES; - } -#endif - - // Check pointer alignment - if ((pointer % sizeof(uintptr_t)) != 0) { - return NO; - } - - // From LLDB: - // Pointers in a class_t will only have bits 0 through 46 set, - // so if any pointer has bits 47 through 63 high, we know that this is not a valid isa - // https://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py - if ((pointer & 0xFFFF800000000000) != 0) { - return NO; - } - - // Make sure dereferencing this address won't crash - if (!FLEXPointerIsReadable(ptr)) { - return NO; - } - - // http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html - // We check if the returned class is readable because object_getClass - // can return a garbage value when given a non-nil pointer to a non-object - Class cls = object_getClass((__bridge id)ptr); - if (!cls || !FLEXPointerIsReadable((__bridge void *)cls)) { - return NO; - } - - // Just because this pointer is readable doesn't mean whatever is at - // it's ISA offset is readable. We need to do the same checks on it's ISA. - // Even this isn't perfect, because once we call object_isClass, we're - // going to dereference a member of the metaclass, which may or may not - // be readable itself. For the time being there is no way to access it - // to check here, and I have yet to hard-code a solution. - Class metaclass = object_getClass(cls); - if (!metaclass || !FLEXPointerIsReadable((__bridge void *)metaclass)) { - return NO; - } - - // Does the class pointer we got appear as a class to the runtime? - if (!object_isClass(cls)) { - return NO; - } - - // Is the allocation size at least as large as the expected instance size? - ssize_t instanceSize = class_getInstanceSize(cls); - if (malloc_size(ptr) < instanceSize) { - return NO; - } - - return YES; -} - - -} // End extern "C" diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeConstants.h b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeConstants.h deleted file mode 100644 index 09b07e7..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeConstants.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// FLEXRuntimeConstants.h -// FLEX -// -// Created by Tanner on 3/11/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import -#import - -#define FLEXEncodeClass(class) ("@\"" #class "\"") -#define FLEXEncodeObject(obj) (obj ? [NSString stringWithFormat:@"@\"%@\"", [obj class]].UTF8String : @encode(id)) - -// Arguments 0 and 1 are self and _cmd always -extern const unsigned int kFLEXNumberOfImplicitArgs; - -// See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6 -extern NSString *const kFLEXPropertyAttributeKeyTypeEncoding; -extern NSString *const kFLEXPropertyAttributeKeyBackingIvarName; -extern NSString *const kFLEXPropertyAttributeKeyReadOnly; -extern NSString *const kFLEXPropertyAttributeKeyCopy; -extern NSString *const kFLEXPropertyAttributeKeyRetain; -extern NSString *const kFLEXPropertyAttributeKeyNonAtomic; -extern NSString *const kFLEXPropertyAttributeKeyCustomGetter; -extern NSString *const kFLEXPropertyAttributeKeyCustomSetter; -extern NSString *const kFLEXPropertyAttributeKeyDynamic; -extern NSString *const kFLEXPropertyAttributeKeyWeak; -extern NSString *const kFLEXPropertyAttributeKeyGarbageCollectable; -extern NSString *const kFLEXPropertyAttributeKeyOldStyleTypeEncoding; - -typedef NS_ENUM(NSUInteger, FLEXPropertyAttribute) { - FLEXPropertyAttributeTypeEncoding = 'T', - FLEXPropertyAttributeBackingIvarName = 'V', - FLEXPropertyAttributeCopy = 'C', - FLEXPropertyAttributeCustomGetter = 'G', - FLEXPropertyAttributeCustomSetter = 'S', - FLEXPropertyAttributeDynamic = 'D', - FLEXPropertyAttributeGarbageCollectible = 'P', - FLEXPropertyAttributeNonAtomic = 'N', - FLEXPropertyAttributeOldTypeEncoding = 't', - FLEXPropertyAttributeReadOnly = 'R', - FLEXPropertyAttributeRetain = '&', - FLEXPropertyAttributeWeak = 'W' -}; //NS_SWIFT_NAME(FLEX.PropertyAttribute); - -typedef NS_ENUM(char, FLEXTypeEncoding) { - FLEXTypeEncodingNull = '\0', - FLEXTypeEncodingUnknown = '?', - FLEXTypeEncodingChar = 'c', - FLEXTypeEncodingInt = 'i', - FLEXTypeEncodingShort = 's', - FLEXTypeEncodingLong = 'l', - FLEXTypeEncodingLongLong = 'q', - FLEXTypeEncodingUnsignedChar = 'C', - FLEXTypeEncodingUnsignedInt = 'I', - FLEXTypeEncodingUnsignedShort = 'S', - FLEXTypeEncodingUnsignedLong = 'L', - FLEXTypeEncodingUnsignedLongLong = 'Q', - FLEXTypeEncodingFloat = 'f', - FLEXTypeEncodingDouble = 'd', - FLEXTypeEncodingLongDouble = 'D', - FLEXTypeEncodingCBool = 'B', - FLEXTypeEncodingVoid = 'v', - FLEXTypeEncodingCString = '*', - FLEXTypeEncodingObjcObject = '@', - FLEXTypeEncodingObjcClass = '#', - FLEXTypeEncodingSelector = ':', - FLEXTypeEncodingArrayBegin = '[', - FLEXTypeEncodingArrayEnd = ']', - FLEXTypeEncodingStructBegin = '{', - FLEXTypeEncodingStructEnd = '}', - FLEXTypeEncodingUnionBegin = '(', - FLEXTypeEncodingUnionEnd = ')', - FLEXTypeEncodingQuote = '\"', - FLEXTypeEncodingBitField = 'b', - FLEXTypeEncodingPointer = '^', - FLEXTypeEncodingConst = 'r' -}; //NS_SWIFT_NAME(FLEX.TypeEncoding); diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeConstants.m b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeConstants.m deleted file mode 100644 index 2b274df..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeConstants.m +++ /dev/null @@ -1,24 +0,0 @@ -// -// FLEXRuntimeConstants.m -// FLEX -// -// Created by Tanner on 3/11/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" - -const unsigned int kFLEXNumberOfImplicitArgs = 2; - -NSString *const kFLEXPropertyAttributeKeyTypeEncoding = @"T"; -NSString *const kFLEXPropertyAttributeKeyBackingIvarName = @"V"; -NSString *const kFLEXPropertyAttributeKeyReadOnly = @"R"; -NSString *const kFLEXPropertyAttributeKeyCopy = @"C"; -NSString *const kFLEXPropertyAttributeKeyRetain = @"&"; -NSString *const kFLEXPropertyAttributeKeyNonAtomic = @"N"; -NSString *const kFLEXPropertyAttributeKeyCustomGetter = @"G"; -NSString *const kFLEXPropertyAttributeKeyCustomSetter = @"S"; -NSString *const kFLEXPropertyAttributeKeyDynamic = @"D"; -NSString *const kFLEXPropertyAttributeKeyWeak = @"W"; -NSString *const kFLEXPropertyAttributeKeyGarbageCollectable = @"P"; -NSString *const kFLEXPropertyAttributeKeyOldStyleTypeEncoding = @"t"; diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeSafety.h b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeSafety.h deleted file mode 100644 index 147db67..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeSafety.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// FLEXRuntimeSafety.h -// FLEX -// -// Created by Tanner on 3/25/17. -// - -#import -#import - -#pragma mark - Classes - -extern NSUInteger const kFLEXKnownUnsafeClassCount; -extern const Class * FLEXKnownUnsafeClassList(void); -extern NSSet * FLEXKnownUnsafeClassNames(void); -extern CFSetRef FLEXKnownUnsafeClasses; - -static Class cNSObject = nil, cNSProxy = nil; - -__attribute__((constructor)) -static void FLEXInitKnownRootClasses(void) { - cNSObject = [NSObject class]; - cNSProxy = [NSProxy class]; -} - -static inline BOOL FLEXClassIsSafe(Class cls) { - // Is it nil or known to be unsafe? - if (!cls || CFSetContainsValue(FLEXKnownUnsafeClasses, (__bridge void *)cls)) { - return NO; - } - - // Is it a known root class? - if (!class_getSuperclass(cls)) { - return cls == cNSObject || cls == cNSProxy; - } - - // Probably safe - return YES; -} - -static inline BOOL FLEXClassNameIsSafe(NSString *cls) { - if (!cls) return NO; - - NSSet *ignored = FLEXKnownUnsafeClassNames(); - return ![ignored containsObject:cls]; -} - -#pragma mark - Ivars - -extern CFSetRef FLEXKnownUnsafeIvars; - -static inline BOOL FLEXIvarIsSafe(Ivar ivar) { - if (!ivar) return NO; - - return !CFSetContainsValue(FLEXKnownUnsafeIvars, ivar); -} diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeSafety.m b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeSafety.m deleted file mode 100644 index 8a80cb7..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXRuntimeSafety.m +++ /dev/null @@ -1,107 +0,0 @@ -// -// FLEXRuntimeSafety.m -// FLEX -// -// Created by Tanner on 3/25/17. -// - -#import "FLEXRuntimeSafety.h" - -NSUInteger const kFLEXKnownUnsafeClassCount = 19; -Class * _UnsafeClasses = NULL; -CFSetRef FLEXKnownUnsafeClasses = nil; -CFSetRef FLEXKnownUnsafeIvars = nil; - -#define FLEXClassPointerOrCFNull(name) \ - (NSClassFromString(name) ?: (__bridge id)kCFNull) - -#define FLEXIvarOrCFNull(cls, name) \ - (class_getInstanceVariable([cls class], name) ?: (void *)kCFNull) - -__attribute__((constructor)) -static void FLEXRuntimeSafteyInit() { - FLEXKnownUnsafeClasses = CFSetCreate( - kCFAllocatorDefault, - (const void **)(uintptr_t)FLEXKnownUnsafeClassList(), - kFLEXKnownUnsafeClassCount, - nil - ); - - Ivar unsafeIvars[] = { - FLEXIvarOrCFNull(NSURL, "_urlString"), - FLEXIvarOrCFNull(NSURL, "_baseURL"), - }; - FLEXKnownUnsafeIvars = CFSetCreate( - kCFAllocatorDefault, - (const void **)unsafeIvars, - sizeof(unsafeIvars), - nil - ); -} - -const Class * FLEXKnownUnsafeClassList() { - if (!_UnsafeClasses) { - const Class ignored[] = { - FLEXClassPointerOrCFNull(@"__ARCLite__"), - FLEXClassPointerOrCFNull(@"__NSCFCalendar"), - FLEXClassPointerOrCFNull(@"__NSCFTimer"), - FLEXClassPointerOrCFNull(@"NSCFTimer"), - FLEXClassPointerOrCFNull(@"__NSGenericDeallocHandler"), - FLEXClassPointerOrCFNull(@"NSAutoreleasePool"), - FLEXClassPointerOrCFNull(@"NSPlaceholderNumber"), - FLEXClassPointerOrCFNull(@"NSPlaceholderString"), - FLEXClassPointerOrCFNull(@"NSPlaceholderValue"), - FLEXClassPointerOrCFNull(@"Object"), - FLEXClassPointerOrCFNull(@"VMUArchitecture"), - FLEXClassPointerOrCFNull(@"JSExport"), - FLEXClassPointerOrCFNull(@"__NSAtom"), - FLEXClassPointerOrCFNull(@"_NSZombie_"), - FLEXClassPointerOrCFNull(@"_CNZombie_"), - FLEXClassPointerOrCFNull(@"__NSMessage"), - FLEXClassPointerOrCFNull(@"__NSMessageBuilder"), - FLEXClassPointerOrCFNull(@"FigIrisAutoTrimmerMotionSampleExport"), - // Temporary until we have our own type encoding parser; - // setVectors: has an invalid type encoding and crashes NSMethodSignature - FLEXClassPointerOrCFNull(@"_UIPointVector"), - }; - - assert((sizeof(ignored) / sizeof(Class)) == kFLEXKnownUnsafeClassCount); - - _UnsafeClasses = (Class *)malloc(sizeof(ignored)); - memcpy(_UnsafeClasses, ignored, sizeof(ignored)); - } - - return _UnsafeClasses; -} - -NSSet * FLEXKnownUnsafeClassNames() { - static NSSet *set = nil; - if (!set) { - NSArray *ignored = @[ - @"__ARCLite__", - @"__NSCFCalendar", - @"__NSCFTimer", - @"NSCFTimer", - @"__NSGenericDeallocHandler", - @"NSAutoreleasePool", - @"NSPlaceholderNumber", - @"NSPlaceholderString", - @"NSPlaceholderValue", - @"Object", - @"VMUArchitecture", - @"JSExport", - @"__NSAtom", - @"_NSZombie_", - @"_CNZombie_", - @"__NSMessage", - @"__NSMessageBuilder", - @"FigIrisAutoTrimmerMotionSampleExport", - @"_UIPointVector", - ]; - - set = [NSSet setWithArray:ignored]; - assert(set.count == kFLEXKnownUnsafeClassCount); - } - - return set; -} diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXTypeEncodingParser.h b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXTypeEncodingParser.h deleted file mode 100644 index 7a8b1fb..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXTypeEncodingParser.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// FLEXTypeEncodingParser.h -// FLEX -// -// Created by Tanner Bennett on 8/22/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/// @return \c YES if the type is supported, \c NO otherwise -BOOL FLEXGetSizeAndAlignment(const char *type, NSUInteger * _Nullable sizep, NSUInteger * _Nullable alignp); - -@interface FLEXTypeEncodingParser : NSObject - -/// \c cleanedEncoding is necessary because a type encoding may contain a pointer -/// to an unsupported type. \c NSMethodSignature will pass each type to \c NSGetSizeAndAlignment -/// which will throw an exception on unsupported struct pointers, and this exception is caught -/// by \c NSMethodSignature, but it still bothers anyone debugging with \c objc_exception_throw -/// -/// @param cleanedEncoding the "safe" type encoding you can pass to \c NSMethodSignature -/// @return whether the given type encoding can be passed to -/// \c NSMethodSignature without it throwing an exception. -+ (BOOL)methodTypeEncodingSupported:(NSString *)typeEncoding cleaned:(NSString *_Nonnull*_Nullable)cleanedEncoding; - -/// @return The type encoding of an individual argument in a method's type encoding string. -/// Pass 0 to get the type of the return value. 1 and 2 are `self` and `_cmd` respectively. -+ (NSString *)type:(NSString *)typeEncoding forMethodArgumentAtIndex:(NSUInteger)idx; - -/// @return The size in bytes of the typeof an individual argument in a method's type encoding string. -/// Pass 0 to get the size of the return value. 1 and 2 are `self` and `_cmd` respectively. -+ (ssize_t)size:(NSString *)typeEncoding forMethodArgumentAtIndex:(NSUInteger)idx; - -/// @param unaligned whether to compute the aligned or unaligned size. -/// @return The size in bytes, or \c -1 if the type encoding is unsupported. -/// Do not pass in the result of \c method_getTypeEncoding -+ (ssize_t)sizeForTypeEncoding:(NSString *)type alignment:(nullable ssize_t *)alignOut unaligned:(BOOL)unaligned; - -/// Defaults to \C unaligned:NO -+ (ssize_t)sizeForTypeEncoding:(NSString *)type alignment:(nullable ssize_t *)alignOut; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXTypeEncodingParser.m b/Tweaks/FLEX/Utility/Runtime/Objc/FLEXTypeEncodingParser.m deleted file mode 100644 index 5bbfb9a..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/FLEXTypeEncodingParser.m +++ /dev/null @@ -1,900 +0,0 @@ -// -// FLEXTypeEncodingParser.m -// FLEX -// -// Created by Tanner Bennett on 8/22/19. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTypeEncodingParser.h" -#import "FLEXRuntimeUtility.h" - -#define S(__ch) ({ \ - unichar __c = __ch; \ - [[NSString alloc] initWithCharacters:&__c length:1]; \ -}) - -typedef struct FLEXTypeInfo { - /// The size is unaligned. -1 if not supported at all. - ssize_t size; - ssize_t align; - /// NO if the type cannot be supported at all - /// YES if the type is either fully or partially supported. - BOOL supported; - /// YES if the type was only partially supported, such as in - /// the case of unions in pointer types, or named structure - /// types without member info. These can be corrected manually - /// since they can be fixed or replaced with less info. - BOOL fixesApplied; - /// Whether this type is a union or one of its members - /// recursively contains a union, exlcuding pointers. - /// - /// Unions are tricky because they're supported by - /// \c NSGetSizeAndAlignment but not by \c NSMethodSignature - /// so we need to track whenever a type contains a union - /// so that we can clean it out of pointer types. - BOOL containsUnion; - /// size can only be 0 if not void - BOOL isVoid; -} FLEXTypeInfo; - -/// Type info for a completely unsupported type. -static FLEXTypeInfo FLEXTypeInfoUnsupported = (FLEXTypeInfo){ -1, 0, NO, NO, NO, NO }; -/// Type info for the void return type. -static FLEXTypeInfo FLEXTypeInfoVoid = (FLEXTypeInfo){ 0, 0, YES, NO, NO, YES }; - -/// Builds type info for a fully or partially supported type. -static inline FLEXTypeInfo FLEXTypeInfoMake(ssize_t size, ssize_t align, BOOL fixed) { - return (FLEXTypeInfo){ size, align, YES, fixed, NO, NO }; -} - -/// Builds type info for a fully or partially supported type. -static inline FLEXTypeInfo FLEXTypeInfoMakeU(ssize_t size, ssize_t align, BOOL fixed, BOOL hasUnion) { - return (FLEXTypeInfo){ size, align, YES, fixed, hasUnion, NO }; -} - -BOOL FLEXGetSizeAndAlignment(const char *type, NSUInteger *sizep, NSUInteger *alignp) { - NSInteger size = 0; - ssize_t align = 0; - size = [FLEXTypeEncodingParser sizeForTypeEncoding:@(type) alignment:&align]; - - if (size == -1) { - return NO; - } - - if (sizep) { - *sizep = (NSUInteger)size; - } - - if (alignp) { - *alignp = (NSUInteger)size; - } - - return YES; -} - -@interface FLEXTypeEncodingParser () -@property (nonatomic, readonly) NSScanner *scan; -@property (nonatomic, readonly) NSString *scanned; -@property (nonatomic, readonly) NSString *unscanned; -@property (nonatomic, readonly) char nextChar; - -/// Replacements are made to this string as we scan as needed -@property (nonatomic) NSMutableString *cleaned; -/// Offset for \e further replacements to be made within \c cleaned -@property (nonatomic, readonly) NSUInteger cleanedReplacingOffset; -@end - -@implementation FLEXTypeEncodingParser - -- (NSString *)scanned { - return [self.scan.string substringToIndex:self.scan.scanLocation]; -} - -- (NSString *)unscanned { - return [self.scan.string substringFromIndex:self.scan.scanLocation]; -} - -#pragma mark Initialization - -- (id)initWithObjCTypes:(NSString *)typeEncoding { - self = [super init]; - if (self) { - _scan = [NSScanner scannerWithString:typeEncoding]; - _scan.caseSensitive = YES; - _cleaned = typeEncoding.mutableCopy; - } - - return self; -} - - -#pragma mark Public - -+ (BOOL)methodTypeEncodingSupported:(NSString *)typeEncoding cleaned:(NSString * __autoreleasing *)cleanedEncoding { - if (!typeEncoding.length) { - return NO; - } - - FLEXTypeEncodingParser *parser = [[self alloc] initWithObjCTypes:typeEncoding]; - - while (!parser.scan.isAtEnd) { - FLEXTypeInfo info = [parser parseNextType]; - - if (!info.supported || info.containsUnion || (info.size == 0 && !info.isVoid)) { - return NO; - } - } - - if (cleanedEncoding) { - *cleanedEncoding = parser.cleaned.copy; - } - - return YES; -} - -+ (NSString *)type:(NSString *)typeEncoding forMethodArgumentAtIndex:(NSUInteger)idx { - FLEXTypeEncodingParser *parser = [[self alloc] initWithObjCTypes:typeEncoding]; - - // Scan up to the argument we want - for (NSUInteger i = 0; i < idx; i++) { - if (![parser scanPastArg]) { - [NSException raise:NSRangeException - format:@"Index %@ out of bounds for type encoding '%@'", - @(idx), typeEncoding - ]; - } - } - - return [parser scanArg]; -} - -+ (ssize_t)size:(NSString *)typeEncoding forMethodArgumentAtIndex:(NSUInteger)idx { - return [self sizeForTypeEncoding:[self type:typeEncoding forMethodArgumentAtIndex:idx] alignment:nil]; -} - -+ (ssize_t)sizeForTypeEncoding:(NSString *)type alignment:(ssize_t *)alignOut { - return [self sizeForTypeEncoding:type alignment:alignOut unaligned:NO]; -} - -+ (ssize_t)sizeForTypeEncoding:(NSString *)type alignment:(ssize_t *)alignOut unaligned:(BOOL)unaligned { - FLEXTypeInfo info = [self parseType:type]; - - ssize_t size = info.size; - ssize_t align = info.align; - - if (info.supported) { - if (alignOut) { - *alignOut = align; - } - - if (!unaligned) { - size += size % align; - } - } - - // size is -1 if not supported - return size; -} - -+ (FLEXTypeInfo)parseType:(NSString *)type cleaned:(NSString * __autoreleasing *)cleanedEncoding { - FLEXTypeEncodingParser *parser = [[self alloc] initWithObjCTypes:type]; - FLEXTypeInfo info = [parser parseNextType]; - if (cleanedEncoding) { - *cleanedEncoding = parser.cleaned; - } - - return info; -} - -+ (FLEXTypeInfo)parseType:(NSString *)type { - return [self parseType:type cleaned:nil]; -} - -#pragma mark Private - -- (NSCharacterSet *)identifierFirstCharCharacterSet { - static NSCharacterSet *identifierFirstSet = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *allowed = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"; - identifierFirstSet = [NSCharacterSet characterSetWithCharactersInString:allowed]; - }); - - return identifierFirstSet; -} - -- (NSCharacterSet *)identifierCharacterSet { - static NSCharacterSet *identifierSet = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *allowed = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$1234567890"; - identifierSet = [NSCharacterSet characterSetWithCharactersInString:allowed]; - }); - - return identifierSet; -} - -- (char)nextChar { - NSScanner *scan = self.scan; - return [scan.string characterAtIndex:scan.scanLocation]; -} - -/// For scanning struct/class names -- (NSString *)scanIdentifier { - NSString *prefix = nil, *suffix = nil; - - // Identifiers cannot start with a number - if (![self.scan scanCharactersFromSet:self.identifierFirstCharCharacterSet intoString:&prefix]) { - return nil; - } - - // Optional because identifier may just be one character - [self.scan scanCharactersFromSet:self.identifierCharacterSet intoString:&suffix]; - - if (suffix) { - return [prefix stringByAppendingString:suffix]; - } - - return prefix; -} - -/// @return the size in bytes -- (ssize_t)sizeForType:(FLEXTypeEncoding)type { - switch (type) { - case FLEXTypeEncodingChar: return sizeof(char); - case FLEXTypeEncodingInt: return sizeof(int); - case FLEXTypeEncodingShort: return sizeof(short); - case FLEXTypeEncodingLong: return sizeof(long); - case FLEXTypeEncodingLongLong: return sizeof(long long); - case FLEXTypeEncodingUnsignedChar: return sizeof(unsigned char); - case FLEXTypeEncodingUnsignedInt: return sizeof(unsigned int); - case FLEXTypeEncodingUnsignedShort: return sizeof(unsigned short); - case FLEXTypeEncodingUnsignedLong: return sizeof(unsigned long); - case FLEXTypeEncodingUnsignedLongLong: return sizeof(unsigned long long); - case FLEXTypeEncodingFloat: return sizeof(float); - case FLEXTypeEncodingDouble: return sizeof(double); - case FLEXTypeEncodingLongDouble: return sizeof(long double); - case FLEXTypeEncodingCBool: return sizeof(_Bool); - case FLEXTypeEncodingVoid: return 0; - case FLEXTypeEncodingCString: return sizeof(char *); - case FLEXTypeEncodingObjcObject: return sizeof(id); - case FLEXTypeEncodingObjcClass: return sizeof(Class); - case FLEXTypeEncodingSelector: return sizeof(SEL); - // Unknown / '?' is typically a pointer. In the rare case - // it isn't, such as in '{?=...}', it is never passed here. - case FLEXTypeEncodingUnknown: - case FLEXTypeEncodingPointer: return sizeof(uintptr_t); - - default: return -1; - } -} - -- (FLEXTypeInfo)parseNextType { - NSUInteger start = self.scan.scanLocation; - - // Check for void first - if ([self scanChar:FLEXTypeEncodingVoid]) { - // Skip argument frame for method signatures - [self scanSize]; - return FLEXTypeInfoVoid; - } - - // Scan optional const - [self scanChar:FLEXTypeEncodingConst]; - - // Check for pointer, then scan next - if ([self scanChar:FLEXTypeEncodingPointer]) { - // Recurse to scan something else - NSUInteger pointerTypeStart = self.scan.scanLocation; - if ([self scanPastArg]) { - // Make sure the pointer type is supported, and clean it if not - NSUInteger pointerTypeLength = self.scan.scanLocation - pointerTypeStart; - NSString *pointerType = [self.scan.string - substringWithRange:NSMakeRange(pointerTypeStart, pointerTypeLength) - ]; - - // Deeeep nested cleaning info gets lost here - NSString *cleaned = nil; - FLEXTypeInfo info = [self.class parseType:pointerType cleaned:&cleaned]; - BOOL needsCleaning = !info.supported || info.containsUnion || info.fixesApplied; - - // Clean the type if it is unsupported, malformed, or contains a union. - // (Unions are supported by NSGetSizeAndAlignment but not - // supported by NSMethodSignature for some reason) - if (needsCleaning) { - // If unsupported, no cleaning occurred in parseType:cleaned: above. - // Otherwise, the type is partially supported and we did clean it, - // and we will replace this type with the cleaned type from above. - if (!info.supported || info.containsUnion) { - cleaned = [self cleanPointeeTypeAtLocation:pointerTypeStart]; - } - - NSInteger offset = self.cleanedReplacingOffset; - NSInteger location = pointerTypeStart - offset; - [self.cleaned replaceCharactersInRange:NSMakeRange( - location, pointerTypeLength - ) withString:cleaned]; - } - - // Skip optional frame offset - [self scanSize]; - - ssize_t size = [self sizeForType:FLEXTypeEncodingPointer]; - return FLEXTypeInfoMake(size, size, !info.supported || info.fixesApplied); - } else { - // Scan failed, abort - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } - } - - // Check for struct/union/array - char next = self.nextChar; - BOOL didScanSUA = YES, structOrUnion = NO, isUnion = NO; - FLEXTypeEncoding opening = FLEXTypeEncodingNull, closing = FLEXTypeEncodingNull; - switch (next) { - case FLEXTypeEncodingStructBegin: - structOrUnion = YES; - opening = FLEXTypeEncodingStructBegin; - closing = FLEXTypeEncodingStructEnd; - break; - case FLEXTypeEncodingUnionBegin: - structOrUnion = isUnion = YES; - opening = FLEXTypeEncodingUnionBegin; - closing = FLEXTypeEncodingUnionEnd; - break; - case FLEXTypeEncodingArrayBegin: - opening = FLEXTypeEncodingArrayBegin; - closing = FLEXTypeEncodingArrayEnd; - break; - - default: - didScanSUA = NO; - break; - } - - if (didScanSUA) { - BOOL containsUnion = isUnion; - BOOL fixesApplied = NO; - - NSUInteger backup = self.scan.scanLocation; - - // Ensure we have a closing tag - if (![self scanPair:opening close:closing]) { - // Scan failed, abort - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } - - // Move cursor just after opening tag (struct/union/array) - NSInteger arrayCount = -1; - self.scan.scanLocation = backup + 1; - - if (!structOrUnion) { - arrayCount = [self scanSize]; - if (!arrayCount || self.nextChar == FLEXTypeEncodingArrayEnd) { - // Malformed array type: - // 1. Arrays must have a count after the opening brace - // 2. Arrays must have an element type after the count - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } - } else { - // If we encounter the ?= portion of something like {?=b8b4b1b1b18[8S]} - // then we skip over it, since it means nothing to us in this context. - // It is completely optional, and if it fails, we go right back where we were. - if (![self scanTypeName] && self.nextChar == FLEXTypeEncodingUnknown) { - // Exception: we are trying to parse {?} which is invalid - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } - } - - // Sum sizes of members together: - // Scan for bitfields before checking for other members - // - // Arrays will only have one "member," but - // this logic still works for them - ssize_t sizeSoFar = 0; - ssize_t maxAlign = 0; - NSMutableString *cleanedBackup = self.cleaned.mutableCopy; - - while (![self scanChar:closing]) { - next = self.nextChar; - // Check for bitfields, which we cannot support because - // type encodings for bitfields do not include alignment info - if (next == FLEXTypeEncodingBitField) { - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } - - // Structure fields could be named - if (next == FLEXTypeEncodingQuote) { - [self scanPair:FLEXTypeEncodingQuote close:FLEXTypeEncodingQuote]; - } - - FLEXTypeInfo info = [self parseNextType]; - if (!info.supported || info.containsUnion) { - // The above call is the only time in this method where - // `cleaned` might be mutated recursively, so this is the - // only place where we need to keep and restore a backup - // - // For instance, if we've been iterating over the members - // of a struct and we've encountered a few pointers so far - // that we needed to clean, and suddenly we come across an - // unsupported member, we need to be able to "rewind" and - // undo any changes to `self.cleaned` so that the parent - // call in the call stack can wipe the current structure - // clean entirely if needed. Example below: - // - // Initial: ^{foo=^{pair}{^pair}{invalid_type}} - // v-- here - // 1st clean: ^{foo=^{?=}{^pair}{invalid_type} - // v-- here - // 2nd clean: ^{foo=^{?=}{?=}{invalid_type} - // v-- here - // Can't clean: ^{foo=^{?=}{?=}{invalid_type} - // v-- to here - // Rewind: ^{foo=^{pair}{^pair}{invalid_type}} - // Final clean: ^{foo=} - self.cleaned = cleanedBackup; - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } - - // Unions are the size of their largest member, - // arrays are element.size x length, and - // structs are the sum of their members - if (structOrUnion) { - if (isUnion) { // Union - sizeSoFar = MAX(sizeSoFar, info.size); - } else { // Struct - sizeSoFar += info.size; - } - } else { // Array - sizeSoFar = info.size * arrayCount; - } - - // Propogate the max alignment and other metadata - maxAlign = MAX(maxAlign, info.align); - containsUnion = containsUnion || info.containsUnion; - fixesApplied = fixesApplied || info.fixesApplied; - } - - // Skip optional frame offset - [self scanSize]; - - return FLEXTypeInfoMakeU(sizeSoFar, maxAlign, fixesApplied, containsUnion); - } - - // Scan single thing and possible size and return - ssize_t size = -1; - char t = self.nextChar; - switch (t) { - case FLEXTypeEncodingUnknown: - case FLEXTypeEncodingChar: - case FLEXTypeEncodingInt: - case FLEXTypeEncodingShort: - case FLEXTypeEncodingLong: - case FLEXTypeEncodingLongLong: - case FLEXTypeEncodingUnsignedChar: - case FLEXTypeEncodingUnsignedInt: - case FLEXTypeEncodingUnsignedShort: - case FLEXTypeEncodingUnsignedLong: - case FLEXTypeEncodingUnsignedLongLong: - case FLEXTypeEncodingFloat: - case FLEXTypeEncodingDouble: - case FLEXTypeEncodingLongDouble: - case FLEXTypeEncodingCBool: - case FLEXTypeEncodingCString: - case FLEXTypeEncodingSelector: - case FLEXTypeEncodingBitField: { - self.scan.scanLocation++; - // Skip optional frame offset - [self scanSize]; - - if (t == FLEXTypeEncodingBitField) { - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; - } else { - // Compute size - size = [self sizeForType:t]; - } - } - break; - - case FLEXTypeEncodingObjcObject: - case FLEXTypeEncodingObjcClass: { - self.scan.scanLocation++; - // These might have numbers OR quotes after them - // Skip optional frame offset - [self scanSize]; - [self scanPair:FLEXTypeEncodingQuote close:FLEXTypeEncodingQuote]; - size = sizeof(id); - } - break; - - default: break; - } - - if (size > 0) { - // Alignment of scalar types is its size - return FLEXTypeInfoMake(size, size, NO); - } - - self.scan.scanLocation = start; - return FLEXTypeInfoUnsupported; -} - -- (BOOL)scanString:(NSString *)str { - return [self.scan scanString:str intoString:nil]; -} - -- (BOOL)canScanString:(NSString *)str { - NSScanner *scan = self.scan; - NSUInteger len = str.length; - unichar buff1[len], buff2[len]; - - [str getCharacters:buff1]; - [scan.string getCharacters:buff2 range:NSMakeRange(scan.scanLocation, len)]; - if (memcmp(buff1, buff2, len) == 0) { - return YES; - } - - return NO; -} - -- (BOOL)canScanChar:(char)c { - // By avoiding any ARC calls on these two objects which we know won't be - // free'd out from under us, we're making HUGE performance savings in this - // parser, because this method is one of the most-used methods of the parser. - // This is probably the most performance-critical method in this class. - __unsafe_unretained NSScanner *scan = self.scan; - __unsafe_unretained NSString *string = scan.string; - if (scan.scanLocation >= string.length) return NO; - - return [string characterAtIndex:scan.scanLocation] == c; -} - -- (BOOL)scanChar:(char)c { - if ([self canScanChar:c]) { - self.scan.scanLocation++; - return YES; - } - - return NO; -} - -- (BOOL)scanChar:(char)c into:(char *)ref { - if ([self scanChar:c]) { - *ref = c; - return YES; - } - - return NO; -} - -- (ssize_t)scanSize { - NSInteger size = 0; - if ([self.scan scanInteger:&size]) { - return size; - } - - return 0; -} - -- (NSString *)scanPair:(char)c1 close:(char)c2 { - // Starting position and string variables - NSUInteger start = self.scan.scanLocation; - NSString *s1 = S(c1); - - // Scan opening tag - if (![self scanChar:c1]) { - self.scan.scanLocation = start; - return nil; - } - - // Character set for scanning up to either symbol - NSCharacterSet *bothChars = ({ - unichar buff[2] = { c1, c2 }; - NSString *bothCharsStr = [[NSString alloc] initWithCharacters:buff length:2]; - [NSCharacterSet characterSetWithCharactersInString:bothCharsStr]; - }); - - // Stack for finding pairs, starting with the opening symbol - NSMutableArray *stack = [NSMutableArray arrayWithObject:s1]; - - // Algorithm for scanning to the closing end of a pair of opening/closing symbols - // scanUpToCharactersFromSet:intoString: returns NO if you're already at one of the chars, - // so we need to check if we can actually scan one if it returns NO - while ([self.scan scanUpToCharactersFromSet:bothChars intoString:nil] || - [self canScanChar:c1] || [self canScanChar:c2]) { - // Closing symbol found - if ([self scanChar:c2]) { - if (!stack.count) { - // Abort, no matching opening symbol - self.scan.scanLocation = start; - return nil; - } - - // Pair found, pop opening symbol - [stack removeLastObject]; - // Exit loop if we reached the closing brace we needed - if (!stack.count) { - break; - } - } - // Opening symbol found - if ([self scanChar:c1]) { - // Begin pair - [stack addObject:s1]; - } - } - - if (stack.count) { - // Abort, no matching closing symbol - self.scan.scanLocation = start; - return nil; - } - - // Slice out the string we just scanned - return [self.scan.string - substringWithRange:NSMakeRange(start, self.scan.scanLocation - start) - ]; -} - -- (BOOL)scanPastArg { - NSUInteger start = self.scan.scanLocation; - - // Check for void first - if ([self scanChar:FLEXTypeEncodingVoid]) { - return YES; - } - - // Scan optional const - [self scanChar:FLEXTypeEncodingConst]; - - // Check for pointer, then scan next - if ([self scanChar:FLEXTypeEncodingPointer]) { - // Recurse to scan something else - if ([self scanPastArg]) { - return YES; - } else { - // Scan failed, abort - self.scan.scanLocation = start; - return NO; - } - } - - char next = self.nextChar; - - // Check for struct/union/array, scan past it - FLEXTypeEncoding opening = FLEXTypeEncodingNull, closing = FLEXTypeEncodingNull; - BOOL checkPair = YES; - switch (next) { - case FLEXTypeEncodingStructBegin: - opening = FLEXTypeEncodingStructBegin; - closing = FLEXTypeEncodingStructEnd; - break; - case FLEXTypeEncodingUnionBegin: - opening = FLEXTypeEncodingUnionBegin; - closing = FLEXTypeEncodingUnionEnd; - break; - case FLEXTypeEncodingArrayBegin: - opening = FLEXTypeEncodingArrayBegin; - closing = FLEXTypeEncodingArrayEnd; - break; - - default: - checkPair = NO; - break; - } - - if (checkPair && [self scanPair:opening close:closing]) { - return YES; - } - - // Scan single thing and possible size and return - switch (next) { - case FLEXTypeEncodingUnknown: - case FLEXTypeEncodingChar: - case FLEXTypeEncodingInt: - case FLEXTypeEncodingShort: - case FLEXTypeEncodingLong: - case FLEXTypeEncodingLongLong: - case FLEXTypeEncodingUnsignedChar: - case FLEXTypeEncodingUnsignedInt: - case FLEXTypeEncodingUnsignedShort: - case FLEXTypeEncodingUnsignedLong: - case FLEXTypeEncodingUnsignedLongLong: - case FLEXTypeEncodingFloat: - case FLEXTypeEncodingDouble: - case FLEXTypeEncodingLongDouble: - case FLEXTypeEncodingCBool: - case FLEXTypeEncodingCString: - case FLEXTypeEncodingSelector: - case FLEXTypeEncodingBitField: { - self.scan.scanLocation++; - // Size is optional - [self scanSize]; - return YES; - } - - case FLEXTypeEncodingObjcObject: - case FLEXTypeEncodingObjcClass: { - self.scan.scanLocation++; - // These might have numbers OR quotes after them - [self scanSize] || [self scanPair:FLEXTypeEncodingQuote close:FLEXTypeEncodingQuote]; - return YES; - } - - default: break; - } - - self.scan.scanLocation = start; - return NO; -} - -- (NSString *)scanArg { - NSUInteger start = self.scan.scanLocation; - if (![self scanPastArg]) { - return nil; - } - - return [self.scan.string - substringWithRange:NSMakeRange(start, self.scan.scanLocation - start) - ]; -} - -- (BOOL)scanTypeName { - NSUInteger start = self.scan.scanLocation; - - // The ?= portion of something like {?=b8b4b1b1b18[8S]} - if ([self scanChar:FLEXTypeEncodingUnknown]) { - if (![self scanString:@"="]) { - // No size information available for strings like {?=} - self.scan.scanLocation = start; - return NO; - } - } else { - if (![self scanIdentifier] || ![self scanString:@"="]) { - // 1. Not a valid identifier - // 2. No size information available for strings like {CGPoint} - self.scan.scanLocation = start; - return NO; - } - } - - return YES; -} - -- (NSString *)extractTypeNameFromScanLocation:(BOOL)allowMissingTypeInfo closing:(FLEXTypeEncoding)closeTag { - NSUInteger start = self.scan.scanLocation; - - // The ?= portion of something like {?=b8b4b1b1b18[8S]} - if ([self scanChar:FLEXTypeEncodingUnknown]) { - return @"?"; - } else { - NSString *typeName = [self scanIdentifier]; - char next = self.nextChar; - - if (!typeName) { - // Did not scan an identifier - self.scan.scanLocation = start; - return nil; - } - - switch (next) { - case '=': - return typeName; - - default: { - // = is non-optional unless we allowMissingTypeInfo, in whcih - // case the next character needs to be a closing brace - if (allowMissingTypeInfo && next == closeTag) { - return typeName; - } else { - // Not a valid identifier; possibly a generic C++ type - // i.e. {pair} where `name` was found as `pair` - self.scan.scanLocation = start; - return nil; - } - } - } - } -} - -- (NSString *)cleanPointeeTypeAtLocation:(NSUInteger)scanLocation { - NSUInteger start = self.scan.scanLocation; - self.scan.scanLocation = scanLocation; - - // The return / cleanup code for when the scanned type is already clean - NSString * (^typeIsClean)(void) = ^NSString * { - NSString *clean = [self.scan.string - substringWithRange:NSMakeRange(scanLocation, self.scan.scanLocation - scanLocation) - ]; - // Reset scan location even on success, because this method is not supposed to change it - self.scan.scanLocation = start; - return clean; - }; - - // No void, this is not a return type - - // Scan optional const - [self scanChar:FLEXTypeEncodingConst]; - - char next = self.nextChar; - switch (next) { - case FLEXTypeEncodingPointer: - // Recurse to scan something else - [self scanChar:next]; - return [self cleanPointeeTypeAtLocation:self.scan.scanLocation]; - - case FLEXTypeEncodingArrayBegin: - // All arrays are supported, scan past them - if ([self scanPair:FLEXTypeEncodingArrayBegin close:FLEXTypeEncodingArrayEnd]) { - return typeIsClean(); - } - break; - - case FLEXTypeEncodingUnionBegin: - // Unions are not supported at all in NSMethodSignature - // We could check for the closing token to be safe, but eh - self.scan.scanLocation = start; - return @"?"; - - case FLEXTypeEncodingStructBegin: { - FLEXTypeInfo info = [self.class parseType:self.unscanned]; - if (info.supported && !info.fixesApplied) { - [self scanPastArg]; - return typeIsClean(); - } - - // The structure we just tried to scan is unsupported, so just return its name - // if it has one. If not, just return a question mark. - self.scan.scanLocation++; // Skip past { - NSString *name = [self extractTypeNameFromScanLocation:YES closing:FLEXTypeEncodingStructEnd]; - if (name) { - // Got the name, scan past the closing token - [self.scan scanUpToString:@"}" intoString:nil]; - if (![self scanChar:FLEXTypeEncodingStructEnd]) { - // Missing struct close token - self.scan.scanLocation = start; - return nil; - } - } else { - // Did not scan valid identifier, possibly a C++ type - self.scan.scanLocation = start; - return @"{?=}"; - } - - // Reset scan location even on success, because this method is not supposed to change it - self.scan.scanLocation = start; - return ({ // "{name=}" - NSMutableString *format = @"{".mutableCopy; - [format appendString:name]; - [format appendString:@"=}"]; - format; - }); - } - - default: - break; - } - - // Check for other types, which in theory are all valid but whatever - FLEXTypeInfo info = [self parseNextType]; - if (info.supported && !info.fixesApplied) { - return typeIsClean(); - } - - self.scan.scanLocation = start; - return @"?"; -} - -- (NSUInteger)cleanedReplacingOffset { - return self.scan.string.length - self.cleaned.length; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.h deleted file mode 100644 index 037abcf..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// FLEXBlockDescription.h -// FLEX -// -// Created by Oliver Letterer on 2012-09-01 -// Forked from CTObjectiveCRuntimeAdditions (MIT License) -// https://github.com/ebf/CTObjectiveCRuntimeAdditions -// -// Copyright (c) 2020 FLEX Team-EDV Beratung Föllmer GmbH -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#import - -typedef NS_OPTIONS(NSUInteger, FLEXBlockOptions) { - FLEXBlockOptionHasCopyDispose = (1 << 25), - FLEXBlockOptionHasCtor = (1 << 26), // helpers have C++ code - FLEXBlockOptionIsGlobal = (1 << 28), - FLEXBlockOptionHasStret = (1 << 29), // IFF BLOCK_HAS_SIGNATURE - FLEXBlockOptionHasSignature = (1 << 30), -}; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - -@interface FLEXBlockDescription : NSObject - -+ (instancetype)describing:(id)block; - -@property (nonatomic, readonly, nullable) NSMethodSignature *signature; -@property (nonatomic, readonly, nullable) NSString *signatureString; -@property (nonatomic, readonly, nullable) NSString *sourceDeclaration; -@property (nonatomic, readonly) FLEXBlockOptions flags; -@property (nonatomic, readonly) NSUInteger size; -@property (nonatomic, readonly) NSString *summary; -@property (nonatomic, readonly) id block; - -- (BOOL)isCompatibleForBlockSwizzlingWithMethodSignature:(NSMethodSignature *)methodSignature; - -@end - -#pragma mark - -@interface NSBlock : NSObject -- (void)invoke; -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.m deleted file mode 100644 index f943e31..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.m +++ /dev/null @@ -1,157 +0,0 @@ -// -// FLEXBlockDescription.m -// FLEX -// -// Created by Oliver Letterer on 2012-09-01 -// Forked from CTObjectiveCRuntimeAdditions (MIT License) -// https://github.com/ebf/CTObjectiveCRuntimeAdditions -// -// Copyright (c) 2020 FLEX Team-EDV Beratung Föllmer GmbH -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#import "FLEXBlockDescription.h" -#import "FLEXRuntimeUtility.h" - -struct block_object { - void *isa; - int flags; - int reserved; - void (*invoke)(void *, ...); - struct block_descriptor { - unsigned long int reserved; // NULL - unsigned long int size; // sizeof(struct Block_literal_1) - // optional helper functions - void (*copy_helper)(void *dst, void *src); // IFF (1<<25) - void (*dispose_helper)(void *src); // IFF (1<<25) - // required ABI.2010.3.16 - const char *signature; // IFF (1<<30) - } *descriptor; - // imported variables -}; - -@implementation FLEXBlockDescription - -+ (instancetype)describing:(id)block { - return [[self alloc] initWithObjcBlock:block]; -} - -- (id)initWithObjcBlock:(id)block { - self = [super init]; - if (self) { - _block = block; - - struct block_object *blockRef = (__bridge struct block_object *)block; - _flags = blockRef->flags; - _size = blockRef->descriptor->size; - - if (_flags & FLEXBlockOptionHasSignature) { - void *signatureLocation = blockRef->descriptor; - signatureLocation += sizeof(unsigned long int); - signatureLocation += sizeof(unsigned long int); - - if (_flags & FLEXBlockOptionHasCopyDispose) { - signatureLocation += sizeof(void(*)(void *dst, void *src)); - signatureLocation += sizeof(void (*)(void *src)); - } - - const char *signature = (*(const char **)signatureLocation); - _signatureString = @(signature); - - @try { - _signature = [NSMethodSignature signatureWithObjCTypes:signature]; - } @catch (NSException *exception) { } - } - - NSMutableString *summary = [NSMutableString stringWithFormat: - @"Type signature: %@\nSize: %@\nIs global: %@\nHas constructor: %@\nIs stret: %@", - self.signatureString ?: @"nil", @(self.size), - @((BOOL)(_flags & FLEXBlockOptionIsGlobal)), - @((BOOL)(_flags & FLEXBlockOptionHasCtor)), - @((BOOL)(_flags & FLEXBlockOptionHasStret)) - ]; - - if (!self.signature) { - [summary appendFormat:@"\nNumber of arguments: %@", @(self.signature.numberOfArguments)]; - } - - _summary = summary.copy; - _sourceDeclaration = [self buildLikelyDeclaration]; - } - - return self; -} - -- (BOOL)isCompatibleForBlockSwizzlingWithMethodSignature:(NSMethodSignature *)methodSignature { - if (!self.signature) { - return NO; - } - - if (self.signature.numberOfArguments != methodSignature.numberOfArguments + 1) { - return NO; - } - - if (strcmp(self.signature.methodReturnType, methodSignature.methodReturnType) != 0) { - return NO; - } - - for (int i = 0; i < methodSignature.numberOfArguments; i++) { - if (i == 1) { - // SEL in method, IMP in block - if (strcmp([methodSignature getArgumentTypeAtIndex:i], ":") != 0) { - return NO; - } - - if (strcmp([self.signature getArgumentTypeAtIndex:i + 1], "^?") != 0) { - return NO; - } - } else { - if (strcmp([self.signature getArgumentTypeAtIndex:i], [self.signature getArgumentTypeAtIndex:i + 1]) != 0) { - return NO; - } - } - } - - return YES; -} - -- (NSString *)buildLikelyDeclaration { - NSMethodSignature *signature = self.signature; - NSUInteger numberOfArguments = signature.numberOfArguments; - const char *returnType = signature.methodReturnType; - - // Return type - NSMutableString *decl = [NSMutableString stringWithString:@"^"]; - if (returnType[0] != FLEXTypeEncodingVoid) { - [decl appendString:[FLEXRuntimeUtility readableTypeForEncoding:@(returnType)]]; - [decl appendString:@" "]; - } - - // Arguments - if (numberOfArguments) { - [decl appendString:@"("]; - for (NSUInteger i = 1; i < numberOfArguments; i++) { - const char *argType = [self.signature getArgumentTypeAtIndex:i] ?: "?"; - NSString *readableArgType = [FLEXRuntimeUtility readableTypeForEncoding:@(argType)]; - [decl appendFormat:@"%@ arg%@, ", readableArgType, @(i)]; - } - - [decl deleteCharactersInRange:NSMakeRange(decl.length-2, 2)]; - [decl appendString:@")"]; - } - - return decl.copy; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.h deleted file mode 100644 index f6d8441..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// FLEXClassBuilder.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/3/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -@class FLEXIvarBuilder, FLEXMethodBase, FLEXProperty, FLEXProtocol; - - -#pragma mark FLEXClassBuilder -@interface FLEXClassBuilder : NSObject - -@property (nonatomic, readonly) Class workingClass; - -/// Begins constructing a class with the given name. -/// -/// This new class will implicitly inherits from \c NSObject with \c 0 extra bytes. -/// Classes created this way must be registered with \c -registerClass before being used. -+ (instancetype)allocateClass:(NSString *)name; -/// Begins constructing a class with the given name and superclass. -/// @discussion Calls \c -allocateClass:superclass:extraBytes: with \c 0 extra bytes. -/// Classes created this way must be registered with \c -registerClass before being used. -+ (instancetype)allocateClass:(NSString *)name superclass:(Class)superclass; -/// Begins constructing a new class object with the given name and superclass. -/// @discussion Pass \c nil to \e superclass to create a new root class. -/// Classes created this way must be registered with \c -registerClass before being used. -+ (instancetype)allocateClass:(NSString *)name superclass:(Class)superclass extraBytes:(size_t)bytes; -/// Begins constructing a new root class object with the given name and \c 0 extra bytes. -/// @discussion Classes created this way must be registered with \c -registerClass before being used. -+ (instancetype)allocateRootClass:(NSString *)name; -/// Use this to modify existing classes. @warning You cannot add instance variables to existing classes. -+ (instancetype)builderForClass:(Class)cls; - -/// @return Any methods that failed to be added. -- (NSArray *)addMethods:(NSArray *)methods; -/// @return Any properties that failed to be added. -- (NSArray *)addProperties:(NSArray *)properties; -/// @return Any protocols that failed to be added. -- (NSArray *)addProtocols:(NSArray *)protocols; -/// @warning Adding Ivars to existing classes is not supported and will always fail. -- (NSArray *)addIvars:(NSArray *)ivars; - -/// Finalizes construction of a new class. -/// @discussion Once a class is registered, instance variables cannot be added. -/// @note Raises an exception if called on a previously registered class. -- (Class)registerClass; -/// Uses \c objc_lookupClass to determine if the working class is registered. -@property (nonatomic, readonly) BOOL isRegistered; - -@end - - -#pragma mark FLEXIvarBuilder -@interface FLEXIvarBuilder : NSObject - -/// Consider using the \c FLEXIvarBuilderWithNameAndType() macro below. -/// @param name The name of the Ivar, such as \c \@"_value". -/// @param size The size of the Ivar. Usually \c sizeof(type). For objects, this is \c sizeof(id). -/// @param alignment The alignment of the Ivar. Usually \c log2(sizeof(type)). -/// @param encoding The type encoding of the Ivar. For objects, this is \c \@(\@encode(id)), and for others it is \c \@(\@encode(type)). -+ (instancetype)name:(NSString *)name size:(size_t)size alignment:(uint8_t)alignment typeEncoding:(NSString *)encoding; - -@property (nonatomic, readonly) NSString *name; -@property (nonatomic, readonly) NSString *encoding; -@property (nonatomic, readonly) size_t size; -@property (nonatomic, readonly) uint8_t alignment; - -@end - - -#define FLEXIvarBuilderWithNameAndType(nameString, type) [FLEXIvarBuilder \ - name:nameString \ - size:sizeof(type) \ - alignment:log2(sizeof(type)) \ - typeEncoding:@(@encode(type)) \ -] diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.m deleted file mode 100644 index f710334..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.m +++ /dev/null @@ -1,168 +0,0 @@ -// -// FLEXClassBuilder.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/3/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXClassBuilder.h" -#import "FLEXProperty.h" -#import "FLEXMethodBase.h" -#import "FLEXProtocol.h" -#import - - -#pragma mark FLEXClassBuilder - -@interface FLEXClassBuilder () -@property (nonatomic) NSString *name; -@end - -@implementation FLEXClassBuilder - -- (id)init { - [NSException - raise:NSInternalInconsistencyException - format:@"Class instance should not be created with -init" - ]; - return nil; -} - -#pragma mark Initializers -+ (instancetype)allocateClass:(NSString *)name { - return [self allocateClass:name superclass:NSObject.class]; -} - -+ (instancetype)allocateClass:(NSString *)name superclass:(Class)superclass { - return [self allocateClass:name superclass:superclass extraBytes:0]; -} - -+ (instancetype)allocateClass:(NSString *)name superclass:(Class)superclass extraBytes:(size_t)bytes { - NSParameterAssert(name); - return [[self alloc] initWithClass:objc_allocateClassPair(superclass, name.UTF8String, bytes)]; -} - -+ (instancetype)allocateRootClass:(NSString *)name { - NSParameterAssert(name); - return [[self alloc] initWithClass:objc_allocateClassPair(Nil, name.UTF8String, 0)]; -} - -+ (instancetype)builderForClass:(Class)cls { - return [[self alloc] initWithClass:cls]; -} - -- (id)initWithClass:(Class)cls { - NSParameterAssert(cls); - - self = [super init]; - if (self) { - _workingClass = cls; - _name = NSStringFromClass(_workingClass); - } - - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@ name=%@, registered=%d>", - NSStringFromClass(self.class), self.name, self.isRegistered]; -} - -#pragma mark Building -- (NSArray *)addMethods:(NSArray *)methods { - NSParameterAssert(methods.count); - - NSMutableArray *failed = [NSMutableArray new]; - for (FLEXMethodBase *m in methods) { - if (!class_addMethod(self.workingClass, m.selector, m.implementation, m.typeEncoding.UTF8String)) { - [failed addObject:m]; - } - } - - return failed; -} - -- (NSArray *)addProperties:(NSArray *)properties { - NSParameterAssert(properties.count); - - NSMutableArray *failed = [NSMutableArray new]; - for (FLEXProperty *p in properties) { - unsigned int pcount; - objc_property_attribute_t *attributes = [p copyAttributesList:&pcount]; - if (!class_addProperty(self.workingClass, p.name.UTF8String, attributes, pcount)) { - [failed addObject:p]; - } - free(attributes); - } - - return failed; -} - -- (NSArray *)addProtocols:(NSArray *)protocols { - NSParameterAssert(protocols.count); - - NSMutableArray *failed = [NSMutableArray new]; - for (FLEXProtocol *p in protocols) { - if (!class_addProtocol(self.workingClass, p.objc_protocol)) { - [failed addObject:p]; - } - } - - return failed; -} - -- (NSArray *)addIvars:(NSArray *)ivars { - NSParameterAssert(ivars.count); - - NSMutableArray *failed = [NSMutableArray new]; - for (FLEXIvarBuilder *ivar in ivars) { - if (!class_addIvar(self.workingClass, ivar.name.UTF8String, ivar.size, ivar.alignment, ivar.encoding.UTF8String)) { - [failed addObject:ivar]; - } - } - - return failed; -} - -- (Class)registerClass { - if (self.isRegistered) { - [NSException raise:NSInternalInconsistencyException format:@"Class is already registered"]; - } - - objc_registerClassPair(self.workingClass); - return self.workingClass; -} - -- (BOOL)isRegistered { - return objc_lookUpClass(self.name.UTF8String) != nil; -} - -@end - - -#pragma mark FLEXIvarBuilder - -@implementation FLEXIvarBuilder - -+ (instancetype)name:(NSString *)name size:(size_t)size alignment:(uint8_t)alignment typeEncoding:(NSString *)encoding { - return [[self alloc] initWithName:name size:size alignment:alignment typeEncoding:encoding]; -} - -- (id)initWithName:(NSString *)name size:(size_t)size alignment:(uint8_t)alignment typeEncoding:(NSString *)encoding { - NSParameterAssert(name); NSParameterAssert(encoding); - NSParameterAssert(size > 0); NSParameterAssert(alignment > 0); - - self = [super init]; - if (self) { - _name = name; - _encoding = encoding; - _size = size; - _alignment = alignment; - } - - return self; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXIvar.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXIvar.h deleted file mode 100644 index db4aa97..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXIvar.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// FLEXIvar.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FLEXIvar : NSObject - -+ (instancetype)ivar:(Ivar)ivar; -+ (instancetype)named:(NSString *)name onClass:(Class)cls; - -/// The underlying \c Ivar data structure. -@property (nonatomic, readonly) Ivar objc_ivar; - -/// The name of the instance variable. -@property (nonatomic, readonly) NSString *name; -/// The type of the instance variable. -@property (nonatomic, readonly) FLEXTypeEncoding type; -/// The type encoding string of the instance variable. -@property (nonatomic, readonly) NSString *typeEncoding; -/// The offset of the instance variable. -@property (nonatomic, readonly) NSInteger offset; -/// The size of the instance variable. 0 if unknown. -@property (nonatomic, readonly) NSUInteger size; -/// Describes the type encoding, size, offset, and objc_ivar -@property (nonatomic, readonly) NSString *details; -/// The full path of the image that contains this ivar definition, -/// or \c nil if this ivar was probably defined at runtime. -@property (nonatomic, readonly, nullable) NSString *imagePath; - -/// For internal use -@property (nonatomic) id tag; - -- (nullable id)getValue:(id)target; -- (void)setValue:(nullable id)value onObject:(id)target; - -/// Calls into -getValue: and passes that value into -/// -[FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:type:] -/// and returns the result -- (nullable id)getPotentiallyUnboxedValue:(id)target; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXIvar.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXIvar.m deleted file mode 100644 index a589036..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXIvar.m +++ /dev/null @@ -1,158 +0,0 @@ -// -// FLEXIvar.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXIvar.h" -#import "FLEXRuntimeUtility.h" -#import "FLEXRuntimeSafety.h" -#import "FLEXTypeEncodingParser.h" -#import "NSString+FLEX.h" -#include "FLEXObjcInternal.h" -#include - -@interface FLEXIvar () { - NSString *_flex_description; -} -@end - -@implementation FLEXIvar - -#pragma mark Initializers - -+ (instancetype)ivar:(Ivar)ivar { - return [[self alloc] initWithIvar:ivar]; -} - -+ (instancetype)named:(NSString *)name onClass:(Class)cls { - Ivar _Nullable ivar = class_getInstanceVariable(cls, name.UTF8String); - NSAssert(ivar, @"Cannot find ivar with name %@ on class %@", name, cls); - return [self ivar:ivar]; -} - -- (id)initWithIvar:(Ivar)ivar { - NSParameterAssert(ivar); - - self = [super init]; - if (self) { - _objc_ivar = ivar; - [self examine]; - } - - return self; -} - -#pragma mark Other - -- (NSString *)description { - if (!_flex_description) { - NSString *readableType = [FLEXRuntimeUtility readableTypeForEncoding:self.typeEncoding]; - _flex_description = [FLEXRuntimeUtility appendName:self.name toType:readableType]; - } - - return _flex_description; -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@"<%@ name=%@, encoding=%@, offset=%ld>", - NSStringFromClass(self.class), self.name, self.typeEncoding, (long)self.offset]; -} - -- (void)examine { - _name = @(ivar_getName(self.objc_ivar) ?: "(nil)"); - _offset = ivar_getOffset(self.objc_ivar); - _typeEncoding = @(ivar_getTypeEncoding(self.objc_ivar) ?: ""); - - NSString *typeForDetails = _typeEncoding; - NSString *sizeForDetails = nil; - if (_typeEncoding.length) { - _type = (FLEXTypeEncoding)[_typeEncoding characterAtIndex:0]; - FLEXGetSizeAndAlignment(_typeEncoding.UTF8String, &_size, nil); - sizeForDetails = [@(_size).stringValue stringByAppendingString:@" bytes"]; - } else { - _type = FLEXTypeEncodingNull; - typeForDetails = @"no type info"; - sizeForDetails = @"unknown size"; - } - - Dl_info exeInfo; - if (dladdr(_objc_ivar, &exeInfo)) { - _imagePath = exeInfo.dli_fname ? @(exeInfo.dli_fname) : nil; - } - - _details = [NSString stringWithFormat: - @"%@, offset %@ — %@", - sizeForDetails, @(_offset), typeForDetails - ]; -} - -- (id)getValue:(id)target { - id value = nil; - if (!FLEXIvarIsSafe(_objc_ivar) || - _type == FLEXTypeEncodingNull || - FLEXPointerIsTaggedPointer(target)) { - return nil; - } - -#ifdef __arm64__ - // See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html - if (self.type == FLEXTypeEncodingObjcClass && [self.name isEqualToString:@"isa"]) { - value = object_getClass(target); - } else -#endif - if (self.type == FLEXTypeEncodingObjcObject || self.type == FLEXTypeEncodingObjcClass) { - value = object_getIvar(target, self.objc_ivar); - } else { - void *pointer = (__bridge void *)target + self.offset; - value = [FLEXRuntimeUtility - valueForPrimitivePointer:pointer - objCType:self.typeEncoding.UTF8String - ]; - } - - return value; -} - -- (void)setValue:(id)value onObject:(id)target { - const char *typeEncodingCString = self.typeEncoding.UTF8String; - if (self.type == FLEXTypeEncodingObjcObject) { - object_setIvar(target, self.objc_ivar, value); - } else if ([value isKindOfClass:[NSValue class]]) { - // Primitive - unbox the NSValue. - NSValue *valueValue = (NSValue *)value; - - // Make sure that the box contained the correct type. - NSAssert( - strcmp(valueValue.objCType, typeEncodingCString) == 0, - @"Type encoding mismatch (value: %s; ivar: %s) in setting ivar named: %@ on object: %@", - valueValue.objCType, typeEncodingCString, self.name, target - ); - - NSUInteger bufferSize = 0; - if (FLEXGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL)) { - void *buffer = calloc(bufferSize, 1); - [valueValue getValue:buffer]; - void *pointer = (__bridge void *)target + self.offset; - memcpy(pointer, buffer, bufferSize); - free(buffer); - } - } -} - -- (id)getPotentiallyUnboxedValue:(id)target { - NSString *type = self.typeEncoding; - if (type.flex_typeIsNonObjcPointer && type.flex_pointeeType != FLEXTypeEncodingVoid) { - return [self getValue:target]; - } - - return [FLEXRuntimeUtility - potentiallyUnwrapBoxedPointer:[self getValue:target] - type:type.UTF8String - ]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.h deleted file mode 100644 index 2565053..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// FLEXMethod.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" -#import "FLEXMethodBase.h" - -NS_ASSUME_NONNULL_BEGIN - -/// A class representing a concrete method which already exists in a class. -/// This class contains helper methods for swizzling or invoking the method. -/// -/// Any of the initializers will return nil if the type encoding -/// of the method is unsupported by `NSMethodSignature`. In general, -/// any method whose return type or parameters involve a struct with -/// bitfields or arrays is unsupported. -/// -/// I do not remember why I didn't include \c signature in the base class -/// when I originally wrote this, but I probably had a good reason. We can -/// always go back and move it to \c FLEXMethodBase if we find we need to. -@interface FLEXMethod : FLEXMethodBase - -/// Defaults to instance method -+ (nullable instancetype)method:(Method)method; -+ (nullable instancetype)method:(Method)method isInstanceMethod:(BOOL)isInstanceMethod; - -/// Constructs an \c FLEXMethod for the given method on the given class. -/// @param cls the class, or metaclass if this is a class method -/// @return The newly constructed \c FLEXMethod object, or \c nil if the -/// specified class or its superclasses do not contain a method with the specified selector. -+ (nullable instancetype)selector:(SEL)selector class:(Class)cls; -/// Constructs an \c FLEXMethod for the given method on the given class, -/// only if the given class itself defines or overrides the desired method. -/// @param cls the class, or metaclass if this is a class method -/// @return The newly constructed \c FLEXMethod object, or \c nil \e if the -/// specified class does not define or override, or if the specified class -/// or its superclasses do not contain, a method with the specified selector. -+ (nullable instancetype)selector:(SEL)selector implementedInClass:(Class)cls; - -@property (nonatomic, readonly) Method objc_method; -/// The implementation of the method. -/// @discussion Setting \c implementation will change the implementation of this method -/// for the entire class which implements said method. It will also not modify the selector of said method. -@property (nonatomic ) IMP implementation; -/// Whether the method is an instance method or not. -@property (nonatomic, readonly) BOOL isInstanceMethod; -/// The number of arguments to the method. -@property (nonatomic, readonly) NSUInteger numberOfArguments; -/// The \c NSMethodSignature object corresponding to the method's type encoding. -@property (nonatomic, readonly) NSMethodSignature *signature; -/// Same as \e typeEncoding but with parameter sizes up front and offsets after the types. -@property (nonatomic, readonly) NSString *signatureString; -/// The return type of the method. -@property (nonatomic, readonly) FLEXTypeEncoding *returnType; -/// The return size of the method. -@property (nonatomic, readonly) NSUInteger returnSize; -/// The full path of the image that contains this method definition, -/// or \c nil if this ivar was probably defined at runtime. -@property (nonatomic, readonly) NSString *imagePath; - -/// Like @code - (void)foo:(int)bar @endcode -@property (nonatomic, readonly) NSString *description; -/// Like @code -[Class foo:] @endcode -- (NSString *)debugNameGivenClassName:(NSString *)name; - -/// Swizzles the recieving method with the given method. -- (void)swapImplementations:(FLEXMethod *)method; - -#define FLEXMagicNumber 0xdeadbeef -#define FLEXArg(expr) FLEXMagicNumber,/// @encode(__typeof__(expr)), (__typeof__(expr) []){ expr } - -/// Sends a message to \e target, and returns it's value, or \c nil if not applicable. -/// @discussion You may send any message with this method. Primitive return values will be wrapped -/// in instances of \c NSNumber and \c NSValue. \c void and bitfield returning methods return \c nil. -/// \c SEL return types are converted to strings using \c NSStringFromSelector. -/// @return The object returned by this method, or an instance of \c NSValue or \c NSNumber containing -/// the primitive return type, or a string for \c SEL return types. -- (id)sendMessage:(id)target, ...; -/// Used internally by \c sendMessage:target,. Pass \c NULL to the first parameter for void methods. -- (void)getReturnValue:(void *)retPtr forMessageSend:(id)target, ...; - -@end - - -@interface FLEXMethod (Comparison) - -- (NSComparisonResult)compare:(FLEXMethod *)method; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.m deleted file mode 100644 index f8c3b82..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethod.m +++ /dev/null @@ -1,430 +0,0 @@ -// -// FLEXMethod.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMethod.h" -#import "FLEXMirror.h" -#import "FLEXTypeEncodingParser.h" -#import "FLEXRuntimeUtility.h" -#include - -@implementation FLEXMethod -@synthesize imagePath = _imagePath; -@dynamic implementation; - -+ (instancetype)buildMethodNamed:(NSString *)name withTypes:(NSString *)typeEncoding implementation:(IMP)implementation { - [NSException raise:NSInternalInconsistencyException format:@"Class instance should not be created with +buildMethodNamed:withTypes:implementation"]; return nil; -} - -- (id)init { - [NSException - raise:NSInternalInconsistencyException - format:@"Class instance should not be created with -init" - ]; - return nil; -} - -#pragma mark Initializers - -+ (instancetype)method:(Method)method { - return [[self alloc] initWithMethod:method isInstanceMethod:YES]; -} - -+ (instancetype)method:(Method)method isInstanceMethod:(BOOL)isInstanceMethod { - return [[self alloc] initWithMethod:method isInstanceMethod:isInstanceMethod]; -} - -+ (instancetype)selector:(SEL)selector class:(Class)cls { - BOOL instance = !class_isMetaClass(cls); - // class_getInstanceMethod will return an instance method if not given - // not given a metaclass, or a class method if given a metaclass, but - // this isn't documented so we just want to be safe here. - Method m = instance ? class_getInstanceMethod(cls, selector) : class_getClassMethod(cls, selector); - if (m == NULL) return nil; - - return [self method:m isInstanceMethod:instance]; -} - -+ (instancetype)selector:(SEL)selector implementedInClass:(Class)cls { - if (![cls superclass]) { return [self selector:selector class:cls]; } - - BOOL unique = [cls methodForSelector:selector] != [[cls superclass] methodForSelector:selector]; - - if (unique) { - return [self selector:selector class:cls]; - } - - return nil; -} - -- (id)initWithMethod:(Method)method isInstanceMethod:(BOOL)isInstanceMethod { - NSParameterAssert(method); - - self = [super init]; - if (self) { - _objc_method = method; - _isInstanceMethod = isInstanceMethod; - _signatureString = @(method_getTypeEncoding(method) ?: "?@:"); - - NSString *cleanSig = nil; - if ([FLEXTypeEncodingParser methodTypeEncodingSupported:_signatureString cleaned:&cleanSig]) { - _signature = [NSMethodSignature signatureWithObjCTypes:cleanSig.UTF8String]; - } - - [self examine]; - } - - return self; -} - - -#pragma mark Other - -- (NSString *)description { - if (!_flex_description) { - _flex_description = [self prettyName]; - } - - return _flex_description; -} - -- (NSString *)debugNameGivenClassName:(NSString *)name { - NSMutableString *string = [NSMutableString stringWithString:_isInstanceMethod ? @"-[" : @"+["]; - [string appendString:name]; - [string appendString:@" "]; - [string appendString:self.selectorString]; - [string appendString:@"]"]; - return string; -} - -- (NSString *)prettyName { - NSString *methodTypeString = self.isInstanceMethod ? @"-" : @"+"; - NSString *readableReturnType = [FLEXRuntimeUtility readableTypeForEncoding:@(self.signature.methodReturnType ?: "")]; - - NSString *prettyName = [NSString stringWithFormat:@"%@ (%@)", methodTypeString, readableReturnType]; - NSArray *components = [self prettyArgumentComponents]; - - if (components.count) { - return [prettyName stringByAppendingString:[components componentsJoinedByString:@" "]]; - } else { - return [prettyName stringByAppendingString:self.selectorString]; - } -} - -- (NSArray *)prettyArgumentComponents { - // NSMethodSignature can't handle some type encodings - // like ^AI@:ir* which happen to very much exist - if (self.signature.numberOfArguments < self.numberOfArguments) { - return nil; - } - - NSMutableArray *components = [NSMutableArray new]; - - NSArray *selectorComponents = [self.selectorString componentsSeparatedByString:@":"]; - NSUInteger numberOfArguments = self.numberOfArguments; - - for (NSUInteger argIndex = 2; argIndex < numberOfArguments; argIndex++) { - assert(argIndex < self.signature.numberOfArguments); - - const char *argType = [self.signature getArgumentTypeAtIndex:argIndex] ?: "?"; - NSString *readableArgType = [FLEXRuntimeUtility readableTypeForEncoding:@(argType)]; - NSString *prettyComponent = [NSString - stringWithFormat:@"%@:(%@) ", - selectorComponents[argIndex - 2], - readableArgType - ]; - - [components addObject:prettyComponent]; - } - - return components; -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@"<%@ selector=%@, signature=%@>", - NSStringFromClass(self.class), self.selectorString, self.signatureString]; -} - -- (void)examine { - _implementation = method_getImplementation(_objc_method); - _selector = method_getName(_objc_method); - _numberOfArguments = method_getNumberOfArguments(_objc_method); - _name = NSStringFromSelector(_selector); - _returnType = (FLEXTypeEncoding *)_signature.methodReturnType ?: ""; - _returnSize = _signature.methodReturnLength; -} - -#pragma mark Public - -- (void)setImplementation:(IMP)implementation { - NSParameterAssert(implementation); - method_setImplementation(self.objc_method, implementation); - [self examine]; -} - -- (NSString *)typeEncoding { - if (!_typeEncoding) { - _typeEncoding = [_signatureString - stringByReplacingOccurrencesOfString:@"[0-9]" - withString:@"" - options:NSRegularExpressionSearch - range:NSMakeRange(0, _signatureString.length) - ]; - } - - return _typeEncoding; -} - -- (NSString *)imagePath { - if (!_imagePath) { - Dl_info exeInfo; - if (dladdr(_implementation, &exeInfo)) { - _imagePath = exeInfo.dli_fname ? @(exeInfo.dli_fname) : @""; - } - } - - return _imagePath; -} - -#pragma mark Misc - -- (void)swapImplementations:(FLEXMethod *)method { - method_exchangeImplementations(self.objc_method, method.objc_method); - [self examine]; - [method examine]; -} - -// Some code borrowed from MAObjcRuntime, by Mike Ash. -- (id)sendMessage:(id)target, ... { - id ret = nil; - va_list args; - va_start(args, target); - - switch (self.returnType[0]) { - case FLEXTypeEncodingUnknown: { - [self getReturnValue:NULL forMessageSend:target arguments:args]; - break; - } - case FLEXTypeEncodingChar: { - char val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingInt: { - int val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingShort: { - short val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingLong: { - long val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingLongLong: { - long long val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingUnsignedChar: { - unsigned char val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingUnsignedInt: { - unsigned int val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingUnsignedShort: { - unsigned short val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingUnsignedLong: { - unsigned long val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingUnsignedLongLong: { - unsigned long long val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingFloat: { - float val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingDouble: { - double val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingLongDouble: { - long double val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = [NSValue value:&val withObjCType:self.returnType]; - break; - } - case FLEXTypeEncodingCBool: { - bool val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingVoid: { - [self getReturnValue:NULL forMessageSend:target arguments:args]; - return nil; - break; - } - case FLEXTypeEncodingCString: { - char *val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = @(val); - break; - } - case FLEXTypeEncodingObjcObject: { - id val = nil; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = val; - break; - } - case FLEXTypeEncodingObjcClass: { - Class val = Nil; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = val; - break; - } - case FLEXTypeEncodingSelector: { - SEL val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = NSStringFromSelector(val); - break; - } - case FLEXTypeEncodingArrayBegin: { - void *val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = [NSValue valueWithBytes:val objCType:self.signature.methodReturnType]; - break; - } - case FLEXTypeEncodingUnionBegin: - case FLEXTypeEncodingStructBegin: { - if (self.signature.methodReturnLength) { - void * val = malloc(self.signature.methodReturnLength); - [self getReturnValue:val forMessageSend:target arguments:args]; - ret = [NSValue valueWithBytes:val objCType:self.signature.methodReturnType]; - } else { - [self getReturnValue:NULL forMessageSend:target arguments:args]; - } - break; - } - case FLEXTypeEncodingBitField: { - [self getReturnValue:NULL forMessageSend:target arguments:args]; - break; - } - case FLEXTypeEncodingPointer: { - void * val = 0; - [self getReturnValue:&val forMessageSend:target arguments:args]; - ret = [NSValue valueWithPointer:val]; - break; - } - - default: { - [NSException raise:NSInvalidArgumentException - format:@"Unsupported type encoding: %s", (char *)self.returnType]; - } - } - - va_end(args); - return ret; -} - -// Code borrowed from MAObjcRuntime, by Mike Ash. -- (void)getReturnValue:(void *)retPtr forMessageSend:(id)target, ... { - va_list args; - va_start(args, target); - [self getReturnValue:retPtr forMessageSend:target arguments:args]; - va_end(args); -} - -// Code borrowed from MAObjcRuntime, by Mike Ash. -- (void)getReturnValue:(void *)retPtr forMessageSend:(id)target arguments:(va_list)args { - if (!_signature) { - return; - } - - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:_signature]; - NSUInteger argumentCount = _signature.numberOfArguments; - - invocation.target = target; - - for (NSUInteger i = 2; i < argumentCount; i++) { - int cookie = va_arg(args, int); - if (cookie != FLEXMagicNumber) { - [NSException - raise:NSInternalInconsistencyException - format:@"%s: incorrect magic cookie %08x; make sure you didn't forget " - "any arguments and that all arguments are wrapped in FLEXArg().", __func__, cookie - ]; - } - const char *typeString = va_arg(args, char *); - void *argPointer = va_arg(args, void *); - - NSUInteger inSize, sigSize; - NSGetSizeAndAlignment(typeString, &inSize, NULL); - NSGetSizeAndAlignment([_signature getArgumentTypeAtIndex:i], &sigSize, NULL); - - if (inSize != sigSize) { - [NSException - raise:NSInternalInconsistencyException - format:@"%s:size mismatch between passed-in argument and " - "required argument; in type:%s (%lu) requested:%s (%lu)", - __func__, typeString, (long)inSize, [_signature getArgumentTypeAtIndex:i], (long)sigSize - ]; - } - - [invocation setArgument:argPointer atIndex:i]; - } - - // Hack to make NSInvocation invoke the desired implementation - IMP imp = [invocation methodForSelector:NSSelectorFromString(@"invokeUsingIMP:")]; - void (*invokeWithIMP)(id, SEL, IMP) = (void *)imp; - invokeWithIMP(invocation, 0, _implementation); - - if (_signature.methodReturnLength && retPtr) { - [invocation getReturnValue:retPtr]; - } -} - -@end - - -@implementation FLEXMethod (Comparison) - -- (NSComparisonResult)compare:(FLEXMethod *)method { - return [self.selectorString compare:method.selectorString]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethodBase.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethodBase.h deleted file mode 100644 index 177ec1d..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethodBase.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// FLEXMethodBase.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/5/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - - -/// A base class for methods which encompasses those that may not -/// have been added to a class yet. Useful on it's own for adding -/// methods to a class, or building a new class from the ground up. -@interface FLEXMethodBase : NSObject { -@protected - SEL _selector; - NSString *_name; - NSString *_typeEncoding; - IMP _implementation; - - NSString *_flex_description; -} - -/// Constructs and returns an \c FLEXSimpleMethod instance with the given name, type encoding, and implementation. -+ (instancetype)buildMethodNamed:(NSString *)name withTypes:(NSString *)typeEncoding implementation:(IMP)implementation; - -/// The selector of the method. -@property (nonatomic, readonly) SEL selector; -/// The selector string of the method. -@property (nonatomic, readonly) NSString *selectorString; -/// Same as selectorString. -@property (nonatomic, readonly) NSString *name; -/// The type encoding of the method. -@property (nonatomic, readonly) NSString *typeEncoding; -/// The implementation of the method. -@property (nonatomic, readonly) IMP implementation; - -/// For internal use -@property (nonatomic) id tag; - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethodBase.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethodBase.m deleted file mode 100644 index a8aeb3f..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMethodBase.m +++ /dev/null @@ -1,49 +0,0 @@ -// -// FLEXMethodBase.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/5/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMethodBase.h" - - -@implementation FLEXMethodBase - -#pragma mark Initializers - -+ (instancetype)buildMethodNamed:(NSString *)name withTypes:(NSString *)typeEncoding implementation:(IMP)implementation { - return [[self alloc] initWithSelector:sel_registerName(name.UTF8String) types:typeEncoding imp:implementation]; -} - -- (id)initWithSelector:(SEL)selector types:(NSString *)types imp:(IMP)imp { - NSParameterAssert(selector); NSParameterAssert(types); NSParameterAssert(imp); - - self = [super init]; - if (self) { - _selector = selector; - _typeEncoding = types; - _implementation = imp; - _name = NSStringFromSelector(self.selector); - } - - return self; -} - -- (NSString *)selectorString { - return _name; -} - -#pragma mark Overrides - -- (NSString *)description { - if (!_flex_description) { - _flex_description = [NSString stringWithFormat:@"%@ '%@'", _name, _typeEncoding]; - } - - return _flex_description; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMirror.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMirror.h deleted file mode 100644 index 7021c70..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMirror.h +++ /dev/null @@ -1,97 +0,0 @@ -// -// FLEXMirror.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/29/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import -@class FLEXMethod, FLEXProperty, FLEXIvar, FLEXProtocol; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark FLEXMirror Protocol -NS_SWIFT_NAME(FLEXMirrorProtocol) -@protocol FLEXMirror - -/// Swift initializer -/// @throws If a metaclass object is passed in. -- (instancetype)initWithSubject:(id)objectOrClass NS_SWIFT_NAME(init(reflecting:)); - -/// The underlying object or \c Class used to create this \c FLEXMirror. -@property (nonatomic, readonly) id value; -/// Whether \c value was a class or a class instance. -@property (nonatomic, readonly) BOOL isClass; -/// The name of the \c Class of the \c value property. -@property (nonatomic, readonly) NSString *className; - -@property (nonatomic, readonly) NSArray *properties; -@property (nonatomic, readonly) NSArray *classProperties; -@property (nonatomic, readonly) NSArray *ivars; -@property (nonatomic, readonly) NSArray *methods; -@property (nonatomic, readonly) NSArray *classMethods; -@property (nonatomic, readonly) NSArray *protocols; - -/// Super mirrors are initialized with the class that corresponds to the value passed in. -/// If you passed in an instance of a class, it's superclass is used to create this mirror. -/// If you passed in a class, then that class's superclass is used. -/// -/// @note This property should be computed, not cached. -@property (nonatomic, readonly, nullable) id superMirror NS_SWIFT_NAME(superMirror); - -@end - -#pragma mark FLEXMirror Class -@interface FLEXMirror : NSObject - -/// Reflects an instance of an object or \c Class. -/// @discussion \c FLEXMirror will immediately gather all useful information. Consider using the -/// \c NSObject categories provided if your code will only use a few pieces of information, -/// or if your code needs to run faster. -/// -/// Regardless of whether you reflect an instance or a class object, \c methods and \c properties -/// will be populated with instance methods and properties, and \c classMethods and \c classProperties -/// will be populated with class methods and properties. -/// -/// @param objectOrClass An instance of an objct or a \c Class object. -/// @throws If a metaclass object is passed in. -/// @return An instance of \c FLEXMirror. -+ (instancetype)reflect:(id)objectOrClass; - -@property (nonatomic, readonly) id value; -@property (nonatomic, readonly) BOOL isClass; -@property (nonatomic, readonly) NSString *className; - -@property (nonatomic, readonly) NSArray *properties; -@property (nonatomic, readonly) NSArray *classProperties; -@property (nonatomic, readonly) NSArray *ivars; -@property (nonatomic, readonly) NSArray *methods; -@property (nonatomic, readonly) NSArray *classMethods; -@property (nonatomic, readonly) NSArray *protocols; - -@property (nonatomic, readonly, nullable) FLEXMirror *superMirror NS_SWIFT_NAME(superMirror); - -@end - - -@interface FLEXMirror (ExtendedMirror) - -/// @return The instance method with the given name, or \c nil if one does not exist. -- (nullable FLEXMethod *)methodNamed:(nullable NSString *)name; -/// @return The class method with the given name, or \c nil if one does not exist. -- (nullable FLEXMethod *)classMethodNamed:(nullable NSString *)name; -/// @return The instance property with the given name, or \c nil if one does not exist. -- (nullable FLEXProperty *)propertyNamed:(nullable NSString *)name; -/// @return The class property with the given name, or \c nil if one does not exist. -- (nullable FLEXProperty *)classPropertyNamed:(nullable NSString *)name; -/// @return The instance variable with the given name, or \c nil if one does not exist. -- (nullable FLEXIvar *)ivarNamed:(nullable NSString *)name; -/// @return The protocol with the given name, or \c nil if one does not exist. -- (nullable FLEXProtocol *)protocolNamed:(nullable NSString *)name; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMirror.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMirror.m deleted file mode 100644 index 688977b..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXMirror.m +++ /dev/null @@ -1,145 +0,0 @@ -// -// FLEXMirror.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/29/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXMirror.h" -#import "FLEXProperty.h" -#import "FLEXMethod.h" -#import "FLEXIvar.h" -#import "FLEXProtocol.h" -#import "FLEXUtility.h" - - -#pragma mark FLEXMirror - -@implementation FLEXMirror - -- (id)init { - [NSException - raise:NSInternalInconsistencyException - format:@"Class instance should not be created with -init" - ]; - return nil; -} - -#pragma mark Initialization -+ (instancetype)reflect:(id)objectOrClass { - return [[self alloc] initWithSubject:objectOrClass]; -} - -- (id)initWithSubject:(id)objectOrClass { - NSParameterAssert(objectOrClass); - - self = [super init]; - if (self) { - _value = objectOrClass; - [self examine]; - } - - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@ %@=%@>", - NSStringFromClass(self.class), - self.isClass ? @"metaclass" : @"class", - self.className - ]; -} - -- (void)examine { - BOOL isClass = object_isClass(self.value); - Class cls = isClass ? self.value : object_getClass(self.value); - Class meta = object_getClass(cls); - _className = NSStringFromClass(cls); - _isClass = isClass; - - unsigned int pcount, cpcount, mcount, cmcount, ivcount, pccount; - Ivar *objcIvars = class_copyIvarList(cls, &ivcount); - Method *objcMethods = class_copyMethodList(cls, &mcount); - Method *objcClsMethods = class_copyMethodList(meta, &cmcount); - objc_property_t *objcProperties = class_copyPropertyList(cls, &pcount); - objc_property_t *objcClsProperties = class_copyPropertyList(meta, &cpcount); - Protocol *__unsafe_unretained *protos = class_copyProtocolList(cls, &pccount); - - _ivars = [NSArray flex_forEachUpTo:ivcount map:^id(NSUInteger i) { - return [FLEXIvar ivar:objcIvars[i]]; - }]; - - _methods = [NSArray flex_forEachUpTo:mcount map:^id(NSUInteger i) { - return [FLEXMethod method:objcMethods[i] isInstanceMethod:YES]; - }]; - _classMethods = [NSArray flex_forEachUpTo:cmcount map:^id(NSUInteger i) { - return [FLEXMethod method:objcClsMethods[i] isInstanceMethod:NO]; - }]; - - _properties = [NSArray flex_forEachUpTo:pcount map:^id(NSUInteger i) { - return [FLEXProperty property:objcProperties[i] onClass:cls]; - }]; - _classProperties = [NSArray flex_forEachUpTo:cpcount map:^id(NSUInteger i) { - return [FLEXProperty property:objcClsProperties[i] onClass:meta]; - }]; - - _protocols = [NSArray flex_forEachUpTo:pccount map:^id(NSUInteger i) { - return [FLEXProtocol protocol:protos[i]]; - }]; - - // Cleanup - free(objcClsProperties); - free(objcProperties); - free(objcClsMethods); - free(objcMethods); - free(objcIvars); - free(protos); - protos = NULL; -} - -#pragma mark Misc - -- (FLEXMirror *)superMirror { - Class cls = _isClass ? _value : object_getClass(_value); - return [FLEXMirror reflect:class_getSuperclass(cls)]; -} - -@end - - -#pragma mark ExtendedMirror - -@implementation FLEXMirror (ExtendedMirror) - -- (id)filter:(NSArray *)array forName:(NSString *)name { - NSPredicate *filter = [NSPredicate predicateWithFormat:@"%K = %@", @"name", name]; - return [array filteredArrayUsingPredicate:filter].firstObject; -} - -- (FLEXMethod *)methodNamed:(NSString *)name { - return [self filter:self.methods forName:name]; -} - -- (FLEXMethod *)classMethodNamed:(NSString *)name { - return [self filter:self.classMethods forName:name]; -} - -- (FLEXProperty *)propertyNamed:(NSString *)name { - return [self filter:self.properties forName:name]; -} - -- (FLEXProperty *)classPropertyNamed:(NSString *)name { - return [self filter:self.classProperties forName:name]; -} - -- (FLEXIvar *)ivarNamed:(NSString *)name { - return [self filter:self.ivars forName:name]; -} - -- (FLEXProtocol *)protocolNamed:(NSString *)name { - return [self filter:self.protocols forName:name]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProperty.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProperty.h deleted file mode 100644 index accc539..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProperty.h +++ /dev/null @@ -1,138 +0,0 @@ -// -// FLEXProperty.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" -@class FLEXPropertyAttributes, FLEXMethodBase; - - -#pragma mark FLEXProperty -@interface FLEXProperty : NSObject - -/// You may use this initializer instead of \c property:onClass: if you don't need -/// to know anything about the uniqueness of this property or where it comes from. -+ (instancetype)property:(objc_property_t)property; -/// This initializer can be used to access additional information -/// in an efficient manner. That information being whether this property -/// is certainly not unique and the name of the binary image which declares it. -/// @param cls the class, or metaclass if this is a class property. -+ (instancetype)property:(objc_property_t)property onClass:(Class)cls; -/// @param cls the class, or metaclass if this is a class property -+ (instancetype)named:(NSString *)name onClass:(Class)cls; -/// Constructs a new property with the given name and attributes. -+ (instancetype)propertyWithName:(NSString *)name attributes:(FLEXPropertyAttributes *)attributes; - -/// \c 0 if the instance was created via \c +propertyWithName:attributes, -/// otherwise this is the first property in \c objc_properties -@property (nonatomic, readonly) objc_property_t objc_property; -@property (nonatomic, readonly) objc_property_t *objc_properties; -@property (nonatomic, readonly) NSInteger objc_propertyCount; -@property (nonatomic, readonly) BOOL isClassProperty; - -/// The name of the property. -@property (nonatomic, readonly) NSString *name; -/// The type of the property. Get the full type from the attributes. -@property (nonatomic, readonly) FLEXTypeEncoding type; -/// The property's attributes. -@property (nonatomic ) FLEXPropertyAttributes *attributes; -/// The (likely) setter, regardless of whether the property is readonly. -/// For example, this might be the custom setter. -@property (nonatomic, readonly) SEL likelySetter; -@property (nonatomic, readonly) NSString *likelySetterString; -/// Not valid unless initialized with the owning class. -@property (nonatomic, readonly) BOOL likelySetterExists; -/// The (likely) getter. For example, this might be the custom getter. -@property (nonatomic, readonly) SEL likelyGetter; -@property (nonatomic, readonly) NSString *likelyGetterString; -/// Not valid unless initialized with the owning class. -@property (nonatomic, readonly) BOOL likelyGetterExists; -/// Always \c nil for class properties. -@property (nonatomic, readonly) NSString *likelyIvarName; -/// Not valid unless initialized with the owning class. -@property (nonatomic, readonly) BOOL likelyIvarExists; - -/// Whether there are certainly multiple definitions of this property, -/// such as in categories in other binary images or something. -/// @return Whether \c objc_property matches the return value of \c class_getProperty, -/// or \c NO if this property was not created with \c property:onClass -@property (nonatomic, readonly) BOOL multiple; -/// @return The bundle of the image that contains this property definition, -/// or \c nil if this property was not created with \c property:onClass or -/// if this property was probably defined at runtime. -@property (nonatomic, readonly) NSString *imageName; -/// The full path of the image that contains this property definition, -/// or \c nil if this property was not created with \c property:onClass or -/// if this property was probably defined at runtime. -@property (nonatomic, readonly) NSString *imagePath; - -/// For internal use -@property (nonatomic) id tag; - -/// @return The value of this property on \c target as given by \c -valueForKey: -/// A source-like description of the property, with all of its attributes. -@property (nonatomic, readonly) NSString *fullDescription; - -/// If this is a class property, you must class the class object. -- (id)getValue:(id)target; -/// Calls into -getValue: and passes that value into -/// -[FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:type:] -/// and returns the result. -/// -/// If this is a class property, you must class the class object. -- (id)getPotentiallyUnboxedValue:(id)target; - -/// Safe to use regardless of how the \c FLEXProperty instance was initialized. -/// -/// This uses \c self.objc_property if it exists, otherwise it uses \c self.attributes -- (objc_property_attribute_t *)copyAttributesList:(unsigned int *)attributesCount; - -/// Replace the attributes of the current property in the given class, -/// using the attributes in \c self.attributes -/// -/// What happens when the property does not exist is undocumented. -- (void)replacePropertyOnClass:(Class)cls; - -#pragma mark Convenience getters and setters -/// @return A getter for the property with the given implementation. -/// @discussion Consider using the \c FLEXPropertyGetter macros. -- (FLEXMethodBase *)getterWithImplementation:(IMP)implementation; -/// @return A setter for the property with the given implementation. -/// @discussion Consider using the \c FLEXPropertySetter macros. -- (FLEXMethodBase *)setterWithImplementation:(IMP)implementation; - -#pragma mark FLEXMethod property getter / setter macros -// Easier than using the above methods yourself in most cases - -/// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and -/// uses the \c FLEXProperty's \c attribute's \c backingIvarName to get the Ivar. -#define FLEXPropertyGetter(FLEXProperty, type) [FLEXProperty \ - getterWithImplementation:imp_implementationWithBlock(^(id self) { \ - return *(type *)[self getIvarAddressByName:FLEXProperty.attributes.backingIvar]; \ - }) \ -]; -/// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and -/// uses the \c FLEXProperty's \c attribute's \c backingIvarName to set the Ivar. -#define FLEXPropertySetter(FLEXProperty, type) [FLEXProperty \ - setterWithImplementation:imp_implementationWithBlock(^(id self, type value) { \ - [self setIvarByName:FLEXProperty.attributes.backingIvar value:&value size:sizeof(type)]; \ - }) \ -]; -/// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and an Ivar name string to get the Ivar. -#define FLEXPropertyGetterWithIvar(FLEXProperty, ivarName, type) [FLEXProperty \ - getterWithImplementation:imp_implementationWithBlock(^(id self) { \ - return *(type *)[self getIvarAddressByName:ivarName]; \ - }) \ -]; -/// Takes a \c FLEXProperty and a type (ie \c NSUInteger or \c id) and an Ivar name string to set the Ivar. -#define FLEXPropertySetterWithIvar(FLEXProperty, ivarName, type) [FLEXProperty \ - setterWithImplementation:imp_implementationWithBlock(^(id self, type value) { \ - [self setIvarByName:ivarName value:&value size:sizeof(type)]; \ - }) \ -]; - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProperty.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProperty.m deleted file mode 100644 index d5d217f..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProperty.m +++ /dev/null @@ -1,295 +0,0 @@ -// -// FLEXProperty.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXProperty.h" -#import "FLEXPropertyAttributes.h" -#import "FLEXMethodBase.h" -#import "FLEXRuntimeUtility.h" -#include - - -@interface FLEXProperty () { - NSString *_flex_description; -} -@property (nonatomic ) BOOL uniqueCheckFlag; -@property (nonatomic, readonly) Class cls; -@end - -@implementation FLEXProperty -@synthesize multiple = _multiple; -@synthesize imageName = _imageName; -@synthesize imagePath = _imagePath; - -#pragma mark Initializers - -- (id)init { - [NSException - raise:NSInternalInconsistencyException - format:@"Class instance should not be created with -init" - ]; - return nil; -} - -+ (instancetype)property:(objc_property_t)property { - return [[self alloc] initWithProperty:property onClass:nil]; -} - -+ (instancetype)property:(objc_property_t)property onClass:(Class)cls { - return [[self alloc] initWithProperty:property onClass:cls]; -} - -+ (instancetype)named:(NSString *)name onClass:(Class)cls { - objc_property_t _Nullable property = class_getProperty(cls, name.UTF8String); - NSAssert(property, @"Cannot find property with name %@ on class %@", name, cls); - return [self property:property onClass:cls]; -} - -+ (instancetype)propertyWithName:(NSString *)name attributes:(FLEXPropertyAttributes *)attributes { - return [[self alloc] initWithName:name attributes:attributes]; -} - -- (id)initWithProperty:(objc_property_t)property onClass:(Class)cls { - NSParameterAssert(property); - - self = [super init]; - if (self) { - _objc_property = property; - _attributes = [FLEXPropertyAttributes attributesForProperty:property]; - _name = @(property_getName(property) ?: "(nil)"); - _cls = cls; - - if (!_attributes) [NSException raise:NSInternalInconsistencyException format:@"Error retrieving property attributes"]; - if (!_name) [NSException raise:NSInternalInconsistencyException format:@"Error retrieving property name"]; - - [self examine]; - } - - return self; -} - -- (id)initWithName:(NSString *)name attributes:(FLEXPropertyAttributes *)attributes { - NSParameterAssert(name); NSParameterAssert(attributes); - - self = [super init]; - if (self) { - _attributes = attributes; - _name = name; - - [self examine]; - } - - return self; -} - -#pragma mark Private - -- (void)examine { - if (self.attributes.typeEncoding.length) { - _type = (FLEXTypeEncoding)[self.attributes.typeEncoding characterAtIndex:0]; - } - - // Return the given selector if the class responds to it - Class cls = _cls; - SEL (^selectorIfValid)(SEL) = ^SEL(SEL sel) { - if (!sel || !cls) return nil; - return [cls instancesRespondToSelector:sel] ? sel : nil; - }; - - SEL customGetter = self.attributes.customGetter; - SEL customSetter = self.attributes.customSetter; - SEL defaultGetter = NSSelectorFromString(self.name); - SEL defaultSetter = NSSelectorFromString([NSString - stringWithFormat:@"set%c%@:", - (char)toupper([self.name characterAtIndex:0]), - [self.name substringFromIndex:1] - ]); - - // Check if the likely getters/setters exist - SEL validGetter = selectorIfValid(customGetter) ?: selectorIfValid(defaultGetter); - SEL validSetter = selectorIfValid(customSetter) ?: selectorIfValid(defaultSetter); - _likelyGetterExists = validGetter != nil; - _likelySetterExists = validSetter != nil; - - // Assign likely getters and setters to the valid one, - // or the default, regardless of whether the default exists - _likelyGetter = validGetter ?: defaultGetter; - _likelySetter = validSetter ?: defaultSetter; - _likelyGetterString = NSStringFromSelector(_likelyGetter); - _likelySetterString = NSStringFromSelector(_likelySetter); - - _isClassProperty = _cls ? class_isMetaClass(_cls) : NO; - - _likelyIvarName = _isClassProperty ? nil : ( - self.attributes.backingIvar ?: [@"_" stringByAppendingString:_name] - ); -} - -#pragma mark Overrides - -- (NSString *)description { - if (!_flex_description) { - NSString *readableType = [FLEXRuntimeUtility readableTypeForEncoding:self.attributes.typeEncoding]; - _flex_description = [FLEXRuntimeUtility appendName:self.name toType:readableType]; - } - - return _flex_description; -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@"<%@ name=%@, property=%p, attributes:\n\t%@\n>", - NSStringFromClass(self.class), self.name, self.objc_property, self.attributes]; -} - -#pragma mark Public - -- (objc_property_attribute_t *)copyAttributesList:(unsigned int *)attributesCount { - if (self.objc_property) { - return property_copyAttributeList(self.objc_property, attributesCount); - } else { - return [self.attributes copyAttributesList:attributesCount]; - } -} - -- (void)replacePropertyOnClass:(Class)cls { - class_replaceProperty(cls, self.name.UTF8String, self.attributes.list, (unsigned int)self.attributes.count); -} - -- (void)computeSymbolInfo:(BOOL)forceBundle { - Dl_info exeInfo; - if (dladdr(_objc_property, &exeInfo)) { - _imagePath = exeInfo.dli_fname ? @(exeInfo.dli_fname) : nil; - } - - if ((!_multiple || !_uniqueCheckFlag) && _cls) { - _multiple = _objc_property != class_getProperty(_cls, self.name.UTF8String); - - if (_multiple || forceBundle) { - NSString *path = _imagePath.stringByDeletingLastPathComponent; - _imageName = [NSBundle bundleWithPath:path].executablePath.lastPathComponent; - } - } -} - -- (BOOL)multiple { - [self computeSymbolInfo:NO]; - return _multiple; -} - -- (NSString *)imagePath { - [self computeSymbolInfo:YES]; - return _imagePath; -} - -- (NSString *)imageName { - [self computeSymbolInfo:YES]; - return _imageName; -} - -- (BOOL)likelyIvarExists { - if (_likelyIvarName && _cls) { - return class_getInstanceVariable(_cls, _likelyIvarName.UTF8String) != nil; - } - - return NO; -} - -- (NSString *)fullDescription { - NSMutableArray *attributesStrings = [NSMutableArray new]; - FLEXPropertyAttributes *attributes = self.attributes; - - // Atomicity - if (attributes.isNonatomic) { - [attributesStrings addObject:@"nonatomic"]; - } else { - [attributesStrings addObject:@"atomic"]; - } - - // Storage - if (attributes.isRetained) { - [attributesStrings addObject:@"strong"]; - } else if (attributes.isCopy) { - [attributesStrings addObject:@"copy"]; - } else if (attributes.isWeak) { - [attributesStrings addObject:@"weak"]; - } else { - [attributesStrings addObject:@"assign"]; - } - - // Mutability - if (attributes.isReadOnly) { - [attributesStrings addObject:@"readonly"]; - } else { - [attributesStrings addObject:@"readwrite"]; - } - - // Class or not - if (self.isClassProperty) { - [attributesStrings addObject:@"class"]; - } - - // Custom getter/setter - SEL customGetter = attributes.customGetter; - SEL customSetter = attributes.customSetter; - if (customGetter) { - [attributesStrings addObject:[NSString stringWithFormat:@"getter=%s", sel_getName(customGetter)]]; - } - if (customSetter) { - [attributesStrings addObject:[NSString stringWithFormat:@"setter=%s", sel_getName(customSetter)]]; - } - - NSString *attributesString = [attributesStrings componentsJoinedByString:@", "]; - return [NSString stringWithFormat:@"@property (%@) %@", attributesString, self.description]; -} - -- (id)getValue:(id)target { - if (!target) return nil; - - // We don't care about checking dynamically whether the getter - // _now_ exists on this object. If the getter doesn't exist - // when this property is initialized, it will never call it. - // Just re-create the property object if you need to call it. - if (self.likelyGetterExists) { - BOOL objectIsClass = object_isClass(target); - BOOL instanceAndInstanceProperty = !objectIsClass && !self.isClassProperty; - BOOL classAndClassProperty = objectIsClass && self.isClassProperty; - - if (instanceAndInstanceProperty || classAndClassProperty) { - return [FLEXRuntimeUtility performSelector:self.likelyGetter onObject:target]; - } - } - - return nil; -} - -- (id)getPotentiallyUnboxedValue:(id)target { - if (!target) return nil; - - return [FLEXRuntimeUtility - potentiallyUnwrapBoxedPointer:[self getValue:target] - type:self.attributes.typeEncoding.UTF8String - ]; -} - -#pragma mark Suggested getters and setters - -- (FLEXMethodBase *)getterWithImplementation:(IMP)implementation { - NSString *types = [NSString stringWithFormat:@"%@%s%s", self.attributes.typeEncoding, @encode(id), @encode(SEL)]; - NSString *name = [NSString stringWithFormat:@"%@", self.name]; - FLEXMethodBase *getter = [FLEXMethodBase buildMethodNamed:name withTypes:types implementation:implementation]; - return getter; -} - -- (FLEXMethodBase *)setterWithImplementation:(IMP)implementation { - NSString *types = [NSString stringWithFormat:@"%s%s%s%@", @encode(void), @encode(id), @encode(SEL), self.attributes.typeEncoding]; - NSString *name = [NSString stringWithFormat:@"set%@:", self.name.capitalizedString]; - FLEXMethodBase *setter = [FLEXMethodBase buildMethodNamed:name withTypes:types implementation:implementation]; - return setter; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.h deleted file mode 100644 index e577101..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// FLEXPropertyAttributes.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/5/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark FLEXPropertyAttributes - -/// See \e FLEXRuntimeUtilitiy.h for valid string tokens. -/// See this link on how to construct a proper attributes string: -/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html -@interface FLEXPropertyAttributes : NSObject { -// These are necessary for the mutable subclass to function -@protected - NSUInteger _count; - NSString *_string, *_backingIvar, *_typeEncoding, *_oldTypeEncoding, *_fullDeclaration; - NSDictionary *_dictionary; - objc_property_attribute_t *_list; - SEL _customGetter, _customSetter; - BOOL _isReadOnly, _isCopy, _isRetained, _isNonatomic, _isDynamic, _isWeak, _isGarbageCollectable; -} - -+ (instancetype)attributesForProperty:(objc_property_t)property; -/// @warning Raises an exception if \e attributes is invalid, \c nil, or contains unsupported keys. -+ (instancetype)attributesFromDictionary:(NSDictionary *)attributes; - -/// Copies the attributes list to a buffer you must \c free() yourself. -/// Use \c list instead if you do not need more control over the lifetime of the list. -/// @param attributesCountOut the number of attributes is returned in this parameter. -- (objc_property_attribute_t *)copyAttributesList:(nullable unsigned int *)attributesCountOut; - -/// The number of property attributes. -@property (nonatomic, readonly) NSUInteger count; -/// For use with \c class_replaceProperty and the like. -@property (nonatomic, readonly) objc_property_attribute_t *list; -/// The string value of the property attributes. -@property (nonatomic, readonly) NSString *string; -/// A human-readable version of the property attributes. -@property (nonatomic, readonly) NSString *fullDeclaration; -/// A dictionary of the property attributes. -/// Values are either a string or \c YES. Boolean attributes -/// which are false will not be present in the dictionary. -@property (nonatomic, readonly) NSDictionary *dictionary; - -/// The name of the instance variable backing the property. -@property (nonatomic, readonly, nullable) NSString *backingIvar; -/// The type encoding of the property. -@property (nonatomic, readonly, nullable) NSString *typeEncoding; -/// The \e old type encoding of the property. -@property (nonatomic, readonly, nullable) NSString *oldTypeEncoding; -/// The property's custom getter, if any. -@property (nonatomic, readonly, nullable) SEL customGetter; -/// The property's custom setter, if any. -@property (nonatomic, readonly, nullable) SEL customSetter; -/// The property's custom getter as a string, if any. -@property (nonatomic, readonly, nullable) NSString *customGetterString; -/// The property's custom setter as a string, if any. -@property (nonatomic, readonly, nullable) NSString *customSetterString; - -@property (nonatomic, readonly) BOOL isReadOnly; -@property (nonatomic, readonly) BOOL isCopy; -@property (nonatomic, readonly) BOOL isRetained; -@property (nonatomic, readonly) BOOL isNonatomic; -@property (nonatomic, readonly) BOOL isDynamic; -@property (nonatomic, readonly) BOOL isWeak; -@property (nonatomic, readonly) BOOL isGarbageCollectable; - -@end - - -#pragma mark FLEXPropertyAttributes -@interface FLEXMutablePropertyAttributes : FLEXPropertyAttributes - -/// Creates and returns an empty property attributes object. -+ (instancetype)attributes; - -/// The name of the instance variable backing the property. -@property (nonatomic, nullable) NSString *backingIvar; -/// The type encoding of the property. -@property (nonatomic, nullable) NSString *typeEncoding; -/// The \e old type encoding of the property. -@property (nonatomic, nullable) NSString *oldTypeEncoding; -/// The property's custom getter, if any. -@property (nonatomic, nullable) SEL customGetter; -/// The property's custom setter, if any. -@property (nonatomic, nullable) SEL customSetter; - -@property (nonatomic) BOOL isReadOnly; -@property (nonatomic) BOOL isCopy; -@property (nonatomic) BOOL isRetained; -@property (nonatomic) BOOL isNonatomic; -@property (nonatomic) BOOL isDynamic; -@property (nonatomic) BOOL isWeak; -@property (nonatomic) BOOL isGarbageCollectable; - -/// A more convenient method of setting the \c typeEncoding property. -/// @discussion This will not work for complex types like structs and primitive pointers. -- (void)setTypeEncodingChar:(char)type; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.m deleted file mode 100644 index 88d8f35..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.m +++ /dev/null @@ -1,376 +0,0 @@ -// -// FLEXPropertyAttributes.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/5/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXPropertyAttributes.h" -#import "FLEXRuntimeUtility.h" -#import "NSString+ObjcRuntime.h" -#import "NSDictionary+ObjcRuntime.h" - - -#pragma mark FLEXPropertyAttributes - -@interface FLEXPropertyAttributes () - -@property (nonatomic) NSString *backingIvar; -@property (nonatomic) NSString *typeEncoding; -@property (nonatomic) NSString *oldTypeEncoding; -@property (nonatomic) SEL customGetter; -@property (nonatomic) SEL customSetter; -@property (nonatomic) BOOL isReadOnly; -@property (nonatomic) BOOL isCopy; -@property (nonatomic) BOOL isRetained; -@property (nonatomic) BOOL isNonatomic; -@property (nonatomic) BOOL isDynamic; -@property (nonatomic) BOOL isWeak; -@property (nonatomic) BOOL isGarbageCollectable; - -- (NSString *)buildFullDeclaration; - -@end - -@implementation FLEXPropertyAttributes -@synthesize list = _list; - -#pragma mark Initializers - -+ (instancetype)attributesForProperty:(objc_property_t)property { - return [self attributesFromDictionary:[NSDictionary attributesDictionaryForProperty:property]]; -} - -+ (instancetype)attributesFromDictionary:(NSDictionary *)attributes { - return [[self alloc] initWithAttributesDictionary:attributes]; -} - -- (id)initWithAttributesDictionary:(NSDictionary *)attributes { - NSParameterAssert(attributes); - - self = [super init]; - if (self) { - _dictionary = attributes; - _string = attributes.propertyAttributesString; - _count = attributes.count; - _typeEncoding = attributes[kFLEXPropertyAttributeKeyTypeEncoding]; - _backingIvar = attributes[kFLEXPropertyAttributeKeyBackingIvarName]; - _oldTypeEncoding = attributes[kFLEXPropertyAttributeKeyOldStyleTypeEncoding]; - _customGetterString = attributes[kFLEXPropertyAttributeKeyCustomGetter]; - _customSetterString = attributes[kFLEXPropertyAttributeKeyCustomSetter]; - _customGetter = NSSelectorFromString(_customGetterString); - _customSetter = NSSelectorFromString(_customSetterString); - _isReadOnly = attributes[kFLEXPropertyAttributeKeyReadOnly] != nil; - _isCopy = attributes[kFLEXPropertyAttributeKeyCopy] != nil; - _isRetained = attributes[kFLEXPropertyAttributeKeyRetain] != nil; - _isNonatomic = attributes[kFLEXPropertyAttributeKeyNonAtomic] != nil; - _isWeak = attributes[kFLEXPropertyAttributeKeyWeak] != nil; - _isGarbageCollectable = attributes[kFLEXPropertyAttributeKeyGarbageCollectable] != nil; - - _fullDeclaration = [self buildFullDeclaration]; - } - - return self; -} - -#pragma mark Misc - -- (NSString *)description { - return [NSString - stringWithFormat:@"<%@ \"%@\", ivar=%@, readonly=%d, nonatomic=%d, getter=%@, setter=%@>", - NSStringFromClass(self.class), - self.string, - self.backingIvar ?: @"none", - self.isReadOnly, - self.isNonatomic, - NSStringFromSelector(self.customGetter) ?: @"none", - NSStringFromSelector(self.customSetter) ?: @"none" - ]; -} - -- (objc_property_attribute_t *)copyAttributesList:(unsigned int *)attributesCount { - NSDictionary *attrs = self.string.propertyAttributes; - objc_property_attribute_t *propertyAttributes = malloc(attrs.count * sizeof(objc_property_attribute_t)); - - if (attributesCount) { - *attributesCount = (unsigned int)attrs.count; - } - - NSUInteger i = 0; - for (NSString *key in attrs.allKeys) { - FLEXPropertyAttribute c = (FLEXPropertyAttribute)[key characterAtIndex:0]; - switch (c) { - case FLEXPropertyAttributeTypeEncoding: { - objc_property_attribute_t pa = { - kFLEXPropertyAttributeKeyTypeEncoding.UTF8String, - self.typeEncoding.UTF8String - }; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeBackingIvarName: { - objc_property_attribute_t pa = { - kFLEXPropertyAttributeKeyBackingIvarName.UTF8String, - self.backingIvar.UTF8String - }; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeCopy: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyCopy.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeCustomGetter: { - objc_property_attribute_t pa = { - kFLEXPropertyAttributeKeyCustomGetter.UTF8String, - NSStringFromSelector(self.customGetter).UTF8String ?: "" - }; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeCustomSetter: { - objc_property_attribute_t pa = { - kFLEXPropertyAttributeKeyCustomSetter.UTF8String, - NSStringFromSelector(self.customSetter).UTF8String ?: "" - }; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeDynamic: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyDynamic.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeGarbageCollectible: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyGarbageCollectable.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeNonAtomic: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyNonAtomic.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeOldTypeEncoding: { - objc_property_attribute_t pa = { - kFLEXPropertyAttributeKeyOldStyleTypeEncoding.UTF8String, - self.oldTypeEncoding.UTF8String ?: "" - }; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeReadOnly: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyReadOnly.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeRetain: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyRetain.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - case FLEXPropertyAttributeWeak: { - objc_property_attribute_t pa = {kFLEXPropertyAttributeKeyWeak.UTF8String, ""}; - propertyAttributes[i] = pa; - break; - } - } - i++; - } - - return propertyAttributes; -} - -- (objc_property_attribute_t *)list { - if (!_list) { - _list = [self copyAttributesList:nil]; - } - - return _list; -} - -- (NSString *)buildFullDeclaration { - NSMutableString *decl = [NSMutableString new]; - - [decl appendFormat:@"%@, ", _isNonatomic ? @"nonatomic" : @"atomic"]; - [decl appendFormat:@"%@, ", _isReadOnly ? @"readonly" : @"readwrite"]; - - BOOL noExplicitMemorySemantics = YES; - if (_isCopy) { noExplicitMemorySemantics = NO; - [decl appendString:@"copy, "]; - } - if (_isRetained) { noExplicitMemorySemantics = NO; - [decl appendString:@"strong, "]; - } - if (_isWeak) { noExplicitMemorySemantics = NO; - [decl appendString:@"weak, "]; - } - - if ([_typeEncoding hasPrefix:@"@"] && noExplicitMemorySemantics) { - // *probably* strong if this is an object; strong is the default. - [decl appendString:@"strong, "]; - } else if (noExplicitMemorySemantics) { - // *probably* assign if this is not an object - [decl appendString:@"assign, "]; - } - - if (_customGetter) { - [decl appendFormat:@"getter=%@, ", NSStringFromSelector(_customGetter)]; - } - if (_customSetter) { - [decl appendFormat:@"setter=%@, ", NSStringFromSelector(_customSetter)]; - } - - [decl deleteCharactersInRange:NSMakeRange(decl.length-2, 2)]; - return decl.copy; -} - -- (void)dealloc { - if (_list) { - free(_list); - _list = nil; - } -} - -#pragma mark Copying - -- (id)copyWithZone:(NSZone *)zone { - return [[FLEXPropertyAttributes class] attributesFromDictionary:self.dictionary]; -} - -- (id)mutableCopyWithZone:(NSZone *)zone { - return [[FLEXMutablePropertyAttributes class] attributesFromDictionary:self.dictionary]; -} - -@end - - - -#pragma mark FLEXMutablePropertyAttributes - -@interface FLEXMutablePropertyAttributes () -@property (nonatomic) BOOL countDelta; -@property (nonatomic) BOOL stringDelta; -@property (nonatomic) BOOL dictDelta; -@property (nonatomic) BOOL listDelta; -@property (nonatomic) BOOL declDelta; -@end - -#define PropertyWithDeltaFlag(type, name, Name) @dynamic name; \ -- (void)set ## Name:(type)name { \ - if (name != _ ## name) { \ - _countDelta = _stringDelta = _dictDelta = _listDelta = _declDelta = YES; \ - _ ## name = name; \ - } \ -} - -@implementation FLEXMutablePropertyAttributes - -PropertyWithDeltaFlag(NSString *, backingIvar, BackingIvar); -PropertyWithDeltaFlag(NSString *, typeEncoding, TypeEncoding); -PropertyWithDeltaFlag(NSString *, oldTypeEncoding, OldTypeEncoding); -PropertyWithDeltaFlag(SEL, customGetter, CustomGetter); -PropertyWithDeltaFlag(SEL, customSetter, CustomSetter); -PropertyWithDeltaFlag(BOOL, isReadOnly, IsReadOnly); -PropertyWithDeltaFlag(BOOL, isCopy, IsCopy); -PropertyWithDeltaFlag(BOOL, isRetained, IsRetained); -PropertyWithDeltaFlag(BOOL, isNonatomic, IsNonatomic); -PropertyWithDeltaFlag(BOOL, isDynamic, IsDynamic); -PropertyWithDeltaFlag(BOOL, isWeak, IsWeak); -PropertyWithDeltaFlag(BOOL, isGarbageCollectable, IsGarbageCollectable); - -+ (instancetype)attributes { - return [self new]; -} - -- (void)setTypeEncodingChar:(char)type { - self.typeEncoding = [NSString stringWithFormat:@"%c", type]; -} - -- (NSUInteger)count { - // Recalculate attribute count after mutations - if (self.countDelta) { - self.countDelta = NO; - _count = self.dictionary.count; - } - - return _count; -} - -- (objc_property_attribute_t *)list { - // Regenerate list after mutations - if (self.listDelta) { - self.listDelta = NO; - if (_list) { - free(_list); - _list = nil; - } - } - - // Super will generate the list if it isn't set - return super.list; -} - -- (NSString *)string { - // Regenerate string after mutations - if (self.stringDelta || !_string) { - self.stringDelta = NO; - _string = self.dictionary.propertyAttributesString; - } - - return _string; -} - -- (NSDictionary *)dictionary { - // Regenerate dictionary after mutations - if (self.dictDelta || !_dictionary) { - // _stringa nd _dictionary depend on each other, - // so we must generate ONE by hand using our properties. - // We arbitrarily choose to generate the dictionary. - NSMutableDictionary *attrs = [NSMutableDictionary new]; - if (self.typeEncoding) - attrs[kFLEXPropertyAttributeKeyTypeEncoding] = self.typeEncoding; - if (self.backingIvar) - attrs[kFLEXPropertyAttributeKeyBackingIvarName] = self.backingIvar; - if (self.oldTypeEncoding) - attrs[kFLEXPropertyAttributeKeyOldStyleTypeEncoding] = self.oldTypeEncoding; - if (self.customGetter) - attrs[kFLEXPropertyAttributeKeyCustomGetter] = NSStringFromSelector(self.customGetter); - if (self.customSetter) - attrs[kFLEXPropertyAttributeKeyCustomSetter] = NSStringFromSelector(self.customSetter); - - if (self.isReadOnly) attrs[kFLEXPropertyAttributeKeyReadOnly] = @YES; - if (self.isCopy) attrs[kFLEXPropertyAttributeKeyCopy] = @YES; - if (self.isRetained) attrs[kFLEXPropertyAttributeKeyRetain] = @YES; - if (self.isNonatomic) attrs[kFLEXPropertyAttributeKeyNonAtomic] = @YES; - if (self.isDynamic) attrs[kFLEXPropertyAttributeKeyDynamic] = @YES; - if (self.isWeak) attrs[kFLEXPropertyAttributeKeyWeak] = @YES; - if (self.isGarbageCollectable) attrs[kFLEXPropertyAttributeKeyGarbageCollectable] = @YES; - - _dictionary = attrs.copy; - } - - return _dictionary; -} - -- (NSString *)fullDeclaration { - if (self.declDelta || !_fullDeclaration) { - _declDelta = NO; - _fullDeclaration = [self buildFullDeclaration]; - } - - return _fullDeclaration; -} - -- (NSString *)customGetterString { - return _customGetter ? NSStringFromSelector(_customGetter) : nil; -} - -- (NSString *)customSetterString { - return _customSetter ? NSStringFromSelector(_customSetter) : nil; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocol.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocol.h deleted file mode 100644 index 3085535..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocol.h +++ /dev/null @@ -1,73 +0,0 @@ -// -// FLEXProtocol.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXRuntimeConstants.h" -@class FLEXProperty, FLEXMethodDescription; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark FLEXProtocol -@interface FLEXProtocol : NSObject - -/// Every protocol registered with the runtime. -+ (NSArray *)allProtocols; -+ (instancetype)protocol:(Protocol *)protocol; - -/// The underlying protocol data structure. -@property (nonatomic, readonly) Protocol *objc_protocol; - -/// The name of the protocol. -@property (nonatomic, readonly) NSString *name; -/// The required methods of the protocol, if any. This includes property getters and setters. -@property (nonatomic, readonly) NSArray *requiredMethods; -/// The optional methods of the protocol, if any. This includes property getters and setters. -@property (nonatomic, readonly) NSArray *optionalMethods; -/// All protocols that this protocol conforms to, if any. -@property (nonatomic, readonly) NSArray *protocols; -/// The full path of the image that contains this protocol definition, -/// or \c nil if this protocol was probably defined at runtime. -@property (nonatomic, readonly, nullable) NSString *imagePath; - -/// The properties in the protocol, if any. \c nil on iOS 10+ -@property (nonatomic, readonly, nullable) NSArray *properties API_DEPRECATED("Use the more specific accessors below", ios(2.0, 10.0)); - -/// The required properties in the protocol, if any. -@property (nonatomic, readonly) NSArray *requiredProperties API_AVAILABLE(ios(10.0)); -/// The optional properties in the protocol, if any. -@property (nonatomic, readonly) NSArray *optionalProperties API_AVAILABLE(ios(10.0)); - -/// For internal use -@property (nonatomic) id tag; - -/// Not to be confused with \c -conformsToProtocol:, which refers to the current -/// \c FLEXProtocol instance and not the underlying \c Protocol object. -- (BOOL)conformsTo:(Protocol *)protocol; - -@end - - -#pragma mark Method descriptions -@interface FLEXMethodDescription : NSObject - -+ (instancetype)description:(struct objc_method_description)description; -+ (instancetype)description:(struct objc_method_description)description instance:(BOOL)isInstance; - -/// The underlying method description data structure. -@property (nonatomic, readonly) struct objc_method_description objc_description; -/// The method's selector. -@property (nonatomic, readonly) SEL selector; -/// The method's type encoding. -@property (nonatomic, readonly) NSString *typeEncoding; -/// The method's return type. -@property (nonatomic, readonly) FLEXTypeEncoding returnType; -/// \c YES if this is an instance method, \c NO if it is a class method, or \c nil if unspecified -@property (nonatomic, readonly) NSNumber *instance; -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocol.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocol.m deleted file mode 100644 index 4000366..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocol.m +++ /dev/null @@ -1,212 +0,0 @@ -// -// FLEXProtocol.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 6/30/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXProtocol.h" -#import "FLEXProperty.h" -#import "FLEXRuntimeUtility.h" -#import "NSArray+FLEX.h" -#include - -@implementation FLEXProtocol - -#pragma mark Initializers - -+ (NSArray *)allProtocols { - unsigned int prcount; - Protocol *__unsafe_unretained*protocols = objc_copyProtocolList(&prcount); - - NSMutableArray *all = [NSMutableArray new]; - for(NSUInteger i = 0; i < prcount; i++) - [all addObject:[self protocol:protocols[i]]]; - - free(protocols); - return all; -} - -+ (instancetype)protocol:(Protocol *)protocol { - return [[self alloc] initWithProtocol:protocol]; -} - -- (id)initWithProtocol:(Protocol *)protocol { - NSParameterAssert(protocol); - - self = [super init]; - if (self) { - _objc_protocol = protocol; - [self examine]; - } - - return self; -} - -#pragma mark Other - -- (NSString *)description { - return self.name; -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@"<%@ name=%@, %lu properties, %lu required methods, %lu optional methods, %lu protocols>", - NSStringFromClass(self.class), self.name, (unsigned long)self.properties.count, - (unsigned long)self.requiredMethods.count, (unsigned long)self.optionalMethods.count, (unsigned long)self.protocols.count]; -} - -- (void)examine { - _name = @(protocol_getName(self.objc_protocol)); - - // imagePath - Dl_info exeInfo; - if (dladdr((__bridge const void *)(_objc_protocol), &exeInfo)) { - _imagePath = exeInfo.dli_fname ? @(exeInfo.dli_fname) : nil; - } - - // Conformances and methods // - - unsigned int pccount, mdrcount, mdocount; - struct objc_method_description *objcrMethods, *objcoMethods; - Protocol *protocol = _objc_protocol; - Protocol * __unsafe_unretained *protocols = protocol_copyProtocolList(protocol, &pccount); - - // Protocols - _protocols = [NSArray flex_forEachUpTo:pccount map:^id(NSUInteger i) { - return [FLEXProtocol protocol:protocols[i]]; - }]; - free(protocols); - - // Required instance methods - objcrMethods = protocol_copyMethodDescriptionList(protocol, YES, YES, &mdrcount); - NSArray *rMethods = [NSArray flex_forEachUpTo:mdrcount map:^id(NSUInteger i) { - return [FLEXMethodDescription description:objcrMethods[i] instance:YES]; - }]; - free(objcrMethods); - - // Required class methods - objcrMethods = protocol_copyMethodDescriptionList(protocol, YES, NO, &mdrcount); - _requiredMethods = [[NSArray flex_forEachUpTo:mdrcount map:^id(NSUInteger i) { - return [FLEXMethodDescription description:objcrMethods[i] instance:NO]; - }] arrayByAddingObjectsFromArray:rMethods]; - free(objcrMethods); - - // Optional instance methods - objcoMethods = protocol_copyMethodDescriptionList(protocol, NO, YES, &mdocount); - NSArray *oMethods = [NSArray flex_forEachUpTo:mdocount map:^id(NSUInteger i) { - return [FLEXMethodDescription description:objcoMethods[i] instance:YES]; - }]; - free(objcoMethods); - - // Optional class methods - objcoMethods = protocol_copyMethodDescriptionList(protocol, NO, NO, &mdocount); - _optionalMethods = [[NSArray flex_forEachUpTo:mdocount map:^id(NSUInteger i) { - return [FLEXMethodDescription description:objcoMethods[i] instance:NO]; - }] arrayByAddingObjectsFromArray:oMethods]; - free(objcoMethods); - - // Properties is a hassle because they didn't fix the API until iOS 10 // - - if (@available(iOS 10.0, *)) { - unsigned int prrcount, procount; - Class instance = [NSObject class], meta = objc_getMetaClass("NSObject"); - - // Required class and instance properties // - - // Instance first - objc_property_t *rProps = protocol_copyPropertyList2(protocol, &prrcount, YES, YES); - NSArray *rProperties = [NSArray flex_forEachUpTo:prrcount map:^id(NSUInteger i) { - return [FLEXProperty property:rProps[i] onClass:instance]; - }]; - free(rProps); - - // Then class - rProps = protocol_copyPropertyList2(protocol, &prrcount, NO, YES); - _requiredProperties = [[NSArray flex_forEachUpTo:prrcount map:^id(NSUInteger i) { - return [FLEXProperty property:rProps[i] onClass:instance]; - }] arrayByAddingObjectsFromArray:rProperties]; - free(rProps); - - // Optional class and instance properties // - - // Instance first - objc_property_t *oProps = protocol_copyPropertyList2(protocol, &procount, YES, YES); - NSArray *oProperties = [NSArray flex_forEachUpTo:prrcount map:^id(NSUInteger i) { - return [FLEXProperty property:oProps[i] onClass:meta]; - }]; - free(oProps); - - // Then class - oProps = protocol_copyPropertyList2(protocol, &procount, NO, YES); - _optionalProperties = [[NSArray flex_forEachUpTo:procount map:^id(NSUInteger i) { - return [FLEXProperty property:oProps[i] onClass:meta]; - }] arrayByAddingObjectsFromArray:oProperties]; - free(oProps); - - } else { - unsigned int prcount; - objc_property_t *objcproperties = protocol_copyPropertyList(protocol, &prcount); - _properties = [NSArray flex_forEachUpTo:prcount map:^id(NSUInteger i) { - return [FLEXProperty property:objcproperties[i]]; - }]; - - _requiredProperties = @[]; - _optionalProperties = @[]; - - free(objcproperties); - } -} - -- (BOOL)conformsTo:(Protocol *)protocol { - return protocol_conformsToProtocol(self.objc_protocol, protocol); -} - -@end - -#pragma mark FLEXMethodDescription - -@implementation FLEXMethodDescription - -- (id)init { - [NSException - raise:NSInternalInconsistencyException - format:@"Class instance should not be created with -init" - ]; - return nil; -} - -+ (instancetype)description:(struct objc_method_description)description { - return [[self alloc] initWithDescription:description instance:nil]; -} - -+ (instancetype)description:(struct objc_method_description)description instance:(BOOL)isInstance { - return [[self alloc] initWithDescription:description instance:@(isInstance)]; -} - -- (id)initWithDescription:(struct objc_method_description)md instance:(NSNumber *)instance { - NSParameterAssert(md.name != NULL); - - self = [super init]; - if (self) { - _objc_description = md; - _selector = md.name; - _typeEncoding = @(md.types); - _returnType = (FLEXTypeEncoding)[self.typeEncoding characterAtIndex:0]; - _instance = instance; - } - - return self; -} - -- (NSString *)description { - return NSStringFromSelector(self.selector); -} - -- (NSString *)debugDescription { - return [NSString stringWithFormat:@"<%@ name=%@, type=%@>", - NSStringFromClass(self.class), NSStringFromSelector(self.selector), self.typeEncoding]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.h b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.h deleted file mode 100644 index e855cd3..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// FLEXProtocolBuilder.h -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/4/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import -@class FLEXProperty, FLEXProtocol, Protocol; - -@interface FLEXProtocolBuilder : NSObject - -/// Begins to construct a new protocol with the given name. -/// @discussion You must register the protocol with the -/// \c registerProtocol method before you can use it. -+ (instancetype)allocateProtocol:(NSString *)name; - -/// Adds a property to a protocol. -/// @param property The property to add. -/// @param isRequired Whether the property is required to implement the protocol. -- (void)addProperty:(FLEXProperty *)property isRequired:(BOOL)isRequired; -/// Adds a property to a protocol. -/// @param selector The selector of the method to add. -/// @param typeEncoding The type encoding of the method to add. -/// @param isRequired Whether the method is required to implement the protocol. -/// @param isInstanceMethod \c YES if the method is an instance method, \c NO if it is a class method. -- (void)addMethod:(SEL)selector - typeEncoding:(NSString *)typeEncoding - isRequired:(BOOL)isRequired - isInstanceMethod:(BOOL)isInstanceMethod; -/// Makes the recieving protocol conform to the given protocol. -- (void)addProtocol:(Protocol *)protocol; - -/// Registers and returns the recieving protocol, which was previously under construction. -- (FLEXProtocol *)registerProtocol; -/// Whether the protocol is still under construction or already registered. -@property (nonatomic, readonly) BOOL isRegistered; - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.m b/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.m deleted file mode 100644 index fdd1283..0000000 --- a/Tweaks/FLEX/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.m +++ /dev/null @@ -1,93 +0,0 @@ -// -// FLEXProtocolBuilder.m -// FLEX -// -// Derived from MirrorKit. -// Created by Tanner on 7/4/15. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXProtocolBuilder.h" -#import "FLEXProtocol.h" -#import "FLEXProperty.h" -#import - -#define MutationAssertion(msg) if (self.isRegistered) { \ - [NSException \ - raise:NSInternalInconsistencyException \ - format:msg \ - ]; \ -} - -@interface FLEXProtocolBuilder () -@property (nonatomic) Protocol *workingProtocol; -@property (nonatomic) NSString *name; -@end - -@implementation FLEXProtocolBuilder - -- (id)init { - [NSException - raise:NSInternalInconsistencyException - format:@"Class instance should not be created with -init" - ]; - return nil; -} - -#pragma mark Initializers -+ (instancetype)allocateProtocol:(NSString *)name { - NSParameterAssert(name); - return [[self alloc] initWithProtocol:objc_allocateProtocol(name.UTF8String)]; - -} - -- (id)initWithProtocol:(Protocol *)protocol { - NSParameterAssert(protocol); - - self = [super init]; - if (self) { - _workingProtocol = protocol; - _name = NSStringFromProtocol(self.workingProtocol); - } - - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@ name=%@, registered=%d>", - NSStringFromClass(self.class), self.name, self.isRegistered]; -} - -#pragma mark Building - -- (void)addProperty:(FLEXProperty *)property isRequired:(BOOL)isRequired { - MutationAssertion(@"Properties cannot be added once a protocol has been registered"); - - unsigned int count; - objc_property_attribute_t *attributes = [property copyAttributesList:&count]; - protocol_addProperty(self.workingProtocol, property.name.UTF8String, attributes, count, isRequired, YES); - free(attributes); -} - -- (void)addMethod:(SEL)selector - typeEncoding:(NSString *)typeEncoding - isRequired:(BOOL)isRequired - isInstanceMethod:(BOOL)isInstanceMethod { - MutationAssertion(@"Methods cannot be added once a protocol has been registered"); - protocol_addMethodDescription(self.workingProtocol, selector, typeEncoding.UTF8String, isRequired, isInstanceMethod); -} - -- (void)addProtocol:(Protocol *)protocol { - MutationAssertion(@"Protocols cannot be added once a protocol has been registered"); - protocol_addProtocol(self.workingProtocol, protocol); -} - -- (FLEXProtocol *)registerProtocol { - MutationAssertion(@"Protocol is already registered"); - - _isRegistered = YES; - objc_registerProtocol(self.workingProtocol); - return [FLEXProtocol protocol:self.workingProtocol]; -} - -@end diff --git a/Tweaks/FLEX/Utility/Runtime/flex_fishhook.c b/Tweaks/FLEX/Utility/Runtime/flex_fishhook.c deleted file mode 100644 index f673f4f..0000000 --- a/Tweaks/FLEX/Utility/Runtime/flex_fishhook.c +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (c) 2013, Facebook, Inc. -// All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name Facebook nor the names of its contributors may be used to -// endorse or promote products derived from this software without specific -// prior written permission. -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "flex_fishhook.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __LP64__ -typedef struct mach_header_64 mach_header_t; -typedef struct segment_command_64 segment_command_t; -typedef struct section_64 section_t; -typedef struct nlist_64 nlist_t; -#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 -#else -typedef struct mach_header mach_header_t; -typedef struct segment_command segment_command_t; -typedef struct section section_t; -typedef struct nlist nlist_t; -#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT -#endif - -#ifndef SEG_DATA_CONST -#define SEG_DATA_CONST "__DATA_CONST" -#endif - -struct rebindings_entry { - struct rebinding *rebindings; - size_t rebindings_nel; - struct rebindings_entry *next; -}; - -static struct rebindings_entry *_flex_rebindings_head; - -/// @return 0 on success -static int flex_prepend_rebindings(struct rebindings_entry **rebindings_head, - struct rebinding rebindings[], - size_t nel) { - struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry)); - if (!new_entry) { - return -1; - } - - new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel); - if (!new_entry->rebindings) { - free(new_entry); - return -1; - } - - memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); - new_entry->rebindings_nel = nel; - new_entry->next = *rebindings_head; - *rebindings_head = new_entry; - - return 0; -} - -static vm_prot_t flex_get_protection(void *sectionStart) { - mach_port_t task = mach_task_self(); - vm_size_t size = 0; - vm_address_t address = (vm_address_t)sectionStart; - memory_object_name_t object; -#if __LP64__ - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; - vm_region_basic_info_data_64_t info; - kern_return_t info_ret = vm_region_64( - task, &address, &size, VM_REGION_BASIC_INFO_64, - (vm_region_info_64_t)&info, &count, &object - ); -#else - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; - vm_region_basic_info_data_t info; - kern_return_t info_ret = vm_region( - task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object - ); -#endif - if (info_ret == KERN_SUCCESS) { - return info.protection; - } else { - return VM_PROT_READ; - } -} -static void flex_perform_rebinding_with_section(struct rebindings_entry *rebindings, - section_t *section, - intptr_t slide, - nlist_t *symtab, - char *strtab, - uint32_t *indirect_symtab) { - const bool isDataConst = strcmp(section->segname, "__DATA_CONST") == 0; - uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; - void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); - vm_prot_t oldProtection = VM_PROT_READ; - - if (isDataConst) { - oldProtection = flex_get_protection(rebindings); - mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE); - } - - for (uint i = 0; i < section->size / sizeof(void *); i++) { - uint32_t symtab_index = indirect_symbol_indices[i]; - - if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || - symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { - continue; - } - - uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; - char *symbol_name = strtab + strtab_offset; - bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1]; - struct rebindings_entry *cur = rebindings; - - while (cur) { - for (uint j = 0; j < cur->rebindings_nel; j++) { - if (symbol_name_longer_than_1 && - strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { - - if (cur->rebindings[j].replaced != NULL && - indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { - - *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; - } - - indirect_symbol_bindings[i] = cur->rebindings[j].replacement; - goto symbol_loop; - } - } - - cur = cur->next; - } - - symbol_loop:; - } - - if (isDataConst) { - int protection = 0; - if (oldProtection & VM_PROT_READ) { - protection |= PROT_READ; - } - if (oldProtection & VM_PROT_WRITE) { - protection |= PROT_WRITE; - } - if (oldProtection & VM_PROT_EXECUTE) { - protection |= PROT_EXEC; - } - - mprotect(indirect_symbol_bindings, section->size, protection); - } -} - -static void flex_rebind_symbols_for_image(struct rebindings_entry *rebindings, - const struct mach_header *header, - intptr_t slide) { - Dl_info info; - if (dladdr(header, &info) == 0) { - return; - } - - segment_command_t *cur_seg_cmd; - segment_command_t *linkedit_segment = NULL; - struct symtab_command* symtab_cmd = NULL; - struct dysymtab_command* dysymtab_cmd = NULL; - - uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); - for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { - cur_seg_cmd = (segment_command_t *)cur; - - if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { - if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { - linkedit_segment = cur_seg_cmd; - } - } else if (cur_seg_cmd->cmd == LC_SYMTAB) { - symtab_cmd = (struct symtab_command*)cur_seg_cmd; - } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { - dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; - } - } - - if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || - !dysymtab_cmd->nindirectsyms) { - return; - } - - // Find base symbol/string table addresses - uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; - nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); - char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); - - // Get indirect symbol table (array of uint32_t indices into symbol table) - uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); - - cur = (uintptr_t)header + sizeof(mach_header_t); - for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { - cur_seg_cmd = (segment_command_t *)cur; - - if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { - if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && - strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { - continue; - } - - for (uint j = 0; j < cur_seg_cmd->nsects; j++) { - section_t *sect = (section_t *)(cur + sizeof(segment_command_t)) + j; - - if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { - flex_perform_rebinding_with_section( - rebindings, sect, slide, symtab, strtab, indirect_symtab - ); - } - if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { - flex_perform_rebinding_with_section( - rebindings, sect, slide, symtab, strtab, indirect_symtab - ); - } - } - } - } -} - -static void _flex_rebind_symbols_for_image(const struct mach_header *header, - intptr_t slide) { - flex_rebind_symbols_for_image(_flex_rebindings_head, header, slide); -} - -int flex_rebind_symbols_image(void *header, - intptr_t slide, - struct rebinding rebindings[], - size_t rebindings_nel) { - struct rebindings_entry *rebindings_head = NULL; - - int retval = flex_prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); - flex_rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide); - - if (rebindings_head) { - free(rebindings_head->rebindings); - } - - free(rebindings_head); - return retval; -} - -/// @return 0 on success -int flex_rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { - int retval = flex_prepend_rebindings(&_flex_rebindings_head, rebindings, rebindings_nel); - if (retval < 0) { - return retval; - } - - // If this was the first call, register callback for image additions (which is also invoked for - // existing images, otherwise, just run on existing images - if (!_flex_rebindings_head->next) { - _dyld_register_func_for_add_image(_flex_rebind_symbols_for_image); - } else { - uint32_t c = _dyld_image_count(); - for (uint32_t i = 0; i < c; i++) { - _flex_rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); - } - } - - return retval; -} diff --git a/Tweaks/FLEX/Utility/Runtime/flex_fishhook.h b/Tweaks/FLEX/Utility/Runtime/flex_fishhook.h deleted file mode 100644 index 1f02191..0000000 --- a/Tweaks/FLEX/Utility/Runtime/flex_fishhook.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2013, Facebook, Inc. -// All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name Facebook nor the names of its contributors may be used to -// endorse or promote products derived from this software without specific -// prior written permission. -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef fishhook_h -#define fishhook_h - -#include -#include - -#if !defined(FISHHOOK_EXPORT) -#define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) -#else -#define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) -#endif - -#ifdef __cplusplus -extern "C" { -#endif //__cplusplus - -/** - * A structure representing a particular intended rebinding from a symbol - * name to its replacement - */ -struct rebinding { - const char *name; - void *replacement; - void **replaced; -}; - -/** - * For each rebinding in rebindings, rebinds references to external, indirect - * symbols with the specified name to instead point at replacement for each - * image in the calling process as well as for all future images that are loaded - * by the process. If rebind_functions is called more than once, the symbols to - * rebind are added to the existing list of rebindings, and if a given symbol - * is rebound more than once, the later rebinding will take precedence. - * @return 0 on success - */ -FISHHOOK_VISIBILITY -int flex_rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); - -/** - * Rebinds as above, but only in the specified image. The header should point - * to the mach-o header, the slide should be the slide offset. Others as above. - * @return 0 on success - */ -FISHHOOK_VISIBILITY -int flex_rebind_symbols_image(void *header, - intptr_t slide, - struct rebinding rebindings[], - size_t rebindings_nel); - -#ifdef __cplusplus -} -#endif //__cplusplus - -#endif //fishhook_h diff --git a/Tweaks/FLEX/ViewHierarchy/FLEXHierarchyViewController.h b/Tweaks/FLEX/ViewHierarchy/FLEXHierarchyViewController.h deleted file mode 100644 index 57fe94d..0000000 --- a/Tweaks/FLEX/ViewHierarchy/FLEXHierarchyViewController.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// FLEXHierarchyViewController.h -// FLEX -// -// Created by Tanner Bennett on 1/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXNavigationController.h" - -@protocol FLEXHierarchyDelegate -- (void)viewHierarchyDidDismiss:(UIView *)selectedView; -@end - -/// A navigation controller which manages two child view controllers: -/// a 3D Reveal-like hierarchy explorer, and a 2D tree-list hierarchy explorer. -@interface FLEXHierarchyViewController : FLEXNavigationController - -+ (instancetype)delegate:(id)delegate; -+ (instancetype)delegate:(id)delegate - viewsAtTap:(NSArray *)viewsAtTap - selectedView:(UIView *)selectedView; - -- (void)toggleHierarchyMode; - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/FLEXHierarchyViewController.m b/Tweaks/FLEX/ViewHierarchy/FLEXHierarchyViewController.m deleted file mode 100644 index eb47b53..0000000 --- a/Tweaks/FLEX/ViewHierarchy/FLEXHierarchyViewController.m +++ /dev/null @@ -1,154 +0,0 @@ -// -// FLEXHierarchyViewController.m -// FLEX -// -// Created by Tanner Bennett on 1/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FLEXHierarchyViewController.h" -#import "FLEXHierarchyTableViewController.h" -#import "FHSViewController.h" -#import "FLEXUtility.h" -#import "FLEXTabList.h" -#import "FLEXResources.h" -#import "UIBarButtonItem+FLEX.h" - -typedef NS_ENUM(NSUInteger, FLEXHierarchyViewMode) { - FLEXHierarchyViewModeTree = 1, - FLEXHierarchyViewMode3DSnapshot -}; - -@interface FLEXHierarchyViewController () -@property (nonatomic, readonly, weak) id hierarchyDelegate; -@property (nonatomic, readonly) FHSViewController *snapshotViewController; -@property (nonatomic, readonly) FLEXHierarchyTableViewController *treeViewController; - -@property (nonatomic) FLEXHierarchyViewMode mode; - -@property (nonatomic, readonly) UIView *selectedView; -@end - -@implementation FLEXHierarchyViewController - -#pragma mark - Initialization - -+ (instancetype)delegate:(id)delegate { - return [self delegate:delegate viewsAtTap:nil selectedView:nil]; -} - -+ (instancetype)delegate:(id)delegate - viewsAtTap:(NSArray *)viewsAtTap - selectedView:(UIView *)selectedView { - return [[self alloc] initWithDelegate:delegate viewsAtTap:viewsAtTap selectedView:selectedView]; -} - -- (id)initWithDelegate:(id)delegate viewsAtTap:(NSArray *)viewsAtTap selectedView:(UIView *)view { - self = [super init]; - if (self) { - NSArray *allWindows = FLEXUtility.allWindows; - _hierarchyDelegate = delegate; - _treeViewController = [FLEXHierarchyTableViewController - windows:allWindows viewsAtTap:viewsAtTap selectedView:view - ]; - - if (viewsAtTap) { - _snapshotViewController = [FHSViewController snapshotViewsAtTap:viewsAtTap selectedView:view]; - } else { - _snapshotViewController = [FHSViewController snapshotWindows:allWindows]; - } - - self.modalPresentationStyle = UIModalPresentationFullScreen; - } - - return self; -} - - -#pragma mark - Lifecycle - -- (void)viewDidLoad { - [super viewDidLoad]; - - // 3D toggle button - self.treeViewController.navigationItem.leftBarButtonItem = [UIBarButtonItem - flex_itemWithImage:FLEXResources.toggle3DIcon target:self action:@selector(toggleHierarchyMode) - ]; - - // Dismiss when tree view row is selected - __weak id delegate = self.hierarchyDelegate; - self.treeViewController.didSelectRowAction = ^(UIView *selectedView) { - [delegate viewHierarchyDidDismiss:selectedView]; - }; - - // Start of in tree view - _mode = FLEXHierarchyViewModeTree; - [self pushViewController:self.treeViewController animated:NO]; -} - -- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { - // Done button: manually added here because the hierarhcy screens need to actually pass - // data back to the explorer view controller so that it can highlight selected views - viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed) - ]; - - [super pushViewController:viewController animated:animated]; -} - - -#pragma mark - Private - -- (void)donePressed { - // We need to manually close ourselves here because - // FLEXNavigationController doesn't ever close tabs itself - [FLEXTabList.sharedList closeTab:self]; - [self.hierarchyDelegate viewHierarchyDidDismiss:self.selectedView]; -} - -- (void)toggleHierarchyMode { - switch (self.mode) { - case FLEXHierarchyViewModeTree: - self.mode = FLEXHierarchyViewMode3DSnapshot; - break; - case FLEXHierarchyViewMode3DSnapshot: - self.mode = FLEXHierarchyViewModeTree; - break; - } -} - -- (void)setMode:(FLEXHierarchyViewMode)mode { - if (mode != _mode) { - // The tree view controller is our top stack view controller, and - // changing the mode simply pushes the snapshot view. In the future, - // I would like to have the 3D toggle button transparently switch - // between two views instead of pushing a new view controller. - // This way the views should share the search controller somehow. - switch (mode) { - case FLEXHierarchyViewModeTree: - [self popViewControllerAnimated:NO]; - self.toolbarHidden = YES; - self.treeViewController.selectedView = self.selectedView; - break; - case FLEXHierarchyViewMode3DSnapshot: - [self pushViewController:self.snapshotViewController animated:NO]; - self.toolbarHidden = NO; - self.snapshotViewController.selectedView = self.selectedView; - break; - } - - // Change this last so that self.selectedView works right above - _mode = mode; - } -} - -- (UIView *)selectedView { - switch (self.mode) { - case FLEXHierarchyViewModeTree: - return self.treeViewController.selectedView; - case FLEXHierarchyViewMode3DSnapshot: - return self.snapshotViewController.selectedView; - } -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/FLEXImagePreviewViewController.h b/Tweaks/FLEX/ViewHierarchy/FLEXImagePreviewViewController.h deleted file mode 100644 index 72bf739..0000000 --- a/Tweaks/FLEX/ViewHierarchy/FLEXImagePreviewViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FLEXImagePreviewViewController.h -// Flipboard -// -// Created by Ryan Olson on 6/12/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXImagePreviewViewController : UIViewController - -+ (instancetype)previewForView:(UIView *)view; -+ (instancetype)previewForLayer:(CALayer *)layer; -+ (instancetype)forImage:(UIImage *)image; - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/FLEXImagePreviewViewController.m b/Tweaks/FLEX/ViewHierarchy/FLEXImagePreviewViewController.m deleted file mode 100644 index a349e02..0000000 --- a/Tweaks/FLEX/ViewHierarchy/FLEXImagePreviewViewController.m +++ /dev/null @@ -1,147 +0,0 @@ -// -// FLEXImagePreviewViewController.m -// Flipboard -// -// Created by Ryan Olson on 6/12/14. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXImagePreviewViewController.h" -#import "FLEXUtility.h" -#import "FLEXColor.h" -#import "FLEXResources.h" - -@interface FLEXImagePreviewViewController () -@property (nonatomic) UIImage *image; -@property (nonatomic) UIScrollView *scrollView; -@property (nonatomic) UIImageView *imageView; -@property (nonatomic) UITapGestureRecognizer *bgColorTapGesture; -@property (nonatomic) NSInteger backgroundColorIndex; -@property (nonatomic, readonly) NSArray *backgroundColors; -@end - -#pragma mark - -@implementation FLEXImagePreviewViewController - -#pragma mark Initialization - -+ (instancetype)previewForView:(UIView *)view { - return [self forImage:[FLEXUtility previewImageForView:view]]; -} - -+ (instancetype)previewForLayer:(CALayer *)layer { - return [self forImage:[FLEXUtility previewImageForLayer:layer]]; -} - -+ (instancetype)forImage:(UIImage *)image { - return [[self alloc] initWithImage:image]; -} - -- (id)initWithImage:(UIImage *)image { - NSParameterAssert(image); - - self = [super init]; - if (self) { - self.title = @"Preview"; - self.image = image; - _backgroundColors = @[FLEXResources.checkerPatternColor, UIColor.whiteColor, UIColor.blackColor]; - } - - return self; -} - - -#pragma mark Lifecycle - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.imageView = [[UIImageView alloc] initWithImage:self.image]; - self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; - self.scrollView.delegate = self; - self.scrollView.backgroundColor = self.backgroundColors.firstObject; - self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self.scrollView addSubview:self.imageView]; - self.scrollView.contentSize = self.imageView.frame.size; - self.scrollView.minimumZoomScale = 1.0; - self.scrollView.maximumZoomScale = 2.0; - [self.view addSubview:self.scrollView]; - - self.bgColorTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeBackground)]; - [self.scrollView addGestureRecognizer:self.bgColorTapGesture]; - - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemAction - target:self - action:@selector(actionButtonPressed:) - ]; -} - -- (void)viewDidLayoutSubviews { - [self centerContentInScrollViewIfNeeded]; -} - - -#pragma mark UIScrollViewDelegate - -- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { - return self.imageView; -} - -- (void)scrollViewDidZoom:(UIScrollView *)scrollView { - [self centerContentInScrollViewIfNeeded]; -} - - -#pragma mark Private - -- (void)centerContentInScrollViewIfNeeded { - CGFloat horizontalInset = 0.0; - CGFloat verticalInset = 0.0; - if (self.scrollView.contentSize.width < self.scrollView.bounds.size.width) { - horizontalInset = (self.scrollView.bounds.size.width - self.scrollView.contentSize.width) / 2.0; - } - if (self.scrollView.contentSize.height < self.scrollView.bounds.size.height) { - verticalInset = (self.scrollView.bounds.size.height - self.scrollView.contentSize.height) / 2.0; - } - self.scrollView.contentInset = UIEdgeInsetsMake(verticalInset, horizontalInset, verticalInset, horizontalInset); -} - -- (void)changeBackground { - self.backgroundColorIndex++; - self.backgroundColorIndex %= self.backgroundColors.count; - self.scrollView.backgroundColor = self.backgroundColors[self.backgroundColorIndex]; -} - -- (void)actionButtonPressed:(id)sender { - static BOOL canSaveToCameraRoll = NO, didShowWarning = NO; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - if (UIDevice.currentDevice.systemVersion.floatValue < 10) { - canSaveToCameraRoll = YES; - return; - } - - NSBundle *mainBundle = NSBundle.mainBundle; - if ([mainBundle.infoDictionary.allKeys containsObject:@"NSPhotoLibraryUsageDescription"]) { - canSaveToCameraRoll = YES; - } - }); - - UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[self.image] applicationActivities:@[]]; - - if (!canSaveToCameraRoll && !didShowWarning) { - didShowWarning = YES; - NSString *msg = @"Add 'NSPhotoLibraryUsageDescription' to this app's Info.plist to save images."; - [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Reminder").message(msg); - make.button(@"OK").handler(^(NSArray *strings) { - [self presentViewController:activityVC animated:YES completion:nil]; - }); - } showFrom:self]; - } else { - [self presentViewController:activityVC animated:YES completion:nil]; - } -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSRangeSlider.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSRangeSlider.h deleted file mode 100644 index c5d3e60..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSRangeSlider.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// FHSRangeSlider.h -// FLEX -// -// Created by Tanner Bennett on 1/7/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FHSRangeSlider : UIControl - -@property (nonatomic) CGFloat allowedMinValue; -@property (nonatomic) CGFloat allowedMaxValue; -@property (nonatomic) CGFloat minValue; -@property (nonatomic) CGFloat maxValue; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSRangeSlider.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSRangeSlider.m deleted file mode 100644 index d027759..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSRangeSlider.m +++ /dev/null @@ -1,201 +0,0 @@ -// -// FHSRangeSlider.m -// FLEX -// -// Created by Tanner Bennett on 1/7/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FHSRangeSlider.h" -#import "FLEXResources.h" -#import "FLEXUtility.h" - -@interface FHSRangeSlider () -@property (nonatomic, readonly) UIImageView *track; -@property (nonatomic, readonly) UIImageView *fill; -@property (nonatomic, readonly) UIImageView *leftHandle; -@property (nonatomic, readonly) UIImageView *rightHandle; - -@property (nonatomic, getter=isTrackingLeftHandle) BOOL trackingLeftHandle; -@property (nonatomic, getter=isTrackingRightHandle) BOOL trackingRightHandle; -@end - -@implementation FHSRangeSlider - -#pragma mark - Initialization - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _allowedMaxValue = 1.f; - _maxValue = 1.f; - [self initSubviews]; - } - - return self; -} - -- (void)initSubviews { - self.userInteractionEnabled = YES; - UIImageView * (^newSubviewImageView)(UIImage *) = ^UIImageView *(UIImage *image) { - UIImageView *iv = [UIImageView new]; - iv.image = image; -// iv.userInteractionEnabled = YES; - [self addSubview:iv]; - return iv; - }; - - _track = newSubviewImageView(FLEXResources.rangeSliderTrack); - _fill = newSubviewImageView(FLEXResources.rangeSliderFill); - _leftHandle = newSubviewImageView(FLEXResources.rangeSliderLeftHandle); - _rightHandle = newSubviewImageView(FLEXResources.rangeSliderRightHandle); -} - -#pragma mark - Setters / Private - -- (CGFloat)valueAt:(CGFloat)x { - CGFloat minX = self.leftHandle.image.size.width; - CGFloat maxX = self.bounds.size.width - self.rightHandle.image.size.width; - CGFloat cappedX = MIN(MAX(x, minX), maxX); - CGFloat delta = maxX - minX; - CGFloat maxDelta = self.allowedMaxValue - self.allowedMinValue; - - return ((delta > 0) ? (cappedX - minX) / delta : 0) * maxDelta + self.allowedMinValue; -} - -- (void)setAllowedMinValue:(CGFloat)allowedMinValue { - _allowedMinValue = allowedMinValue; - - if (self.minValue < self.allowedMaxValue) { - self.minValue = self.allowedMaxValue; - } else { - [self setNeedsLayout]; - } -} - -- (void)setAllowedMaxValue:(CGFloat)allowedMaxValue { - _allowedMaxValue = allowedMaxValue; - - if (self.maxValue > self.allowedMaxValue) { - self.maxValue = self.allowedMaxValue; - } else { - [self valuesChanged:NO]; - } -} - -- (void)setMinValue:(CGFloat)minValue { - _minValue = minValue; - [self valuesChanged:YES]; -} - -- (void)setMaxValue:(CGFloat)maxValue { - _maxValue = maxValue; - [self valuesChanged:YES]; -} - -- (void)valuesChanged:(BOOL)sendActions { - if (NSThread.isMainThread) { - if (sendActions) { - [self sendActionsForControlEvents:UIControlEventValueChanged]; - } - [self setNeedsLayout]; - } -} - -#pragma mark - Overrides - -- (CGSize)intrinsicContentSize { - return CGSizeMake(UIViewNoIntrinsicMetric, self.leftHandle.image.size.height); -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGSize lhs = self.leftHandle.image.size; - CGSize rhs = self.rightHandle.image.size; - CGSize trackSize = self.track.image.size; - - CGFloat delta = self.allowedMaxValue - self.allowedMinValue; - CGFloat minPercent, maxPercent; - - if (delta <= 0) { - minPercent = maxPercent = 0; - } else { - minPercent = MAX(0, (self.minValue - self.allowedMinValue) / delta); - maxPercent = MAX(minPercent, (self.maxValue - self.allowedMinValue) / delta); - } - - CGFloat rangeSliderWidth = self.bounds.size.width - lhs.width - rhs.width; - - self.leftHandle.frame = FLEXRectMake( - rangeSliderWidth * minPercent, - CGRectGetMidY(self.bounds) - (lhs.height / 2.f) + 3.f, - lhs.width, - lhs.height - ); - - self.rightHandle.frame = FLEXRectMake( - lhs.width + (rangeSliderWidth * maxPercent), - CGRectGetMidY(self.bounds) - (rhs.height / 2.f) + 3.f, - rhs.width, - rhs.height - ); - - self.track.frame = FLEXRectMake( - lhs.width / 2.f, - CGRectGetMidY(self.bounds) - trackSize.height / 2.f, - self.bounds.size.width - (lhs.width / 2.f) - (rhs.width / 2.f), - trackSize.height - ); - - self.fill.frame = FLEXRectMake( - CGRectGetMidX(self.leftHandle.frame), - CGRectGetMinY(self.track.frame), - CGRectGetMidX(self.rightHandle.frame) - CGRectGetMidX(self.leftHandle.frame), - self.track.frame.size.height - ); -} - -- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { - CGPoint loc = [touch locationInView:self]; - - if (CGRectContainsPoint(self.leftHandle.frame, loc)) { - self.trackingLeftHandle = YES; - self.trackingRightHandle = NO; - } else if (CGRectContainsPoint(self.rightHandle.frame, loc)) { - self.trackingLeftHandle = NO; - self.trackingRightHandle = YES; - } else { - return NO; - } - - return YES; -} - -- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { - CGPoint loc = [touch locationInView:self]; - - if (self.isTrackingLeftHandle) { - self.minValue = MIN(MAX(self.allowedMinValue, [self valueAt:loc.x]), self.maxValue); - } else if (self.isTrackingRightHandle) { - self.maxValue = MAX(MIN(self.allowedMaxValue, [self valueAt:loc.x]), self.minValue); - } else { - return NO; - } - - [self setNeedsLayout]; - [self layoutIfNeeded]; - - return YES; -} - -- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { - self.trackingLeftHandle = NO; - self.trackingRightHandle = NO; -} - -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { - return NO; -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSSnapshotView.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSSnapshotView.h deleted file mode 100644 index c0c9241..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSSnapshotView.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// FHSSnapshotView.h -// FLEX -// -// Created by Tanner Bennett on 1/7/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FHSViewSnapshot.h" -#import "FHSRangeSlider.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol FHSSnapshotViewDelegate - -- (void)didSelectView:(FHSViewSnapshot *)snapshot; -- (void)didDeselectView:(FHSViewSnapshot *)snapshot; -- (void)didLongPressView:(FHSViewSnapshot *)snapshot; - -@end - -@interface FHSSnapshotView : UIView - -+ (instancetype)delegate:(id)delegate; - -@property (nonatomic, weak) id delegate; - -@property (nonatomic) NSArray *snapshots; -@property (nonatomic, nullable) FHSViewSnapshot *selectedView; - -/// Views of these classes will have their headers hidden -@property (nonatomic) NSArray *headerExclusions; - -@property (nonatomic, readonly) UISlider *spacingSlider; -@property (nonatomic, readonly) FHSRangeSlider *depthSlider; - -- (void)emphasizeViews:(NSArray *)emphasizedViews; - -- (void)toggleShowHeaders; -- (void)toggleShowBorders; - -- (void)hideView:(FHSViewSnapshot *)view; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSSnapshotView.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSSnapshotView.m deleted file mode 100644 index d4b1126..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSSnapshotView.m +++ /dev/null @@ -1,304 +0,0 @@ -// -// FHSSnapshotView.m -// FLEX -// -// Created by Tanner Bennett on 1/7/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FHSSnapshotView.h" -#import "FHSSnapshotNodes.h" -#import "SceneKit+Snapshot.h" -#import "FLEXColor.h" - -@interface FHSSnapshotView () -@property (nonatomic, readonly) SCNView *sceneView; -@property (nonatomic) NSString *currentSummary; - -/// Maps nodes by snapshot IDs -@property (nonatomic) NSDictionary *nodesMap; -@property (nonatomic) NSInteger maxDepth; - -@property (nonatomic) FHSSnapshotNodes *highlightedNodes; -@property (nonatomic, getter=wantsHideHeaders) BOOL hideHeaders; -@property (nonatomic, getter=wantsHideBorders) BOOL hideBorders; -@property (nonatomic) BOOL suppressSelectionEvents; - -@property (nonatomic, readonly) BOOL mustHideHeaders; -@end - -@implementation FHSSnapshotView - -#pragma mark - Initialization - -+ (instancetype)delegate:(id)delegate { - FHSSnapshotView *view = [self new]; - view.delegate = delegate; - return view; -} - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:CGRectZero]; - if (self) { - [self initSpacingSlider]; - [self initDepthSlider]; - [self initSceneView]; // Must be last; calls setMaxDepth -// self.hideHeaders = YES; - - // Self - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - // Scene - self.sceneView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self addGestureRecognizer:[[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleTap:) - ]]; - } - - return self; -} - -- (void)initSceneView { - _sceneView = [SCNView new]; - self.sceneView.allowsCameraControl = YES; - - [self addSubview:self.sceneView]; -} - -- (void)initSpacingSlider { - _spacingSlider = [UISlider new]; - self.spacingSlider.minimumValue = 0; - self.spacingSlider.maximumValue = 100; - self.spacingSlider.continuous = YES; - [self.spacingSlider - addTarget:self - action:@selector(spacingSliderDidChange:) - forControlEvents:UIControlEventValueChanged - ]; - - self.spacingSlider.value = 50; -} - -- (void)initDepthSlider { - _depthSlider = [FHSRangeSlider new]; - [self.depthSlider - addTarget:self - action:@selector(depthSliderDidChange:) - forControlEvents:UIControlEventValueChanged - ]; -} - - -#pragma mark - Public - -- (void)setSelectedView:(FHSViewSnapshot *)view { - // Ivar set in selectSnapshot: - [self selectSnapshot:view ? self.nodesMap[view.view.identifier] : nil]; -} - -- (void)setSnapshots:(NSArray *)snapshots { - _snapshots = snapshots; - - // Create new scene (possibly discarding old scene) - SCNScene *scene = [SCNScene new]; - scene.background.contents = FLEXColor.primaryBackgroundColor; - self.sceneView.scene = scene; - - NSInteger depth = 0; - NSMutableDictionary *nodesMap = [NSMutableDictionary new]; - - // Add every root snapshot to the root scene node with increasing depths - SCNNode *root = scene.rootNode; - for (FHSViewSnapshot *snapshot in self.snapshots) { - [SCNNode - snapshot:snapshot - parent:nil - parentNode:nil - root:root - depth:&depth - nodesMap:nodesMap - hideHeaders:_hideHeaders - ]; - } - - self.maxDepth = depth; - self.nodesMap = nodesMap; -} - -- (void)setHeaderExclusions:(NSArray *)headerExclusions { - _headerExclusions = headerExclusions; - - if (headerExclusions.count) { - for (FHSSnapshotNodes *nodes in self.nodesMap.allValues) { - if ([headerExclusions containsObject:nodes.snapshotItem.view.view.class]) { - nodes.forceHideHeader = YES; - } else { - nodes.forceHideHeader = NO; - } - } - } -} - -- (void)emphasizeViews:(NSArray *)emphasizedViews { - if (emphasizedViews.count) { - [self emphasizeViews:emphasizedViews inSnapshots:self.snapshots]; - [self setNeedsLayout]; - } -} - -- (void)emphasizeViews:(NSArray *)emphasizedViews inSnapshots:(NSArray *)snapshots { - for (FHSViewSnapshot *snapshot in snapshots) { - FHSSnapshotNodes *nodes = self.nodesMap[snapshot.view.identifier]; - nodes.dimmed = ![emphasizedViews containsObject:snapshot.view.view]; - [self emphasizeViews:emphasizedViews inSnapshots:snapshot.children]; - } -} - -- (void)toggleShowHeaders { - self.hideHeaders = !self.hideHeaders; -} - -- (void)toggleShowBorders { - self.hideBorders = !self.hideBorders; -} - -- (void)hideView:(FHSViewSnapshot *)view { - NSParameterAssert(view); - FHSSnapshotNodes *nodes = self.nodesMap[view.view.identifier]; - [nodes.snapshot removeFromParentNode]; -} - -#pragma mark - Helper - -- (BOOL)mustHideHeaders { - return self.spacingSlider.value <= kFHSSmallZOffset; -} - -- (void)setMaxDepth:(NSInteger)maxDepth { - _maxDepth = maxDepth; - - self.depthSlider.allowedMinValue = 0; - self.depthSlider.allowedMaxValue = maxDepth; - self.depthSlider.maxValue = maxDepth; - self.depthSlider.minValue = 0; -} - -- (void)setHideHeaders:(BOOL)hideHeaders { - if (_hideHeaders != hideHeaders) { - _hideHeaders = hideHeaders; - - if (!self.mustHideHeaders) { - if (hideHeaders) { - [self hideHeaders]; - } else { - [self unhideHeaders]; - } - } - } -} - -- (void)setHideBorders:(BOOL)hideBorders { - if (_hideBorders != hideBorders) { - _hideBorders = hideBorders; - - for (FHSSnapshotNodes *nodes in self.nodesMap.allValues) { - nodes.border.hidden = hideBorders; - } - } -} - -- (FHSSnapshotNodes *)nodesAtPoint:(CGPoint)point { - NSArray *results = [self.sceneView hitTest:point options:nil]; - for (SCNHitTestResult *result in results) { - SCNNode *nearestSnapshot = result.node.nearestAncestorSnapshot; - if (nearestSnapshot) { - return self.nodesMap[nearestSnapshot.name]; - } - } - - return nil; -} - -- (void)selectSnapshot:(FHSSnapshotNodes *)selected { - // Notify delegate of de-select - if (!selected && self.selectedView) { - [self.delegate didDeselectView:self.selectedView]; - } - - _selectedView = selected.snapshotItem; - - // Case: selected the currently selected node - if (selected == self.highlightedNodes) { - return; - } - - // No-op if nothng is selected (yay objc!) - self.highlightedNodes.highlighted = NO; - self.highlightedNodes = nil; - - // No node means we tapped the background - if (selected) { - selected.highlighted = YES; - // TODO: update description text here - self.highlightedNodes = selected; - } - - // Notify delegate - [self.delegate didSelectView:selected.snapshotItem]; - - [self setNeedsLayout]; -} - -- (void)hideHeaders { - for (FHSSnapshotNodes *nodes in self.nodesMap.allValues) { - nodes.header.hidden = YES; - } -} - -- (void)unhideHeaders { - for (FHSSnapshotNodes *nodes in self.nodesMap.allValues) { - if (!nodes.forceHideHeader) { - nodes.header.hidden = NO; - } - } -} - - -#pragma mark - Event Handlers - -- (void)handleTap:(UITapGestureRecognizer *)gesture { - if (gesture.state == UIGestureRecognizerStateRecognized) { - CGPoint tap = [gesture locationInView:self.sceneView]; - [self selectSnapshot:[self nodesAtPoint:tap]]; - } -} - -- (void)spacingSliderDidChange:(UISlider *)slider { - // TODO: hiding the header when flat logic - - for (FHSSnapshotNodes *nodes in self.nodesMap.allValues) { - nodes.snapshot.position = ({ - SCNVector3 pos = nodes.snapshot.position; - pos.z = MAX(slider.value, kFHSSmallZOffset) * nodes.depth; - pos; - }); - - if (!self.wantsHideHeaders) { - if (self.mustHideHeaders) { - [self hideHeaders]; - } else { - [self unhideHeaders]; - } - } - } -} - -- (void)depthSliderDidChange:(FHSRangeSlider *)slider { - CGFloat min = slider.minValue, max = slider.maxValue; - for (FHSSnapshotNodes *nodes in self.nodesMap.allValues) { - CGFloat depth = nodes.depth; - nodes.snapshot.hidden = depth < min || max < depth; - } -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.h deleted file mode 100644 index 70122c1..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// FHSView.h -// FLEX -// -// Created by Tanner Bennett on 1/6/20. -// - -#import - -@interface FHSView : NSObject { - @private - BOOL _inScrollView; -} - -+ (instancetype)forView:(UIView *)view isInScrollView:(BOOL)inScrollView; - -/// Intentionally not weak -@property (nonatomic, readonly) UIView *view; -@property (nonatomic, readonly) NSString *identifier; - -@property (nonatomic, readonly) NSString *title; -/// Whether or not this view item should be visually distinguished -@property (nonatomic, readwrite) BOOL important; - -@property (nonatomic, readonly) CGRect frame; -@property (nonatomic, readonly) BOOL hidden; -@property (nonatomic, readonly) UIImage *snapshotImage; - -@property (nonatomic, readonly) NSArray *children; -@property (nonatomic, readonly) NSString *summary; - -/// @return importantAttr if .important, otherwise normalAttr -//- (id)ifImportant:(id)importantAttr ifNormal:(id)normalAttr; - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.m deleted file mode 100644 index 65bf1cf..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSView.m +++ /dev/null @@ -1,194 +0,0 @@ -// -// FHSView.m -// FLEX -// -// Created by Tanner Bennett on 1/6/20. -// - -#import "FHSView.h" -#import "FLEXUtility.h" -#import "NSArray+FLEX.h" - -@interface FHSView (Snapshotting) -+ (UIImage *)_snapshotView:(UIView *)view; -@end - -@implementation FHSView - -+ (instancetype)forView:(UIView *)view isInScrollView:(BOOL)inScrollView { - return [[self alloc] initWithView:view isInScrollView:inScrollView]; -} - -- (id)initWithView:(UIView *)view isInScrollView:(BOOL)inScrollView { - self = [super init]; - if (self) { - _view = view; - _inScrollView = inScrollView; - _identifier = NSUUID.UUID.UUIDString; - - UIViewController *controller = [FLEXUtility viewControllerForView:view]; - if (controller) { - _important = YES; - _title = [NSString stringWithFormat: - @"%@ (for %@)", - NSStringFromClass([controller class]), - NSStringFromClass([view class]) - ]; - } else { - _title = NSStringFromClass([view class]); - } - } - - return self; -} - -- (CGRect)frame { - if (_inScrollView) { - CGPoint offset = [(UIScrollView *)self.view.superview contentOffset]; - return CGRectOffset(self.view.frame, -offset.x, -offset.y); - } else { - return self.view.frame; - } -} - -- (BOOL)hidden { - return self.view.isHidden; -} - -- (UIImage *)snapshotImage { - return [FHSView _snapshotView:self.view]; -} - -- (NSArray *)children { - BOOL isScrollView = [self.view isKindOfClass:[UIScrollView class]]; - return [self.view.subviews flex_mapped:^id(UIView *subview, NSUInteger idx) { - return [FHSView forView:subview isInScrollView:isScrollView]; - }]; -} - -- (NSString *)summary { - CGRect f = self.frame; - return [NSString stringWithFormat: - @"%@ (%.1f, %.1f, %.1f, %.1f)", - NSStringFromClass([self.view class]), - f.origin.x, f.origin.y, f.size.width, f.size.height - ]; -} - -- (NSString *)description{ - return self.view.description; -} - -- (id)ifImportant:(id)importantAttr ifNormal:(id)normalAttr { - return self.important ? importantAttr : normalAttr; -} - -@end - -@implementation FHSView (Snapshotting) - -+ (UIImage *)drawView:(UIView *)view { - UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0); - [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -/// Recursively hides all views that may be obscuring the given view and collects them -/// in the given array. You should unhide them all when you are done. -+ (BOOL)_hideViewsCoveringView:(UIView *)view - root:(UIView *)rootView - hiddenViews:(NSMutableArray *)hiddenViews { - // Stop when we reach this view - if (view == rootView) { - return YES; - } - - for (UIView *subview in rootView.subviews.reverseObjectEnumerator.allObjects) { - if ([self _hideViewsCoveringView:view root:subview hiddenViews:hiddenViews]) { - return YES; - } - } - - if (!rootView.isHidden) { - rootView.hidden = YES; - [hiddenViews addObject:rootView]; - } - - return NO; -} - - -/// Recursively hides all views that may be obscuring the given view and collects them -/// in the given array. You should unhide them all when you are done. -+ (void)hideViewsCoveringView:(UIView *)view doWhileHidden:(void(^)(void))block { - NSMutableArray *viewsToUnhide = [NSMutableArray new]; - if ([self _hideViewsCoveringView:view root:view.window hiddenViews:viewsToUnhide]) { - block(); - } - - for (UIView *v in viewsToUnhide) { - v.hidden = NO; - } -} - -+ (UIImage *)_snapshotVisualEffectBackdropView:(UIView *)view { - NSParameterAssert(view.window); - - // UIVisualEffectView is a special case that cannot be snapshotted - // the same way as any other view. From Apple docs: - // - // Many effects require support from the window that hosts the - // UIVisualEffectView. Attempting to take a snapshot of only the - // UIVisualEffectView will result in a snapshot that does not - // contain the effect. To take a snapshot of a view hierarchy - // that contains a UIVisualEffectView, you must take a snapshot - // of the entire UIWindow or UIScreen that contains it. - // - // To snapshot this view, we traverse the view hierarchy starting - // from the window and hide any views that are on top of the - // _UIVisualEffectBackdropView so that it is visible in a snapshot - // of the window. We then take a snapshot of the window and crop - // it to the part that contains the backdrop view. This appears to - // be the same technique that Xcode's own view debugger uses to - // snapshot visual effect views. - __block UIImage *image = nil; - [self hideViewsCoveringView:view doWhileHidden:^{ - image = [self drawView:view]; - CGRect cropRect = [view.window convertRect:view.bounds fromView:view]; - image = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage, cropRect)]; - }]; - - return image; -} - -+ (UIImage *)_snapshotView:(UIView *)view { - UIView *superview = view.superview; - // Is this view inside a UIVisualEffectView? - if ([superview isKindOfClass:[UIVisualEffectView class]]) { - // Is it (probably) the "backdrop" view of this UIVisualEffectView? - if (superview.subviews.firstObject == view) { - return [self _snapshotVisualEffectBackdropView:view]; - } - } - - // Hide the view's subviews before we snapshot it - NSMutableIndexSet *toUnhide = [NSMutableIndexSet new]; - [view.subviews flex_forEach:^(UIView *v, NSUInteger idx) { - if (!v.isHidden) { - v.hidden = YES; - [toUnhide addIndex:idx]; - } - }]; - - // Snapshot the view, then unhide the previously-unhidden views - UIImage *snapshot = [self drawView:view]; - for (UIView *v in [view.subviews objectsAtIndexes:toUnhide]) { - v.hidden = NO; - } - - return snapshot; -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewController.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewController.h deleted file mode 100644 index 32891dc..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewController.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// FHSViewController.h -// FLEX -// -// Created by Tanner Bennett on 1/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/// The view controller -/// "FHS" stands for "FLEX (view) hierarchy snapshot" -@interface FHSViewController : UIViewController - -/// Use this when you want to snapshot a set of windows. -+ (instancetype)snapshotWindows:(NSArray *)windows; -/// Use this when you want to snapshot a specific slice of the view hierarchy. -+ (instancetype)snapshotView:(UIView *)view; -/// Use this when you want to emphasize specific views on the screen. -/// These views must all be in the same window as the selected view. -+ (instancetype)snapshotViewsAtTap:(NSArray *)viewsAtTap selectedView:(UIView *)view; - -@property (nonatomic, nullable) UIView *selectedView; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewController.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewController.m deleted file mode 100644 index 6fbc933..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewController.m +++ /dev/null @@ -1,270 +0,0 @@ -// -// FHSViewController.m -// FLEX -// -// Created by Tanner Bennett on 1/6/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FHSViewController.h" -#import "FHSSnapshotView.h" -#import "FLEXHierarchyViewController.h" -#import "FLEXColor.h" -#import "FLEXAlert.h" -#import "FLEXWindow.h" -#import "FLEXResources.h" -#import "NSArray+FLEX.h" -#import "UIBarButtonItem+FLEX.h" - -BOOL const kFHSViewControllerExcludeFLEXWindows = YES; - -@interface FHSViewController () -/// An array of only the target views whose hierarchies -/// we wish to snapshot, not every view in the snapshot. -@property (nonatomic, readonly) NSArray *targetViews; -@property (nonatomic, readonly) NSArray *views; -@property (nonatomic ) NSArray *snapshots; -@property (nonatomic, ) FHSSnapshotView *snapshotView; - -@property (nonatomic, readonly) UIView *containerView; -@property (nonatomic, readonly) NSArray *viewsAtTap; -@property (nonatomic, readonly) NSMutableSet *forceHideHeaders; -@end - -@implementation FHSViewController -@synthesize views = _views; -@synthesize snapshotView = _snapshotView; - -#pragma mark - Initialization - -+ (instancetype)snapshotWindows:(NSArray *)windows { - return [[self alloc] initWithViews:windows viewsAtTap:nil selectedView:nil]; -} - -+ (instancetype)snapshotView:(UIView *)view { - return [[self alloc] initWithViews:@[view] viewsAtTap:nil selectedView:nil]; -} - -+ (instancetype)snapshotViewsAtTap:(NSArray *)viewsAtTap selectedView:(UIView *)view { - NSParameterAssert(viewsAtTap.count); - NSParameterAssert(view.window); - return [[self alloc] initWithViews:@[view.window] viewsAtTap:viewsAtTap selectedView:view]; -} - -- (id)initWithViews:(NSArray *)views - viewsAtTap:(NSArray *)viewsAtTap - selectedView:(UIView *)view { - NSParameterAssert(views.count); - - self = [super init]; - if (self) { - _forceHideHeaders = [NSMutableSet setWithObject:NSClassFromString(@"_UITableViewCellSeparatorView")]; - _selectedView = view; - _viewsAtTap = viewsAtTap; - - if (!viewsAtTap && kFHSViewControllerExcludeFLEXWindows) { - Class flexwindow = [FLEXWindow class]; - views = [views flex_filtered:^BOOL(UIView *view, NSUInteger idx) { - return [view class] != flexwindow; - }]; - } - - _targetViews = views; - _views = [views flex_mapped:^id(UIView *view, NSUInteger idx) { - BOOL isScrollView = [view.superview isKindOfClass:[UIScrollView class]]; - return [FHSView forView:view isInScrollView:isScrollView]; - }]; - } - - return self; -} - -- (void)refreshSnapshotView { - // Alert view to block interaction while we load everything - UIAlertController *loading = [FLEXAlert makeAlert:^(FLEXAlert *make) { - make.title(@"Please Wait").message(@"Generating snapshot…"); - }]; - [self presentViewController:loading animated:YES completion:^{ - self.snapshots = [self.views flex_mapped:^id(FHSView *view, NSUInteger idx) { - return [FHSViewSnapshot snapshotWithView:view]; - }]; - FHSSnapshotView *newSnapshotView = [FHSSnapshotView delegate:self]; - - // This work is highly intensive so we do it on a background thread first - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - // Setting the snapshots computes lots of SCNNodes, takes several seconds - newSnapshotView.snapshots = self.snapshots; - - // After we finish generating all the model objects and scene nodes, display the view - dispatch_async(dispatch_get_main_queue(), ^{ - // Dismiss alert - [loading dismissViewControllerAnimated:YES completion:nil]; - - self.snapshotView = newSnapshotView; - }); - }); - }]; -} - - -#pragma mark - View Controller Lifecycle - -- (void)loadView { - [super loadView]; - self.view.backgroundColor = FLEXColor.primaryBackgroundColor; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Initialize back bar button item for 3D view to look like a button - self.navigationItem.hidesBackButton = YES; - self.navigationItem.leftBarButtonItem = [UIBarButtonItem - flex_itemWithImage:FLEXResources.toggle2DIcon - target:self.navigationController - action:@selector(toggleHierarchyMode) - ]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - if (!_snapshotView) { - [self refreshSnapshotView]; - } -} - - -#pragma mark - Public - -- (void)setSelectedView:(UIView *)view { - _selectedView = view; - self.snapshotView.selectedView = view ? [self snapshotForView:view] : nil; -} - - -#pragma mark - Private - -#pragma mark Properties - -- (FHSSnapshotView *)snapshotView { - return self.isViewLoaded ? _snapshotView : nil; -} - -- (void)setSnapshotView:(FHSSnapshotView *)snapshotView { - NSParameterAssert(snapshotView); - - _snapshotView = snapshotView; - - // Initialize our toolbar items - self.toolbarItems = @[ - [UIBarButtonItem flex_itemWithCustomView:snapshotView.spacingSlider], - UIBarButtonItem.flex_flexibleSpace, - [UIBarButtonItem - flex_itemWithImage:FLEXResources.moreIcon - target:self action:@selector(didPressOptionsButton:) - ], - UIBarButtonItem.flex_flexibleSpace, - [UIBarButtonItem flex_itemWithCustomView:snapshotView.depthSlider] - ]; - [self resizeToolbarItems:self.view.frame.size]; - - // If we have views-at-tap, dim the other views - [snapshotView emphasizeViews:self.viewsAtTap]; - // Set the selected view, if any - snapshotView.selectedView = [self snapshotForView:self.selectedView]; - snapshotView.headerExclusions = self.forceHideHeaders.allObjects; - [snapshotView setNeedsLayout]; - - // Remove old snapshot, if any, and add the new one - [_snapshotView removeFromSuperview]; - snapshotView.frame = self.containerView.bounds; - [self.containerView addSubview:snapshotView]; -} - -- (UIView *)containerView { - return self.view; -} - -#pragma mark Helper - -- (FHSViewSnapshot *)snapshotForView:(UIView *)view { - if (!view || !self.snapshots.count) return nil; - - for (FHSViewSnapshot *snapshot in self.snapshots) { - FHSViewSnapshot *found = [snapshot snapshotForView:view]; - if (found) { - return found; - } - } - - // Error: we have snapshots but the view we requested is not in one - @throw NSInternalInconsistencyException; - return nil; -} - -#pragma mark Events - -- (void)didPressOptionsButton:(UIBarButtonItem *)sender { - [FLEXAlert makeSheet:^(FLEXAlert *make) { - if (self.selectedView) { - make.button(@"Hide selected view").handler(^(NSArray *strings) { - [self.snapshotView hideView:[self snapshotForView:self.selectedView]]; - }); - make.button(@"Hide headers for views like this").handler(^(NSArray *strings) { - Class cls = [self.selectedView class]; - if (![self.forceHideHeaders containsObject:cls]) { - [self.forceHideHeaders addObject:[self.selectedView class]]; - self.snapshotView.headerExclusions = self.forceHideHeaders.allObjects; - } - }); - } - make.title(@"Options"); - make.button(@"Toggle headers").handler(^(NSArray *strings) { - [self.snapshotView toggleShowHeaders]; - }); - make.button(@"Toggle outlines").handler(^(NSArray *strings) { - [self.snapshotView toggleShowBorders]; - }); - make.button(@"Cancel").cancelStyle(); - } showFrom:self source:sender]; -} - -- (void)resizeToolbarItems:(CGSize)viewSize { - CGFloat sliderHeights = self.snapshotView.spacingSlider.bounds.size.height; - CGFloat sliderWidths = viewSize.width / 3.f; - CGRect frame = CGRectMake(0, 0, sliderWidths, sliderHeights); - self.snapshotView.spacingSlider.frame = frame; - self.snapshotView.depthSlider.frame = frame; - - [self.navigationController.toolbar setNeedsLayout]; -} - -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator:(id)coordinator { - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; - - [coordinator animateAlongsideTransition:^(id _Nonnull context) { - [self resizeToolbarItems:self.view.frame.size]; - } completion:nil]; -} - -#pragma mark FHSSnapshotViewDelegate - -- (void)didDeselectView:(FHSViewSnapshot *)snapshot { - // Our setter would also call the setter for the snapshot view, - // which we don't need to do here since it is already selected - _selectedView = nil; -} - -- (void)didLongPressView:(FHSViewSnapshot *)snapshot { - -} - -- (void)didSelectView:(FHSViewSnapshot *)snapshot { - // Our setter would also call the setter for the snapshot view, - // which we don't need to do here since it is already selected - _selectedView = snapshot.view.view; -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewSnapshot.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewSnapshot.h deleted file mode 100644 index eee84e4..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewSnapshot.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// FHSViewSnapshot.h -// FLEX -// -// Created by Tanner Bennett on 1/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FHSView.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FHSViewSnapshot : NSObject - -+ (instancetype)snapshotWithView:(FHSView *)view; - -@property (nonatomic, readonly) FHSView *view; - -@property (nonatomic, readonly) NSString *title; -/// Whether or not this view item should be visually distinguished -@property (nonatomic, readwrite) BOOL important; - -@property (nonatomic, readonly) CGRect frame; -@property (nonatomic, readonly) BOOL hidden; -@property (nonatomic, readonly) UIImage *snapshotImage; - -@property (nonatomic, readonly) NSArray *children; -@property (nonatomic, readonly) NSString *summary; - -/// Returns a different color based on whether or not the view is important -@property (nonatomic, readonly) UIColor *headerColor; - -- (FHSViewSnapshot *)snapshotForView:(UIView *)view; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewSnapshot.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewSnapshot.m deleted file mode 100644 index 4911e03..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/FHSViewSnapshot.m +++ /dev/null @@ -1,62 +0,0 @@ -// -// FHSViewSnapshot.m -// FLEX -// -// Created by Tanner Bennett on 1/9/20. -// Copyright © 2020 FLEX Team. All rights reserved. -// - -#import "FHSViewSnapshot.h" -#import "NSArray+FLEX.h" - -@implementation FHSViewSnapshot - -+ (instancetype)snapshotWithView:(FHSView *)view { - NSArray *children = [view.children flex_mapped:^id(FHSView *v, NSUInteger idx) { - return [self snapshotWithView:v]; - }]; - return [[self alloc] initWithView:view children:children]; -} - -- (id)initWithView:(FHSView *)view children:(NSArray *)children { - NSParameterAssert(view); NSParameterAssert(children); - - self = [super init]; - if (self) { - _view = view; - _title = view.title; - _important = view.important; - _frame = view.frame; - _hidden = view.hidden; - _snapshotImage = view.snapshotImage; - _children = children; - _summary = view.summary; - } - - return self; -} - -- (UIColor *)headerColor { - if (self.important) { - return [UIColor colorWithRed: 0.000 green: 0.533 blue: 1.000 alpha: 0.900]; - } else { - return [UIColor colorWithRed:0.961 green: 0.651 blue: 0.137 alpha: 0.900]; - } -} - -- (FHSViewSnapshot *)snapshotForView:(UIView *)view { - if (view == self.view.view) { - return self; - } - - for (FHSViewSnapshot *child in self.children) { - FHSViewSnapshot *snapshot = [child snapshotForView:view]; - if (snapshot) { - return snapshot; - } - } - - return nil; -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/FHSSnapshotNodes.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/FHSSnapshotNodes.h deleted file mode 100644 index 8e32249..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/FHSSnapshotNodes.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// FHSSnapshotNodes.h -// FLEX -// -// Created by Tanner Bennett on 1/7/20. -// - -#import "FHSViewSnapshot.h" -#import - -NS_ASSUME_NONNULL_BEGIN - -/// Container that holds references to the SceneKit nodes associated with a snapshot. -@interface FHSSnapshotNodes : NSObject - -+ (instancetype)snapshot:(FHSViewSnapshot *)snapshot depth:(NSInteger)depth; - -@property (nonatomic, readonly) FHSViewSnapshot *snapshotItem; -@property (nonatomic, readonly) NSInteger depth; - -/// The view image itself -@property (nonatomic, nullable) SCNNode *snapshot; -/// Goes on top of the snapshot, has rounded top corners -@property (nonatomic, nullable) SCNNode *header; -/// The bounding box drawn around the snapshot -@property (nonatomic, nullable) SCNNode *border; - -/// Used to indicate when a view is selected -@property (nonatomic, getter=isHighlighted) BOOL highlighted; -/// Used to indicate when a view is de-emphasized -@property (nonatomic, getter=isDimmed) BOOL dimmed; - -@property (nonatomic) BOOL forceHideHeader; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/FHSSnapshotNodes.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/FHSSnapshotNodes.m deleted file mode 100644 index 052418e..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/FHSSnapshotNodes.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// FHSSnapshotNodes.m -// FLEX -// -// Created by Tanner Bennett on 1/7/20. -// - -#import "FHSSnapshotNodes.h" -#import "SceneKit+Snapshot.h" - -@interface FHSSnapshotNodes () -@property (nonatomic, nullable) SCNNode *highlight; -@property (nonatomic, nullable) SCNNode *dimming; -@end -@implementation FHSSnapshotNodes - -+ (instancetype)snapshot:(FHSViewSnapshot *)snapshot depth:(NSInteger)depth { - FHSSnapshotNodes *nodes = [self new]; - nodes->_snapshotItem = snapshot; - nodes->_depth = depth; - return nodes; -} - -- (void)setHighlighted:(BOOL)highlighted { - if (_highlighted != highlighted) { - _highlighted = highlighted; - - if (highlighted) { - if (!self.highlight) { - // Create highlight node - self.highlight = [SCNNode - highlight:self.snapshotItem - color:[UIColor.blueColor colorWithAlphaComponent:0.5] - ]; - } - // Add add highlight node, remove dimming node if dimmed - [self.snapshot addChildNode:self.highlight]; - if (self.isDimmed) { - [self.dimming removeFromParentNode]; - } - } else { - // Remove highlight node, add back dimming node if dimmed - [self.highlight removeFromParentNode]; - if (self.isDimmed) { - [self.snapshot addChildNode:self.dimming]; - } - } - } -} - -- (void)setDimmed:(BOOL)dimmed { - if (_dimmed != dimmed) { - _dimmed = dimmed; - - if (dimmed) { - if (!self.dimming) { - // Create dimming node - self.dimming = [SCNNode - highlight:self.snapshotItem - color:[UIColor.blackColor colorWithAlphaComponent:0.5] - ]; - } - // Add add dimming node if not highlighted - if (!self.isHighlighted) { - [self.snapshot addChildNode:self.dimming]; - } - } else { - // Remove dimming node (if not already highlighted) - if (!self.isHighlighted) { - [self.dimming removeFromParentNode]; - } - } - } -} - -- (void)setForceHideHeader:(BOOL)forceHideHeader { - if (_forceHideHeader != forceHideHeader) { - _forceHideHeader = forceHideHeader; - - if (self.header.parentNode) { - self.header.hidden = YES; - [self.header removeFromParentNode]; - } else { - self.header.hidden = NO; - [self.snapshot addChildNode:self.header]; - } - } -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/SceneKit+Snapshot.h b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/SceneKit+Snapshot.h deleted file mode 100644 index 8148ff9..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/SceneKit+Snapshot.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// SceneKit+Snapshot.h -// FLEX -// -// Created by Tanner Bennett on 1/8/20. -// - -#import -#import "FHSViewSnapshot.h" -@class FHSSnapshotNodes; - -extern CGFloat const kFHSSmallZOffset; - -#pragma mark SCNNode -@interface SCNNode (Snapshot) - -/// @return the nearest ancestor snapshot node starting at this node -@property (nonatomic, readonly) SCNNode *nearestAncestorSnapshot; - -/// @return a node that renders a highlight overlay over a specified snapshot -+ (instancetype)highlight:(FHSViewSnapshot *)view color:(UIColor *)color; -/// @return a node that renders a snapshot image -+ (instancetype)snapshot:(FHSViewSnapshot *)view; -/// @return a node that draws a line between two vertices -+ (instancetype)lineFrom:(SCNVector3)v1 to:(SCNVector3)v2 color:(UIColor *)lineColor; - -/// @return a node that can be used to render a colored border around the specified node -- (instancetype)borderWithColor:(UIColor *)color; -/// @return a node that renders a header above a snapshot node -/// using the title text from the view, if specified -+ (instancetype)header:(FHSViewSnapshot *)view; - -/// @return a SceneKit node that recursively renders a hierarchy -/// of UI elements starting at the specified snapshot -+ (instancetype)snapshot:(FHSViewSnapshot *)view - parent:(FHSViewSnapshot *)parentView - parentNode:(SCNNode *)parentNode - root:(SCNNode *)rootNode - depth:(NSInteger *)depthOut - nodesMap:(NSMutableDictionary *)nodesMap - hideHeaders:(BOOL)hideHeaders; - -@end - - -#pragma mark SCNShape -@interface SCNShape (Snapshot) -/// @return a shape with the given path, 0 extrusion depth, and a double-sided -/// material with the given diffuse contents inserted at index 0 -+ (instancetype)shapeWithPath:(UIBezierPath *)path materialDiffuse:(id)contents; -/// @return a shape that is used to render the background of the snapshot header -+ (instancetype)nameHeader:(UIColor *)color frame:(CGRect)frame corners:(CGFloat)cornerRadius; - -@end - - -#pragma mark SCNText -@interface SCNText (Snapshot) -/// @return text geometry used to render text inside the snapshot header -+ (instancetype)labelGeometry:(NSString *)text font:(UIFont *)font; - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/SceneKit+Snapshot.m b/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/SceneKit+Snapshot.m deleted file mode 100644 index 4dff682..0000000 --- a/Tweaks/FLEX/ViewHierarchy/SnapshotExplorer/Scene/SceneKit+Snapshot.m +++ /dev/null @@ -1,278 +0,0 @@ -// -// SceneKit+Snapshot.m -// FLEX -// -// Created by Tanner Bennett on 1/8/20. -// - -#import "SceneKit+Snapshot.h" -#import "FHSSnapshotNodes.h" - -/// This value is chosen such that this offset can be applied to avoid -/// z-fighting amongst nodes at the same z-position, but small enough -/// that they appear to visually be on the same plane. -CGFloat const kFHSSmallZOffset = 0.05; -CGFloat const kHeaderVerticalInset = 8.0; - -#pragma mark SCNGeometry -@interface SCNGeometry (SnapshotPrivate) -@end -@implementation SCNGeometry (SnapshotPrivate) - -- (void)addDoubleSidedMaterialWithDiffuseContents:(id)contents { - SCNMaterial *material = [SCNMaterial new]; - material.doubleSided = YES; - material.diffuse.contents = contents; - [self insertMaterial:material atIndex:0]; -} - -@end - -#pragma mark SCNNode -@implementation SCNNode (Snapshot) - -- (SCNNode *)nearestAncestorSnapshot { - SCNNode *node = self; - - while (!node.name && node) { - node = node.parentNode; - } - - return node; -} - -+ (instancetype)shapeNodeWithSize:(CGSize)size materialDiffuse:(id)contents offsetZ:(BOOL)offsetZ { - UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake( - 0, 0, size.width, size.height - )]; - SCNShape *shape = [SCNShape shapeWithPath:path materialDiffuse:contents]; - SCNNode *node = [SCNNode nodeWithGeometry:shape]; - - if (offsetZ) { - node.position = SCNVector3Make(0, 0, kFHSSmallZOffset); - } - return node; -} - -+ (instancetype)highlight:(FHSViewSnapshot *)view color:(UIColor *)color { - return [self shapeNodeWithSize:view.frame.size materialDiffuse:color offsetZ:YES]; -} - -+ (instancetype)snapshot:(FHSViewSnapshot *)view { - id image = view.snapshotImage; - return [self shapeNodeWithSize:view.frame.size materialDiffuse:image offsetZ:NO]; -} - -+ (instancetype)lineFrom:(SCNVector3)v1 to:(SCNVector3)v2 color:(UIColor *)lineColor { - SCNVector3 vertices[2] = { v1, v2 }; - int32_t _indices[2] = { 0, 1 }; - NSData *indices = [NSData dataWithBytes:_indices length:sizeof(_indices)]; - - SCNGeometrySource *source = [SCNGeometrySource geometrySourceWithVertices:vertices count:2]; - SCNGeometryElement *element = [SCNGeometryElement - geometryElementWithData:indices - primitiveType:SCNGeometryPrimitiveTypeLine - primitiveCount:2 - bytesPerIndex:sizeof(int32_t) - ]; - - SCNGeometry *geometry = [SCNGeometry geometryWithSources:@[source] elements:@[element]]; - [geometry addDoubleSidedMaterialWithDiffuseContents:lineColor]; - return [SCNNode nodeWithGeometry:geometry]; -} - -- (instancetype)borderWithColor:(UIColor *)color { - struct { SCNVector3 min, max; } bb; - [self getBoundingBoxMin:&bb.min max:&bb.max]; - - SCNVector3 topLeft = SCNVector3Make(bb.min.x, bb.max.y, kFHSSmallZOffset); - SCNVector3 bottomLeft = SCNVector3Make(bb.min.x, bb.min.y, kFHSSmallZOffset); - SCNVector3 topRight = SCNVector3Make(bb.max.x, bb.max.y, kFHSSmallZOffset); - SCNVector3 bottomRight = SCNVector3Make(bb.max.x, bb.min.y, kFHSSmallZOffset); - - SCNNode *top = [SCNNode lineFrom:topLeft to:topRight color:color]; - SCNNode *left = [SCNNode lineFrom:bottomLeft to:topLeft color:color]; - SCNNode *bottom = [SCNNode lineFrom:bottomLeft to:bottomRight color:color]; - SCNNode *right = [SCNNode lineFrom:bottomRight to:topRight color:color]; - - SCNNode *border = [SCNNode new]; - [border addChildNode:top]; - [border addChildNode:left]; - [border addChildNode:bottom]; - [border addChildNode:right]; - - return border; -} - -+ (instancetype)header:(FHSViewSnapshot *)view { - SCNText *text = [SCNText labelGeometry:view.title font:[UIFont boldSystemFontOfSize:13.0]]; - SCNNode *textNode = [SCNNode nodeWithGeometry:text]; - - struct { SCNVector3 min, max; } bb; - [textNode getBoundingBoxMin:&bb.min max:&bb.max]; - CGFloat textWidth = bb.max.x - bb.min.x; - CGFloat textHeight = bb.max.y - bb.min.y; - - CGFloat snapshotWidth = view.frame.size.width; - CGFloat headerWidth = MAX(snapshotWidth, textWidth); - CGRect frame = CGRectMake(0, 0, headerWidth, textHeight + (kHeaderVerticalInset * 2)); - SCNNode *headerNode = [SCNNode nodeWithGeometry:[SCNShape - nameHeader:view.headerColor frame:frame corners:8 - ]]; - [headerNode addChildNode:textNode]; - - textNode.position = SCNVector3Make( - (frame.size.width / 2.f) - (textWidth / 2.f), - (frame.size.height / 2.f) - (textHeight / 2.f), - kFHSSmallZOffset - ); - headerNode.position = SCNVector3Make( - (snapshotWidth / 2.f) - (headerWidth / 2.f), - view.frame.size.height, - kFHSSmallZOffset - ); - - return headerNode; -} - -+ (instancetype)snapshot:(FHSViewSnapshot *)view - parent:(FHSViewSnapshot *)parent - parentNode:(SCNNode *)parentNode - root:(SCNNode *)rootNode - depth:(NSInteger *)depthOut - nodesMap:(NSMutableDictionary *)nodesMap - hideHeaders:(BOOL)hideHeaders { - NSInteger const depth = *depthOut; - - // Ignore elements that are not visible. - // These should appear in the list, but not in the 3D view. - if (view.hidden || CGSizeEqualToSize(view.frame.size, CGSizeZero)) { - return nil; - } - - // Create a node whose contents are the snapshot of the element - SCNNode *node = [self snapshot:view]; - node.name = view.view.identifier; - - // Begin building node tree - FHSSnapshotNodes *nodes = [FHSSnapshotNodes snapshot:view depth:depth]; - nodes.snapshot = node; - - // The node must be added to the root node - // for the coordinate space calculations below to work - [rootNode addChildNode:node]; - node.position = ({ - // Flip the y-coordinate since SceneKit has a - // flipped version of the UIKit coordinate system - CGRect pframe = parent ? parent.frame : CGRectZero; - CGFloat y = parent ? pframe.size.height - CGRectGetMaxY(view.frame) : 0; - - // To simplify calculating the z-axis spacing between the layers, we make - // each snapshot node a direct child of the root rather than embedding - // the nodes in their parent nodes in the same structure as the UI elements - // themselves. With this flattened hierarchy, the z-position can be - // calculated for every node simply by multiplying the spacing by the depth. - // - // `parentSnapshotNode` as referenced here is NOT the actual parent node - // of `node`, it is the node corresponding to the parent of the UI element. - // It is used to convert from frame coordinates, which are relative to - // the bounds of the parent, to coordinates relative to the root node. - SCNVector3 positionRelativeToParent = SCNVector3Make(view.frame.origin.x, y, 0); - SCNVector3 positionRelativeToRoot; - if (parent) { - positionRelativeToRoot = [rootNode convertPosition:positionRelativeToParent fromNode:parentNode]; - } else { - positionRelativeToRoot = positionRelativeToParent; - } - positionRelativeToRoot.z = 50 * depth; - positionRelativeToRoot; - }); - - // Make border node - nodes.border = [node borderWithColor:view.headerColor]; - [node addChildNode:nodes.border]; - - // Make header node - nodes.header = [SCNNode header:view]; - [node addChildNode:nodes.header]; - if (hideHeaders) { - nodes.header.hidden = YES; - } - - nodesMap[view.view.identifier] = nodes; - - NSMutableArray *checkForIntersect = [NSMutableArray new]; - NSInteger maxChildDepth = depth; - - // Recurse to child nodes; overlapping children have higher depths - for (FHSViewSnapshot *child in view.children) { - NSInteger childDepth = depth + 1; - - // Children that intersect a sibling are rendered - // in a separate layer above the previous siblings - for (FHSViewSnapshot *sibling in checkForIntersect) { - if (CGRectIntersectsRect(sibling.frame, child.frame)) { - childDepth = maxChildDepth + 1; - break; - } - } - - id didMakeNode = [SCNNode - snapshot:child - parent:view - parentNode:node - root:rootNode - depth:&childDepth - nodesMap:nodesMap - hideHeaders:hideHeaders - ]; - if (didMakeNode) { - maxChildDepth = MAX(childDepth, maxChildDepth); - [checkForIntersect addObject:child]; - } - } - - *depthOut = maxChildDepth; - return node; -} - -@end - - -#pragma mark SCNShape -@implementation SCNShape (Snapshot) - -+ (instancetype)shapeWithPath:(UIBezierPath *)path materialDiffuse:(id)contents { - SCNShape *shape = [SCNShape shapeWithPath:path extrusionDepth:0]; - [shape addDoubleSidedMaterialWithDiffuseContents:contents]; - return shape; -} - -+ (instancetype)nameHeader:(UIColor *)color frame:(CGRect)frame corners:(CGFloat)radius { - UIBezierPath *path = [UIBezierPath - bezierPathWithRoundedRect:frame - byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight - cornerRadii:CGSizeMake(radius, radius) - ]; - return [SCNShape shapeWithPath:path materialDiffuse:color]; -} - -@end - - -#pragma mark SCNText -@implementation SCNText (Snapshot) - -+ (instancetype)labelGeometry:(NSString *)text font:(UIFont *)font { - NSParameterAssert(text); - - SCNText *label = [self new]; - label.string = text; - label.font = font; - label.alignmentMode = kCAAlignmentCenter; - label.truncationMode = kCATruncationEnd; - - return label; -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewCell.h b/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewCell.h deleted file mode 100644 index 4b69478..0000000 --- a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewCell.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// FLEXHierarchyTableViewCell.h -// Flipboard -// -// Created by Ryan Olson on 2014-05-02. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import - -@interface FLEXHierarchyTableViewCell : UITableViewCell - -- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier; - -@property (nonatomic) NSInteger viewDepth; -@property (nonatomic) UIColor *randomColorTag; -@property (nonatomic) UIColor *indicatedViewColor; - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewCell.m b/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewCell.m deleted file mode 100644 index f2c60db..0000000 --- a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewCell.m +++ /dev/null @@ -1,169 +0,0 @@ -// -// FLEXHierarchyTableViewCell.m -// Flipboard -// -// Created by Ryan Olson on 2014-05-02. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXHierarchyTableViewCell.h" -#import "FLEXUtility.h" -#import "FLEXResources.h" -#import "FLEXColor.h" - -@interface FLEXHierarchyTableViewCell () - -/// Indicates how deep the view is in the hierarchy -@property (nonatomic) UIView *depthIndicatorView; -/// Holds the color that visually distinguishes views from one another -@property (nonatomic) UIImageView *colorCircleImageView; -/// A checker-patterned view, used to help show the color of a view, like a photoshop canvas -@property (nonatomic) UIView *backgroundColorCheckerPatternView; -/// The subview of the checker pattern view which holds the actual color of the view -@property (nonatomic) UIView *viewBackgroundColorView; - -@end - -@implementation FLEXHierarchyTableViewCell - -- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier { - return [self initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier]; -} - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - self.depthIndicatorView = [UIView new]; - self.depthIndicatorView.backgroundColor = FLEXUtility.hierarchyIndentPatternColor; - [self.contentView addSubview:self.depthIndicatorView]; - - UIImage *defaultCircleImage = [FLEXUtility circularImageWithColor:UIColor.blackColor radius:5]; - self.colorCircleImageView = [[UIImageView alloc] initWithImage:defaultCircleImage]; - [self.contentView addSubview:self.colorCircleImageView]; - - self.textLabel.font = UIFont.flex_defaultTableCellFont; - self.detailTextLabel.font = UIFont.flex_defaultTableCellFont; - self.accessoryType = UITableViewCellAccessoryDetailButton; - - // Use a pattern-based color to simplify application of the checker pattern - static UIColor *checkerPatternColor = nil; - static dispatch_once_t once; - dispatch_once(&once, ^{ - checkerPatternColor = [UIColor colorWithPatternImage:FLEXResources.checkerPattern]; - }); - - self.backgroundColorCheckerPatternView = [UIView new]; - self.backgroundColorCheckerPatternView.clipsToBounds = YES; - self.backgroundColorCheckerPatternView.layer.borderColor = FLEXColor.tertiaryBackgroundColor.CGColor; - self.backgroundColorCheckerPatternView.layer.borderWidth = 2.f / UIScreen.mainScreen.scale; - self.backgroundColorCheckerPatternView.backgroundColor = checkerPatternColor; - [self.contentView addSubview:self.backgroundColorCheckerPatternView]; - self.viewBackgroundColorView = [UIView new]; - [self.backgroundColorCheckerPatternView addSubview:self.viewBackgroundColorView]; - } - return self; -} - -- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { - UIColor *originalColour = self.viewBackgroundColorView.backgroundColor; - [super setHighlighted:highlighted animated:animated]; - - // UITableViewCell changes all subviews in the contentView to backgroundColor = clearColor. - // We want to preserve the hierarchy background color when highlighted. - self.depthIndicatorView.backgroundColor = FLEXUtility.hierarchyIndentPatternColor; - - self.viewBackgroundColorView.backgroundColor = originalColour; -} - -- (void)setSelected:(BOOL)selected animated:(BOOL)animated { - UIColor *originalColour = self.viewBackgroundColorView.backgroundColor; - [super setSelected:selected animated:animated]; - - // See setHighlighted above. - self.depthIndicatorView.backgroundColor = FLEXUtility.hierarchyIndentPatternColor; - - self.viewBackgroundColorView.backgroundColor = originalColour; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - const CGFloat kContentPadding = 6; - const CGFloat kDepthIndicatorWidthMultiplier = 4; - const CGFloat kViewColorIndicatorSize = 22; - - const CGRect bounds = self.contentView.bounds; - const CGFloat centerY = CGRectGetMidY(bounds); - const CGFloat textLabelCenterY = CGRectGetMidY(self.textLabel.frame); - - BOOL hideCheckerView = self.backgroundColorCheckerPatternView.hidden; - CGFloat maxWidth = CGRectGetMaxX(bounds); - maxWidth -= (hideCheckerView ? kContentPadding : (kViewColorIndicatorSize + kContentPadding * 2)); - - CGRect depthIndicatorFrame = self.depthIndicatorView.frame = CGRectMake( - kContentPadding, 0, self.viewDepth * kDepthIndicatorWidthMultiplier, CGRectGetHeight(bounds) - ); - - // Circle goes after depth, and its center Y = textLabel's center Y - CGRect circleFrame = self.colorCircleImageView.frame; - circleFrame.origin.x = CGRectGetMaxX(depthIndicatorFrame) + kContentPadding; - circleFrame.origin.y = FLEXFloor(textLabelCenterY - CGRectGetHeight(circleFrame) / 2.f); - self.colorCircleImageView.frame = circleFrame; - - // Text label goes after random color circle, width extends to the edge - // of the contentView or to the padding before the color indicator view - CGRect textLabelFrame = self.textLabel.frame; - CGFloat textOriginX = CGRectGetMaxX(circleFrame) + kContentPadding; - textLabelFrame.origin.x = textOriginX; - textLabelFrame.size.width = maxWidth - textOriginX; - self.textLabel.frame = textLabelFrame; - - // detailTextLabel leading edge lines up with the circle, and the - // width extends to the same max X as the same max X as the textLabel - CGRect detailTextLabelFrame = self.detailTextLabel.frame; - CGFloat detailOriginX = circleFrame.origin.x; - detailTextLabelFrame.origin.x = detailOriginX; - detailTextLabelFrame.size.width = maxWidth - detailOriginX; - self.detailTextLabel.frame = detailTextLabelFrame; - - // Checker pattern view starts after the padding after the max X of textLabel, - // and is centered vertically within the entire contentView - self.backgroundColorCheckerPatternView.frame = CGRectMake( - CGRectGetMaxX(self.textLabel.frame) + kContentPadding, - centerY - kViewColorIndicatorSize / 2.f, - kViewColorIndicatorSize, - kViewColorIndicatorSize - ); - - // Background color view fills it's superview - self.viewBackgroundColorView.frame = self.backgroundColorCheckerPatternView.bounds; - self.backgroundColorCheckerPatternView.layer.cornerRadius = kViewColorIndicatorSize / 2.f; -} - -- (void)setRandomColorTag:(UIColor *)randomColorTag { - if (![_randomColorTag isEqual:randomColorTag]) { - _randomColorTag = randomColorTag; - self.colorCircleImageView.image = [FLEXUtility circularImageWithColor:randomColorTag radius:6]; - } -} - -- (void)setViewDepth:(NSInteger)viewDepth { - if (_viewDepth != viewDepth) { - _viewDepth = viewDepth; - [self setNeedsLayout]; - } -} - -- (UIColor *)indicatedViewColor { - return self.viewBackgroundColorView.backgroundColor; -} - -- (void)setIndicatedViewColor:(UIColor *)color { - self.viewBackgroundColorView.backgroundColor = color; - - // Hide the checker pattern view if there is no background color - self.backgroundColorCheckerPatternView.hidden = color == nil; - [self setNeedsLayout]; -} - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewController.h b/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewController.h deleted file mode 100644 index 1eca05e..0000000 --- a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// FLEXHierarchyTableViewController.h -// Flipboard -// -// Created by Ryan Olson on 2014-05-01. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXTableViewController.h" - -@interface FLEXHierarchyTableViewController : FLEXTableViewController - -+ (instancetype)windows:(NSArray *)allWindows - viewsAtTap:(NSArray *)viewsAtTap - selectedView:(UIView *)selectedView; - -@property (nonatomic) UIView *selectedView; -@property (nonatomic) void(^didSelectRowAction)(UIView *selectedView); - -@end diff --git a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewController.m b/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewController.m deleted file mode 100644 index ef50d9e..0000000 --- a/Tweaks/FLEX/ViewHierarchy/TreeExplorer/FLEXHierarchyTableViewController.m +++ /dev/null @@ -1,253 +0,0 @@ -// -// FLEXHierarchyTableViewController.m -// Flipboard -// -// Created by Ryan Olson on 2014-05-01. -// Copyright (c) 2020 FLEX Team. All rights reserved. -// - -#import "FLEXColor.h" -#import "FLEXHierarchyTableViewController.h" -#import "NSMapTable+FLEX_Subscripting.h" -#import "FLEXUtility.h" -#import "FLEXHierarchyTableViewCell.h" -#import "FLEXObjectExplorerViewController.h" -#import "FLEXObjectExplorerFactory.h" -#import "FLEXResources.h" -#import "FLEXWindow.h" - -typedef NS_ENUM(NSUInteger, FLEXHierarchyScope) { - FLEXHierarchyScopeFullHierarchy, - FLEXHierarchyScopeViewsAtTap -}; - -@interface FLEXHierarchyTableViewController () - -@property (nonatomic) NSArray *allViews; -@property (nonatomic) NSMapTable *depthsForViews; -@property (nonatomic) NSArray *viewsAtTap; -@property (nonatomic) NSArray *displayedViews; -@property (nonatomic, readonly) BOOL showScopeBar; - -@end - -@implementation FLEXHierarchyTableViewController - -+ (instancetype)windows:(NSArray *)allWindows - viewsAtTap:(NSArray *)viewsAtTap - selectedView:(UIView *)selected { - NSParameterAssert(allWindows.count); - - NSArray *allViews = [self allViewsInHierarchy:allWindows]; - NSMapTable *depths = [self hierarchyDepthsForViews:allViews]; - return [[self alloc] initWithViews:allViews viewsAtTap:viewsAtTap selectedView:selected depths:depths]; -} - -- (instancetype)initWithViews:(NSArray *)allViews - viewsAtTap:(NSArray *)viewsAtTap - selectedView:(UIView *)selectedView - depths:(NSMapTable *)depthsForViews { - NSParameterAssert(allViews); - NSParameterAssert(depthsForViews.count == allViews.count); - - self = [super initWithStyle:UITableViewStylePlain]; - if (self) { - self.allViews = allViews; - self.depthsForViews = depthsForViews; - self.viewsAtTap = viewsAtTap; - self.selectedView = selectedView; - - self.title = @"View Hierarchy Tree"; - } - - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Preserve selection between presentations - self.clearsSelectionOnViewWillAppear = NO; - - // A little more breathing room - self.tableView.rowHeight = 50.0; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - // Separator inset clashes with persistent cell selection - [self.tableView setSeparatorInset:UIEdgeInsetsZero]; - - self.showsSearchBar = YES; - self.showSearchBarInitially = YES; - // Using pinSearchBar on this screen causes a weird visual - // thing on the next view controller that gets pushed. - // - // self.pinSearchBar = YES; - self.searchBarDebounceInterval = kFLEXDebounceInstant; - self.automaticallyShowsSearchBarCancelButton = NO; - if (self.showScopeBar) { - self.searchController.searchBar.showsScopeBar = YES; - self.searchController.searchBar.scopeButtonTitles = @[@"Full Hierarchy", @"Views at Tap"]; - self.selectedScope = FLEXHierarchyScopeViewsAtTap; - } - - [self updateDisplayedViews]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self disableToolbar]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - [self trySelectCellForSelectedView]; -} - - -#pragma mark - Hierarchy helpers - -+ (NSArray *)allViewsInHierarchy:(NSArray *)windows { - return [windows flex_flatmapped:^id(UIWindow *window, NSUInteger idx) { - if (![window isKindOfClass:[FLEXWindow class]]) { - return [self viewWithRecursiveSubviews:window]; - } - - return nil; - }]; -} - -+ (NSArray *)viewWithRecursiveSubviews:(UIView *)view { - NSMutableArray *subviews = [NSMutableArray arrayWithObject:view]; - for (UIView *subview in view.subviews) { - [subviews addObjectsFromArray:[self viewWithRecursiveSubviews:subview]]; - } - - return subviews; -} - -+ (NSMapTable *)hierarchyDepthsForViews:(NSArray *)views { - NSMapTable *depths = [NSMapTable strongToStrongObjectsMapTable]; - for (UIView *view in views) { - NSInteger depth = 0; - UIView *tryView = view; - while (tryView.superview) { - tryView = tryView.superview; - depth++; - } - depths[(id)view] = @(depth); - } - - return depths; -} - - -#pragma mark Selection and Filtering Helpers - -- (void)trySelectCellForSelectedView { - NSUInteger selectedViewIndex = [self.displayedViews indexOfObject:self.selectedView]; - if (selectedViewIndex != NSNotFound) { - UITableViewScrollPosition scrollPosition = UITableViewScrollPositionMiddle; - NSIndexPath *selectedViewIndexPath = [NSIndexPath indexPathForRow:selectedViewIndex inSection:0]; - [self.tableView selectRowAtIndexPath:selectedViewIndexPath animated:YES scrollPosition:scrollPosition]; - } -} - -- (void)updateDisplayedViews { - NSArray *candidateViews = nil; - if (self.showScopeBar) { - if (self.selectedScope == FLEXHierarchyScopeViewsAtTap) { - candidateViews = self.viewsAtTap; - } else if (self.selectedScope == FLEXHierarchyScopeFullHierarchy) { - candidateViews = self.allViews; - } - } else { - candidateViews = self.allViews; - } - - if (self.searchText.length) { - self.displayedViews = [candidateViews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIView *candidateView, NSDictionary *bindings) { - NSString *title = [FLEXUtility descriptionForView:candidateView includingFrame:NO]; - NSString *candidateViewPointerAddress = [NSString stringWithFormat:@"%p", candidateView]; - BOOL matchedViewPointerAddress = [candidateViewPointerAddress rangeOfString:self.searchText options:NSCaseInsensitiveSearch].location != NSNotFound; - BOOL matchedViewTitle = [title rangeOfString:self.searchText options:NSCaseInsensitiveSearch].location != NSNotFound; - return matchedViewPointerAddress || matchedViewTitle; - }]]; - } else { - self.displayedViews = candidateViews; - } - - [self.tableView reloadData]; -} - -- (void)setSelectedView:(UIView *)selectedView { - _selectedView = selectedView; - if (self.isViewLoaded) { - [self trySelectCellForSelectedView]; - } -} - - -#pragma mark - Search Bar / Scope Bar - -- (BOOL)showScopeBar { - return self.viewsAtTap.count > 0; -} - -- (void)updateSearchResults:(NSString *)newText { - [self updateDisplayedViews]; - - // If the search bar text field is active, don't scroll on selection because we may want - // to continue typing. Otherwise, scroll so that the selected cell is visible. - if (!self.searchController.searchBar.isFirstResponder) { - [self trySelectCellForSelectedView]; - } -} - - -#pragma mark - Table View Data Source - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.displayedViews.count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *CellIdentifier = @"Cell"; - FLEXHierarchyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (!cell) { - cell = [[FLEXHierarchyTableViewCell alloc] initWithReuseIdentifier:CellIdentifier]; - } - - UIView *view = self.displayedViews[indexPath.row]; - - cell.textLabel.text = [FLEXUtility descriptionForView:view includingFrame:NO]; - cell.detailTextLabel.text = [FLEXUtility detailDescriptionForView:view]; - cell.randomColorTag = [FLEXUtility consistentRandomColorForObject:view]; - cell.viewDepth = self.depthsForViews[view].integerValue; - cell.indicatedViewColor = view.backgroundColor; - - if (view.isHidden || view.alpha < 0.01) { - cell.textLabel.textColor = FLEXColor.deemphasizedTextColor; - cell.detailTextLabel.textColor = FLEXColor.deemphasizedTextColor; - } else { - cell.textLabel.textColor = FLEXColor.primaryTextColor; - cell.detailTextLabel.textColor = FLEXColor.primaryTextColor; - } - - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - _selectedView = self.displayedViews[indexPath.row]; // Don't scroll, avoid setter - if (self.didSelectRowAction) { - self.didSelectRowAction(_selectedView); - } -} - -- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - UIView *drillInView = self.displayedViews[indexPath.row]; - FLEXObjectExplorerViewController *viewExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:drillInView]; - [self.navigationController pushViewController:viewExplorer animated:YES]; -} - -@end diff --git a/Tweaks/PSHeader b/Tweaks/PSHeader new file mode 160000 index 0000000..0d8d658 --- /dev/null +++ b/Tweaks/PSHeader @@ -0,0 +1 @@ +Subproject commit 0d8d65844256441e7e9b8f6010eef57c6a5fe190 diff --git a/Tweaks/PSHeader/.gitignore b/Tweaks/PSHeader/.gitignore deleted file mode 100644 index e43b0f9..0000000 --- a/Tweaks/PSHeader/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store diff --git a/Tweaks/PSHeader/CameraApp/AVCaptureDeviceFormat+CameraUI.h b/Tweaks/PSHeader/CameraApp/AVCaptureDeviceFormat+CameraUI.h deleted file mode 100644 index 2135a8e..0000000 --- a/Tweaks/PSHeader/CameraApp/AVCaptureDeviceFormat+CameraUI.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface AVCaptureDeviceFormat (CameraUI) - -- (BOOL)cam_supportsVideoConfiguration:(NSInteger)videoConfiguration; - -@end diff --git a/Tweaks/PSHeader/CameraApp/AVCaptureSession+CAMCaptureEngine.h b/Tweaks/PSHeader/CameraApp/AVCaptureSession+CAMCaptureEngine.h deleted file mode 100644 index e9b8abd..0000000 --- a/Tweaks/PSHeader/CameraApp/AVCaptureSession+CAMCaptureEngine.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface AVCaptureSession (CAMCaptureEngine) - -- (void)cam_ensureInputs:(NSArray *)inputs; -- (void)cam_removeInputs:(NSArray *)inputs; - -@end - diff --git a/Tweaks/PSHeader/CameraApp/CAMApplicationSpec.h b/Tweaks/PSHeader/CameraApp/CAMApplicationSpec.h deleted file mode 100644 index b6de71e..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMApplicationSpec.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "CAMCameraSpec.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMApplicationSpec : CAMCameraSpec - -+ (instancetype)specForPhone; -+ (instancetype)specForPad; - -@property (readonly) NSInteger modeDialOrientation; -@property (readonly) NSInteger bottomBarOrientation; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMApplicationViewController.h b/Tweaks/PSHeader/CameraApp/CAMApplicationViewController.h deleted file mode 100644 index 5574b3a..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMApplicationViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "CAMCameraViewController.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMApplicationViewController : CAMCameraViewController -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMAvalancheCaptureService.h b/Tweaks/PSHeader/CameraApp/CAMAvalancheCaptureService.h deleted file mode 100644 index 273689f..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMAvalancheCaptureService.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "CAMAvalancheSession.h" - -NS_DEPRECATED_IOS(8_0, 8_4) -@interface CAMAvalancheCaptureService : NSObject - -- (CAMAvalancheSession *)_activeAvalancheSession; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMAvalancheSession.h b/Tweaks/PSHeader/CameraApp/CAMAvalancheSession.h deleted file mode 100644 index 6473815..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMAvalancheSession.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_DEPRECATED_IOS(7_0, 8_4) -@interface CAMAvalancheSession : NSObject - -@property (readonly, assign, nonatomic) NSUInteger numberOfPhotos; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMBottomBar.h b/Tweaks/PSHeader/CameraApp/CAMBottomBar.h deleted file mode 100644 index 912712e..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMBottomBar.h +++ /dev/null @@ -1,44 +0,0 @@ -#import "CAMFilterButton.h" -#import "CAMFlashButton.h" -#import "CAMFlipButton.h" -#import "CAMHDRButton.h" -#import "CAMTimerButton.h" -#import "CAMShutterButton.h" -#import "CAMImageWell.h" -#import "CAMModeDial.h" -#import "CAMSlalomIndicatorView.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMBottomBar : UIView -@property (readonly, assign, nonatomic) UIView *backgroundView; -@property (retain, nonatomic) CAMFilterButton *filterButton; -@property (retain, nonatomic) CAMFlashButton *flashButton; -@property (retain, nonatomic) CAMFlipButton *flipButton; -@property (retain, nonatomic) CAMHDRButton *HDRButton; -@property (retain, nonatomic) CAMTimerButton *timerButton API_AVAILABLE(ios(8.0)); -@property (retain, nonatomic) CAMShutterButton *shutterButton; -@property (retain, nonatomic) CAMShutterButton *stillDuringVideoButton; -@property (retain, nonatomic) CAMImageWell *imageWell; -@property (retain, nonatomic) CAMModeDial *modeDial; -@property (retain, nonatomic) CAMSlalomIndicatorView *slalomIndicatorView; -@property (assign) NSInteger layoutStyle; - -+ (BOOL)wantsVerticalBarForTraitCollection:(UITraitCollection *)traitCollection API_AVAILABLE(ios(8.0)); -+ (BOOL)wantsVerticalBarForLayoutStyle:(NSInteger)style API_AVAILABLE(ios(10.0)); - -- (CGRect)alignmentRectForFrame:(CGRect)frame; - -- (NSObject *)delegate; -- (UIButton *)_expandedMenuButton; -- (UIView *)backgroundView; -- (UIView *)_shutterButtomBottomLayoutSpacer; -- (UIView *)_filterButtonBottomLayoutSpacer; - -- (void)_setupHorizontalFilterButtonConstraints; -- (void)_setupVerticalFilterButtonConstraints; - -- (BOOL)_isTimerButtonExpanded API_AVAILABLE(ios(8.0)); -- (BOOL)shouldHideFlashButtonForMode:(NSInteger)mode device:(NSInteger)device; -- (BOOL)shouldHideFlipButtonForMode:(NSInteger)mode device:(NSInteger)device; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMButtonLabel.h b/Tweaks/PSHeader/CameraApp/CAMButtonLabel.h deleted file mode 100644 index fbbe90a..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMButtonLabel.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -API_AVAILABLE(ios(7.0)) -@interface CAMButtonLabel : UILabel - -@property BOOL useLegibilityView; -@property BOOL wantsLegibilityShadow; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCameraSpec.h b/Tweaks/PSHeader/CameraApp/CAMCameraSpec.h deleted file mode 100644 index 73d176e..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCameraSpec.h +++ /dev/null @@ -1,8 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMCameraSpec : NSObject - -+ (instancetype)specForCurrentPlatform; -+ (instancetype)specForPhone; -+ (instancetype)specForPad; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCameraView.h b/Tweaks/PSHeader/CameraApp/CAMCameraView.h deleted file mode 100644 index 8d221de..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCameraView.h +++ /dev/null @@ -1,120 +0,0 @@ -#import "CAMModeDial.h" -#import "CAMTopBar.h" -#import "CAMBottomBar.h" -#import "CAMFlashButton.h" -#import "CAMFlipButton.h" -#import "CAMTimerButton.h" -#import "CAMFilterButton.h" -#import "CAMHDRButton.h" -#import "CAMElapsedTimeView.h" -#import "CAMHDRBadge.h" -#import "CAMAvalancheSession.h" -#import "CAMApplicationSpec.h" -#import "CAMTorchPatternController.h" -#import "CAMPreviewView.h" -#import "CAMZoomSlider.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMCameraView : UIView - -@property (assign, nonatomic) NSInteger videoFlashMode; -@property (assign, nonatomic) NSInteger flashMode; -@property (assign, nonatomic) NSInteger lastSelectedPhotoFlashMode; -@property (assign, nonatomic) NSInteger cameraDevice; -@property (assign, nonatomic) NSInteger cameraMode; -@property (getter=_numFilterSelectionsBeforeCapture, setter = _setNumFilterSelectionsBeforeCapture:) NSUInteger _numFilterSelectionsBeforeCapture; - -@property (assign, nonatomic, getter=isTallScreen) BOOL tallScreen; -@property (getter=_isFlipping, setter = _setFlipping:) BOOL _flipping; -@property (readonly, assign, nonatomic) BOOL isCameraReady; -@property (assign, nonatomic) BOOL HDRIsOn; - -@property (readonly, assign, nonatomic) CGRect unzoomedPreviewFrame; - -@property (readonly, assign, nonatomic) CAMModeDial *_modeDial; -@property (readonly, assign, nonatomic) CAMZoomSlider *_zoomSlider; -@property (readonly, assign, nonatomic) CAMTopBar *_topBar; -@property (readonly, assign, nonatomic) CAMBottomBar *_bottomBar; -@property (readonly, assign, nonatomic) CAMFlashButton *_flashButton; -@property (readonly, assign, nonatomic) CAMFlipButton *_flipButton; -@property (readonly, assign, nonatomic) CAMTimerButton *_timerButton; -@property (readonly, assign, nonatomic) CAMFilterButton *_filterButton; -@property (readonly, assign, nonatomic) CAMHDRButton *_HDRButton; -@property (readonly, assign, nonatomic) CAMHDRBadge *_HDRBadge; -@property (readonly, assign, nonatomic) CAMShutterButton *_shutterButton; -@property (readonly, assign, nonatomic) CAMShutterButton *_stillDuringVideoButton; -@property (readonly, assign, nonatomic) CAMElapsedTimeView *_elapsedTimeView; -@property (readonly, assign, nonatomic) CAMAvalancheSession *_avalancheSession NS_DEPRECATED_IOS(7_0, 8_4); -@property (readonly, assign, nonatomic) CAMTorchPatternController *_torchPatternController; - -- (BOOL)_avalancheCaptureInProgress; -- (BOOL)_didEverMoveToWindow; -- (BOOL)_isCapturing; -- (BOOL)_isHidingBadgesForFilterUI; -- (BOOL)_isStillImageMode:(NSInteger)mode; -- (BOOL)_isVideoMode:(NSInteger)mode; -- (BOOL)_performingDelayedCapture; -- (BOOL)_performingTimedCapture; -- (BOOL)_shouldEnableFlashButton; -- (BOOL)_shouldEnableModeDial; -- (BOOL)_shouldHideFilterButtonForMode:(NSInteger)mode; -- (BOOL)_shouldHideFlashButtonForMode:(NSInteger)mode; -- (BOOL)_shouldHideHDRBadgeForMode:(NSInteger)mode; -- (BOOL)_shouldHideModeDialForMode:(NSInteger)mode; -- (BOOL)_shouldHideTopBarForMode:(NSInteger)mode; -- (BOOL)_shouldUseAvalancheForDelayedCapture; -- (BOOL)bottomBarShouldHideFilterButton:(id)sender; -- (BOOL)hasInFlightCaptures; -- (BOOL)HDRIsOn; - -- (CAMApplicationSpec *)spec; -- (CAMPreviewView *)previewView; - -- (CGRect)_bottomBarFrame; - -- (NSInteger)_currentFlashMode; -- (NSInteger)_currentTimerDuration; -- (NSInteger)_glyphOrientationForCameraOrientation:(NSInteger)cameraOrientation; -- (NSInteger)_HDRMode; -- (NSInteger)_photoFlashMode; -- (NSInteger)_remainingDelayedCaptureTicks; -- (NSString *)modeDial:(CAMModeDial *)modeDial titleForItemAtIndex:(NSUInteger)index; - -- (void)_addZoomAnimationDisplayLinkWithSelector:(SEL)selector; -- (void)_beginZooming; -- (void)_captureStillDuringVideo; -- (void)_clearFocusViews; -- (void)_collapseExpandedButtonsAnimated:(BOOL)animated; -- (void)_createHDRBadgeIfNecessary; -- (void)_createZoomSliderIfNecessary; -- (void)_endZooming; -- (void)_handleVolumeUpEvents:(NSUInteger)events; -- (void)_layoutTopBarForOrientation:(NSInteger)orientation; -- (void)_rotateCameraControlsAndInterface; -- (void)_setBottomBarEnabled:(BOOL)enabled; -- (void)_setFlashMode:(NSInteger)mode; -- (void)_setOverlayControlsEnabled:(BOOL)enabled; -- (void)_setShouldShowFocus:(BOOL)focus; -- (void)_setSwipeToModeSwitchEnabled:(BOOL)enabled; -- (void)_setZoomFactor:(CGFloat)factor; -- (void)_shutterButtonClicked; -- (void)_startDelayedCapture; -- (void)_switchFromCameraModeAtIndex:(NSUInteger)fromIndex toCameraModeAtIndex:(NSUInteger)toIndex; -- (void)_teardownAvalancheCaptureTimer; -- (void)_updateForFocusCapabilities; -- (void)_updateHDRBadge; -- (void)_updatePreviewWellImage:(UIImage *)image; -- (void)_updateTopBarStyleForDeviceOrientation:(NSInteger)orientation; - -- (void)cameraShutterReleased:(id)arg1; -- (void)flashButtonDidChangeFlashMode:(id)arg1; -- (void)flashButtonModeDidChange:(NSInteger)mode; -- (void)hideStaticClosedIris; -- (void)pausePreview; -- (void)resumePreview; -- (void)setCameraButtonsEnabled:(BOOL)enabled; -- (void)showZoomSlider; -- (void)takePicture; -- (void)takePictureOpenIrisAnimationFinished; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCameraViewController.h b/Tweaks/PSHeader/CameraApp/CAMCameraViewController.h deleted file mode 100644 index 56ed69e..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCameraViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMCameraViewController : UIViewController -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureCapabilities.h b/Tweaks/PSHeader/CameraApp/CAMCaptureCapabilities.h deleted file mode 100644 index 808b459..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureCapabilities.h +++ /dev/null @@ -1,16 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMCaptureCapabilities : NSObject - -+ (instancetype)capabilities; - -- (BOOL)isSupportedVideoConfiguration:(NSInteger)videoConfiguration forMode:(NSInteger)mode device:(NSInteger)device API_AVAILABLE(ios(10.0)); -- (BOOL)isSupportedVideoModeConfiguration:(NSInteger)videoConfiguration forDevice:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)isSupportedSlomoModeConfiguration:(NSInteger)videoConfiguration forDevice:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)isFlashSupportedForDevice:(NSInteger)device; -- (BOOL)isTorchPatternSupportedForDevice:(NSInteger)device; -- (BOOL)isBackCameraSupported; -- (BOOL)isFrontCameraSupported; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureConfiguration.h b/Tweaks/PSHeader/CameraApp/CAMCaptureConfiguration.h deleted file mode 100644 index 7ddb306..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureConfiguration.h +++ /dev/null @@ -1,10 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(10_0) -@interface CAMCaptureConfiguration : NSObject - -- (NSInteger)videoConfiguration; -- (NSInteger)audioConfiguration; -- (NSInteger)previewConfiguration; -- (NSInteger)mode; -- (NSInteger)device; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureController.h b/Tweaks/PSHeader/CameraApp/CAMCaptureController.h deleted file mode 100644 index 4c402ba..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureController.h +++ /dev/null @@ -1,63 +0,0 @@ -#import "CAMCameraView.h" -#import "CAMAvalancheCaptureService.h" -#import "CAMEffectsRenderer.h" -#import - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMCaptureController : NSObject - -@property (assign, nonatomic) AVCaptureDevice *currentDevice; -@property (assign, nonatomic) AVCaptureOutput *currentOutput; -@property (retain, nonatomic) AVCaptureVideoPreviewLayer *previewLayer; -@property (readonly, assign, nonatomic) AVCaptureSession *currentSession; -@property (assign, nonatomic) NSInteger cameraDevice; -@property (assign, nonatomic) NSInteger cameraMode; -@property (assign, nonatomic) NSInteger flashMode; -@property (readonly, assign, nonatomic) NSInteger cameraOrientation; -@property (assign, nonatomic, getter=isHDREnabled) BOOL HDREnabled; -@property (getter=_isPreviewPaused, setter = _setPreviewPaused:) BOOL _previewPaused; -@property (retain, nonatomic) CAMEffectsRenderer *effectsRenderer; -@property (assign, nonatomic) CGFloat videoZoomFactor; -@property BOOL performingAvalancheCapture; - -+ (BOOL)isStillImageMode:(NSInteger)mode; -+ (BOOL)isVideoMode:(NSInteger)mode; - -- (BOOL)_isSessionReady; -- (BOOL)_isVideoMode:(NSInteger)mode; -- (BOOL)_lockCurrentDeviceForConfiguration; - -- (BOOL)canCaptureVideo; -- (BOOL)flashWillFire; -- (BOOL)hasFrontCamera; -- (BOOL)hasRearCamera; -- (BOOL)isCameraApp; -- (BOOL)isCapturingPanorama; -- (BOOL)isCapturingTimelapse; -- (BOOL)isCapturingVideo; -- (BOOL)isChangingModes; -- (BOOL)isFocusLockSupported; -- (BOOL)isReady; - -- (CAMAvalancheCaptureService *)_avalancheCaptureService NS_DEPRECATED_IOS(7_0, 8_4); -- (CAMCameraView *)delegate; -- (NSMutableArray *)supportedCameraModes; - -- (CGFloat)maximumZoomFactorForDevice:(AVCaptureDevice *)device; -- (double)mogulFrameRate; - -- (NSUInteger)_activeFilterIndex; -- (NSUInteger)effectFilterIndexForMode:(NSInteger)mode; - -- (void)_lockFocus:(BOOL)focus lockExposure:(BOOL)exposure lockWhiteBalance:(BOOL)whiteBalance; -- (void)_setFlashMode:(NSInteger)mode force:(BOOL)force; -- (void)_suggestedHDRChanged; -- (void)_unlockCurrentDeviceForConfiguration; - -- (void)pausePreview; -- (void)resumePreview; -- (void)setFaceDetectionEnabled:(BOOL)enabled forceDisableImageProcessing:(BOOL)disableIP; -- (void)setFaceDetectionEnabled:(BOOL)enabled; -- (void)setFocusDisabled:(BOOL)disabled; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureEngine.h b/Tweaks/PSHeader/CameraApp/CAMCaptureEngine.h deleted file mode 100644 index 94171af..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureEngine.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "CAMCaptureMovieFileOutput.h" -#import - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMCaptureEngine : NSObject - -@property (retain, nonatomic) AVCaptureDevice *cameraDevice; -@property (retain, nonatomic) AVCaptureSession *_captureSession; - -- (CAMCaptureMovieFileOutput *)movieFileOutput; -- (AVCaptureDeviceInput *)audioCaptureDeviceInput; - -- (void)_handleSessionDidStartRunning:(id)arg1; - -@end \ No newline at end of file diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureGraphConfiguration.h b/Tweaks/PSHeader/CameraApp/CAMCaptureGraphConfiguration.h deleted file mode 100644 index a32a24f..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureGraphConfiguration.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "CAMCaptureConfiguration.h" - -NS_CLASS_AVAILABLE_IOS(10_0) -@interface CAMCaptureGraphConfiguration : NSObject - -+ (instancetype)captureGraphConfigurationUsingConfiguration:(CAMCaptureConfiguration *)configuration; - -- (NSInteger)flashMode; -- (NSInteger)torchMode; -- (NSInteger)HDRMode; -- (NSInteger)timerDuration; -- (NSInteger)irisMode; -- (NSInteger)photoModeEffectFilterType; -- (NSInteger)squareModeEffectFilterType; -- (NSInteger)mode; -- (NSInteger)device; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureModeWithOptions.h b/Tweaks/PSHeader/CameraApp/CAMCaptureModeWithOptions.h deleted file mode 100644 index 94ea943..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureModeWithOptions.h +++ /dev/null @@ -1,6 +0,0 @@ -typedef struct { - NSInteger mode; - NSInteger videoConfiguration; - NSInteger previewConfiguration; - NSInteger audioConfiguration; -} CAMCaptureModeWithOptions; diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureMovieFileOutput.h b/Tweaks/PSHeader/CameraApp/CAMCaptureMovieFileOutput.h deleted file mode 100644 index 8e4229f..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureMovieFileOutput.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -API_AVAILABLE(ios(9.0)) -@interface CAMCaptureMovieFileOutput : AVCaptureMovieFileOutput -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMCaptureStillImageOutput.h b/Tweaks/PSHeader/CameraApp/CAMCaptureStillImageOutput.h deleted file mode 100644 index 396ceee..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMCaptureStillImageOutput.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(9_0) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -@interface CAMCaptureStillImageOutput : AVCaptureStillImageOutput -@end -#pragma clang diagnostic pop diff --git a/Tweaks/PSHeader/CameraApp/CAMClosedViewfinderController.h b/Tweaks/PSHeader/CameraApp/CAMClosedViewfinderController.h deleted file mode 100644 index 7598b93..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMClosedViewfinderController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMClosedViewfinderController : NSObject - -- (void)addClosedViewfinderReason:(NSInteger)reason; -- (void)removeClosedViewfinderReason:(NSInteger)reason; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMControlStatusIndicator.h b/Tweaks/PSHeader/CameraApp/CAMControlStatusIndicator.h deleted file mode 100644 index 5e65bb0..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMControlStatusIndicator.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface CAMControlStatusIndicator : UIControl -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMEffectFilterManager.h b/Tweaks/PSHeader/CameraApp/CAMEffectFilterManager.h deleted file mode 100644 index 8b21b76..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMEffectFilterManager.h +++ /dev/null @@ -1,17 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMEffectFilterManager : NSObject - -+ (instancetype)sharedInstance; - -+ (NSString *)displayNameForType:(NSInteger)type; - -- (NSUInteger)blackAndWhiteFilterStartIndex; -- (NSUInteger)filterCount; - -- (CIFilter *)filterForIndex:(NSUInteger)index; - -- (void)_addEffectNamed:(NSString *)name aggdName:(NSString *)aggdName filter:(CIFilter *)filter; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMEffectSelectionViewController.h b/Tweaks/PSHeader/CameraApp/CAMEffectSelectionViewController.h deleted file mode 100644 index 00819cb..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMEffectSelectionViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_DEPRECATED_IOS(7_0, 8_4) -@interface CAMEffectSelectionViewController : UIViewController -- (void)_setSelectedIndexPath:(NSIndexPath *)indexPath; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMEffectsFullsizeView.h b/Tweaks/PSHeader/CameraApp/CAMEffectsFullsizeView.h deleted file mode 100644 index f7ee467..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMEffectsFullsizeView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "CAMGLView.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMEffectsFullsizeView : CAMGLView -@property NSInteger filterType; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMEffectsGridView.h b/Tweaks/PSHeader/CameraApp/CAMEffectsGridView.h deleted file mode 100644 index 1fb1b78..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMEffectsGridView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "CAMGLView.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMEffectsGridView : CAMGLView -- (NSUInteger)_cellCount; -- (NSUInteger)_filterIndexForGridIndex:(NSUInteger)index; -- (BOOL)isBlackAndWhite; -- (BOOL)isSquare; -- (CGRect)rectForFilterType:(NSInteger)type; -- (CGRect)_squareCropFromRect:(CGRect)rect; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMEffectsRenderer.h b/Tweaks/PSHeader/CameraApp/CAMEffectsRenderer.h deleted file mode 100644 index fa7054f..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMEffectsRenderer.h +++ /dev/null @@ -1,11 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMEffectsRenderer : NSObject - -@property (assign, nonatomic, getter=isShowingGrid) BOOL showGrid; - -- (void)setShowGrid:(BOOL)show animated:(BOOL)animated; -- (void)_previewStarted:(id)arg1; -- (void)_deviceStarted:(id)arg1; -- (void)_setPreviewStartedNotificationNeeded:(BOOL)arg1; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMElapsedTimeView.h b/Tweaks/PSHeader/CameraApp/CAMElapsedTimeView.h deleted file mode 100644 index 90bb98c..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMElapsedTimeView.h +++ /dev/null @@ -1,17 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMElapsedTimeView : UIView -@property (readonly) UILabel *_timeLabel; -@property (readonly) UIImageView *_recordingImageView; -@property (readonly) NSTimer *_updateTimer; -@property (readonly) NSDate *_startTime; -- (void)_beginRecordingAnimation; -- (void)_endRecordingAnimation; -- (void)startTimer; -- (void)endTimer; -- (void)resetTimer; -- (void)_update:(NSTimer *)timer; -- (BOOL)usingBadgeAppearance; -- (UIColor *)_backgroundRedColor; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMExpandableMenuButton.h b/Tweaks/PSHeader/CameraApp/CAMExpandableMenuButton.h deleted file mode 100644 index 71bc3d8..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMExpandableMenuButton.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMExpandableMenuButton : UIView -@property NSUInteger selectedIndex; -+ (double)expansionDuration; -- (NSArray *)_menuItems; -- (void)setHighlighted:(BOOL)highlighted forIndex:(NSUInteger)index; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMFilterButton.h b/Tweaks/PSHeader/CameraApp/CAMFilterButton.h deleted file mode 100644 index 094c22c..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMFilterButton.h +++ /dev/null @@ -1,19 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMFilterButton : UIButton - -@property (readonly) UIImageView *_circlesImageView; -@property (getter=isOn) BOOL on; -@property UIEdgeInsets tappableEdgeInsets; - -+ (instancetype)filterButton; - -- (void)_commonCAMFilterButtonInitialization; - -- (UIImage *)_filterImage; -- (UIImage *)_filterOnImage; - -- (CGFloat)_selectedIndicatorAlpha; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMFlashButton.h b/Tweaks/PSHeader/CameraApp/CAMFlashButton.h deleted file mode 100644 index a91225a..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMFlashButton.h +++ /dev/null @@ -1,31 +0,0 @@ -#import "CAMButtonLabel.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMFlashButton : UIButton - -@property (assign, nonatomic) NSInteger orientation; -@property NSInteger flashMode; - -@property BOOL allowsAutomaticFlash; -@property (getter=isUnavailable) BOOL unavailable; -@property (assign, nonatomic, getter=isAutoHidden) BOOL autoHidden; - -@property (readonly) UIImageView *_glyphView; -@property (readonly, assign, nonatomic) UIImageView *_flashIconView; -@property (readonly, assign, nonatomic) UIImageView *_iconView; -@property (readonly, assign, nonatomic) CAMButtonLabel *_offLabel; -@property (readonly, assign, nonatomic) CAMButtonLabel *_onLabel; -@property (readonly, assign, nonatomic) CAMButtonLabel *_autoLabel; - -@property (assign, nonatomic) NSUInteger selectedIndex; - -- (UIView *)delegate; - -- (BOOL)isExpanded; - -- (void)collapseMenuAnimated:(BOOL)animated; -- (void)expandMenuAnimated:(BOOL)animated; - -- (NSUInteger)indexForMode:(NSInteger)mode; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMFlipButton.h b/Tweaks/PSHeader/CameraApp/CAMFlipButton.h deleted file mode 100644 index e544c86..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMFlipButton.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMFlipButton : UIButton - -- (UIImage *)_flipImage; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMFramerateIndicatorView.h b/Tweaks/PSHeader/CameraApp/CAMFramerateIndicatorView.h deleted file mode 100644 index 3eadfe6..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMFramerateIndicatorView.h +++ /dev/null @@ -1,18 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMFramerateIndicatorView : UIView - -@property NSInteger style; -- (NSInteger)_framesPerSecond; - -- (NSString *)_labelText; -- (UIImageView *)_borderImageView; - -- (UILabel *)_bottomLabel; -- (UILabel *)_topLabel; - -- (void)_updateForAppearanceChange; -- (void)_updateLabels; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMGLView.h b/Tweaks/PSHeader/CameraApp/CAMGLView.h deleted file mode 100644 index dc0fe06..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMGLView.h +++ /dev/null @@ -1,9 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMGLView : UIView - -@property CGSize fixedSize; - -- (CGFloat)drawableHeight; -- (CGFloat)drawableWidth; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMHDRBadge.h b/Tweaks/PSHeader/CameraApp/CAMHDRBadge.h deleted file mode 100644 index 3d3f25c..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMHDRBadge.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMHDRBadge : UIButton -@end - diff --git a/Tweaks/PSHeader/CameraApp/CAMHDRButton.h b/Tweaks/PSHeader/CameraApp/CAMHDRButton.h deleted file mode 100644 index 0d4b4ca..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMHDRButton.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "CAMButtonLabel.h" - -API_AVAILABLE(ios(7.0)) -@interface CAMHDRButton : UIButton -@property (readonly, nonatomic) CAMButtonLabel *_onLabel; -@property (readonly, nonatomic) CAMButtonLabel *_offLabel; -@property (readonly, nonatomic) CAMButtonLabel *_hdrLabel; -@property (nonatomic) NSInteger orientation; -@property (nonatomic, getter=isOn) BOOL on; -- (void)_updateFromOrientationChangeAnimated:(BOOL)animated; -- (void)_updateFrameFromOrientation; -- (CGAffineTransform)_transformForOrientation:(NSInteger)orientation; -- (void)_updateLabelsFromOrientation; -- (void)_updateFromOnState; -- (void)setOrientation:(NSInteger)orientation animated:(BOOL)animated; -- (void)_layoutForLandscapeOrientation; -- (void)_layoutForPortraitOrientation; -- (void)_commonCAMHDRButtonInitialization; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMImageWell.h b/Tweaks/PSHeader/CameraApp/CAMImageWell.h deleted file mode 100644 index f14899f..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMImageWell.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMImageWell : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMLegibilityViewHelper.h b/Tweaks/PSHeader/CameraApp/CAMLegibilityViewHelper.h deleted file mode 100644 index e5a3d37..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMLegibilityViewHelper.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMLegibilityViewHelper : NSObject -+ (UIImage *)_imageFromLabel:(UILabel *)label sizeToFit:(BOOL)fit; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMModeDial.h b/Tweaks/PSHeader/CameraApp/CAMModeDial.h deleted file mode 100644 index 702e6a7..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMModeDial.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "CAMModeDialItem.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMModeDial : UIView - -@property (retain, nonatomic) NSMutableArray * _items; -@property (retain, nonatomic) UIView *_itemsContainerView; - -@property (assign) NSUInteger selectedIndex; -@property (assign) NSInteger orientation; - -+ (BOOL)wantsVerticalModeDialForTraitCollection:(UITraitCollection *)traitCollection NS_DEPRECATED_IOS(8_0, 9_3); -+ (BOOL)wantsVerticalModeDialForLayoutStyle:(NSInteger)style NS_AVAILABLE_IOS(10_0); - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMModeDialItem.h b/Tweaks/PSHeader/CameraApp/CAMModeDialItem.h deleted file mode 100644 index aeca307..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMModeDialItem.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMModeDialItem : UIView -@property (retain, nonatomic) NSString *title; -- (BOOL)isSelected; -- (CAShapeLayer *)_scalableTextLayer; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPadApplicationSpec.h b/Tweaks/PSHeader/CameraApp/CAMPadApplicationSpec.h deleted file mode 100644 index 205751c..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPadApplicationSpec.h +++ /dev/null @@ -1,5 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_0) -#import "CAMApplicationSpec.h" - -@interface CAMPadApplicationSpec : CAMApplicationSpec -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPanoramaArrowView.h b/Tweaks/PSHeader/CameraApp/CAMPanoramaArrowView.h deleted file mode 100644 index 9dec832..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPanoramaArrowView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMPanoramaArrowView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPanoramaLabel.h b/Tweaks/PSHeader/CameraApp/CAMPanoramaLabel.h deleted file mode 100644 index 9c16551..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPanoramaLabel.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMPanoramaLabel : UILabel -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPanoramaLevelView.h b/Tweaks/PSHeader/CameraApp/CAMPanoramaLevelView.h deleted file mode 100644 index fd4fd70..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPanoramaLevelView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMPanoramaLevelView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPanoramaView.h b/Tweaks/PSHeader/CameraApp/CAMPanoramaView.h deleted file mode 100644 index d52e41d..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPanoramaView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "PanoramaViewDelegate.h" - -@interface CAMPanoramaView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPanoramaViewController.h b/Tweaks/PSHeader/CameraApp/CAMPanoramaViewController.h deleted file mode 100644 index 834c2cb..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPanoramaViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMPanoramaViewController : UIViewController -- (void)_handleDirectionChange:(id)arg1; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPhoneApplicationSpec.h b/Tweaks/PSHeader/CameraApp/CAMPhoneApplicationSpec.h deleted file mode 100644 index 44cf41c..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPhoneApplicationSpec.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "CAMApplicationSpec.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMPhoneApplicationSpec : CAMApplicationSpec -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPreviewView.h b/Tweaks/PSHeader/CameraApp/CAMPreviewView.h deleted file mode 100644 index b91ce6b..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPreviewView.h +++ /dev/null @@ -1,12 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMPreviewView : UIView - -@property (retain, nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer; - -@property CGFloat dimmingStrength; - -- (void)setDimmingStrength:(CGFloat)strength duration:(NSTimeInterval)duration; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMPreviewViewController.h b/Tweaks/PSHeader/CameraApp/CAMPreviewViewController.h deleted file mode 100644 index d1209b1..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMPreviewViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "CAMEffectsRenderer.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMPreviewViewController : UIViewController - -- (CAMEffectsRenderer *)effectsRenderer; - -- (BOOL)_userLockedFocusAndExposure; - -- (void)updateIndicatorVisibilityAnimated:(BOOL)animated; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMShutterButton.h b/Tweaks/PSHeader/CameraApp/CAMShutterButton.h deleted file mode 100644 index 889a6bd..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMShutterButton.h +++ /dev/null @@ -1,21 +0,0 @@ -#import "CAMShutterButtonSpec.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMShutterButton : UIButton -+ (instancetype)shutterButton; -+ (instancetype)smallShutterButton; -+ (instancetype)tinyShutterButton NS_AVAILABLE_IOS(8_0); - -@property (getter=isPulsing) BOOL pulsing; -@property (getter=isSpinning) BOOL spinning; - -@property NSInteger mode; - -- (UIColor *)_colorForMode:(NSInteger)mode; -- (UIView *)_innerView; -- (UIView *)_outerView; - -- (void)_updateOuterAndInnerLayers; -- (void)_setSpec:(CAMShutterButtonSpec)spec; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMShutterButtonSpec.h b/Tweaks/PSHeader/CameraApp/CAMShutterButtonSpec.h deleted file mode 100644 index b448a28..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMShutterButtonSpec.h +++ /dev/null @@ -1,6 +0,0 @@ -typedef struct CAMShutterButtonSpec { - CGFloat outerRingDiameter; - CGFloat outerRingStrokeWidth; - CGFloat stopSquareSideLength; - CGFloat stopSquareCornerRadius; -} CAMShutterButtonSpec; diff --git a/Tweaks/PSHeader/CameraApp/CAMSlalomIndicatorView.h b/Tweaks/PSHeader/CameraApp/CAMSlalomIndicatorView.h deleted file mode 100644 index effcf87..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMSlalomIndicatorView.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMSlalomIndicatorView : UIView -- (void)setFramesPerSecond:(NSInteger)sec; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMStillImageCaptureResponse.h b/Tweaks/PSHeader/CameraApp/CAMStillImageCaptureResponse.h deleted file mode 100644 index 4726cc9..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMStillImageCaptureResponse.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMStillImageCaptureResponse : NSObject -- (UIImage *)thumbnailImage; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMTimerButton.h b/Tweaks/PSHeader/CameraApp/CAMTimerButton.h deleted file mode 100644 index ef06315..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMTimerButton.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "CAMExpandableMenuButton.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMTimerButton : CAMExpandableMenuButton - -@property NSInteger duration; - -- (NSString *)titleForMenuItemAtIndex:(NSUInteger)index; - -- (NSInteger)numberOfMenuItems; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMTopBar.h b/Tweaks/PSHeader/CameraApp/CAMTopBar.h deleted file mode 100644 index c7fafeb..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMTopBar.h +++ /dev/null @@ -1,43 +0,0 @@ -#import "CAMFilterButton.h" -#import "CAMHDRButton.h" -#import "CAMFlashButton.h" -#import "CAMTimerButton.h" -#import "CAMFlipButton.h" -#import "CAMElapsedTimeView.h" -#import "CAMCaptureGraphConfiguration.h" - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface CAMTopBar : UIView -@property (readonly, assign, nonatomic) UIView *_backgroundView; -@property (retain, nonatomic) CAMFilterButton *filterButton; -@property (retain, nonatomic) CAMHDRButton *HDRButton; -@property (retain, nonatomic) CAMFlashButton *flashButton; -@property (retain, nonatomic) CAMTimerButton *timerButton NS_AVAILABLE_IOS(8_0); -@property (retain, nonatomic) CAMFlipButton *flipButton; -@property (retain, nonatomic) CAMElapsedTimeView *elapsedTimeView; -@property (readonly, assign, nonatomic, getter=isFloating) BOOL floating; -@property (assign, nonatomic) NSInteger orientation; -@property (assign, nonatomic) NSInteger style; -@property (assign, nonatomic) NSInteger backgroundStyle; - -- (UIButton *)_expandedMenuButton NS_AVAILABLE_IOS(8_0); -- (NSObject *)delegate; - -- (NSMutableArray *)_allowedControlsForVideoMode NS_AVAILABLE_IOS(8_0); -- (NSMutableArray *)_allowedControlsForStillImageMode NS_AVAILABLE_IOS(8_0); -- (NSMutableArray *)_allowedControlsForPanoramaMode NS_AVAILABLE_IOS(8_0); -- (NSMutableArray *)_allowedControlsForTimelapseMode NS_AVAILABLE_IOS(8_0); - -- (BOOL)_isFlashButtonExpanded; -- (BOOL)_shouldHideFlashButton; -- (BOOL)shouldHideFlipButtonForMode:(NSInteger)mode device:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)shouldHideFlashButtonForMode:(NSInteger)mode device:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)shouldHideFlashButtonForGraphConfiguration:(CAMCaptureGraphConfiguration *)configuration NS_AVAILABLE_IOS(10_0); -- (BOOL)shouldHideFramerateIndicatorForGraphConfiguration:(CAMCaptureGraphConfiguration *)configuration NS_AVAILABLE_IOS(10_0); - -- (void)setBackgroundStyle:(NSInteger)style animated:(BOOL)animated; -- (void)setStyle:(NSInteger)style animated:(BOOL)animated; -- (void)expandMenuButton:(UIButton *)button animated:(BOOL)animated; -- (void)collapseMenuButton:(UIButton *)button animated:(BOOL)animated; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMTorchPattern.h b/Tweaks/PSHeader/CameraApp/CAMTorchPattern.h deleted file mode 100644 index 1cabe91..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMTorchPattern.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMTorchPattern : NSObject -- (id)initWithType:(NSInteger)type; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMTorchPatternController.h b/Tweaks/PSHeader/CameraApp/CAMTorchPatternController.h deleted file mode 100644 index f682329..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMTorchPatternController.h +++ /dev/null @@ -1,5 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMTorchPatternController : NSObject -- (void)blink; -- (void)doubleBlink; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMTriStateButton.h b/Tweaks/PSHeader/CameraApp/CAMTriStateButton.h deleted file mode 100644 index b2063a7..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMTriStateButton.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_1) -@interface CAMTriStateButton : UIControl -@property (assign, nonatomic) NSInteger flashMode; -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMUserPreferences.h b/Tweaks/PSHeader/CameraApp/CAMUserPreferences.h deleted file mode 100644 index 36c9722..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMUserPreferences.h +++ /dev/null @@ -1,4 +0,0 @@ -@interface CAMUserPreferences : NSObject -+ (instancetype)preferences; -- (NSInteger)videoConfiguration; -@end \ No newline at end of file diff --git a/Tweaks/PSHeader/CameraApp/CAMVideoConfigurationStatusIndicator.h b/Tweaks/PSHeader/CameraApp/CAMVideoConfigurationStatusIndicator.h deleted file mode 100644 index 98d7867..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMVideoConfigurationStatusIndicator.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "CAMControlStatusIndicator.h" - -@interface CAMVideoConfigurationStatusIndicator : CAMControlStatusIndicator -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMVideoPreviewView.h b/Tweaks/PSHeader/CameraApp/CAMVideoPreviewView.h deleted file mode 100644 index a7134e9..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMVideoPreviewView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMVideoPreviewView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMViewfinderView.h b/Tweaks/PSHeader/CameraApp/CAMViewfinderView.h deleted file mode 100644 index 2037da3..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMViewfinderView.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "CAMPreviewView.h" -#import "CAMTopBar.h" -#import "CAMBottomBar.h" -#import "CAMZoomSlider.h" - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMViewfinderView : UIView -- (CAMPreviewView *)previewView; -- (CAMTopBar *)topBar; -- (CAMBottomBar *)bottomBar; -- (CAMZoomSlider *)zoomSlider; -- (CGFloat)_interpolatedTopBarHeight; -- (CGSize)_topBarSizeForTraitCollection:(UITraitCollection *)traitCollection NS_DEPRECATED_IOS(9_0, 9_3); -- (CGSize)_topBarSizeForLayoutStyle:(NSInteger)layoutStyle NS_AVAILABLE_IOS(10_0); -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMViewfinderViewController.h b/Tweaks/PSHeader/CameraApp/CAMViewfinderViewController.h deleted file mode 100644 index cf83e04..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMViewfinderViewController.h +++ /dev/null @@ -1,82 +0,0 @@ -#import "CAMTopBar.h" -#import "CAMBottomBar.h" -#import "CAMViewfinderView.h" -#import "CAMZoomSlider.h" -#import "CAMElapsedTimeView.h" -#import "CAMFramerateIndicatorView.h" -#import "CAMFlashButton.h" -#import "CUShutterButton.h" -#import "CAMPreviewViewController.h" -#import "CUCaptureController.h" -#import "CAMCaptureGraphConfiguration.h" -#import "CAMVideoConfigurationStatusIndicator.h" - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CAMViewfinderViewController : UIViewController - -@property NSInteger _desiredFlashMode; -@property NSInteger flashMode; -@property NSInteger _flashMode; -@property NSInteger _desiredTorchMode; -@property NSInteger torchMode NS_AVAILABLE_IOS(10_0);; -@property NSInteger _torchMode NS_DEPRECATED_IOS(9_0, 9_3);; -@property NSInteger _currentMode; -@property NSInteger _currentDevice; -@property NSInteger _desiredCaptureDevice; -@property (nonatomic, assign, readwrite, setter=_setResolvedLowLightMode:) NSInteger _resolvedLowLightMode; -@property (getter=_numFilterSelectionsBeforeCapture, setter = _setNumFilterSelectionsBeforeCapture:) NSUInteger _numFilterSelectionsBeforeCapture; - -@property (nonatomic, strong) CAMViewfinderView *view; -@property (retain, nonatomic) CAMFramerateIndicatorView *_framerateIndicatorView; -@property (readonly, assign, nonatomic) CAMModeDial *_modeDial; -@property (readonly, assign, nonatomic) CAMTopBar *_topBar; -@property (readonly, assign, nonatomic) CAMBottomBar *_bottomBar; -@property (readonly, assign, nonatomic) CAMFlashButton *_flashButton; -@property (readonly, assign, nonatomic) CAMFlipButton *_flipButton; -@property (readonly, assign, nonatomic) CAMTimerButton *_timerButton; -@property (readonly, assign, nonatomic) CAMFilterButton *_filterButton; -@property (readonly, assign, nonatomic) CAMZoomSlider *_zoomSlider; -@property (readonly, assign, nonatomic) CAMHDRButton *_HDRButton; -@property (readonly, assign, nonatomic) CUShutterButton *_shutterButton; -@property (readonly, assign, nonatomic) CUShutterButton *_stillDuringVideoButton; -@property (readonly, assign, nonatomic) CAMElapsedTimeView *_elapsedTimeView; - -- (BOOL)_isCapturingFromTimer; -- (BOOL)_isCapturingTimelapse; -- (BOOL)_shouldEnableFlashButton; -- (BOOL)_shouldHideFlashButtonForGraphConfiguration:(CAMCaptureGraphConfiguration *)configuration NS_AVAILABLE_IOS(10_0); -- (BOOL)_shouldHideFlashButtonForMode:(NSInteger)mode device:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)_shouldHideModeDialForMode:(NSInteger)mode device:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)_shouldHideTopBarForGraphConfiguration:(CAMCaptureGraphConfiguration *)configuration NS_AVAILABLE_IOS(10_0); -- (BOOL)_shouldHideTopBarForMode:(NSInteger)mode device:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (BOOL)isEmulatingImagePicker; - -- (CAMCaptureGraphConfiguration *)_currentGraphConfiguration; -- (CAMPreviewViewController *)_previewViewController; -- (CUCaptureController *)_captureController; -- (CAMVideoConfigurationStatusIndicator *)_targetVideoConfigurationStatusIndicator NS_AVAILABLE_IOS(14_0); - -- (NSInteger)_effectFilterTypeForMode:(NSInteger)mode; -- (NSInteger)_remainingCaptureTimerTicks; -- (NSInteger)_resolvedTimerDuration; -- (NSInteger)_timerDuration; -- (NSInteger)timerDuration; - -- (NSMutableArray *)modesForModeDial:(id)arg; - -- (void)_captureStillImageWithCurrentSettings; -- (void)_collapseExpandedButtonsAnimated:(BOOL)animated; -- (void)_flashButtonDidChangeFlashMode:(CAMFlashButton *)flashButton; -- (void)_handleUserChangedToFlashMode:(NSInteger)flashMode; -- (void)_handleShutterButtonPressed:(id)arg1; -- (void)_handleShutterButtonReleased:(id)arg1; -- (void)_handleUserChangedFromDevice:(NSInteger)from toDevice:(NSInteger)to; -- (void)_readUserPreferencesAndHandleChanges NS_DEPRECATED_IOS(9_0, 12_4); -- (void)_setCurrentMode:(NSInteger)mode NS_DEPRECATED_IOS(9_0, 9_3); -- (void)_stopCapturingVideo; -- (void)_writeUserPreferences; - -- (void)captureController:(id)arg1 didChangeToMode:(NSInteger)mode device:(NSInteger)device NS_DEPRECATED_IOS(9_0, 9_3); -- (void)readUserPreferencesAndHandleChangesWithOverrides:(id)arg1 NS_AVAILABLE_IOS(13_0); - -@end diff --git a/Tweaks/PSHeader/CameraApp/CAMZoomSlider.h b/Tweaks/PSHeader/CameraApp/CAMZoomSlider.h deleted file mode 100644 index 4046908..0000000 --- a/Tweaks/PSHeader/CameraApp/CAMZoomSlider.h +++ /dev/null @@ -1,28 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface CAMZoomSlider : UISlider - -@property (getter=isMinimumAutozooming) BOOL minimumAutozooming; -@property (getter=isMaximumAutozooming) BOOL maximumAutozooming; -@property (getter=_isAutozooming, setter = _setAutozooming :) BOOL _autozooming; -@property (readonly) NSTimer *_visibilityTimer; -@property (readonly) UIImageView *_thumbImageView; -@property (readonly) UIView *_minTrackMaskView; -@property (readonly) UIView *_maxTrackMaskView; -@property (assign, nonatomic) UIView *delegate; - -- (BOOL)visibilityTimerIsValid; - -- (void)_beginAutozooming; -- (void)_commonCAMZoomSliderInitialization; -- (void)_endAutozooming; -- (void)_hideZoomSlider:(id)arg1; -- (void)_postHideZoomSliderAnimation; -- (void)_updateAutozooming; - -- (void)makeInvisible; -- (void)makeVisible; -- (void)makeVisibleAnimated:(BOOL)animated; -- (void)startVisibilityTimer; -- (void)stopVisibilityTimer; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CUCaptureController.h b/Tweaks/PSHeader/CameraApp/CUCaptureController.h deleted file mode 100644 index 6814b27..0000000 --- a/Tweaks/PSHeader/CameraApp/CUCaptureController.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "CAMCaptureEngine.h" - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CUCaptureController : NSObject -- (BOOL)isCapturingVideo; -- (BOOL)isCapturingCTMVideo; -- (BOOL)isCapturingStandardVideo; -- (BOOL)isCapturingBurst; -- (BOOL)isCapturingPanorama; -- (BOOL)isCapturingTimelapse; -- (CAMCaptureEngine *)_captureEngine; -@end diff --git a/Tweaks/PSHeader/CameraApp/CUShutterButton.h b/Tweaks/PSHeader/CameraApp/CUShutterButton.h deleted file mode 100644 index 31be8f8..0000000 --- a/Tweaks/PSHeader/CameraApp/CUShutterButton.h +++ /dev/null @@ -1,24 +0,0 @@ -#import "CAMShutterButtonSpec.h" - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface CUShutterButton : UIButton -+ (instancetype)shutterButton; -+ (instancetype)smallShutterButton; -+ (instancetype)smallShutterButtonWithLayoutStyle:(NSInteger)style NS_AVAILABLE_IOS(10_0); -+ (instancetype)tinyShutterButton; -+ (instancetype)tinyShutterButtonWithLayoutStyle:(NSInteger)style NS_AVAILABLE_IOS(10_0); - -@property (getter=isPulsing) BOOL pulsing; -@property (getter=isSpinning) BOOL spinning; -@property NSInteger mode; - -- (UIColor *)_colorForMode:(NSInteger)mode; -- (UIColor *)_innerCircleColorForMode:(NSInteger)mode spinning:(BOOL)spinning; - -- (UIView *)_innerView; -- (UIView *)_outerView; - -- (void)_updateOuterAndInnerLayers; -- (void)_setSpec:(CAMShutterButtonSpec)spec; - -@end diff --git a/Tweaks/PSHeader/CameraApp/CameraApp.h b/Tweaks/PSHeader/CameraApp/CameraApp.h deleted file mode 100644 index ad9686e..0000000 --- a/Tweaks/PSHeader/CameraApp/CameraApp.h +++ /dev/null @@ -1,94 +0,0 @@ -#import "AVCaptureDeviceFormat+CameraUI.h" -#import "AVCaptureSession+CAMCaptureEngine.h" -#import "CAMApplicationSpec.h" -#import "CAMApplicationViewController.h" -#import "CAMAvalancheCaptureService.h" -#import "CAMAvalancheSession.h" -#import "CAMBottomBar.h" -#import "CAMButtonLabel.h" -#import "CAMCameraSpec.h" -#import "CAMCameraView.h" -#import "CAMCameraViewController.h" -#import "CAMCaptureCapabilities.h" -#import "CAMCaptureConfiguration.h" -#import "CAMCaptureController.h" -#import "CAMCaptureEngine.h" -#import "CAMCaptureGraphConfiguration.h" -#import "CAMCaptureModeWithOptions.h" -#import "CAMCaptureMovieFileOutput.h" -#import "CAMCaptureStillImageOutput.h" -#import "CAMClosedViewfinderController.h" -#import "CAMEffectFilterManager.h" -#import "CAMEffectSelectionViewController.h" -#import "CAMEffectsFullsizeView.h" -#import "CAMEffectsGridView.h" -#import "CAMEffectsRenderer.h" -#import "CAMElapsedTimeView.h" -#import "CAMExpandableMenuButton.h" -#import "CAMFilterButton.h" -#import "CAMFlashButton.h" -#import "CAMFlipButton.h" -#import "CAMFramerateIndicatorView.h" -#import "CAMGLView.h" -#import "CAMHDRBadge.h" -#import "CAMHDRButton.h" -#import "CAMImageWell.h" -#import "CAMLegibilityViewHelper.h" -#import "CAMModeDial.h" -#import "CAMModeDialItem.h" -#import "CAMPadApplicationSpec.h" -#import "CAMPanoramaArrowView.h" -#import "CAMPanoramaLabel.h" -#import "CAMPanoramaLevelView.h" -#import "CAMPanoramaView.h" -#import "CAMPanoramaViewController.h" -#import "CAMPhoneApplicationSpec.h" -#import "CAMPreviewView.h" -#import "CAMPreviewViewController.h" -#import "CAMShutterButton.h" -#import "CAMShutterButtonSpec.h" -#import "CAMSlalomIndicatorView.h" -#import "CAMStillImageCaptureResponse.h" -#import "CAMTimerButton.h" -#import "CAMTopBar.h" -#import "CAMTorchPattern.h" -#import "CAMTorchPatternController.h" -#import "CAMTriStateButton.h" -#import "CAMUserPreferences.h" -#import "CAMVideoPreviewView.h" -#import "CAMViewfinderView.h" -#import "CAMViewfinderViewController.h" -#import "CAMZoomSlider.h" -#import "CUCaptureController.h" -#import "CUShutterButton.h" -#import "DCIMImageWellUtilities.h" -#import "NSValue+CameraUI.h" -#import "PanoramaViewDelegate.h" -#import "PLCameraButton.h" -#import "PLCameraButtonBar.h" -#import "PLCameraController.h" -#import "PLCameraEffectsRenderer.h" -#import "PLCameraFlashButton.h" -#import "PLCameraLevelView.h" -#import "PLCameraOptionsButton.h" -#import "PLCameraPanoramaBrokenArrowView.h" -#import "PLCameraPanoramaTextLabel.h" -#import "PLCameraPanoramaView.h" -#import "PLCameraSettingsGroupView.h" -#import "PLCameraSettingsView.h" -#import "PLCameraVideoStillCaptureButton.h" -#import "PLCameraView.h" -#import "PLCameraZoomSlider.h" -#import "PLCropOverlayBottomBar.h" -#import "PLEffectFilterManager.h" -#import "PLEffectSelectionViewController.h" -#import "PLEffectsFullsizeView.h" -#import "PLEffectsGridView.h" -#import "PLGLView.h" -#import "PLImageAdjustmentView.h" -#import "PLIOSurfaceData.h" -#import "PLPreviewOverlayView.h" -#import "PLReorientingButton.h" -#import "PLUICameraViewController.h" -#import "PLVideoPreviewView.h" -#import "UIView+CameraApp.h" diff --git a/Tweaks/PSHeader/CameraApp/DCIMImageWellUtilities.h b/Tweaks/PSHeader/CameraApp/DCIMImageWellUtilities.h deleted file mode 100644 index 791ae9e..0000000 --- a/Tweaks/PSHeader/CameraApp/DCIMImageWellUtilities.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface DCIMImageWellUtilities : NSObject - -+ (UIImage *)cameraPreviewWellImage; - -@end diff --git a/Tweaks/PSHeader/CameraApp/NSValue+CameraUI.h b/Tweaks/PSHeader/CameraApp/NSValue+CameraUI.h deleted file mode 100644 index eede268..0000000 --- a/Tweaks/PSHeader/CameraApp/NSValue+CameraUI.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "CAMCaptureModeWithOptions.h" - -NS_CLASS_AVAILABLE_IOS(9_0) -@interface NSValue (CameraUI) - -+ (NSValue *)valueWithModeWithOptions:(CAMCaptureModeWithOptions)options; - -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraButton.h b/Tweaks/PSHeader/CameraApp/PLCameraButton.h deleted file mode 100644 index ff722d8..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraButton.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLCameraButton : UIButton -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraButtonBar.h b/Tweaks/PSHeader/CameraApp/PLCameraButtonBar.h deleted file mode 100644 index 28921ec..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraButtonBar.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "PLCameraButton.h" - -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLCameraButtonBar : UIToolbar -@property (retain, nonatomic) PLCameraButton *cameraButton; -- (UIView *)_backgroundView; -- (void)_setVisibility:(BOOL)visible; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraController.h b/Tweaks/PSHeader/CameraApp/PLCameraController.h deleted file mode 100644 index c155ac2..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraController.h +++ /dev/null @@ -1,56 +0,0 @@ -#import "PLCameraView.h" -#import "PLCameraEffectsRenderer.h" -#import - -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraController : NSObject - -@property (assign, nonatomic)AVCaptureDevice *currentDevice; -@property (assign, nonatomic) AVCaptureOutput *currentOutput; -@property (retain, nonatomic) AVCaptureVideoPreviewLayer *previewLayer; -@property (readonly, assign, nonatomic) AVCaptureSession *currentSession; -@property (assign, nonatomic) NSInteger cameraDevice; -@property (assign, nonatomic) NSInteger cameraMode; -@property (assign, nonatomic) NSInteger flashMode; -@property (readonly, assign, nonatomic) NSInteger cameraOrientation; -@property (assign, nonatomic, getter=isHDREnabled) BOOL HDREnabled; -@property (retain, nonatomic) PLCameraEffectsRenderer *effectsRenderer NS_AVAILABLE_IOS(7_0); -@property (assign, nonatomic) CGFloat videoZoomFactor; -@property (getter=_isPreviewPaused, setter = _setPreviewPaused:) BOOL _previewPaused; -@property BOOL performingTimedCapture NS_AVAILABLE_IOS(7_0); - -+ (BOOL)isStillImageMode:(NSInteger)mode; - -- (BOOL)_isSessionReady; -- (BOOL)_isVideoMode:(NSInteger)mode; -- (BOOL)_lockCurrentDeviceForConfiguration; - -- (BOOL)canCaptureVideo; -- (BOOL)flashWillFire; -- (BOOL)hasFrontCamera; -- (BOOL)hasRearCamera; -- (BOOL)isCameraApp; -- (BOOL)isCapturingVideo; -- (BOOL)isChangingModes; -- (BOOL)isFocusLockSupported; -- (BOOL)isReady; - -- (CGFloat)maximumZoomFactorForDevice:(AVCaptureDevice *)device; -- (double)mogulFrameRate; - -- (NSMutableArray *)supportedCameraModes; -- (PLCameraView *)delegate; - -- (NSUInteger)_activeFilterIndex; -- (NSUInteger)effectFilterIndexForMode:(NSInteger)mode; - -- (void)_lockFocus:(BOOL)focus lockExposure:(BOOL)exposure lockWhiteBalance:(BOOL)whiteBalance; -- (void)_setFlashMode:(NSInteger)mode force:(BOOL)force; -- (void)_suggestedHDRChanged; -- (void)_unlockCurrentDeviceForConfiguration; - -- (void)pausePreview; -- (void)resumePreview; -- (void)setFaceDetectionEnabled:(BOOL)enabled; -- (void)setFocusDisabled:(BOOL)disabled; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraEffectsRenderer.h b/Tweaks/PSHeader/CameraApp/PLCameraEffectsRenderer.h deleted file mode 100644 index 82753ae..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraEffectsRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(7_0, 7_1) -@interface PLCameraEffectsRenderer : NSObject -@property (assign, nonatomic, getter=isShowingGrid) BOOL showGrid; -- (void)setShowGrid:(BOOL)show animated:(BOOL)animated; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraFlashButton.h b/Tweaks/PSHeader/CameraApp/PLCameraFlashButton.h deleted file mode 100644 index 6850087..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraFlashButton.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "PLReorientingButton.h" - -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLCameraFlashButton : PLReorientingButton - -@property (assign, nonatomic, getter=isAutoHidden) BOOL autoHidden; -@property NSInteger flashMode; - -- (void)_expandAnimated:(BOOL)animated; -- (void)_collapseAndSetMode:(NSInteger)mode animated:(BOOL)animated; - -- (UIView *)delegate; - -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraLevelView.h b/Tweaks/PSHeader/CameraApp/PLCameraLevelView.h deleted file mode 100644 index 9cf9c3c..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraLevelView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraLevelView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraOptionsButton.h b/Tweaks/PSHeader/CameraApp/PLCameraOptionsButton.h deleted file mode 100644 index 7e93253..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraOptionsButton.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "PLReorientingButton.h" - -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLCameraOptionsButton : PLReorientingButton -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraPanoramaBrokenArrowView.h b/Tweaks/PSHeader/CameraApp/PLCameraPanoramaBrokenArrowView.h deleted file mode 100644 index fcf169a..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraPanoramaBrokenArrowView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraPanoramaBrokenArrowView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraPanoramaTextLabel.h b/Tweaks/PSHeader/CameraApp/PLCameraPanoramaTextLabel.h deleted file mode 100644 index b81c82a..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraPanoramaTextLabel.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraPanoramaTextLabel : UILabel -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraPanoramaView.h b/Tweaks/PSHeader/CameraApp/PLCameraPanoramaView.h deleted file mode 100644 index 589cbb4..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraPanoramaView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "PanoramaViewDelegate.h" - -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraPanoramaView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraSettingsGroupView.h b/Tweaks/PSHeader/CameraApp/PLCameraSettingsGroupView.h deleted file mode 100644 index 57ac51d..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraSettingsGroupView.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLCameraSettingsGroupView : UIView -@property (retain, nonatomic) UIView *accessorySwitch; -- (void)setType:(NSInteger)type; -- (void)setTitle:(NSString *)title; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraSettingsView.h b/Tweaks/PSHeader/CameraApp/PLCameraSettingsView.h deleted file mode 100644 index dfa612e..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraSettingsView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLCameraSettingsView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraVideoStillCaptureButton.h b/Tweaks/PSHeader/CameraApp/PLCameraVideoStillCaptureButton.h deleted file mode 100644 index 4b01540..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraVideoStillCaptureButton.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "PLReorientingButton.h" - -NS_CLASS_DEPRECATED_IOS(6_0, 6_1) -@interface PLCameraVideoStillCaptureButton : PLReorientingButton -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraView.h b/Tweaks/PSHeader/CameraApp/PLCameraView.h deleted file mode 100644 index 57d2228..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraView.h +++ /dev/null @@ -1,116 +0,0 @@ -#import "PLVideoPreviewView.h" -#import "CAMModeDial.h" -#import "CAMTopBar.h" -#import "CAMBottomBar.h" -#import "CAMFlashButton.h" -#import "CAMFlipButton.h" -#import "CAMFilterButton.h" -#import "CAMHDRButton.h" -#import "CAMElapsedTimeView.h" -#import "CAMHDRBadge.h" -#import "CAMAvalancheSession.h" -#import "CAMApplicationSpec.h" -#import "CAMPreviewView.h" - -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraView : UIView - -@property (retain, nonatomic) UIToolbar *bottomButtonBar; -@property NSInteger photoFlashMode; -@property (assign, nonatomic) NSInteger videoFlashMode; -@property (assign, nonatomic) NSInteger flashMode; -@property (assign, nonatomic) NSInteger lastSelectedPhotoFlashMode; -@property (readonly, assign, nonatomic) CAMModeDial *_modeDial NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMTopBar *_topBar NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMBottomBar *_bottomBar NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMFlashButton *_flashButton NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMFlipButton *_flipButton NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMFilterButton *_filterButton; -@property (readonly, assign, nonatomic) CAMHDRButton *_HDRButton NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMShutterButton *_shutterButton NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMShutterButton *_stillDuringVideoButton NS_AVAILABLE_IOS(7_0); -@property (readonly, assign, nonatomic) CAMElapsedTimeView *_elapsedTimeView NS_AVAILABLE_IOS(7_0); -@property (assign, nonatomic, getter=isTallScreen) BOOL tallScreen; -@property (readonly, assign, nonatomic) BOOL isCameraReady; -@property (assign, nonatomic) NSInteger cameraDevice; -@property (assign, nonatomic) NSInteger cameraMode; -@property (readonly, assign, nonatomic) CAMAvalancheSession *_avalancheSession NS_DEPRECATED_IOS(7_0, 8_4); -@property (assign, nonatomic) BOOL HDRIsOn; -@property (readonly, assign, nonatomic) CGRect unzoomedPreviewFrame; -@property (getter=_isFlipping, setter = _setFlipping:) BOOL _flipping; -@property (getter=_numFilterSelectionsBeforeCapture, setter = _setNumFilterSelectionsBeforeCapture:) NSUInteger _numFilterSelectionsBeforeCapture; - -- (BOOL)_didEverMoveToWindow; -- (BOOL)_isCapturing; -- (BOOL)_isHidingBadgesForFilterUI; -- (BOOL)_isStillImageMode:(NSInteger)mode NS_AVAILABLE_IOS(7_0); -- (BOOL)_isStillImageMode:(NSInteger)mode; -- (BOOL)_isVideoMode:(NSInteger)mode NS_AVAILABLE_IOS(7_0); -- (BOOL)_performingTimedCapture NS_AVAILABLE_IOS(7_0); -- (BOOL)_shouldEnableFlashButton; -- (BOOL)_shouldEnableModeDial NS_AVAILABLE_IOS(7_0); -- (BOOL)_shouldHideFilterButtonForMode:(NSInteger)mode NS_AVAILABLE_IOS(7_0); -- (BOOL)_shouldHideFlashButtonForMode:(NSInteger)mode NS_AVAILABLE_IOS(7_0); -- (BOOL)_shouldHideHDRBadgeForMode:(NSInteger)mode; -- (BOOL)_shouldHideModeDialForMode:(NSInteger)mode NS_AVAILABLE_IOS(7_0); -- (BOOL)_shouldHideTopBarForMode:(NSInteger)mode NS_AVAILABLE_IOS(7_0); - -- (BOOL)bottomBarShouldHideFilterButton:(id)arg1 NS_AVAILABLE_IOS(7_0); -- (BOOL)hasInFlightCaptures; -- (BOOL)HDRIsOn; - -- (CAMApplicationSpec *)spec NS_AVAILABLE_IOS(7_0); -- (CAMHDRBadge *)_HDRBadge NS_AVAILABLE_IOS(7_0); - -- (CGRect)_bottomBarFrame; - -- (NSInteger)_currentFlashMode; -- (NSInteger)_glyphOrientationForCameraOrientation:(NSInteger)cameraOrientation; -- (NSInteger)_photoFlashMode; - -- (NSString *)modeDial:(CAMModeDial *)modeDial titleForItemAtIndex:(NSUInteger)index NS_AVAILABLE_IOS(7_0); - -- (PLVideoPreviewView *)videoPreviewView; - -- (void)_addZoomAnimationDisplayLinkWithSelector:(SEL)selector; -- (void)_beginZooming; -- (void)_captureStillDuringVideo; -- (void)_checkDiskSpaceAfterCapture; -- (void)_clearFocusViews; -- (void)_createHDRBadgeIfNecessary; -- (void)_createZoomSliderIfNecessary; -- (void)_disableBottomBarForContinuousCapture; -- (void)_endZooming; -- (void)_handleVolumeUpEvents:(NSUInteger)events; -- (void)_layoutTopBarForOrientation:(NSInteger)orientation NS_AVAILABLE_IOS(7_0); -- (void)_loadZoomSliderResources; -- (void)_rotateCameraControlsAndInterface; -- (void)_setBottomBarEnabled:(BOOL)enabled; -- (void)_setBottomBarEnabled:(BOOL)enabled; -- (void)_setFlashMode:(NSInteger)mode; -- (void)_setOverlayControlsEnabled:(BOOL)enabled; -- (void)_setSettingsButtonAlpha:(CGFloat)alpha duration:(NSTimeInterval)duration NS_DEPRECATED_IOS(5_0, 6_1); -- (void)_setShouldShowFocus:(BOOL)focus; -- (void)_setShouldShowFocus:(BOOL)show; -- (void)_setSwipeToModeSwitchEnabled:(BOOL)enabled; -- (void)_setZoomFactor:(CGFloat)factor; -- (void)_shutterButtonClicked; -- (void)_switchFromCameraModeAtIndex:(NSUInteger)fromIndex toCameraModeAtIndex:(NSUInteger)toIndex; -- (void)_updateHDRBadge; -- (void)_updatePreviewWellImage:(UIImage *)image; -- (void)_updateTopBarStyleForDeviceOrientation:(NSInteger)orientation NS_AVAILABLE_IOS(7_0); - -- (void)cameraShutterReleased:(id)arg1; -- (void)closeIrisWithDidFinishSelector:(SEL)closeIrisWith withDuration:(NSTimeInterval)duration; -- (void)flashButtonDidChangeFlashMode:(id)arg1; -- (void)flashButtonModeDidChange:(NSInteger)mode; -- (void)hideStaticClosedIris; -- (void)openIrisWithDidFinishSelector:(SEL)openIrisWith withDuration:(NSTimeInterval)duration; -- (void)pausePreview; -- (void)resumePreview; -- (void)setCameraButtonsEnabled:(BOOL)enabled; -- (void)showZoomSlider; -- (void)takePicture; -- (void)takePictureOpenIrisAnimationFinished; - -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCameraZoomSlider.h b/Tweaks/PSHeader/CameraApp/PLCameraZoomSlider.h deleted file mode 100644 index f164820..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCameraZoomSlider.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCameraZoomSlider : UISlider -- (void)makeInvisible; -- (void)makeVisible; -- (void)makeVisibleAnimated:(BOOL)animated; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLCropOverlayBottomBar.h b/Tweaks/PSHeader/CameraApp/PLCropOverlayBottomBar.h deleted file mode 100644 index 0157cee..0000000 --- a/Tweaks/PSHeader/CameraApp/PLCropOverlayBottomBar.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLCropOverlayBottomBar : UIToolbar -- (void)_setVisibility:(BOOL)visible; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLEffectFilterManager.h b/Tweaks/PSHeader/CameraApp/PLEffectFilterManager.h deleted file mode 100644 index d341d26..0000000 --- a/Tweaks/PSHeader/CameraApp/PLEffectFilterManager.h +++ /dev/null @@ -1,15 +0,0 @@ -#import - -NS_CLASS_DEPRECATED_IOS(7_0, 7_1) -@interface PLEffectFilterManager : NSObject - -+ (instancetype)sharedInstance; - -- (NSUInteger)blackAndWhiteFilterStartIndex; -- (NSUInteger)filterCount; - -- (CIFilter *)filterForIndex:(NSUInteger)index; - -- (void)_addEffectNamed:(NSString *)name aggdName:(NSString *)aggdName filter:(CIFilter *)filter; - -@end diff --git a/Tweaks/PSHeader/CameraApp/PLEffectSelectionViewController.h b/Tweaks/PSHeader/CameraApp/PLEffectSelectionViewController.h deleted file mode 100644 index 2d3e56e..0000000 --- a/Tweaks/PSHeader/CameraApp/PLEffectSelectionViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(7_0, 7_1) -@interface PLEffectSelectionViewController : UIViewController -- (void)_setSelectedIndexPath:(NSIndexPath *)indexPath; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLEffectsFullsizeView.h b/Tweaks/PSHeader/CameraApp/PLEffectsFullsizeView.h deleted file mode 100644 index c74393b..0000000 --- a/Tweaks/PSHeader/CameraApp/PLEffectsFullsizeView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "PLGLView.h" - -NS_CLASS_DEPRECATED_IOS(7_0, 7_1) -@interface PLEffectsFullsizeView : PLGLView -@end diff --git a/Tweaks/PSHeader/CameraApp/PLEffectsGridView.h b/Tweaks/PSHeader/CameraApp/PLEffectsGridView.h deleted file mode 100644 index 2a17cf9..0000000 --- a/Tweaks/PSHeader/CameraApp/PLEffectsGridView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "PLGLView.h" - -NS_CLASS_DEPRECATED_IOS(7_0, 7_1) -@interface PLEffectsGridView : PLGLView -- (NSUInteger)_cellCount; -- (NSUInteger)_filterIndexForGridIndex:(NSUInteger)index; -- (BOOL)isBlackAndWhite; -- (BOOL)isSquare; -- (CGRect)rectForFilterIndex:(NSUInteger)index; -- (CGRect)_squareCropFromRect:(CGRect)rect; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLGLView.h b/Tweaks/PSHeader/CameraApp/PLGLView.h deleted file mode 100644 index 4f6ac29..0000000 --- a/Tweaks/PSHeader/CameraApp/PLGLView.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(7_0, 7_1) -@interface PLGLView : UIView -@property CGSize fixedSize; -- (CGFloat)drawableHeight; -- (CGFloat)drawableWidth; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLIOSurfaceData.h b/Tweaks/PSHeader/CameraApp/PLIOSurfaceData.h deleted file mode 100644 index 19c85f2..0000000 --- a/Tweaks/PSHeader/CameraApp/PLIOSurfaceData.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(6_0, 7_1) -@interface PLIOSurfaceData : NSData -@end diff --git a/Tweaks/PSHeader/CameraApp/PLImageAdjustmentView.h b/Tweaks/PSHeader/CameraApp/PLImageAdjustmentView.h deleted file mode 100644 index 92a6df6..0000000 --- a/Tweaks/PSHeader/CameraApp/PLImageAdjustmentView.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(6_0, 7_1) -@interface PLImageAdjustmentView : UIView -@property (retain) UIImage *editedImage; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLPreviewOverlayView.h b/Tweaks/PSHeader/CameraApp/PLPreviewOverlayView.h deleted file mode 100644 index 8730c63..0000000 --- a/Tweaks/PSHeader/CameraApp/PLPreviewOverlayView.h +++ /dev/null @@ -1,2 +0,0 @@ -@interface PLPreviewOverlayView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/PLReorientingButton.h b/Tweaks/PSHeader/CameraApp/PLReorientingButton.h deleted file mode 100644 index 15152ff..0000000 --- a/Tweaks/PSHeader/CameraApp/PLReorientingButton.h +++ /dev/null @@ -1,5 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 6_1) -@interface PLReorientingButton : UIButton -@property (assign, nonatomic) CGFloat endCapRadius; -- (void)setButtonOrientation:(NSInteger)orientation animated:(BOOL)animated; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLUICameraViewController.h b/Tweaks/PSHeader/CameraApp/PLUICameraViewController.h deleted file mode 100644 index 3ac95a2..0000000 --- a/Tweaks/PSHeader/CameraApp/PLUICameraViewController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "PLCameraView.h" - -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLUICameraViewController : UIViewController -- (PLCameraView *)_cameraView; -@end diff --git a/Tweaks/PSHeader/CameraApp/PLVideoPreviewView.h b/Tweaks/PSHeader/CameraApp/PLVideoPreviewView.h deleted file mode 100644 index f3dfcee..0000000 --- a/Tweaks/PSHeader/CameraApp/PLVideoPreviewView.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_DEPRECATED_IOS(5_0, 7_1) -@interface PLVideoPreviewView : UIView -@end diff --git a/Tweaks/PSHeader/CameraApp/PanoramaViewDelegate.h b/Tweaks/PSHeader/CameraApp/PanoramaViewDelegate.h deleted file mode 100644 index 6be75f1..0000000 --- a/Tweaks/PSHeader/CameraApp/PanoramaViewDelegate.h +++ /dev/null @@ -1,4 +0,0 @@ -@protocol panoramaViewDelegate -- (void)setCaptureDirection:(NSInteger)direction; -- (void)_arrowWasTapped:(id)arg1; -@end diff --git a/Tweaks/PSHeader/CameraApp/UIView+CameraApp.h b/Tweaks/PSHeader/CameraApp/UIView+CameraApp.h deleted file mode 100644 index 086f082..0000000 --- a/Tweaks/PSHeader/CameraApp/UIView+CameraApp.h +++ /dev/null @@ -1,10 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface UIView (CameraUI) -- (void)cam_setHidden:(BOOL)hidden animated:(BOOL)animated; -- (void)cam_ensureSubview:(UIView *)view; -@end - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface UIView (PhotoLibrary) -- (void)pl_setHidden:(BOOL)hidden animated:(BOOL)animated; -@end \ No newline at end of file diff --git a/Tweaks/PSHeader/CameraGestaltKeys.h b/Tweaks/PSHeader/CameraGestaltKeys.h deleted file mode 100644 index 83b3ee9..0000000 --- a/Tweaks/PSHeader/CameraGestaltKeys.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef _PS_CAMGESTALT -#define _PS_CAMGESTALT - -// All capability keys with "?" as a comment prefix requires use with MGGetBoolAnswer(key) -// Otherwise, use MGGetSInt32Answer(key, defaultValue) - -// ? has front-facing or rear-facing camera -#define kBackCameraSupportedKey "rear-facing-camera" -#define kFrontCameraSupportedKey "front-facing-camera" - -// ? supports flash on front/rear camera -#define kBackFlashSupportedKey "camera-flash" -// deobfuscated: camera-front-flash -#define kFrontFlashSupportedKey "fJZs6N8SqTS4RuQVh3szxA" - -// ? supports video recording -#define kVideoSupportedKey "video-camera" -// ? supports taking stills during video recording -#define kStillDuringVideoSupportedKey "video-stills" - -// ? supports HDR on front/rear camera -#define kBackHDRSupportedKey "RearFacingCameraHDRCapability" -#define kFrontHDRSupportedKey "FrontFacingCameraHDRCapability" - -// ? supports setting HDR mode as on on front/rear camera -// deobfuscated: RearFacingCameraHDROnCapability -#define kBackHDROnSupportedKey "LkWb+FyA1+ef2UD1Fx+kAw" -// deobfuscated: FrontFacingCameraHDROnCapability -#define kFrontHDROnSupportedKey "HnHX0gXt8RvhMQzIVMM7hw" - -// ? supports auto HDR mode on front/rear camera -#define kBackAutoHDRSupportedKey "RearFacingCameraAutoHDRCapability" -#define kFrontAutoHDRSupportedKey "FrontFacingCameraAutoHDRCapability" - -// ? supports live camera effect -#define kLiveFilterSupportedKey "CameraLiveEffectsCapability" - -// ? supports burst mode on front/rear camera -#define kBackBurstSupportedKey "RearFacingCameraBurstCapability" -#define kFrontBurstSupportedKey "FrontFacingCameraBurstCapability" - -// interval value for each burst photo captured on front/rear camera -// deobfuscated: RearFacingCameraStillDurationForBurst -#define kBackCaptureIntervalKey "gq0j1GmcIcaD4DjJoo9pfg" -// deobfuscated: FrontFacingCameraStillDurationForBurst -#define kFrontCaptureIntervalKey "TDM8SEI14n2KE9PGHO0a4A" - -// ? supports iris mode on rear camera -// deobfuscated: SupportsIrisCapture -#define kIrisSupportedKey "pLzf7OiX5nWAPUMj7BfI4Q" - -// ? supports slo-mo capture on front/rear camera -#define kBackSlomoSupportedKey "RearFacingCameraHFRCapability" -#define kFrontSlomoSupportedKey "FrontFacingCameraHFRCapability" - -// ? supports 1080p60 on rear camera -#define kBack60FPSVideoSupportedKey "RearFacingCamera60fpsVideoCaptureCapability" - -// maximum 4k FPS supported on front/rear camera -// deobfuscated: RearFacingCameraVideoCapture4kMaxFPS -#define kBack4kMaxFPSKey "po7g0ATDzGoVI1DO8ISmuw" -// deobfuscated: FrontFacingCameraVideoCapture4kMaxFPS -#define kFront4KMaxFPSKey "cux58RcuSiBhpxWnT3pE4A" // iOS 10+ - -// maximum 1080p FPS supported on front/rear camera -// deobfuscated: RearFacingCameraVideoCapture1080pMaxFPS -#define kBack1080pMaxFPSKey "jBGZJ71pRJrqD8VZ6Tk2VQ" // iOS 10+ -// deobfuscated: FrontFacingCameraVideoCapture1080pMaxFPS -#define kFront1080pMaxFPSKey "3yzXj0lJhQi+r3kgQlwiOg" // iOS 10+ - -// maximum 720p FPS supported on front/rear camera -// deobfuscated: RearFacingCameraVideoCapture720pMaxFPS -#define kBack720pMaxFPSKey "0/7QNywWU4IqDcyvTv9UYQ" -// deobfuscated: FrontFacingCameraVideoCapture720pMaxFPS -#define kFront720pMaxFPSKey "0AFeHRmliNJ4pSlVb8ltZA" // iOS 10+ - -// maximum slo-mo 720p FPS supported on rear camera -// deobfuscated: RearFacingCameraHFRVideoCapture720pMaxFPS -#define kBackSlomo720pMaxFPSKey "XellXEQUbOIgUPoTrIj5nA" - -// maximum slo-mo 1080p FPS supported on rear camera -// deobfuscated: RearFacingCameraHFRVideoCapture1080pMaxFPS -#define kBackSlomo1080pMaxFPSKey "jKFTzVOYcfTfNBh+yDrprw" - -// ? supports HEVC encoding -// deobfuscated: HEVCEncodingCapability -#define kHEVCEncodingSupportedKey "g/MkWm2Ac6+TLNBgtBGxsg" // iOS 11+ - -// maximum video zoom factor on front/rear camera -#define kBackVideoMaximumZoomFactorKey "RearFacingCameraMaxVideoZoomFactor" -#define kFrontVideoMaximumZoomFactorKey "FrontFacingCameraMaxVideoZoomFactor" - -// ? supports telephoto on rear camera -// deobfuscated: RearFacingTelephotoCameraCapability -#define kBackTelephotoSupportedKey "YzrS+WPEMqyh/FBv/n/jvA" // iOS 11+ -// ? supports dual on rear camera, is used for portrait mode -// deobfuscated: DeviceHasAggregateCamera -#define kBackDualSupportedKey "0/VAyl58TL5U/mAQEJNRQw" // iOS 11+ - -// maximum len zoom factor for photo/video on dual rear camera -// deobfuscated: AggregateDevicePhotoZoomFactor -#define kBackDualPhotoMaximumZoomFactorKey "JLP/IinyzetEPztvoNUNKg" // iOS 11+ -// deobfuscated: AggregateDeviceVideoZoomFactor -#define kBackDualVideoMaximumZoomFactorKey "IweaHIDpz+rknAcb3+xg9g" // iOS 11+ - -// ? has front pearl camera (might require use with MGIsQuestionValid()) -// is used for portrait mode -// deobfuscated: PearlCameraCapability -// counterpart: 8S7ydMJ4DlCUF38/hI/fJA -#define kFrontPearlSupportedKey "BfEIy3W3t0Wxf7Hf7LEsAw" // iOS 11+ - -// ? supports portrait effects -// deobfuscated: DeviceSupportsPortraitLightEffectFilters -#define kPortraitEffectsSupportedKey "hewg+QX1h57eGJGphdCong" // iOS 11+ - -// ? supports forcing shutter sound on -#define kShutterSoundRequiredKey "RegionalBehaviorShutterClick" - -// ? supports using lock button as shutter button -// deobfuscated: IsPwrOpposedVol -#define kLockButtonAppropriateForShutterKey "euampscYbKXqj/bSaHD0QA" // iOS 11+ - -// ? supports pipelined still image processing -// deobfuscated: PipelinedStillImageProcessingCapability -#define kPipelinedStillImageProcessingSupportedKey "XIcF5FOyQlt/H79oFw9ciA" // iOS 11+ - -// ? supports modern HDR mode -// suspected to be the key to check if the device is introduced as of 2017 -// deobfuscated: CameraHDR2Capability -#define kModernHDRSupportedKey "cWWKdUn+rIclZ60ZGAVhBw" // iOS 12+ - -// ? supports auto low light video capture -#define kAutoLowLightVideoSupportedKey "DeviceSupportsAutoLowLightVideo" // iOS 12+ - -// ? supports recording stereo audio -#define kStereoAudioRecordingSupportedKey "DeviceSupportsStereoAudioRecording" // iOS 12+ - -// ? supports studio light portrait preview -#define kStudioLightPortraitPreviewKey "DeviceSupportsStudioLightPortraitPreview" // iOS 12+ - -// ? supports single camera portrait mode -// deobfuscated: DeviceSupportsSingleCameraPortrait -#define kSSingleCameraPortraitKey "FymLPtOEy6FdE7TmKeoTdg" // iOS 12+ - -// ? supports capturing on finger touch down -#define kCameraCaptureOnTouchDownSupportedKey "DeviceSupportsCameraCaptureOnTouchDown" // iOS 12+ - -#endif diff --git a/Tweaks/PSHeader/CameraMacros.h b/Tweaks/PSHeader/CameraMacros.h deleted file mode 100644 index ac280a3..0000000 --- a/Tweaks/PSHeader/CameraMacros.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _PS_CAMMACRO -#define _PS_CAMMACRO - -#import -#import "Misc.h" - -#define CAMERAUI "/System/Library/PrivateFrameworks/CameraUI.framework/CameraUI" -#define openCamera10() dlopen(realPath2(@CAMERAUI), RTLD_NOW) -#define openCamera9() openCamera10() -#define CAMERAKIT "/System/Library/PrivateFrameworks/CameraKit.framework/CameraKit" -#define openCamera8() dlopen(realPath2(@CAMERAKIT), RTLD_NOW) -#define PHOTOLIBRARY "/System/Library/PrivateFrameworks/PhotoLibrary.framework/PhotoLibrary" -#define openCamera7() dlopen(realPath2(@PHOTOLIBRARY), RTLD_NOW) -#define openCamera6() openCamera7() -#define openCamera5() openCamera7() - -#endif diff --git a/Tweaks/PSHeader/CoreImage/CoreImage.h b/Tweaks/PSHeader/CoreImage/CoreImage.h deleted file mode 100644 index 542cbdd..0000000 --- a/Tweaks/PSHeader/CoreImage/CoreImage.h +++ /dev/null @@ -1 +0,0 @@ -#import "PrivateFilters.h" diff --git a/Tweaks/PSHeader/CoreImage/PrivateFilters.h b/Tweaks/PSHeader/CoreImage/PrivateFilters.h deleted file mode 100644 index ca9759b..0000000 --- a/Tweaks/PSHeader/CoreImage/PrivateFilters.h +++ /dev/null @@ -1,112 +0,0 @@ -#import - -@interface CIColorPosterize : CIFilter -@property (retain, nonatomic) NSNumber *inputLevels; -@end - -@interface CIColorMonochrome : CIFilter -@property (retain, nonatomic) NSNumber *inputIntensity; -@property (retain, nonatomic) CIColor *inputColor; -@end - -@interface CIFalseColor : CIFilter -@property (retain, nonatomic) CIColor *inputColor0; -@property (retain, nonatomic) CIColor *inputColor1; -@end - -@interface CISepiaTone : CIFilter -@property (retain, nonatomic) NSNumber *inputIntensity; -@end - -@interface CIVibrance : CIFilter -@property (retain, nonatomic) NSNumber *inputAmount; -@end - -@interface CIBloom : CIFilter -@property (retain, nonatomic) NSNumber *inputIntensity; -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CIGloom : CIFilter -@property (retain, nonatomic) NSNumber *inputIntensity; -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CIGaussianBlur : CIFilter -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CIThermal : CIFilter -@end - -@interface CIXRay : CIFilter -@end - -@interface CIPixellate : CIFilter -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputScale; -@end - -@interface CIStretch : CIFilter -@property (retain, nonatomic) CIVector *inputPoint; -@property (retain, nonatomic) CIVector *inputSize; -@end - -@interface CITwirlDistortion : CIFilter -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputRadius; -@property (retain, nonatomic) NSNumber *inputAngle; -@end - -@interface CIHoleDistortion : CIFilter -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CIPinchDistortion : CIFilter -@property (retain, nonatomic) NSNumber *inputScale; -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CIMirror : CIFilter -@property (retain, nonatomic) NSNumber *inputAngle; -@property (retain, nonatomic) CIVector *inputPoint; -@end - -@interface CIWrapMirror : CIFilter -@end - -@interface CISharpenLuminance : CIFilter -@property (retain, nonatomic) NSNumber *inputSharpness; -@end - -@interface CITriangleKaleidoscope : CIFilter -@property (retain, nonatomic) NSNumber *inputDecay; -@property (retain, nonatomic) NSNumber *inputSize; -@property (retain, nonatomic) NSNumber *inputAngle; -@property (retain, nonatomic) CIVector *inputPoint; -@end - -@interface CILightTunnel : CIFilter -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputRotation; -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CICircleSplashDistortion : CIFilter -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputRadius; -@end - -@interface CICircularScreen : CIFilter -@property (retain, nonatomic) CIVector *inputCenter; -@property (retain, nonatomic) NSNumber *inputWidth; -@property (retain, nonatomic) NSNumber *inputSharpness; -@end - -@interface CILineScreen : CIFilter -@property (retain, nonatomic) NSNumber *inputAngle; -@property (retain, nonatomic) NSNumber *inputWidth; -@property (retain, nonatomic) NSNumber *inputSharpness; -@end diff --git a/Tweaks/PSHeader/Misc.h b/Tweaks/PSHeader/Misc.h deleted file mode 100644 index 069a87b..0000000 --- a/Tweaks/PSHeader/Misc.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _PS_MISC -#define _PS_MISC - -#import -#import -#import "PAC.h" - -#if TARGET_OS_SIMULATOR - -#import - -#define realPath(path) [UISystemRootDirectory() stringByAppendingPathComponent:path] -#define realPath2(path) [realPath(path) UTF8String] -#define realPrefPath(domain) [NSString stringWithFormat:@"%@/Library/Preferences/%@.plist", @(getenv("SIMULATOR_SHARED_RESOURCES_DIRECTORY")), domain] -#else -#define realPath(path) (path) -#define realPath2(path) ([path UTF8String]) -#define realPrefPath(domain) [NSString stringWithFormat:@"/var/mobile/Library/Preferences/%@.plist", domain] -#endif - -#define fileExist(path) [[NSFileManager defaultManager] fileExistsAtPath:path] -#define CFStringEqual(s1, s2) (CFStringCompare(s1, s2, kCFCompareCaseInsensitive) == kCFCompareEqualTo) -#define NSStringEqual(str1, str2) ([str1 isEqualToString:str2]) - -#define _PSFindSymbolCallable(image, name) make_sym_callable(MSFindSymbol(image, name)) -#define _PSFindSymbolReadable(image, name) make_sym_readable(MSFindSymbol(image, name)) - -#endif diff --git a/Tweaks/PSHeader/MockMac.h b/Tweaks/PSHeader/MockMac.h deleted file mode 100644 index 8278a2a..0000000 --- a/Tweaks/PSHeader/MockMac.h +++ /dev/null @@ -1,59 +0,0 @@ -#if TARGET_OS_OSX - -typedef NSInteger UIImageOrientation; - -@protocol UITextInputTraits -@end - -@protocol UITableViewDataSource -@end - -@protocol UITableViewDelegate -@end - -@protocol UIScrollViewDelegate -@end - -@interface UIViewController : NSObject -@end - -@interface UIResponder : NSObject -@end - -@interface UIColor : NSObject -@end - -@interface UIView : UIResponder -@end - -@interface UITableView : UIView -@end - -@interface UISlider : UIView -@end - -@interface UILabel : UIView -@end - -@interface UIButton : UIView -@end - -@interface UIToolbar : NSObject -@end - -@interface UIImage : UIView -@end - -@interface UIImageView : UIView -@end - -@interface UICollectionView : UIView -@end - -@interface UICollectionViewCell : UIView -@end - -@interface UIPageControl : NSObject -@end - -#endif \ No newline at end of file diff --git a/Tweaks/PSHeader/PAC.h b/Tweaks/PSHeader/PAC.h deleted file mode 100644 index e106f58..0000000 --- a/Tweaks/PSHeader/PAC.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef PTRAUTH_HELPERS_H -#define PTRAUTH_HELPERS_H -// Helpers for PAC archs. -// https://gist.github.com/summertriangle-dev/6b0449ce561f756ac82a4bc3de7af30a - -// If the compiler understands __arm64e__, assume it's paired with an SDK that has -// ptrauth.h. Otherwise, it'll probably error if we try to include it so don't. -#if __arm64e__ -#include -#endif - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" - -// Given a pointer to instructions, sign it so you can call it like a normal fptr. -static void *make_sym_callable(void *ptr) { -#if __arm64e__ - if (ptr == NULL) - return NULL; - ptr = ptrauth_sign_unauthenticated(ptrauth_strip(ptr, ptrauth_key_function_pointer), ptrauth_key_function_pointer, 0); -#endif - return ptr; -} - -// Given a function pointer, strip the PAC so you can read the instructions. -static void *make_sym_readable(void *ptr) { -#if __arm64e__ - if (ptr == NULL) - return NULL; - ptr = ptrauth_strip(ptr, ptrauth_key_function_pointer); -#endif - return ptr; -} - -#pragma clang diagnostic pop -#endif \ No newline at end of file diff --git a/Tweaks/PSHeader/PS.h b/Tweaks/PSHeader/PS.h deleted file mode 100644 index 34739cd..0000000 --- a/Tweaks/PSHeader/PS.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef _PS -#define _PS - -#import "iOSVersions.h" -#import "Misc.h" - -#define PS_DONATE_URL @"https://poomsmart.github.io/repo/" -#define PS_TWITTER_URL @"https://twitter.com/PoomSmart" - -#ifdef CHECK_TARGET - -#import - -typedef NS_ENUM(NSUInteger, TargetType) { - TargetTypeApps = 1 << 0, - TargetTypeGenericExtensions = 1 << 1, - TargetTypeKeyboardExtensions = 1 << 2 -}; - -FOUNDATION_EXPORT char ***_NSGetArgv(); - -static BOOL _isTarget(NSUInteger type, NSArray *whitelist, NSArray *blacklist) { - char *executablePathC = **_NSGetArgv(); - NSString *executablePath = [NSString stringWithUTF8String:executablePathC]; - if (executablePath) { -#ifdef __DEBUG__ - HBLogDebug(@"Executable path: %@", executablePath); -#endif - BOOL isExtension = [executablePath rangeOfString:@"appex"].location != NSNotFound; - if (type & TargetTypeGenericExtensions && isExtension) { - HBLogDebug(@"Injected: extension"); - return YES; - } - NSString *processName = [executablePath lastPathComponent]; -#ifdef CHECK_BLACKLIST - if (blacklist.count) { - BOOL disallow = [blacklist containsObject:processName]; - NSString *bundleIdentifier = NSBundle.mainBundle.bundleIdentifier; - if (!disallow && bundleIdentifier) - disallow = [blacklist containsObject:bundleIdentifier]; - if (disallow) - return NO; - } -#endif -#ifdef CHECK_WHITELIST - if (whitelist.count) { - BOOL allow = [whitelist containsObject:processName]; - NSString *bundleIdentifier = NSBundle.mainBundle.bundleIdentifier; - if (!allow && bundleIdentifier) - allow = [whitelist containsObject:bundleIdentifier]; - if (allow) { - HBLogDebug(@"Injected: whitelist"); - return YES; - } - } -#endif - BOOL isSpringBoard = NSStringEqual(processName, @"SpringBoard"); - BOOL isExtensionOrApp = [executablePath rangeOfString:@"/Application"].location != NSNotFound; - BOOL isUILike = isSpringBoard || isExtensionOrApp; - if (type & TargetTypeApps && isUILike && !isExtension) { - HBLogDebug(@"Injected: app"); - return YES; - } - if (type & TargetTypeKeyboardExtensions && isExtension) { - id val = NSBundle.mainBundle.infoDictionary[@"NSExtension"][@"NSExtensionPointIdentifier"]; - BOOL isKeyboardExtension = val ? NSStringEqual(val, @"com.apple.keyboard-service") : NO; - if (isKeyboardExtension) - HBLogDebug(@"Injected: keyboard extension"); - return isKeyboardExtension; - } - } - return NO; -} - -#define isTarget(type) _isTarget(type, nil, nil) - -#ifdef CHECK_TARGET_GUI - -static void *observer = NULL; -static void lateLoad(void); - -static void appLoaded(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { - lateLoad(); -} - -static void appLoadedCallback() { - CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &observer, appLoaded, (CFStringRef)UIApplicationDidFinishLaunchingNotification, NULL, CFNotificationSuspensionBehaviorCoalesce); -} - -#endif - -#endif - -#ifdef KILL_PROCESS - -#include - -void killProcess(const char *name) { - pid_t pid; - int status; - const char *args[] = { - "killall", "-9", name, NULL - }; - posix_spawn(&pid, "/usr/bin/killall", NULL, NULL, (char *const *)args, NULL); - waitpid(pid, &status, WEXITED); -} - -#endif - -#endif diff --git a/Tweaks/PSHeader/PhotoLibrary/PFVideoAdjustments.h b/Tweaks/PSHeader/PhotoLibrary/PFVideoAdjustments.h deleted file mode 100644 index 8fee9ce..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PFVideoAdjustments.h +++ /dev/null @@ -1,16 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(7_0) -@interface PFVideoAdjustments : NSObject - -+ (CMTimeRange)defaultSlowMotionTimeRangeForDuration:(CMTime)duration; -+ (float)defaultSlowMotionRateForNominalFrameRate:(float)framerate; - -@property CMTimeRange slowMotionTimeRange; - -- (id)initWithURL:(NSURL *)url; -- (id)initWithSlowMotionTimeRange:(CMTimeRange)range rate:(float)rate; - -- (BOOL)isRecognizedFormat; - -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PHAsset.h b/Tweaks/PSHeader/PhotoLibrary/PHAsset.h deleted file mode 100644 index 0be017b..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PHAsset.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "PLManagedAsset.h" - -@interface PHAsset : NSObject -- (PLManagedAsset *)pl_managedAsset; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLCIFilterUtilties.h b/Tweaks/PSHeader/PhotoLibrary/PLCIFilterUtilties.h deleted file mode 100644 index 2fcb93e..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLCIFilterUtilties.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface PLCIFilterUtilties : NSObject -+ (CIImage *)outputImageFromFilters:(NSArray *)filters inputImage:(CIImage *)inputImage orientation:(UIImageOrientation)orientation copyFiltersFirst:(BOOL)copyFirst; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLEditPhotoController.h b/Tweaks/PSHeader/PhotoLibrary/PLEditPhotoController.h deleted file mode 100644 index 9cca055..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLEditPhotoController.h +++ /dev/null @@ -1,19 +0,0 @@ -#import - -NS_CLASS_AVAILABLE_IOS(5_0) -@interface PLEditPhotoController : UIViewController - -@property (readonly) CGRect normalizedCropRect; - -- (UINavigationItem *)navigationItem; -- (CIImage *)_newCIImageFromUIImage:(UIImage *)image; -- (NSArray *)_currentNonGeometryFiltersWithEffectFilters:(NSArray *)filters; -- (NSArray *)_cropAndStraightenFiltersForImageSize:(CGSize)size forceSquareCrop:(BOOL)crop forceUseGeometry:(BOOL)geometry; - -- (void)_setControlsEnabled:(BOOL)enabled animated:(BOOL)animated; -- (void)_presentSavingHUD; -- (void)_dismissSavingHUD; -- (void)save:(UIBarButtonItem *)item; -- (void)cancel:(UIBarButtonItem *)item; -- (void)saveAdjustments; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLManagedAsset.h b/Tweaks/PSHeader/PhotoLibrary/PLManagedAsset.h deleted file mode 100644 index 6bdaa94..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLManagedAsset.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "_PLManagedAsset.h" - -@interface PLManagedAsset : _PLManagedAsset -@property (readonly, nonatomic) NSString *pathForImageFile; -@property (readonly, nonatomic) NSString *pathForOriginalFile; -@property (readonly, nonatomic) NSString *pathForAdjustmentFile; -@property short kindSubtype; -@property short savedAssetType; -@property BOOL hasAdjustments; -- (BOOL)isMogul NS_AVAILABLE_IOS(7_0); -- (BOOL)isVideo; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLPhotoBrowserController.h b/Tweaks/PSHeader/PhotoLibrary/PLPhotoBrowserController.h deleted file mode 100644 index cce972d..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLPhotoBrowserController.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "PLVideoView.h" -#import "PLManagedAsset.h" - -NS_CLASS_AVAILABLE_IOS(5_0) -@interface PLPhotoBrowserController : UIViewController -@property (assign, nonatomic) BOOL isCameraApp; -@property (readonly, assign, nonatomic) PLVideoView *currentVideoView; -- (PLManagedAsset *)currentAsset; -- (UINavigationBar *)navigationBar; -- (BOOL)isEditingVideo; -- (id)_toolbarButtonForIdentifier:(NSString *)identifier; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLPhotoEffect.h b/Tweaks/PSHeader/PhotoLibrary/PLPhotoEffect.h deleted file mode 100644 index 0620e24..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLPhotoEffect.h +++ /dev/null @@ -1,11 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PLPhotoEffect : NSObject -+ (NSArray *)allEffects; -+ (instancetype)_effectWithIdentifier:(NSString *)identifier CIFilterName:(NSString *)filterName displayName:(NSString *)displayName; -+ (instancetype)_effectWithIdentifier:(NSString *)identifier; -+ (instancetype)_effectWithCIFilterName:(NSString *)identifier; -+ (NSUInteger)indexOfEffectWithIdentifier:(NSString *)identifier; -- (NSString *)displayName; -- (NSString *)filterIdentifier; -- (NSString *)CIFilterName; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLProgressHUD.h b/Tweaks/PSHeader/PhotoLibrary/PLProgressHUD.h deleted file mode 100644 index 47bd863..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLProgressHUD.h +++ /dev/null @@ -1,6 +0,0 @@ -@interface PLProgressHUD : UIView -- (void)done; -- (void)showInView:(UIView *)view; -- (void)hide; -- (void)setText:(NSString *)text; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLPublisingAgent.h b/Tweaks/PSHeader/PhotoLibrary/PLPublisingAgent.h deleted file mode 100644 index 49157a8..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLPublisingAgent.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "PLManagedAsset.h" - -@interface PLPublishingAgent : NSObject -@property BOOL enableHDUpload; -@property BOOL mediaIsHDVideo; -@property NSInteger remakerMode; -@property NSInteger selectedOption; -+ (instancetype)publishingAgentForBundleNamed:(NSString *)name toPublishMedia:(PLManagedAsset *)media; -- (NSInteger)_remakerModeForSelectedOption; -- (void)_transcodeVideo:(PLManagedAsset *)asset; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PLVideoView.h b/Tweaks/PSHeader/PhotoLibrary/PLVideoView.h deleted file mode 100644 index 505cebb..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PLVideoView.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "PLManagedAsset.h" - -@interface PLVideoView : UIView - -@property (readonly) PLManagedAsset *videoCameraImage; - -- (BOOL)isPlaying; -- (BOOL)canEdit; -- (BOOL)_canAccessVideo; -- (BOOL)_mediaIsPlayable; -- (BOOL)_mediaIsVideo; -- (BOOL)_shouldShowSlalomEditor NS_AVAILABLE_IOS(7_0); - -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PUAbstractAlbumListViewController.h b/Tweaks/PSHeader/PhotoLibrary/PUAbstractAlbumListViewController.h deleted file mode 100644 index 29424fd..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PUAbstractAlbumListViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PUAbstractAlbumListViewController : UIViewController -- (UIBarButtonItem *)_internalButtonItem; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PUAvalancheReviewControllerPhoneSpec.h b/Tweaks/PSHeader/PhotoLibrary/PUAvalancheReviewControllerPhoneSpec.h deleted file mode 100644 index aee5987..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PUAvalancheReviewControllerPhoneSpec.h +++ /dev/null @@ -1,3 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PUAvalancheReviewControllerPhoneSpec : NSObject -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PUPhotoBrowserController.h b/Tweaks/PSHeader/PhotoLibrary/PUPhotoBrowserController.h deleted file mode 100644 index 1d895f5..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PUPhotoBrowserController.h +++ /dev/null @@ -1,20 +0,0 @@ -#import "PUPhotoEditViewController.h" -#import "PLVideoView.h" -#import "PLManagedAsset.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PUPhotoBrowserController : UIViewController - -@property (assign, nonatomic) BOOL isCameraApp; -@property (readonly, assign, nonatomic) PLVideoView *currentVideoView; - -- (PLManagedAsset *)currentAsset; -- (UINavigationBar *)navigationBar; - -- (BOOL)isEditingVideo; - -- (id)_toolbarButtonForIdentifier:(NSString *)identifier; - -- (void)photoEditController:(PUPhotoEditViewController *)controller didFinishWithSavedChanges:(BOOL)change; - -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PUPhotoEditProtoSettings.h b/Tweaks/PSHeader/PhotoLibrary/PUPhotoEditProtoSettings.h deleted file mode 100644 index e51131b..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PUPhotoEditProtoSettings.h +++ /dev/null @@ -1,4 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PUPhotoEditProtoSettings : NSObject -@property BOOL useOldPhotosEditor2; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PUPhotoEditViewController.h b/Tweaks/PSHeader/PhotoLibrary/PUPhotoEditViewController.h deleted file mode 100644 index cec60b6..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PUPhotoEditViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PUPhotoEditViewController : NSObject -- (UIViewController *)delegate; -- (void)_handleDoneButton:(id)arg1; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PURootSettings.h b/Tweaks/PSHeader/PhotoLibrary/PURootSettings.h deleted file mode 100644 index d9e831f..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PURootSettings.h +++ /dev/null @@ -1,6 +0,0 @@ -NS_CLASS_AVAILABLE_IOS(7_0) -@interface PURootSettings : NSObject - -+ (void)presentSettingsController; - -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PUVideoEditViewController.h b/Tweaks/PSHeader/PhotoLibrary/PUVideoEditViewController.h deleted file mode 100644 index 29860b2..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PUVideoEditViewController.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "PHAsset.h" - -NS_CLASS_AVAILABLE_IOS(8_0) -@interface PUVideoEditViewController : UIViewController -- (PHAsset *)_videoAsset; -- (void)_handleMainActionButton:(id)arg1; -- (void)_handleSaveButton:(id)arg1; -@end diff --git a/Tweaks/PSHeader/PhotoLibrary/PhotoLibrary.h b/Tweaks/PSHeader/PhotoLibrary/PhotoLibrary.h deleted file mode 100644 index 23f13b1..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/PhotoLibrary.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "_PLManagedAsset.h" -#import "PFVideoAdjustments.h" -#import "PHAsset.h" -#import "PLCIFilterUtilties.h" -#import "PLEditPhotoController.h" -#import "PLManagedAsset.h" -#import "PLPhotoBrowserController.h" -#import "PLPhotoEffect.h" -#import "PLProgressHUD.h" -#import "PLPublisingAgent.h" -#import "PLVideoView.h" -#import "PUAbstractAlbumListViewController.h" -#import "PUAvalancheReviewControllerPhoneSpec.h" -#import "PUPhotoBrowserController.h" -#import "PUPhotoEditProtoSettings.h" -#import "PUPhotoEditViewController.h" -#import "PURootSettings.h" -#import "PUVideoEditViewController.h" diff --git a/Tweaks/PSHeader/PhotoLibrary/_PLManagedAsset.h b/Tweaks/PSHeader/PhotoLibrary/_PLManagedAsset.h deleted file mode 100644 index 71700a5..0000000 --- a/Tweaks/PSHeader/PhotoLibrary/_PLManagedAsset.h +++ /dev/null @@ -1,3 +0,0 @@ -@interface _PLManagedAsset : NSObject -- (NSInteger)orientationValue; -@end diff --git a/Tweaks/PSHeader/README.md b/Tweaks/PSHeader/README.md deleted file mode 100644 index 6313610..0000000 --- a/Tweaks/PSHeader/README.md +++ /dev/null @@ -1,14 +0,0 @@ -PoomSmart's headers -=========== - -A collection of headers used by most of PoomSmart's tweaks. - -Setup -====== - -Make a folder named `PSHeader` containing all headers outside of your project folder. Also create `PS.h` header file that contains this line `#import "PSHeader/PS.h"`. - -Usage -====== - -In your tweak source code, `#import "../PS.h"` diff --git a/Tweaks/PSHeader/generateHeaders.sh b/Tweaks/PSHeader/generateHeaders.sh deleted file mode 100755 index f1bd364..0000000 --- a/Tweaks/PSHeader/generateHeaders.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -for d in $(find . -type d ! -name .git -depth 1); do - D=${d/\.\//} - cd ${D} - find . -type f -name '*.h' ! -name ${D}.h | sed 's/\.\///g' | sed '/^ *$/d;s/.*/#import "&"/' > ${D}.h - cd .. -done diff --git a/Tweaks/PSHeader/iOSVersions.h b/Tweaks/PSHeader/iOSVersions.h deleted file mode 100644 index 642e4d6..0000000 --- a/Tweaks/PSHeader/iOSVersions.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _PS_IOSVER -#define _PS_IOSVER - -#import -#import - -#define IS_IOS_BETWEEN_EEX(start, end) (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_ ## start && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_ ## end) - -#endif diff --git a/Tweaks/RemoteLog b/Tweaks/RemoteLog new file mode 160000 index 0000000..beee6c7 --- /dev/null +++ b/Tweaks/RemoteLog @@ -0,0 +1 @@ +Subproject commit beee6c731223abdd9b9d7a69d5df79e5b51b6a53 diff --git a/Tweaks/RemoteLog/README.md b/Tweaks/RemoteLog/README.md deleted file mode 100644 index af2ee3b..0000000 --- a/Tweaks/RemoteLog/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## Usage - -RemoteLog supports all the format specifiers of `NSLog` so it should be very easy to migrate to. - -- Copy `RemoteLog.h` to `$THEOS/include` -- Change the ip addresses in the `RemoteLog.h` file to match your computer's ip address -- Include the header in any source files you want to use it in: -``` -#include -``` -- Replace calls to `NSLog` with calls to `RLog`: -``` -RLog(@"Test log: %@", someObject); -``` -- Run the python server on your computer and watch the logs coming in :) diff --git a/Tweaks/RemoteLog/RemoteLog.h b/Tweaks/RemoteLog/RemoteLog.h deleted file mode 100644 index d9759b3..0000000 --- a/Tweaks/RemoteLog/RemoteLog.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _REMOTE_LOG_H_ -#define _REMOTE_LOG_H_ - -#import -#import -#import -#import - -// change this to match your destination (server) IP address -#define RLOG_IP_ADDRESS "replace with ip" -#define RLOG_PORT 11909 - -__attribute__((unused)) static void RLogv(NSString* format, va_list args) -{ - #if DEBUG - NSString* str = [[NSString alloc] initWithFormat:format arguments:args]; - - int sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sd <= 0) - { - NSLog(@"[RemoteLog] Error: Could not open socket"); - return; - } - - int broadcastEnable = 1; - int ret = setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); - if (ret) - { - NSLog(@"[RemoteLog] Error: Could not open set socket to broadcast mode"); - close(sd); - return; - } - - struct sockaddr_in broadcastAddr; - memset(&broadcastAddr, 0, sizeof broadcastAddr); - broadcastAddr.sin_family = AF_INET; - inet_pton(AF_INET, RLOG_IP_ADDRESS, &broadcastAddr.sin_addr); - broadcastAddr.sin_port = htons(RLOG_PORT); - - char* request = (char*)[str UTF8String]; - ret = sendto(sd, request, strlen(request), 0, (struct sockaddr*)&broadcastAddr, sizeof broadcastAddr); - if (ret < 0) - { - NSLog(@"[RemoteLog] Error: Could not send broadcast"); - close(sd); - return; - } - close(sd); - #endif -} - -__attribute__((unused)) static void RLog(NSString* format, ...) -{ - #if DEBUG - va_list args; - va_start(args, format); - RLogv(format, args); - va_end(args); - #endif -} -#endif diff --git a/Tweaks/RemoteLog/rlogserver.py b/Tweaks/RemoteLog/rlogserver.py deleted file mode 100644 index b14685c..0000000 --- a/Tweaks/RemoteLog/rlogserver.py +++ /dev/null @@ -1,19 +0,0 @@ -# created by Tonyk7 -import logging -import socket - -# change this to match the port in RemoteLog.h -rlog_port = 11909 - -# code is from: https://gist.github.com/majek/1763628 -def udp_server(host="0.0.0.0", port=rlog_port): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind((host, port)) - - while True: - (data, addr) = s.recvfrom(128*1024) - yield data - -for data in udp_server(): - print(data.decode('utf-8').strip()) diff --git a/Tweaks/Return-YouTube-Dislikes b/Tweaks/Return-YouTube-Dislikes new file mode 160000 index 0000000..91fc25a --- /dev/null +++ b/Tweaks/Return-YouTube-Dislikes @@ -0,0 +1 @@ +Subproject commit 91fc25a8504faa62eca55dae451fe11ac7d1602d diff --git a/Tweaks/Return-YouTube-Dislikes/.gitattributes b/Tweaks/Return-YouTube-Dislikes/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Tweaks/Return-YouTube-Dislikes/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Tweaks/Return-YouTube-Dislikes/.gitignore b/Tweaks/Return-YouTube-Dislikes/.gitignore deleted file mode 100644 index 9c04476..0000000 --- a/Tweaks/Return-YouTube-Dislikes/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos -.DS_Store -packages diff --git a/Tweaks/Return-YouTube-Dislikes/LICENSE b/Tweaks/Return-YouTube-Dislikes/LICENSE deleted file mode 100644 index f288702..0000000 --- a/Tweaks/Return-YouTube-Dislikes/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/Tweaks/Return-YouTube-Dislikes/Makefile b/Tweaks/Return-YouTube-Dislikes/Makefile deleted file mode 100644 index 2431cdd..0000000 --- a/Tweaks/Return-YouTube-Dislikes/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -TARGET := iphone:clang:latest:11.0 -INSTALL_TARGET_PROCESSES = YouTube -ARCHS = arm64 -DEBUG = 0 - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YouTubeDislikesReturn -$(TWEAK_NAME)_FILES = Tweak.xm -$(TWEAK_NAME)_CFLAGS = -fobjc-arc - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/Return-YouTube-Dislikes/README.md b/Tweaks/Return-YouTube-Dislikes/README.md deleted file mode 100644 index 6c06100..0000000 --- a/Tweaks/Return-YouTube-Dislikes/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Return-YouTube-Dislikes - -An iOS tweak that brings back dislikes on YouTube app, sideloadable. - -## How it works - -The tweak accesses the [Return YouTube Dislike](https://www.returnyoutubedislike.com) database. The 11-digit identifier of videos and shorts you watch will be shared with the Return YouTube Dislike server in order to retrieve dislike count data and have that replaced the "Dislike" text with the actual number. - -The tweak also provides an option to submit your like/dislike data to their RYD database, along with your uniquely generated anonymous ID and the video identifier. Head over to Settings > General and you will see "Enable vote submission" option near the bottom. This option is disabled by default. - -## Building - -- Clone this project (of course). -- Use latest [Theos](https://github.com/theos/theos). -- Have [YouTubeHeader](https://github.com/PoomSmart/YouTubeHeader) cloned alongside this project. -- Run `make` or `make package FINALPACKAGE=1` in your Terminal. - -## Credits - -Vote submission code is ported to Objective-C, from https://github.com/Anarios/return-youtube-dislike diff --git a/Tweaks/Return-YouTube-Dislikes/Tweak.h b/Tweaks/Return-YouTube-Dislikes/Tweak.h deleted file mode 100644 index 56ba2b0..0000000 --- a/Tweaks/Return-YouTube-Dislikes/Tweak.h +++ /dev/null @@ -1,28 +0,0 @@ -#import "../YouTubeHeader/YTIFormattedString.h" -#import "../YouTubeHeader/YTAlertView.h" -#import "../YouTubeHeader/YTQTMButton.h" -#import "../YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h" -#import "../YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h" -#import "../YouTubeHeader/YTIToggleButtonRenderer.h" -#import "../YouTubeHeader/YTIButtonSupportedRenderers.h" -#import "../YouTubeHeader/YTSlimVideoDetailsActionView.h" -#import "../YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h" -#import "../YouTubeHeader/YTILikeButtonRenderer.h" -#import "../YouTubeHeader/YTReelWatchLikesController.h" -#import "../YouTubeHeader/YTSettingsCell.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../YouTubeHeader/YTSettingsViewController.h" -#import "../YouTubeHeader/YTPlayerViewController.h" -#import "../YouTubeHeader/YTWatchController.h" -#import "../YouTubeHeader/ELMContainerNode.h" -#import "../YouTubeHeader/ELMTextNode.h" -#import "../YouTubeHeader/ELMNodeController.h" -#import "../YouTubeHeader/ELMNodeFactory.h" -#import "../YouTubeHeader/ASNodeContext.h" -#import "../YouTubeHeader/_ASDisplayView.h" -#import "../YouTubeHeader/UIView+AsyncDisplayKit.h" - -@interface ELMTextNode (RYD) -@property (assign) BOOL blockUpdate; -@end diff --git a/Tweaks/Return-YouTube-Dislikes/Tweak.xm b/Tweaks/Return-YouTube-Dislikes/Tweak.xm deleted file mode 100644 index 4554999..0000000 --- a/Tweaks/Return-YouTube-Dislikes/Tweak.xm +++ /dev/null @@ -1,833 +0,0 @@ -#import -#import -#import -#import -#import -#import "unicode/unum.h" -#import "Tweak.h" - -#define TWEAK_NAME @"Return YouTube Dislike" -#define maxRetryCount 3 -#define apiUrl @"https://returnyoutubedislikeapi.com" -#define UserIDKey @"RYD-USER-ID" -#define RegistrationConfirmedKey @"RYD-USER-REGISTERED" -#define EnabledKey @"RYD-ENABLED" -#define EnableVoteSubmissionKey @"RYD-VOTE-SUBMISSION" -#define ExactLikeKey @"RYD-EXACT-LIKE-NUMBER" -#define ExactDislikeKey @"RYD-EXACT-NUMBER" -#define DidShowEnableVoteSubmissionAlertKey @"RYD-DID-SHOW-VOTE-SUBMISSION-ALERT" -#define FETCHING @"⌛" -#define FAILED @"❌" - -#define _LOC(b, x) [b localizedStringForKey:x value:nil table:nil] -#define LOC(x) _LOC(tweakBundle, x) - -static const NSInteger RYDSection = 1080; - -@interface YTSettingsSectionItemManager (RYD) -- (void)updateRYDSectionWithEntry:(id)entry; -@end - -static NSCache *cache; - -void (*ASNodeContextPush)(ASNodeContext *); -void (*ASNodeContextPop)(void); - -NSBundle *RYDBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"RYD" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/RYD.bundle")]; - }); - return bundle; -} - -static int toRYDLikeStatus(YTLikeStatus likeStatus) { - switch (likeStatus) { - case YTLikeStatusLike: - return 1; - case YTLikeStatusDislike: - return -1; - default: - return 0; - } -} - -static NSString *getUserID() { - return [[NSUserDefaults standardUserDefaults] stringForKey:UserIDKey]; -} - -static BOOL isRegistered() { - return [[NSUserDefaults standardUserDefaults] boolForKey:RegistrationConfirmedKey]; -} - -static BOOL TweakEnabled() { - return [[NSUserDefaults standardUserDefaults] boolForKey:EnabledKey]; -} - -static BOOL VoteSubmissionEnabled() { - return [[NSUserDefaults standardUserDefaults] boolForKey:EnableVoteSubmissionKey]; -} - -static BOOL ExactLikeNumber() { - return [[NSUserDefaults standardUserDefaults] boolForKey:ExactLikeKey]; -} - -static BOOL ExactDislikeNumber() { - return [[NSUserDefaults standardUserDefaults] boolForKey:ExactDislikeKey]; -} - -static const char *charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -// Ported to objc from RYD browser extension -static NSString *generateUserID() { - NSString *existingID = getUserID(); - if (existingID) return existingID; - HBLogDebug(@"generateUserID()"); - char userID[36 + 1]; - for (int i = 0; i < 36; ++i) - userID[i] = charset[arc4random_uniform(64)]; - userID[36] = '\0'; - NSString *result = [NSString stringWithUTF8String:userID]; - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:result forKey:UserIDKey]; - [defaults synchronize]; - return result; -} - -// Ported to objc from RYD browser extension -static int countLeadingZeroes(uint8_t *hash) { - int zeroes = 0; - int value = 0; - for (int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++) { - value = hash[i]; - if (value == 0) - zeroes += 8; - else { - int count = 1; - if (value >> 4 == 0) { - count += 4; - value <<= 4; - } - if (value >> 6 == 0) { - count += 2; - value <<= 2; - } - zeroes += count - (value >> 7); - break; - } - } - return zeroes; -} - -// Ported to objc from RYD browser extension -static NSString *btoa(NSString *input) { - NSMutableString *output = [NSMutableString string]; - for (int i = 0; i < input.length; i += 3) { - int groupsOfSix[4] = { -1, -1, -1, -1 }; - unichar ci = [input characterAtIndex:i]; - groupsOfSix[0] = ci >> 2; - groupsOfSix[1] = (ci & 0x03) << 4; - if (input.length > i + 1) { - unichar ci1 = [input characterAtIndex:i + 1]; - groupsOfSix[1] |= ci1 >> 4; - groupsOfSix[2] = (ci1 & 0x0f) << 2; - } - if (input.length > i + 2) { - unichar ci2 = [input characterAtIndex:i + 2]; - groupsOfSix[2] |= ci2 >> 6; - groupsOfSix[3] = ci2 & 0x3f; - } - for (int j = 0; j < 4; ++j) { - if (groupsOfSix[j] == -1) - [output appendString:@"="]; - else - [output appendFormat:@"%c", charset[groupsOfSix[j]]]; - } - } - return output; -} - -static void fetch( - NSString *endpoint, - NSString *method, - NSDictionary *body, - void (^dataHandler)(NSDictionary *data), - BOOL (^responseCodeHandler)(NSUInteger responseCode), - void (^networkErrorHandler)(void), - void (^dataErrorHandler)(void) -) { - NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", apiUrl, endpoint]]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; - NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; - urlRequest.HTTPMethod = method; - if (body) { - [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; - NSError *error = nil; - NSData *data = [NSJSONSerialization dataWithJSONObject:body options:NSJSONWritingPrettyPrinted error:&error]; - if (error) { - if (dataErrorHandler) { - dispatch_async(dispatch_get_main_queue(), ^{ - dataErrorHandler(); - }); - } - return; - } - HBLogDebug(@"fetch() POST body: %@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]); - urlRequest.HTTPBody = data; - } else - [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"]; - [[session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - NSUInteger responseCode = [httpResponse statusCode]; - if (responseCodeHandler) { - if (!responseCodeHandler(responseCode)) - return; - } - if (error || responseCode != 200) { - HBLogDebug(@"fetch() error requesting: %@ (%lu)", error, responseCode); - if (networkErrorHandler) { - dispatch_async(dispatch_get_main_queue(), ^{ - networkErrorHandler(); - }); - } - return; - } - NSError *jsonError; - NSDictionary *myData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingFragmentsAllowed error:&jsonError]; - if (jsonError) { - HBLogDebug(@"fetch() error decoding response: %@", jsonError); - if (dataErrorHandler) { - dispatch_async(dispatch_get_main_queue(), ^{ - dataErrorHandler(); - }); - } - return; - } - dispatch_async(dispatch_get_main_queue(), ^{ - dataHandler(myData); - }); - }] resume]; -} - -// Ported to objc from RYD browser extension -static NSString *solvePuzzle(NSDictionary *data) { - NSString *solution = nil; - NSString *challenge = data[@"challenge"]; - int difficulty = [data[@"difficulty"] intValue]; - NSData *cd = [[NSData alloc] initWithBase64EncodedString:challenge options:0]; - NSString *decoded = [[NSString alloc] initWithData:cd encoding:NSASCIIStringEncoding]; - uint8_t c[decoded.length]; - char *buffer = (char *)calloc(20, sizeof(char)); - uint32_t *uInt32View = (uint32_t *)buffer; - for (int i = 0; i < decoded.length; ++i) - c[i] = [decoded characterAtIndex:i]; - int maxCount = (1 << difficulty) * 3; - for (int i = 4; i < 20; ++i) - buffer[i] = c[i - 4]; - for (int i = 0; i < maxCount; ++i) { - uInt32View[0] = i; - uint8_t hash[CC_SHA512_DIGEST_LENGTH] = {0}; - CC_SHA512(buffer, 20, hash); - if (countLeadingZeroes(hash) >= difficulty) { - char chars[4] = { buffer[0], buffer[1], buffer[2], buffer[3] }; - NSString *s = [[NSString alloc] initWithBytes:chars length:4 encoding:NSASCIIStringEncoding]; - solution = btoa(s); - HBLogDebug(@"solvePuzzle() success (%@)", solution); - break; - } - } - free(buffer); - if (!solution) - HBLogDebug(@"solvePuzzle() failed"); - return solution; -} - -// Ported to objc from RYD browser extension -static void registerUser() { - NSString *userId = generateUserID(); - HBLogDebug(@"registerUser() (%@)", userId); - NSString *puzzleEndpoint = [NSString stringWithFormat:@"/puzzle/registration?userId=%@", userId]; - fetch( - puzzleEndpoint, - @"GET", - nil, - ^(NSDictionary *data) { - NSString *solution = solvePuzzle(data); - if (!solution) { - HBLogDebug(@"registerUser() skipped"); - return; - } - fetch( - puzzleEndpoint, - @"POST", - @{ @"solution": solution }, - ^(NSDictionary *data) { - if ([data isKindOfClass:[NSNumber class]] && ![(NSNumber *)data boolValue]) { - HBLogInfo(@"registerUser() failed"); - return; - } - if (!isRegistered()) { - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:RegistrationConfirmedKey]; - [[NSUserDefaults standardUserDefaults] synchronize]; - } - HBLogDebug(@"registerUser() success or already registered"); - }, - NULL, - ^() { - HBLogDebug(@"registerUser() puzzle failed (network)"); - }, - ^() { - HBLogDebug(@"registerUser() puzzle failed (data)"); - } - ); - }, - NULL, - ^() { - HBLogDebug(@"registerUser() failed (network)"); - }, - ^() { - HBLogDebug(@"registerUser() failed (data)"); - } - ); -} - -// Ported to objc from RYD browser extension -static void sendVote(NSString *videoId, YTLikeStatus s) { - NSString *userId = getUserID(); - if (!userId || !isRegistered()) { - registerUser(); - return; - } - int likeStatus = toRYDLikeStatus(s); - HBLogDebug(@"sendVote(%@, %d)", videoId, likeStatus); - fetch( - @"/interact/vote", - @"POST", - @{ - @"userId": userId, - @"videoId": videoId, - @"value": @(likeStatus) - }, - ^(NSDictionary *data) { - NSString *solution = solvePuzzle(data); - if (!solution) { - HBLogDebug(@"sendVote() skipped"); - return; - } - fetch( - @"/interact/confirmVote", - @"POST", - @{ - @"userId": userId, - @"videoId": videoId, - @"solution": solution - }, - ^(NSDictionary *data) { - HBLogDebug(@"sendVote() success"); - }, - NULL, - ^() { - HBLogDebug(@"sendVote() confirm failed (network)"); - }, - ^() { - HBLogDebug(@"sendVote() confirm failed (data)"); - } - ); - }, - ^BOOL(NSUInteger responseCode) { - if (responseCode == 401) { - HBLogDebug(@"sendVote() error 401, trying again"); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - registerUser(); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - sendVote(videoId, s); - }); - }); - return NO; - } - return YES; - }, - ^() { - HBLogDebug(@"sendVote() failed (network)"); - }, - ^() { - HBLogDebug(@"sendVote() failed (data)"); - } - ); -} - -static NSString *formattedLongNumber(NSNumber *number, NSString *error) { - return error ?: [NSNumberFormatter localizedStringFromNumber:number numberStyle:NSNumberFormatterDecimalStyle]; -} - -static NSString *getXPointYFormat(NSString *count, char c) { - char firstInt = [count characterAtIndex:0]; - char secondInt = [count characterAtIndex:1]; - if (secondInt == '0') - return [NSString stringWithFormat:@"%c%c", firstInt, c]; - return [NSString stringWithFormat:@"%c.%c%c", firstInt, secondInt, c]; -} - -// https://gist.github.com/danpashin/5951706a6aa25748a7faa1acd5c1db8b -API_AVAILABLE(ios(13)) -static NSString *formattedShortNumber(int64_t number) { - UErrorCode status; - status = U_ZERO_ERROR; - NSString *currentLocale = [[[NSLocale preferredLanguages] firstObject] stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; - UNumberFormat *formatter = unum_open(UNUM_DECIMAL_COMPACT_SHORT, NULL, 0, [currentLocale UTF8String], NULL, &status); - assert(!U_FAILURE(status)); - status = U_ZERO_ERROR; - int32_t used = unum_formatInt64(formatter, number, NULL, 0, NULL, &status); - NSString *resultString = nil; - if (status == U_BUFFER_OVERFLOW_ERROR) { - NSUInteger length = sizeof(UChar) * (NSUInteger)used; - UChar *ustr = (UChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, (CFIndex)length + 1, 0); - status = U_ZERO_ERROR; - unum_formatInt64(formatter, number, ustr, used, NULL, &status); - resultString = [[NSString alloc] initWithBytesNoCopy:ustr length:length encoding:NSUTF16LittleEndianStringEncoding freeWhenDone:YES]; - } - unum_close(formatter); - formatter = NULL; - return resultString; -} - -static NSString *getNormalizedDislikes(NSNumber *dislikeNumber, NSString *error) { - if (!dislikeNumber) return FAILED; - if (error) return error; - if (ExactDislikeNumber()) - return formattedLongNumber(dislikeNumber, nil); - NSString *dislikeCount = [dislikeNumber stringValue]; - NSUInteger digits = dislikeCount.length; - if (digits <= 3) // 0 - 999 - return dislikeCount; - if (@available(iOS 13.0, *)) - return formattedShortNumber([dislikeNumber unsignedIntegerValue]); - if (digits == 4) // 1000 - 9999 - return getXPointYFormat(dislikeCount, 'K'); - if (digits <= 6) // 10_000 - 999_999 - return [NSString stringWithFormat:@"%@K", [dislikeCount substringToIndex:digits - 3]]; - if (digits <= 9) // 1_000_000 - 999_999_999 - return [NSString stringWithFormat:@"%@M", [dislikeCount substringToIndex:digits - 6]]; - return [NSString stringWithFormat:@"%@B", [dislikeCount substringToIndex:digits - 9]]; // 1_000_000_000+ -} - -static void getVoteFromVideoWithHandler(NSString *videoId, int retryCount, void (^handler)(NSDictionary *d, NSString *error)) { - if (retryCount <= 0) return; - NSDictionary *data = [cache objectForKey:videoId]; - if (data) { - handler(data, nil); - return; - } - fetch( - [NSString stringWithFormat:@"/votes?videoId=%@", videoId], - @"GET", - nil, - ^(NSDictionary *data) { - [cache setObject:data forKey:videoId]; - handler(data, nil); - }, - ^BOOL(NSUInteger responseCode) { - if (responseCode == 502 || responseCode == 503) { - handler(nil, @"CON"); // connection error - return NO; - } - if (responseCode == 401 || responseCode == 403 || responseCode == 407) { - handler(nil, @"AUTH"); // unauthorized - return NO; - } - if (responseCode == 429) { - handler(nil, @"RL"); // rate limit - return NO; - } - if (responseCode == 404) { - handler(nil, @"NULL"); // non-existing video - return NO; - } - if (responseCode == 400) { - handler(nil, @"INV"); // malformed video - return NO; - } - return YES; - }, - ^() { - handler(nil, FAILED); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - getVoteFromVideoWithHandler(videoId, retryCount - 1, handler); - }); - }, - ^() { - handler(nil, FAILED); - } - ); -} - -%hook YTSlimVideoDetailsActionView - -+ (YTSlimVideoDetailsActionView *)actionViewWithSlimMetadataButtonSupportedRenderer:(YTISlimMetadataButtonSupportedRenderers *)renderer withElementsContextBlock:(id)block { - if ([renderer rendererOneOfCase] == 153515154 && TweakEnabled()) - return [[%c(YTSlimVideoDetailsActionView) alloc] initWithSlimMetadataButtonSupportedRenderer:renderer]; - return %orig; -} - -- (id)initWithSlimMetadataButtonSupportedRenderer:(id)arg1 { - self = %orig; - if (self && TweakEnabled()) { - YTISlimMetadataButtonSupportedRenderers *renderer = [self valueForKey:@"_supportedRenderer"]; - if ((ExactLikeNumber() && [renderer slimButton_isLikeButton]) || [renderer slimButton_isDislikeButton]) { - YTISlimMetadataToggleButtonRenderer *meta = renderer.slimMetadataToggleButtonRenderer; - getVoteFromVideoWithHandler(meta.target.videoId, maxRetryCount, ^(NSDictionary *data, NSString *error) { - dispatch_async(dispatch_get_main_queue(), ^{ - if ([renderer slimButton_isDislikeButton]) - [self.label setFormattedString:[%c(YTIFormattedString) formattedStringWithString:getNormalizedDislikes(data[@"dislikes"], error)]]; - else if ([renderer slimButton_isLikeButton] && error == nil) - [self.label setFormattedString:[%c(YTIFormattedString) formattedStringWithString:formattedLongNumber(data[@"likes"], nil)]]; - [self setNeedsLayout]; - }); - }); - } - } - return self; -} - -- (void)setToggled:(BOOL)toggled { - if (!TweakEnabled()) { - %orig; - return; - } - YTISlimMetadataButtonSupportedRenderers *renderer = [self valueForKey:@"_supportedRenderer"]; - BOOL isLikeButton = ExactLikeNumber() && [renderer slimButton_isLikeButton]; - BOOL isDislikeButton = [renderer slimButton_isDislikeButton]; - YTISlimMetadataToggleButtonRenderer *meta = renderer.slimMetadataToggleButtonRenderer; - YTIToggleButtonRenderer *buttonRenderer = meta.button.toggleButtonRenderer; - BOOL changed = NO; - if (isLikeButton || isDislikeButton) { - changed = self.toggled != toggled; - YTIFormattedString *formattedText = [%c(YTIFormattedString) formattedStringWithString:FETCHING]; - buttonRenderer.defaultText = formattedText; - buttonRenderer.toggledText = formattedText; - } - %orig; - if (changed && (isLikeButton || isDislikeButton)) { - getVoteFromVideoWithHandler(meta.target.videoId, maxRetryCount, ^(NSDictionary *data, NSString *error) { - NSString *defaultText = isDislikeButton ? getNormalizedDislikes(data[@"dislikes"], error) : formattedLongNumber(data[@"likes"], error); - NSString *toggledText = isDislikeButton ? getNormalizedDislikes(@([data[@"dislikes"] unsignedIntegerValue] + 1), error) : formattedLongNumber(@([data[@"likes"] unsignedIntegerValue] + 1), error); - YTIFormattedString *formattedDefaultText = [%c(YTIFormattedString) formattedStringWithString:defaultText]; - YTIFormattedString *formattedToggledText = [%c(YTIFormattedString) formattedStringWithString:toggledText]; - buttonRenderer.defaultText = formattedDefaultText; - buttonRenderer.toggledText = formattedToggledText; - if ([self isKindOfClass:%c(YTSlimVideoDetailsActionView)]) { - [self.label setFormattedString:toggled ? formattedToggledText : formattedDefaultText]; - [self setNeedsLayout]; - } - }); - } -} - -%end - -%hook YTFullscreenEngagementActionBarButtonView - -- (void)updateButtonAndLabelForToggled:(BOOL)toggled { - if (!TweakEnabled()) { - %orig; - return; - } - YTFullscreenEngagementActionBarButtonRenderer *renderer = [self valueForKey:@"_buttonRenderer"]; - BOOL isLikeButton = ExactLikeNumber() && [renderer isLikeButton]; - BOOL isDislikeButton = [renderer isDislikeButton]; - YTISlimMetadataToggleButtonRenderer *meta = [renderer valueForKey:@"_toggleButtonRenderer"]; - YTIToggleButtonRenderer *buttonRenderer = meta.button.toggleButtonRenderer; - if (isLikeButton || isDislikeButton) { - YTIFormattedString *formattedText = [%c(YTIFormattedString) formattedStringWithString:FETCHING]; - buttonRenderer.defaultText = formattedText; - buttonRenderer.toggledText = formattedText; - } - %orig; - if (isLikeButton || isDislikeButton) { - getVoteFromVideoWithHandler(meta.target.videoId, maxRetryCount, ^(NSDictionary *data, NSString *error) { - NSString *defaultText = isDislikeButton ? getNormalizedDislikes(data[@"dislikes"], error) : formattedLongNumber(data[@"likes"], error); - NSString *toggledText = isDislikeButton ? getNormalizedDislikes(@([data[@"dislikes"] unsignedIntegerValue] + 1), error) : formattedLongNumber(@([data[@"likes"] unsignedIntegerValue] + 1), error); - YTIFormattedString *formattedDefaultText = [%c(YTIFormattedString) formattedStringWithString:defaultText]; - YTIFormattedString *formattedToggledText = [%c(YTIFormattedString) formattedStringWithString:toggledText]; - buttonRenderer.defaultText = formattedDefaultText; - buttonRenderer.toggledText = formattedToggledText; - if ([self isKindOfClass:%c(YTFullscreenEngagementActionBarButtonView)]) { - [self.label setFormattedString:toggled ? formattedToggledText : formattedDefaultText]; - [self setNeedsLayout]; - } - }); - } -} - -%end - -%hook YTReelWatchLikesController - -- (void)updateLikeButtonWithRenderer:(YTILikeButtonRenderer *)renderer { - %orig; - if (!TweakEnabled()) return; - YTQTMButton *dislikeButton = self.dislikeButton; - [dislikeButton setTitle:FETCHING forState:UIControlStateNormal]; - [dislikeButton setTitle:FETCHING forState:UIControlStateSelected]; - YTLikeStatus likeStatus = renderer.likeStatus; - getVoteFromVideoWithHandler(renderer.target.videoId, maxRetryCount, ^(NSDictionary *data, NSString *error) { - NSString *formattedDislikeCount = getNormalizedDislikes(data[@"dislikes"], error); - NSString *formattedToggledDislikeCount = getNormalizedDislikes(@([data[@"dislikes"] unsignedIntegerValue] + 1), error); - YTIFormattedString *formattedText = [%c(YTIFormattedString) formattedStringWithString:formattedDislikeCount]; - YTIFormattedString *formattedToggledText = [%c(YTIFormattedString) formattedStringWithString:formattedToggledDislikeCount]; - if (renderer.hasDislikeCountText) - renderer.dislikeCountText = formattedText; - if (renderer.hasDislikeCountWithDislikeText) - renderer.dislikeCountWithDislikeText = formattedToggledText; - if (renderer.hasDislikeCountWithUndislikeText) - renderer.dislikeCountWithUndislikeText = formattedText; - dispatch_async(dispatch_get_main_queue(), ^{ - if (likeStatus == YTLikeStatusDislike) { - [dislikeButton setTitle:[renderer.dislikeCountWithUndislikeText stringWithFormattingRemoved] forState:UIControlStateNormal]; - [dislikeButton setTitle:[renderer.dislikeCountText stringWithFormattingRemoved] forState:UIControlStateSelected]; - } else { - [dislikeButton setTitle:[renderer.dislikeCountText stringWithFormattingRemoved] forState:UIControlStateNormal]; - [dislikeButton setTitle:[renderer.dislikeCountWithDislikeText stringWithFormattingRemoved] forState:UIControlStateSelected]; - } - }); - if (ExactLikeNumber() && error == nil) { - YTQTMButton *likeButton = self.likeButton; - NSString *formattedLikeCount = formattedLongNumber(data[@"likes"], nil); - NSString *formattedToggledLikeCount = getNormalizedDislikes(@([data[@"likes"] unsignedIntegerValue] + 1), nil); - YTIFormattedString *formattedText = [%c(YTIFormattedString) formattedStringWithString:formattedLikeCount]; - YTIFormattedString *formattedToggledText = [%c(YTIFormattedString) formattedStringWithString:formattedToggledLikeCount]; - if (renderer.hasLikeCountText) - renderer.likeCountText = formattedText; - if (renderer.hasLikeCountWithLikeText) - renderer.likeCountWithLikeText = formattedToggledText; - if (renderer.hasLikeCountWithUnlikeText) - renderer.likeCountWithUnlikeText = formattedText; - dispatch_async(dispatch_get_main_queue(), ^{ - if (likeStatus == YTLikeStatusLike) { - [likeButton setTitle:[renderer.likeCountWithUnlikeText stringWithFormattingRemoved] forState:UIControlStateNormal]; - [likeButton setTitle:[renderer.likeCountText stringWithFormattingRemoved] forState:UIControlStateSelected]; - } else { - [likeButton setTitle:[renderer.likeCountText stringWithFormattingRemoved] forState:UIControlStateNormal]; - [likeButton setTitle:[renderer.likeCountWithLikeText stringWithFormattingRemoved] forState:UIControlStateSelected]; - } - }); - } - }); -} - -%end - -%hook YTLikeService - -- (void)makeRequestWithStatus:(YTLikeStatus)likeStatus target:(YTILikeTarget *)target clickTrackingParams:(id)arg3 requestParams:(id)arg4 responseBlock:(id)arg5 errorBlock:(id)arg6 { - if (TweakEnabled() && VoteSubmissionEnabled()) - sendVote(target.videoId, likeStatus); - %orig; -} - -- (void)makeRequestWithStatus:(YTLikeStatus)likeStatus target:(YTILikeTarget *)target clickTrackingParams:(id)arg3 queueContextParams:(id)arg4 requestParams:(id)arg5 responseBlock:(id)arg6 errorBlock:(id)arg7 { - if (TweakEnabled() && VoteSubmissionEnabled()) - sendVote(target.videoId, likeStatus); - %orig; -} - -%end - -%hook ELMTextNode - -%property (assign) BOOL blockUpdate; - -- (void)updatedAttributedText { - if (self.blockUpdate) return; - %orig; -} - -%end - -%hook _ASDisplayView - -- (void)didMoveToSuperview { - %orig; - if (!TweakEnabled()) return; - int mode = 0; - BOOL pair = NO; - BOOL exactLikeNumber = ExactLikeNumber(); - ELMContainerNode *node = (ELMContainerNode *)self.keepalive_node; - if (![node.accessibilityIdentifier isEqualToString:@"id.video.dislike.button"]) { - if (![node.accessibilityIdentifier isEqualToString:@"id.video.like.button"]) - return; - mode = 1; - } - UIViewController *vc = [node closestViewController]; - if (![vc isKindOfClass:%c(YTWatchNextResultsViewController)]) return; - if (node.yogaChildren.count < 1) return; - ELMTextNode *likeTextNode = nil; - ELMTextNode *dislikeTextNode = nil; - NSMutableAttributedString *mutableDislikeText = nil; - if (mode == 0) { - _ASDisplayView *superview = (_ASDisplayView *)self.superview; - ELMContainerNode *snode = (ELMContainerNode *)superview.keepalive_node; - ELMContainerNode *likeNode = snode.yogaChildren[0]; - if ([likeNode.accessibilityIdentifier isEqualToString:@"id.video.like.button"] && likeNode.yogaChildren.count == 2) { - likeTextNode = likeNode.yogaChildren[1]; - if (![likeTextNode isKindOfClass:%c(ELMTextNode)]) return; - ASNodeContext *context = [(ASNodeContext *)[%c(ASNodeContext) alloc] initWithOptions:1]; - ASNodeContextPush(context); - dislikeTextNode = [[%c(ELMTextNode) alloc] initWithElement:likeTextNode.element context:[likeTextNode valueForKey:@"_context"]]; - ASNodeContextPop(); - mutableDislikeText = [[NSMutableAttributedString alloc] initWithAttributedString:likeTextNode.attributedText]; - dislikeTextNode.attributedText = mutableDislikeText; - [node addYogaChild:dislikeTextNode]; - dislikeTextNode.blockUpdate = YES; - [self addSubview:dislikeTextNode.view]; - pair = YES; - } else { - dislikeTextNode = node.yogaChildren[1]; - if (![dislikeTextNode isKindOfClass:%c(ELMTextNode)]) return; - mutableDislikeText = [[NSMutableAttributedString alloc] initWithAttributedString:dislikeTextNode.attributedText]; - } - } else { - likeTextNode = node.yogaChildren[1]; - if (![likeTextNode isKindOfClass:%c(ELMTextNode)]) return; - } - NSObject *wc = [vc valueForKey:@"_metadataPanelStateProvider"]; - YTPlayerViewController *pvc; - @try { - YTWatchPlaybackController *wpc = ((YTWatchController *)wc).watchPlaybackController; - pvc = [wpc valueForKey:@"_playerViewController"]; - } @catch (id ex) { - pvc = [wc valueForKey:@"_playerViewController"]; - } - NSString *videoId = [pvc currentVideoID]; - if (mode == 0) { - mutableDislikeText.mutableString.string = FETCHING; - dislikeTextNode.attributedText = mutableDislikeText; - } - getVoteFromVideoWithHandler(videoId, maxRetryCount, ^(NSDictionary *data, NSString *error) { - dispatch_async(dispatch_get_main_queue(), ^{ - if (exactLikeNumber && error == nil) { - NSString *likeCount = formattedLongNumber(data[@"likes"], nil); - if (likeCount) { - NSMutableAttributedString *mutableLikeText = [[NSMutableAttributedString alloc] initWithAttributedString:likeTextNode.attributedText]; - mutableLikeText.mutableString.string = likeCount; - likeTextNode.attributedText = mutableLikeText; - likeTextNode.accessibilityLabel = likeCount; - } - } - if (mode == 0) { - NSString *dislikeCount = getNormalizedDislikes(data[@"dislikes"], error); - mutableDislikeText.mutableString.string = pair ? [NSString stringWithFormat:@" %@ ", dislikeCount] : dislikeCount; - dislikeTextNode.attributedText = mutableDislikeText; - dislikeTextNode.accessibilityLabel = dislikeCount; - } - }); - }); -} - -%end - -static void enableVoteSubmission(BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:EnableVoteSubmissionKey]; -} - -%hook YTAppSettingsPresentationData - -+ (NSArray *)settingsCategoryOrder { - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - NSUInteger insertIndex = [order indexOfObject:@(1)]; - if (insertIndex != NSNotFound) - [mutableOrder insertObject:@(RYDSection) atIndex:insertIndex + 1]; - return mutableOrder; -} - -%end - -%hook YTSettingsSectionItemManager - -%new(v@:@) -- (void)updateRYDSectionWithEntry:(id)entry { - NSMutableArray *sectionItems = [NSMutableArray array]; - NSBundle *tweakBundle = RYDBundle(); - YTSettingsViewController *delegate = [self valueForKey:@"_dataDelegate"]; - YTSettingsSectionItem *enabled = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"ENABLED") - titleDescription:nil - accessibilityIdentifier:nil - switchOn:TweakEnabled() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:EnabledKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:enabled]; - YTSettingsSectionItem *vote = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"ENABLE_VOTE_SUBMIT") - titleDescription:[NSString stringWithFormat:LOC(@"ENABLE_VOTE_SUBMIT_DESC"), apiUrl] - accessibilityIdentifier:nil - switchOn:VoteSubmissionEnabled() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - enableVoteSubmission(enabled); - return YES; - } - settingItemId:0]; - [sectionItems addObject:vote]; - YTSettingsSectionItem *exactDislike = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"EXACT_DISLIKE_NUMBER") - titleDescription:[NSString stringWithFormat:LOC(@"EXACT_DISLIKE_NUMBER_DESC"), @"12345", [NSNumberFormatter localizedStringFromNumber:@(12345) numberStyle:NSNumberFormatterDecimalStyle]] - accessibilityIdentifier:nil - switchOn:ExactDislikeNumber() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:ExactDislikeKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:exactDislike]; - YTSettingsSectionItem *exactLike = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"EXACT_LIKE_NUMBER") - titleDescription:nil - accessibilityIdentifier:nil - switchOn:ExactLikeNumber() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:ExactLikeKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:exactLike]; - [delegate setSectionItems:sectionItems forCategory:RYDSection title:TWEAK_NAME titleDescription:nil headerHidden:NO]; -} - -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { - if (category == RYDSection) { - [self updateRYDSectionWithEntry:entry]; - return; - } - %orig; -} - -%end - -%ctor { - cache = [NSCache new]; - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - if (![defaults boolForKey:DidShowEnableVoteSubmissionAlertKey] && !VoteSubmissionEnabled()) { - [defaults setBool:YES forKey:DidShowEnableVoteSubmissionAlertKey]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - NSBundle *tweakBundle = RYDBundle(); - YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ - enableVoteSubmission(YES); - } actionTitle:_LOC([NSBundle mainBundle], @"settings.yes")]; - alertView.title = TWEAK_NAME; - alertView.subtitle = [NSString stringWithFormat:LOC(@"WANT_TO_ENABLE"), apiUrl, TWEAK_NAME, LOC(@"ENABLE_VOTE_SUBMIT")]; - [alertView show]; - }); - } - NSString *frameworkPath = [NSString stringWithFormat:@"%@/Frameworks/Module_Framework.framework/Module_Framework", NSBundle.mainBundle.bundlePath]; - NSBundle *bundle = [NSBundle bundleWithPath:frameworkPath]; - if (!bundle.loaded) [bundle load]; - MSImageRef ref = MSGetImageByName([frameworkPath UTF8String]); - ASNodeContextPush = (void (*)(ASNodeContext *))MSFindSymbol(ref, "_ASNodeContextPush"); - ASNodeContextPop = (void (*)(void))MSFindSymbol(ref, "_ASNodeContextPop"); - %init; -} \ No newline at end of file diff --git a/Tweaks/Return-YouTube-Dislikes/YouTubeDislikesReturn.plist b/Tweaks/Return-YouTube-Dislikes/YouTubeDislikesReturn.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/Return-YouTube-Dislikes/YouTubeDislikesReturn.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/Return-YouTube-Dislikes/control b/Tweaks/Return-YouTube-Dislikes/control deleted file mode 100644 index 22db836..0000000 --- a/Tweaks/Return-YouTube-Dislikes/control +++ /dev/null @@ -1,13 +0,0 @@ -Package: weeb.lillie.youtubedislikesreturn -Name: Return YouTube Dislike -Version: 1.11.3 -Architecture: iphoneos-arm -Description: Bring Back Dislikes On iOS YouTube -Maintainer: PoomSmart and kirb -Author: PoomSmart and kirb -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 11.0) -Tag: compatible_min::ios11.0 -Icon: https://img.chariz.cloud/icon/return-youtube-dislike/icon@3x.png -Header: https://img.chariz.cloud/sileo-banner/return-youtube-dislike.jpg -Depiction: https://chariz.com/get/return-youtube-dislike diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/Info.plist b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/Info.plist deleted file mode 100644 index 77a7261..0000000 Binary files a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/Info.plist and /dev/null differ diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ar.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ar.lproj/Localizable.strings deleted file mode 100644 index c5a291e..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ar.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "مفعَّل"; -"ENABLE_VOTE_SUBMIT" = "تفعيل إرسال التصويت"; -"ENABLE_VOTE_SUBMIT_DESC" = "السماح بإرسال بيانات الإعجاب وعدم الإعجاب عبر معرف فريد ومجهول المصدر (بشكل حافظ للخصوصية) إلى %@."; -"EXACT_LIKE_NUMBER" = "عدد مرات الإعجاب بالضبط"; -"EXACT_DISLIKE_NUMBER" = "عدد عدم الإعجاب بالضبط"; -"EXACT_DISLIKE_NUMBER_DESC" = "إظهار العدد الدقيق لمرات عدم الإعجاب. مثلاً: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "هل ترغب في تمكين إرسال بيانات الإعجاب وعدم الإعجاب إلى %@ الآن؟ بإمكانك تعطيل ذلك من الإعدادات > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/de.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/de.lproj/Localizable.strings deleted file mode 100644 index 7234462..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/de.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Aktiviert"; -"ENABLE_VOTE_SUBMIT" = "Bewertungen übermitteln"; -"ENABLE_VOTE_SUBMIT_DESC" = "Erlaubt, dass Ihre eindeutige, aber anonyme ID und Ihre Like-/Dislike-Bewertungen auf Videos/Shorts an %@ übermittelt werden."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Möchten Sie die Übermittlung Ihrer Like-/Dislike-Bewertungen an %@ nun genehmigen? Sie können dies jederzeit in den Einstellungen > %@ > %@ wieder deaktivieren."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/en.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 6ca22e3..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Enabled"; -"ENABLE_VOTE_SUBMIT" = "Enable vote submission"; -"ENABLE_VOTE_SUBMIT_DESC" = "Allow your unique anonymous ID and videos/shorts likes/dislikes data to be submitted to %@."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Do you want to enable submission of your likes/dislikes data to %@ now? You may disable it later from Settings > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/es.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/es.lproj/Localizable.strings deleted file mode 100644 index 2b0d686..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/es.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Habilitado"; -"ENABLE_VOTE_SUBMIT" = "Habilitar la participación de voto"; -"ENABLE_VOTE_SUBMIT_DESC" = "Autoriza que su ID anónimo único y los datos de Me gusta/No me gusta de videos/shorts se envíen a %@."; -"EXACT_LIKE_NUMBER" = "Numeros exactos de likes"; -"EXACT_DISLIKE_NUMBER" = "Numeros exactos de dislikes"; -"EXACT_DISLIKE_NUMBER_DESC" = "Mostrar el número exacto de dislikes. Por ejemplo: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "¿Quieres habilitar el envío de tus datos de Me gusta/No me gusta a %@ ahora? Puedes deshabilitarlo más tarde en Configuración > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/fr.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/fr.lproj/Localizable.strings deleted file mode 100644 index fb13a8a..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/fr.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Enabled"; -"ENABLE_VOTE_SUBMIT" = "Active l'envoie des votes"; -"ENABLE_VOTE_SUBMIT_DESC" = "Autorise votre identifiant anonyme unique ainsi que vos likes/dislikes sur les vidéos/shorts d'être envoyés à %@."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Voulez-vous autoriser l'envoi de vos données de likes/dislikes à %@ ? Vous pouvez le désactiver à tout moment dans Réglages > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/hu.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/hu.lproj/Localizable.strings deleted file mode 100644 index 33bdeab..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/hu.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Engedélyezve"; -"ENABLE_VOTE_SUBMIT" = "Szavazatküldés engedélyezése"; -"ENABLE_VOTE_SUBMIT_DESC" = "Engedélyezze egyedi névtelen azonosítójának és videóinak/rövidfilmjének tetszésnyilvánítási/nemtetszési adatainak elküldését a %@ címre."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Engedélyezi a tetszésnyilvánítási/nemtetszésnyilvánítási adatok elküldését a %@ számára? Később letilthatja a Beállítások > %@ > %@ menüpontban."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/it.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/it.lproj/Localizable.strings deleted file mode 100644 index 181ce7f..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/it.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Enabled"; -"ENABLE_VOTE_SUBMIT" = "Attiva invio voti"; -"ENABLE_VOTE_SUBMIT_DESC" = "Permette l'invio dei dati relativi al tuo ID univoco anonimizzato e ai mi piace/non mi piace sui video/shorts a %@."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Vuoi abilitare ora l'invio dei dati relativi ai tuoi mi piace/non mi piace a %@? Puoi disabilitarlo in seguito in Impostazioni > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ja.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ja.lproj/Localizable.strings deleted file mode 100644 index 4dbba90..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ja.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "有効"; -"ENABLE_VOTE_SUBMIT" = "評価の送信を許可"; -"ENABLE_VOTE_SUBMIT_DESC" = "固有の匿名IDと動画/ショートの高評価/低評価のデータを %@ に送信することを許可します。"; -"EXACT_LIKE_NUMBER" = "正確な高評価の数"; -"EXACT_DISLIKE_NUMBER" = "正確な低評価の数"; -"EXACT_DISLIKE_NUMBER_DESC" = "低評価の数を正確に表示します。 例: %@ -> %@"; - -// On app launch -"WANT_TO_ENABLE" = "高評価/低評価のデータを %@ に送信することを許可しますか?後から設定 > %@ > %@ で無効にすることができます。"; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ko.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ko.lproj/Localizable.strings deleted file mode 100644 index d36f798..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ko.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "활성화"; -"ENABLE_VOTE_SUBMIT" = "투표 제출 활성화"; -"ENABLE_VOTE_SUBMIT_DESC" = "고유한 익명 ID와 동영상/쇼츠의 좋아요/싫어요 데이터를 %@ 에 제출하도록 허용합니다."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "%@ 에 좋아요/싫어요 데이터 제출을 활성화하시겠습니까? 나중에 설정 > %@ > %@ 에서 비활성화할 수 있습니다."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/pt.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/pt.lproj/Localizable.strings deleted file mode 100644 index 0f53f4b..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/pt.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Ativado"; -"ENABLE_VOTE_SUBMIT" = "Ativar envio de votos"; -"ENABLE_VOTE_SUBMIT_DESC" = "Permite que seu único ID anônimo e dados de curtidas/não curtidas de vídeos/shorts sejam enviados para %@."; -"EXACT_LIKE_NUMBER" = "Números exatos de gostei"; -"EXACT_DISLIKE_NUMBER" = "Números exatos de não gostei"; -"EXACT_DISLIKE_NUMBER_DESC" = "Exibe o número exato de não gostei. Por exemplo: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Você deseja ativar o envio de seus dados de curtidas/não curtidas para %@ agora? Você pode desativá-lo mais tarde em Configurações > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ro.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ro.lproj/Localizable.strings deleted file mode 100644 index 848a7be..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ro.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Enabled"; -"ENABLE_VOTE_SUBMIT" = "Activați trimiterea voturilor"; -"ENABLE_VOTE_SUBMIT_DESC" = "Permiteți ca ID-ul dvs. unic anonim și datele despre apreciez/nu apreciez și video/shorts să fie trimise către %@."; -"EXACT_LIKE_NUMBER" = "Exact like numbers"; -"EXACT_DISLIKE_NUMBER" = "Exact dislike numbers"; -"EXACT_DISLIKE_NUMBER_DESC" = "Display exact number of dislikes. For example: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Doriți să activați acum trimiterea datelor dvs. despre apreciez/nu apreciez către %@? Puteți să-l dezactivați mai târziu din Setări > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ru.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index 876279a..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Активировать"; -"ENABLE_VOTE_SUBMIT" = "Включить отправку голосов"; -"ENABLE_VOTE_SUBMIT_DESC" = "Разрешает отправку ваших данных о Лайках/Дизлайках в Видео и Shorts под уникальным анонимным идентификатором на сайт %@."; -"EXACT_LIKE_NUMBER" = "Точное количество лайков"; -"EXACT_DISLIKE_NUMBER" = "Точное количество дизлайков"; -"EXACT_DISLIKE_NUMBER_DESC" = "Отображает точное количество дизлайков. Например: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Хотите разрешить отправку ваших данных о Лайках/Дизлайках на %@? Данную функцию можно отключить в Настройках > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/tr.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/tr.lproj/Localizable.strings deleted file mode 100644 index 2e5c6c8..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/tr.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Etkinleştir"; -"ENABLE_VOTE_SUBMIT" = "Oy gönderimini etkinleştir"; -"ENABLE_VOTE_SUBMIT_DESC" = "Benzersiz anonim kimliğinin ve video/short beğeni/beğenmeme verilerinin şu adrese gönderilmesine izin ver %@."; -"EXACT_LIKE_NUMBER" = "Tam beğeni sayıları"; -"EXACT_DISLIKE_NUMBER" = "Tam beğenmeme sayıları"; -"EXACT_DISLIKE_NUMBER_DESC" = "Toplam beğenmeme sayısını gösterir. Örneğin: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Beğenme/beğenmeme verilerinin %@'ye gönderilmesini şimdi etkinleştirmek istiyor musun? Bunu daha sonra Ayarlar > %@ > %@ bölümünden devre dışı bırakabilirsin."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/vi.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/vi.lproj/Localizable.strings deleted file mode 100644 index 710c5c8..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/vi.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "Kích hoạt"; -"ENABLE_VOTE_SUBMIT" = "Chia sẻ dữ liệu về lượt thích/không thích"; -"ENABLE_VOTE_SUBMIT_DESC" = "Cho phép sử dụng ID ẩn danh ngẫu nhiên để chia sẻ dữ liệu về các lượt thích/không thích của bạn với các Video/Shorts tới %@."; -"EXACT_LIKE_NUMBER" = "Hiển thị chính xác số lượt thích"; -"EXACT_DISLIKE_NUMBER" = "Hiển thị chính xác số lượt không thích"; -"EXACT_DISLIKE_NUMBER_DESC" = "Hiển thị chính xác số lượt không thích. Ví dụ: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "Bạn có muốn chia sẻ dữ liệu về các lượt thích/không thích của bạn tới %@ bây giờ không? Bạn có thể tắt tùy chọn này trong Cài đặt của YouTube > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/zh_cn.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/zh_cn.lproj/Localizable.strings deleted file mode 100644 index 068317a..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/zh_cn.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "启用"; -"ENABLE_VOTE_SUBMIT" = "上传顶/踩数据"; -"ENABLE_VOTE_SUBMIT_DESC" = "允许将您的唯一匿名ID和顶/踩数据上传至 %@。"; -"EXACT_LIKE_NUMBER" = "显示完整的“顶”计数"; -"EXACT_DISLIKE_NUMBER" = "显示完整的“踩”计数"; -"EXACT_DISLIKE_NUMBER_DESC" = "以未经缩写的,精确到个位数的方式显示“踩”的数量。示例:%@ -> %@。"; - -// On app launch -"WANT_TO_ENABLE" = "您想将您的顶/踩数据上传到 %@ 吗?您可随时通过“设置 > %@ > %@”关闭数据上传。"; diff --git a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/zh_tw.lproj/Localizable.strings b/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/zh_tw.lproj/Localizable.strings deleted file mode 100644 index 3b04e0d..0000000 --- a/Tweaks/Return-YouTube-Dislikes/layout/Library/Application Support/RYD.bundle/zh_tw.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -// Settings -"ENABLED" = "啟用"; -"ENABLE_VOTE_SUBMIT" = "將按下\"讚/爛\"上傳"; -"ENABLE_VOTE_SUBMIT_DESC" = "允許將您在影片/Shorts中按下的 \"讚/爛\" 資料使用匿名ID上傳至 %@。"; -"EXACT_LIKE_NUMBER" = "顯示精確\"讚\"數字"; -"EXACT_DISLIKE_NUMBER" = "顯示精確\"爛\"數字"; -"EXACT_DISLIKE_NUMBER_DESC" = "將\"爛\"的數字加上千位分隔符號. 例如: %@ -> %@."; - -// On app launch -"WANT_TO_ENABLE" = "您願意將按下的\"讚/爛\"資料上傳到 %@ 嗎? 您稍後可以在設定中關閉 > %@ > %@."; diff --git a/Tweaks/Return-YouTube-Dislikes/unicode/uenum.h b/Tweaks/Return-YouTube-Dislikes/unicode/uenum.h deleted file mode 100644 index c693c86..0000000 --- a/Tweaks/Return-YouTube-Dislikes/unicode/uenum.h +++ /dev/null @@ -1,210 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* -* Copyright (C) 2002-2013, International Business Machines -* Corporation and others. All Rights Reserved. -* -******************************************************************************* -* file name: uenum.h -* encoding: UTF-8 -* tab size: 8 (not used) -* indentation:2 -* -* created on: 2002jul08 -* created by: Vladimir Weinstein -*/ - -#ifndef __UENUM_H -#define __UENUM_H - -#include "unicode/utypes.h" -#include "unicode/localpointer.h" - -#if U_SHOW_CPLUSPLUS_API -U_NAMESPACE_BEGIN -class StringEnumeration; -U_NAMESPACE_END -#endif - -/** - * \file - * \brief C API: String Enumeration - */ - -/** - * An enumeration object. - * For usage in C programs. - * @stable ICU 2.2 - */ -struct UEnumeration; -/** structure representing an enumeration object instance @stable ICU 2.2 */ -typedef struct UEnumeration UEnumeration; - -/** - * Disposes of resources in use by the iterator. If en is NULL, - * does nothing. After this call, any char* or UChar* pointer - * returned by uenum_unext() or uenum_next() is invalid. - * @param en UEnumeration structure pointer - * @stable ICU 2.2 - */ -U_STABLE void U_EXPORT2 -uenum_close(UEnumeration* en); - -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUEnumerationPointer - * "Smart pointer" class, closes a UEnumeration via uenum_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUEnumerationPointer, UEnumeration, uenum_close); - -U_NAMESPACE_END - -#endif - -/** - * Returns the number of elements that the iterator traverses. If - * the iterator is out-of-sync with its service, status is set to - * U_ENUM_OUT_OF_SYNC_ERROR. - * This is a convenience function. It can end up being very - * expensive as all the items might have to be pre-fetched (depending - * on the type of data being traversed). Use with caution and only - * when necessary. - * @param en UEnumeration structure pointer - * @param status error code, can be U_ENUM_OUT_OF_SYNC_ERROR if the - * iterator is out of sync. - * @return number of elements in the iterator - * @stable ICU 2.2 - */ -U_STABLE int32_t U_EXPORT2 -uenum_count(UEnumeration* en, UErrorCode* status); - -/** - * Returns the next element in the iterator's list. If there are - * no more elements, returns NULL. If the iterator is out-of-sync - * with its service, status is set to U_ENUM_OUT_OF_SYNC_ERROR and - * NULL is returned. If the native service string is a char* string, - * it is converted to UChar* with the invariant converter. - * The result is terminated by (UChar)0. - * @param en the iterator object - * @param resultLength pointer to receive the length of the result - * (not including the terminating \\0). - * If the pointer is NULL it is ignored. - * @param status the error code, set to U_ENUM_OUT_OF_SYNC_ERROR if - * the iterator is out of sync with its service. - * @return a pointer to the string. The string will be - * zero-terminated. The return pointer is owned by this iterator - * and must not be deleted by the caller. The pointer is valid - * until the next call to any uenum_... method, including - * uenum_next() or uenum_unext(). When all strings have been - * traversed, returns NULL. - * @stable ICU 2.2 - */ -U_STABLE const UChar* U_EXPORT2 -uenum_unext(UEnumeration* en, - int32_t* resultLength, - UErrorCode* status); - -/** - * Returns the next element in the iterator's list. If there are - * no more elements, returns NULL. If the iterator is out-of-sync - * with its service, status is set to U_ENUM_OUT_OF_SYNC_ERROR and - * NULL is returned. If the native service string is a UChar* - * string, it is converted to char* with the invariant converter. - * The result is terminated by (char)0. If the conversion fails - * (because a character cannot be converted) then status is set to - * U_INVARIANT_CONVERSION_ERROR and the return value is undefined - * (but non-NULL). - * @param en the iterator object - * @param resultLength pointer to receive the length of the result - * (not including the terminating \\0). - * If the pointer is NULL it is ignored. - * @param status the error code, set to U_ENUM_OUT_OF_SYNC_ERROR if - * the iterator is out of sync with its service. Set to - * U_INVARIANT_CONVERSION_ERROR if the underlying native string is - * UChar* and conversion to char* with the invariant converter - * fails. This error pertains only to current string, so iteration - * might be able to continue successfully. - * @return a pointer to the string. The string will be - * zero-terminated. The return pointer is owned by this iterator - * and must not be deleted by the caller. The pointer is valid - * until the next call to any uenum_... method, including - * uenum_next() or uenum_unext(). When all strings have been - * traversed, returns NULL. - * @stable ICU 2.2 - */ -U_STABLE const char* U_EXPORT2 -uenum_next(UEnumeration* en, - int32_t* resultLength, - UErrorCode* status); - -/** - * Resets the iterator to the current list of service IDs. This - * re-establishes sync with the service and rewinds the iterator - * to start at the first element. - * @param en the iterator object - * @param status the error code, set to U_ENUM_OUT_OF_SYNC_ERROR if - * the iterator is out of sync with its service. - * @stable ICU 2.2 - */ -U_STABLE void U_EXPORT2 -uenum_reset(UEnumeration* en, UErrorCode* status); - -#if U_SHOW_CPLUSPLUS_API - -/** - * Given a StringEnumeration, wrap it in a UEnumeration. The - * StringEnumeration is adopted; after this call, the caller must not - * delete it (regardless of error status). - * @param adopted the C++ StringEnumeration to be wrapped in a UEnumeration. - * @param ec the error code. - * @return a UEnumeration wrapping the adopted StringEnumeration. - * @stable ICU 4.2 - */ -U_STABLE UEnumeration* U_EXPORT2 -uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec); - -#endif - -/** - * Given an array of const UChar* strings, return a UEnumeration. String pointers from 0..count-1 must not be null. - * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close. - * \snippet test/cintltst/uenumtst.c uenum_openUCharStringsEnumeration - * @param strings array of const UChar* strings (each null terminated). All storage is owned by the caller. - * @param count length of the array - * @param ec error code - * @return the new UEnumeration object. Caller is responsible for calling uenum_close to free memory. - * @see uenum_close - * @stable ICU 50 - */ -U_STABLE UEnumeration* U_EXPORT2 -uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count, - UErrorCode* ec); - -/* Note: next function is not hidden as draft, as it is used internally (it was formerly an internal function). */ - -/** - * Given an array of const char* strings (invariant chars only), return a UEnumeration. String pointers from 0..count-1 must not be null. - * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close. - * \snippet test/cintltst/uenumtst.c uenum_openCharStringsEnumeration - * @param strings array of char* strings (each null terminated). All storage is owned by the caller. - * @param count length of the array - * @param ec error code - * @return the new UEnumeration object. Caller is responsible for calling uenum_close to free memory - * @see uenum_close - * @stable ICU 50 - */ -U_STABLE UEnumeration* U_EXPORT2 -uenum_openCharStringsEnumeration(const char* const strings[], int32_t count, - UErrorCode* ec); - -#endif \ No newline at end of file diff --git a/Tweaks/Return-YouTube-Dislikes/unicode/uloc.h b/Tweaks/Return-YouTube-Dislikes/unicode/uloc.h deleted file mode 100644 index d412da4..0000000 --- a/Tweaks/Return-YouTube-Dislikes/unicode/uloc.h +++ /dev/null @@ -1,1272 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -********************************************************************** -* Copyright (C) 1997-2016, International Business Machines -* Corporation and others. All Rights Reserved. -********************************************************************** -* -* File ULOC.H -* -* Modification History: -* -* Date Name Description -* 04/01/97 aliu Creation. -* 08/22/98 stephen JDK 1.2 sync. -* 12/08/98 rtg New C API for Locale -* 03/30/99 damiba overhaul -* 03/31/99 helena Javadoc for uloc functions. -* 04/15/99 Madhu Updated Javadoc -******************************************************************************** -*/ - -#ifndef ULOC_H -#define ULOC_H - -#include "unicode/utypes.h" -#include "uenum.h" - -/** - * \file - * \brief C API: Locale - * - *

ULoc C API for Locale

- * A Locale represents a specific geographical, political, - * or cultural region. An operation that requires a Locale to perform - * its task is called locale-sensitive and uses the Locale - * to tailor information for the user. For example, displaying a number - * is a locale-sensitive operation--the number should be formatted - * according to the customs/conventions of the user's native country, - * region, or culture. In the C APIs, a locales is simply a const char string. - * - *

- * You create a Locale with one of the three options listed below. - * Each of the component is separated by '_' in the locale string. - * \htmlonly

\endhtmlonly - *
- * \code
- *       newLanguage
- * 
- *       newLanguage + newCountry
- * 
- *       newLanguage + newCountry + newVariant
- * \endcode
- * 
- * \htmlonly
\endhtmlonly - * The first option is a valid ISO - * Language Code. These codes are the lower-case two-letter - * codes as defined by ISO-639. - * You can find a full list of these codes at a number of sites, such as: - *
- * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt - * - *

- * The second option includes an additional ISO Country - * Code. These codes are the upper-case two-letter codes - * as defined by ISO-3166. - * You can find a full list of these codes at a number of sites, such as: - *
- * http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html - * - *

- * The third option requires another additional information--the - * Variant. - * The Variant codes are vendor and browser-specific. - * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX. - * Where there are two variants, separate them with an underscore, and - * put the most important one first. For - * example, a Traditional Spanish collation might be referenced, with - * "ES", "ES", "Traditional_WIN". - * - *

- * Because a Locale is just an identifier for a region, - * no validity check is performed when you specify a Locale. - * If you want to see whether particular resources are available for the - * Locale you asked for, you must query those resources. For - * example, ask the UNumberFormat for the locales it supports - * using its getAvailable method. - *
Note: When you ask for a resource for a particular - * locale, you get back the best available match, not necessarily - * precisely what you asked for. For more information, look at - * UResourceBundle. - * - *

- * The Locale provides a number of convenient constants - * that you can use to specify the commonly used - * locales. For example, the following refers to a locale - * for the United States: - * \htmlonly

\endhtmlonly - *
- * \code
- *       ULOC_US
- * \endcode
- * 
- * \htmlonly
\endhtmlonly - * - *

- * Once you've specified a locale you can query it for information about - * itself. Use uloc_getCountry to get the ISO Country Code and - * uloc_getLanguage to get the ISO Language Code. You can - * use uloc_getDisplayCountry to get the - * name of the country suitable for displaying to the user. Similarly, - * you can use uloc_getDisplayLanguage to get the name of - * the language suitable for displaying to the user. Interestingly, - * the uloc_getDisplayXXX methods are themselves locale-sensitive - * and have two versions: one that uses the default locale and one - * that takes a locale as an argument and displays the name or country in - * a language appropriate to that locale. - * - *

- * The ICU provides a number of services that perform locale-sensitive - * operations. For example, the unum_xxx functions format - * numbers, currency, or percentages in a locale-sensitive manner. - *

- * \htmlonly
\endhtmlonly - *
- * \code
- *     UErrorCode success = U_ZERO_ERROR;
- *     UNumberFormat *nf;
- *     const char* myLocale = "fr_FR";
- * 
- *     nf = unum_open( UNUM_DEFAULT, NULL, success );          
- *     unum_close(nf);
- *     nf = unum_open( UNUM_CURRENCY, NULL, success );
- *     unum_close(nf);
- *     nf = unum_open( UNUM_PERCENT, NULL, success );   
- *     unum_close(nf);
- * \endcode
- * 
- * \htmlonly
\endhtmlonly - * Each of these methods has two variants; one with an explicit locale - * and one without; the latter using the default locale. - * \htmlonly
\endhtmlonly - *
- * \code 
- * 
- *     nf = unum_open( UNUM_DEFAULT, myLocale, success );          
- *     unum_close(nf);
- *     nf = unum_open( UNUM_CURRENCY, myLocale, success );
- *     unum_close(nf);
- *     nf = unum_open( UNUM_PERCENT, myLocale, success );   
- *     unum_close(nf);
- * \endcode
- * 
- * \htmlonly
\endhtmlonly - * A Locale is the mechanism for identifying the kind of services - * (UNumberFormat) that you would like to get. The locale is - * just a mechanism for identifying these services. - * - *

- * Each international service that performs locale-sensitive operations - * allows you - * to get all the available objects of that type. You can sift - * through these objects by language, country, or variant, - * and use the display names to present a menu to the user. - * For example, you can create a menu of all the collation objects - * suitable for a given language. Such classes implement these - * three class methods: - * \htmlonly

\endhtmlonly - *
- * \code
- *       const char* uloc_getAvailable(int32_t index);
- *       int32_t uloc_countAvailable();
- *       int32_t
- *       uloc_getDisplayName(const char* localeID,
- *                 const char* inLocaleID, 
- *                 UChar* result,
- *                 int32_t maxResultSize,
- *                  UErrorCode* err);
- * 
- * \endcode
- * 
- * \htmlonly
\endhtmlonly - *

- * Concerning POSIX/RFC1766 Locale IDs, - * the getLanguage/getCountry/getVariant/getName functions do understand - * the POSIX type form of language_COUNTRY.ENCODING\@VARIANT - * and if there is not an ICU-stype variant, uloc_getVariant() for example - * will return the one listed after the \@at sign. As well, the hyphen - * "-" is recognized as a country/variant separator similarly to RFC1766. - * So for example, "en-us" will be interpreted as en_US. - * As a result, uloc_getName() is far from a no-op, and will have the - * effect of converting POSIX/RFC1766 IDs into ICU form, although it does - * NOT map any of the actual codes (i.e. russian->ru) in any way. - * Applications should call uloc_getName() at the point where a locale ID - * is coming from an external source (user entry, OS, web browser) - * and pass the resulting string to other ICU functions. For example, - * don't use de-de\@EURO as an argument to resourcebundle. - * - * @see UResourceBundle - */ - -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_CHINESE "zh" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_ENGLISH "en" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_FRENCH "fr" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_GERMAN "de" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_ITALIAN "it" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_JAPANESE "ja" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_KOREAN "ko" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_SIMPLIFIED_CHINESE "zh_CN" -/** Useful constant for this language. @stable ICU 2.0 */ -#define ULOC_TRADITIONAL_CHINESE "zh_TW" - -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_CANADA "en_CA" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_CANADA_FRENCH "fr_CA" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_CHINA "zh_CN" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_PRC "zh_CN" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_FRANCE "fr_FR" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_GERMANY "de_DE" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_ITALY "it_IT" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_JAPAN "ja_JP" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_KOREA "ko_KR" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_TAIWAN "zh_TW" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_UK "en_GB" -/** Useful constant for this country/region. @stable ICU 2.0 */ -#define ULOC_US "en_US" - -/** - * Useful constant for the maximum size of the language part of a locale ID. - * (including the terminating NULL). - * @stable ICU 2.0 - */ -#define ULOC_LANG_CAPACITY 12 - -/** - * Useful constant for the maximum size of the country part of a locale ID - * (including the terminating NULL). - * @stable ICU 2.0 - */ -#define ULOC_COUNTRY_CAPACITY 4 -/** - * Useful constant for the maximum size of the whole locale ID - * (including the terminating NULL and all keywords). - * @stable ICU 2.0 - */ -#define ULOC_FULLNAME_CAPACITY 157 - -/** - * Useful constant for the maximum size of the script part of a locale ID - * (including the terminating NULL). - * @stable ICU 2.8 - */ -#define ULOC_SCRIPT_CAPACITY 6 - -/** - * Useful constant for the maximum size of keywords in a locale - * @stable ICU 2.8 - */ -#define ULOC_KEYWORDS_CAPACITY 96 - -/** - * Useful constant for the maximum total size of keywords and their values in a locale - * @stable ICU 2.8 - */ -#define ULOC_KEYWORD_AND_VALUES_CAPACITY 100 - -/** - * Invariant character separating keywords from the locale string - * @stable ICU 2.8 - */ -#define ULOC_KEYWORD_SEPARATOR '@' - -/** - * Unicode code point for '@' separating keywords from the locale string. - * @see ULOC_KEYWORD_SEPARATOR - * @stable ICU 4.6 - */ -#define ULOC_KEYWORD_SEPARATOR_UNICODE 0x40 - -/** - * Invariant character for assigning value to a keyword - * @stable ICU 2.8 - */ -#define ULOC_KEYWORD_ASSIGN '=' - -/** - * Unicode code point for '=' for assigning value to a keyword. - * @see ULOC_KEYWORD_ASSIGN - * @stable ICU 4.6 - */ -#define ULOC_KEYWORD_ASSIGN_UNICODE 0x3D - -/** - * Invariant character separating keywords - * @stable ICU 2.8 - */ -#define ULOC_KEYWORD_ITEM_SEPARATOR ';' - -/** - * Unicode code point for ';' separating keywords - * @see ULOC_KEYWORD_ITEM_SEPARATOR - * @stable ICU 4.6 - */ -#define ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE 0x3B - -/** - * Constants for *_getLocale() - * Allow user to select whether she wants information on - * requested, valid or actual locale. - * For example, a collator for "en_US_CALIFORNIA" was - * requested. In the current state of ICU (2.0), - * the requested locale is "en_US_CALIFORNIA", - * the valid locale is "en_US" (most specific locale supported by ICU) - * and the actual locale is "root" (the collation data comes unmodified - * from the UCA) - * The locale is considered supported by ICU if there is a core ICU bundle - * for that locale (although it may be empty). - * @stable ICU 2.1 - */ -typedef enum { - /** This is locale the data actually comes from - * @stable ICU 2.1 - */ - ULOC_ACTUAL_LOCALE = 0, - /** This is the most specific locale supported by ICU - * @stable ICU 2.1 - */ - ULOC_VALID_LOCALE = 1, - -#ifndef U_HIDE_DEPRECATED_API - /** This is the requested locale - * @deprecated ICU 2.8 - */ - ULOC_REQUESTED_LOCALE = 2, - - /** - * One more than the highest normal ULocDataLocaleType value. - * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. - */ - ULOC_DATA_LOCALE_TYPE_LIMIT = 3 -#endif // U_HIDE_DEPRECATED_API -} ULocDataLocaleType; - -#ifndef U_HIDE_SYSTEM_API -/** - * Gets ICU's default locale. - * The returned string is a snapshot in time, and will remain valid - * and unchanged even when uloc_setDefault() is called. - * The returned storage is owned by ICU, and must not be altered or deleted - * by the caller. - * - * @return the ICU default locale - * @system - * @stable ICU 2.0 - */ -U_STABLE const char* U_EXPORT2 -uloc_getDefault(void); - -/** - * Sets ICU's default locale. - * By default (without calling this function), ICU's default locale will be based - * on information obtained from the underlying system environment. - *

- * Changes to ICU's default locale do not propagate back to the - * system environment. - *

- * Changes to ICU's default locale to not affect any ICU services that - * may already be open based on the previous default locale value. - * - * @param localeID the new ICU default locale. A value of NULL will try to get - * the system's default locale. - * @param status the error information if the setting of default locale fails - * @system - * @stable ICU 2.0 - */ -U_STABLE void U_EXPORT2 -uloc_setDefault(const char* localeID, - UErrorCode* status); -#endif /* U_HIDE_SYSTEM_API */ - -/** - * Gets the language code for the specified locale. - * - * @param localeID the locale to get the ISO language code with - * @param language the language code for localeID - * @param languageCapacity the size of the language buffer to store the - * language code with - * @param err error information if retrieving the language code failed - * @return the actual buffer size needed for the language code. If it's greater - * than languageCapacity, the returned language code will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getLanguage(const char* localeID, - char* language, - int32_t languageCapacity, - UErrorCode* err); - -/** - * Gets the script code for the specified locale. - * - * @param localeID the locale to get the ISO language code with - * @param script the language code for localeID - * @param scriptCapacity the size of the language buffer to store the - * language code with - * @param err error information if retrieving the language code failed - * @return the actual buffer size needed for the language code. If it's greater - * than scriptCapacity, the returned language code will be truncated. - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getScript(const char* localeID, - char* script, - int32_t scriptCapacity, - UErrorCode* err); - -/** - * Gets the country code for the specified locale. - * - * @param localeID the locale to get the country code with - * @param country the country code for localeID - * @param countryCapacity the size of the country buffer to store the - * country code with - * @param err error information if retrieving the country code failed - * @return the actual buffer size needed for the country code. If it's greater - * than countryCapacity, the returned country code will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getCountry(const char* localeID, - char* country, - int32_t countryCapacity, - UErrorCode* err); - -/** - * Gets the variant code for the specified locale. - * - * @param localeID the locale to get the variant code with - * @param variant the variant code for localeID - * @param variantCapacity the size of the variant buffer to store the - * variant code with - * @param err error information if retrieving the variant code failed - * @return the actual buffer size needed for the variant code. If it's greater - * than variantCapacity, the returned variant code will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getVariant(const char* localeID, - char* variant, - int32_t variantCapacity, - UErrorCode* err); - - -/** - * Gets the full name for the specified locale. - * Note: This has the effect of 'canonicalizing' the ICU locale ID to - * a certain extent. Upper and lower case are set as needed. - * It does NOT map aliased names in any way. - * See the top of this header file. - * This API supports preflighting. - * - * @param localeID the locale to get the full name with - * @param name fill in buffer for the name without keywords. - * @param nameCapacity capacity of the fill in buffer. - * @param err error information if retrieving the full name failed - * @return the actual buffer size needed for the full name. If it's greater - * than nameCapacity, the returned full name will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getName(const char* localeID, - char* name, - int32_t nameCapacity, - UErrorCode* err); - -/** - * Gets the full name for the specified locale. - * Note: This has the effect of 'canonicalizing' the string to - * a certain extent. Upper and lower case are set as needed, - * and if the components were in 'POSIX' format they are changed to - * ICU format. It does NOT map aliased names in any way. - * See the top of this header file. - * - * @param localeID the locale to get the full name with - * @param name the full name for localeID - * @param nameCapacity the size of the name buffer to store the - * full name with - * @param err error information if retrieving the full name failed - * @return the actual buffer size needed for the full name. If it's greater - * than nameCapacity, the returned full name will be truncated. - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_canonicalize(const char* localeID, - char* name, - int32_t nameCapacity, - UErrorCode* err); - -/** - * Gets the ISO language code for the specified locale. - * - * @param localeID the locale to get the ISO language code with - * @return language the ISO language code for localeID - * @stable ICU 2.0 - */ -U_STABLE const char* U_EXPORT2 -uloc_getISO3Language(const char* localeID); - - -/** - * Gets the ISO country code for the specified locale. - * - * @param localeID the locale to get the ISO country code with - * @return country the ISO country code for localeID - * @stable ICU 2.0 - */ -U_STABLE const char* U_EXPORT2 -uloc_getISO3Country(const char* localeID); - -/** - * Gets the Win32 LCID value for the specified locale. - * If the ICU locale is not recognized by Windows, 0 will be returned. - * - * LCIDs were deprecated with Windows Vista and Microsoft recommends - * that developers use BCP47 style tags instead (uloc_toLanguageTag). - * - * @param localeID the locale to get the Win32 LCID value with - * @return country the Win32 LCID for localeID - * @stable ICU 2.0 - */ -U_STABLE uint32_t U_EXPORT2 -uloc_getLCID(const char* localeID); - -/** - * Gets the language name suitable for display for the specified locale. - * - * @param locale the locale to get the ISO language code with - * @param displayLocale Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "Anglais", while passing Locale::getGerman() - * for inLocale would result in "Englisch". - * @param language the displayable language code for localeID - * @param languageCapacity the size of the language buffer to store the - * displayable language code with - * @param status error information if retrieving the displayable language code failed - * @return the actual buffer size needed for the displayable language code. If it's greater - * than languageCapacity, the returned language code will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayLanguage(const char* locale, - const char* displayLocale, - UChar* language, - int32_t languageCapacity, - UErrorCode* status); - -/** - * Gets the script name suitable for display for the specified locale. - * - * @param locale the locale to get the displayable script code with. NULL may be used to specify the default. - * @param displayLocale Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "", while passing Locale::getGerman() - * for inLocale would result in "". NULL may be used to specify the default. - * @param script the displayable script for the localeID - * @param scriptCapacity the size of the script buffer to store the - * displayable script code with - * @param status error information if retrieving the displayable script code failed - * @return the actual buffer size needed for the displayable script code. If it's greater - * than scriptCapacity, the returned displayable script code will be truncated. - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayScript(const char* locale, - const char* displayLocale, - UChar* script, - int32_t scriptCapacity, - UErrorCode* status); - -/** - * Gets the country name suitable for display for the specified locale. - * Warning: this is for the region part of a valid locale ID; it cannot just be the region code (like "FR"). - * To get the display name for a region alone, or for other options, use ULocaleDisplayNames instead. - * - * @param locale the locale to get the displayable country code with. NULL may be used to specify the default. - * @param displayLocale Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "Anglais", while passing Locale::getGerman() - * for inLocale would result in "Englisch". NULL may be used to specify the default. - * @param country the displayable country code for localeID - * @param countryCapacity the size of the country buffer to store the - * displayable country code with - * @param status error information if retrieving the displayable country code failed - * @return the actual buffer size needed for the displayable country code. If it's greater - * than countryCapacity, the returned displayable country code will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayCountry(const char* locale, - const char* displayLocale, - UChar* country, - int32_t countryCapacity, - UErrorCode* status); - - -/** - * Gets the variant name suitable for display for the specified locale. - * - * @param locale the locale to get the displayable variant code with. NULL may be used to specify the default. - * @param displayLocale Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "Anglais", while passing Locale::getGerman() - * for inLocale would result in "Englisch". NULL may be used to specify the default. - * @param variant the displayable variant code for localeID - * @param variantCapacity the size of the variant buffer to store the - * displayable variant code with - * @param status error information if retrieving the displayable variant code failed - * @return the actual buffer size needed for the displayable variant code. If it's greater - * than variantCapacity, the returned displayable variant code will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayVariant(const char* locale, - const char* displayLocale, - UChar* variant, - int32_t variantCapacity, - UErrorCode* status); - -/** - * Gets the keyword name suitable for display for the specified locale. - * E.g: for the locale string de_DE\@collation=PHONEBOOK, this API gets the display - * string for the keyword collation. - * Usage: - * - * UErrorCode status = U_ZERO_ERROR; - * const char* keyword =NULL; - * int32_t keywordLen = 0; - * int32_t keywordCount = 0; - * UChar displayKeyword[256]; - * int32_t displayKeywordLen = 0; - * UEnumeration* keywordEnum = uloc_openKeywords("de_DE@collation=PHONEBOOK;calendar=TRADITIONAL", &status); - * for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ - * if(U_FAILURE(status)){ - * ...something went wrong so handle the error... - * break; - * } - * // the uenum_next returns NUL terminated string - * keyword = uenum_next(keywordEnum, &keywordLen, &status); - * displayKeywordLen = uloc_getDisplayKeyword(keyword, "en_US", displayKeyword, 256); - * ... do something interesting ..... - * } - * uenum_close(keywordEnum); - * - * @param keyword The keyword whose display string needs to be returned. - * @param displayLocale Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "Anglais", while passing Locale::getGerman() - * for inLocale would result in "Englisch". NULL may be used to specify the default. - * @param dest the buffer to which the displayable keyword should be written. - * @param destCapacity The size of the buffer (number of UChars). If it is 0, then - * dest may be NULL and the function will only return the length of the - * result without writing any of the result string (pre-flighting). - * @param status error information if retrieving the displayable string failed. - * Should not be NULL and should not indicate failure on entry. - * @return the actual buffer size needed for the displayable variant code. - * @see #uloc_openKeywords - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayKeyword(const char* keyword, - const char* displayLocale, - UChar* dest, - int32_t destCapacity, - UErrorCode* status); -/** - * Gets the value of the keyword suitable for display for the specified locale. - * E.g: for the locale string de_DE\@collation=PHONEBOOK, this API gets the display - * string for PHONEBOOK, in the display locale, when "collation" is specified as the keyword. - * - * @param locale The locale to get the displayable variant code with. NULL may be used to specify the default. - * @param keyword The keyword for whose value should be used. - * @param displayLocale Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "Anglais", while passing Locale::getGerman() - * for inLocale would result in "Englisch". NULL may be used to specify the default. - * @param dest the buffer to which the displayable keyword should be written. - * @param destCapacity The size of the buffer (number of UChars). If it is 0, then - * dest may be NULL and the function will only return the length of the - * result without writing any of the result string (pre-flighting). - * @param status error information if retrieving the displayable string failed. - * Should not be NULL and must not indicate failure on entry. - * @return the actual buffer size needed for the displayable variant code. - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayKeywordValue( const char* locale, - const char* keyword, - const char* displayLocale, - UChar* dest, - int32_t destCapacity, - UErrorCode* status); -/** - * Gets the full name suitable for display for the specified locale. - * - * @param localeID the locale to get the displayable name with. NULL may be used to specify the default. - * @param inLocaleID Specifies the locale to be used to display the name. In other words, - * if the locale's language code is "en", passing Locale::getFrench() for - * inLocale would result in "Anglais", while passing Locale::getGerman() - * for inLocale would result in "Englisch". NULL may be used to specify the default. - * @param result the displayable name for localeID - * @param maxResultSize the size of the name buffer to store the - * displayable full name with - * @param err error information if retrieving the displayable name failed - * @return the actual buffer size needed for the displayable name. If it's greater - * than maxResultSize, the returned displayable name will be truncated. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getDisplayName(const char* localeID, - const char* inLocaleID, - UChar* result, - int32_t maxResultSize, - UErrorCode* err); - - -/** - * Gets the specified locale from a list of all available locales. - * The return value is a pointer to an item of - * a locale name array. Both this array and the pointers - * it contains are owned by ICU and should not be deleted or written through - * by the caller. The locale name is terminated by a null pointer. - * @param n the specific locale name index of the available locale list - * @return a specified locale name of all available locales - * @stable ICU 2.0 - */ -U_STABLE const char* U_EXPORT2 -uloc_getAvailable(int32_t n); - -/** - * Gets the size of the all available locale list. - * - * @return the size of the locale list - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 uloc_countAvailable(void); - -/** - * - * Gets a list of all available 2-letter language codes defined in ISO 639, - * plus additional 3-letter codes determined to be useful for locale generation as - * defined by Unicode CLDR. This is a pointer - * to an array of pointers to arrays of char. All of these pointers are owned - * by ICU-- do not delete them, and do not write through them. The array is - * terminated with a null pointer. - * @return a list of all available language codes - * @stable ICU 2.0 - */ -U_STABLE const char* const* U_EXPORT2 -uloc_getISOLanguages(void); - -/** - * - * Gets a list of all available 2-letter country codes defined in ISO 639. This is a - * pointer to an array of pointers to arrays of char. All of these pointers are - * owned by ICU-- do not delete them, and do not write through them. The array is - * terminated with a null pointer. - * @return a list of all available country codes - * @stable ICU 2.0 - */ -U_STABLE const char* const* U_EXPORT2 -uloc_getISOCountries(void); - -/** - * Truncate the locale ID string to get the parent locale ID. - * Copies the part of the string before the last underscore. - * The parent locale ID will be an empty string if there is no - * underscore, or if there is only one underscore at localeID[0]. - * - * @param localeID Input locale ID string. - * @param parent Output string buffer for the parent locale ID. - * @param parentCapacity Size of the output buffer. - * @param err A UErrorCode value. - * @return The length of the parent locale ID. - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getParent(const char* localeID, - char* parent, - int32_t parentCapacity, - UErrorCode* err); - - - - -/** - * Gets the full name for the specified locale, like uloc_getName(), - * but without keywords. - * - * Note: This has the effect of 'canonicalizing' the string to - * a certain extent. Upper and lower case are set as needed, - * and if the components were in 'POSIX' format they are changed to - * ICU format. It does NOT map aliased names in any way. - * See the top of this header file. - * - * This API strips off the keyword part, so "de_DE\@collation=phonebook" - * will become "de_DE". - * This API supports preflighting. - * - * @param localeID the locale to get the full name with - * @param name fill in buffer for the name without keywords. - * @param nameCapacity capacity of the fill in buffer. - * @param err error information if retrieving the full name failed - * @return the actual buffer size needed for the full name. If it's greater - * than nameCapacity, the returned full name will be truncated. - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getBaseName(const char* localeID, - char* name, - int32_t nameCapacity, - UErrorCode* err); - -/** - * Gets an enumeration of keywords for the specified locale. Enumeration - * must get disposed of by the client using uenum_close function. - * - * @param localeID the locale to get the variant code with - * @param status error information if retrieving the keywords failed - * @return enumeration of keywords or NULL if there are no keywords. - * @stable ICU 2.8 - */ -U_STABLE UEnumeration* U_EXPORT2 -uloc_openKeywords(const char* localeID, - UErrorCode* status); - -/** - * Get the value for a keyword. Locale name does not need to be normalized. - * - * @param localeID locale name containing the keyword ("de_DE@currency=EURO;collation=PHONEBOOK") - * @param keywordName name of the keyword for which we want the value; must not be - * NULL or empty, and must consist only of [A-Za-z0-9]. Case insensitive. - * @param buffer receiving buffer - * @param bufferCapacity capacity of receiving buffer - * @param status containing error code: e.g. buffer not big enough or ill-formed localeID - * or keywordName parameters. - * @return the length of keyword value - * @stable ICU 2.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getKeywordValue(const char* localeID, - const char* keywordName, - char* buffer, int32_t bufferCapacity, - UErrorCode* status); - - -/** - * Sets or removes the value of the specified keyword. - * - * For removing all keywords, use uloc_getBaseName(). - * - * NOTE: Unlike almost every other ICU function which takes a - * buffer, this function will NOT truncate the output text, and will - * not update the buffer with unterminated text setting a status of - * U_STRING_NOT_TERMINATED_WARNING. If a BUFFER_OVERFLOW_ERROR is received, - * it means a terminated version of the updated locale ID would not fit - * in the buffer, and the original buffer is untouched. This is done to - * prevent incorrect or possibly even malformed locales from being generated - * and used. - * - * @param keywordName name of the keyword to be set; must not be - * NULL or empty, and must consist only of [A-Za-z0-9]. Case insensitive. - * @param keywordValue value of the keyword to be set. If 0-length or - * NULL, will result in the keyword being removed; no error is given if - * that keyword does not exist. Otherwise, must consist only of - * [A-Za-z0-9] and [/_+-]. - * @param buffer input buffer containing well-formed locale ID to be - * modified. - * @param bufferCapacity capacity of receiving buffer - * @param status containing error code: e.g. buffer not big enough - * or ill-formed keywordName or keywordValue parameters, or ill-formed - * locale ID in buffer on input. - * @return the length needed for the buffer - * @see uloc_getKeywordValue - * @stable ICU 3.2 - */ -U_STABLE int32_t U_EXPORT2 -uloc_setKeywordValue(const char* keywordName, - const char* keywordValue, - char* buffer, int32_t bufferCapacity, - UErrorCode* status); - -/** - * Returns whether the locale's script is written right-to-left. - * If there is no script subtag, then the likely script is used, see uloc_addLikelySubtags(). - * If no likely script is known, then FALSE is returned. - * - * A script is right-to-left according to the CLDR script metadata - * which corresponds to whether the script's letters have Bidi_Class=R or AL. - * - * Returns TRUE for "ar" and "en-Hebr", FALSE for "zh" and "fa-Cyrl". - * - * @param locale input locale ID - * @return TRUE if the locale's script is written right-to-left - * @stable ICU 54 - */ -U_STABLE UBool U_EXPORT2 -uloc_isRightToLeft(const char *locale); - -/** - * enums for the return value for the character and line orientation - * functions. - * @stable ICU 4.0 - */ -typedef enum { - ULOC_LAYOUT_LTR = 0, /* left-to-right. */ - ULOC_LAYOUT_RTL = 1, /* right-to-left. */ - ULOC_LAYOUT_TTB = 2, /* top-to-bottom. */ - ULOC_LAYOUT_BTT = 3, /* bottom-to-top. */ - ULOC_LAYOUT_UNKNOWN -} ULayoutType; - -/** - * Get the layout character orientation for the specified locale. - * - * @param localeId locale name - * @param status Error status - * @return an enum indicating the layout orientation for characters. - * @stable ICU 4.0 - */ -U_STABLE ULayoutType U_EXPORT2 -uloc_getCharacterOrientation(const char* localeId, - UErrorCode *status); - -/** - * Get the layout line orientation for the specified locale. - * - * @param localeId locale name - * @param status Error status - * @return an enum indicating the layout orientation for lines. - * @stable ICU 4.0 - */ -U_STABLE ULayoutType U_EXPORT2 -uloc_getLineOrientation(const char* localeId, - UErrorCode *status); - -/** - * enums for the 'outResult' parameter return value - * @see uloc_acceptLanguageFromHTTP - * @see uloc_acceptLanguage - * @stable ICU 3.2 - */ -typedef enum { - ULOC_ACCEPT_FAILED = 0, /* No exact match was found. */ - ULOC_ACCEPT_VALID = 1, /* An exact match was found. */ - ULOC_ACCEPT_FALLBACK = 2 /* A fallback was found, for example, - Accept list contained 'ja_JP' - which matched available locale 'ja'. */ -} UAcceptResult; - - -/** - * Based on a HTTP header from a web browser and a list of available locales, - * determine an acceptable locale for the user. - * @param result - buffer to accept the result locale - * @param resultAvailable the size of the result buffer. - * @param outResult - An out parameter that contains the fallback status - * @param httpAcceptLanguage - "Accept-Language:" header as per HTTP. - * @param availableLocales - list of available locales to match - * @param status Error status, may be BUFFER_OVERFLOW_ERROR - * @return length needed for the locale. - * @stable ICU 3.2 - */ -U_STABLE int32_t U_EXPORT2 -uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, - UAcceptResult *outResult, - const char *httpAcceptLanguage, - UEnumeration* availableLocales, - UErrorCode *status); - -/** - * Based on a list of available locales, - * determine an acceptable locale for the user. - * @param result - buffer to accept the result locale - * @param resultAvailable the size of the result buffer. - * @param outResult - An out parameter that contains the fallback status - * @param acceptList - list of acceptable languages - * @param acceptListCount - count of acceptList items - * @param availableLocales - list of available locales to match - * @param status Error status, may be BUFFER_OVERFLOW_ERROR - * @return length needed for the locale. - * @stable ICU 3.2 - */ -U_STABLE int32_t U_EXPORT2 -uloc_acceptLanguage(char *result, int32_t resultAvailable, - UAcceptResult *outResult, const char **acceptList, - int32_t acceptListCount, - UEnumeration* availableLocales, - UErrorCode *status); - - -/** - * Gets the ICU locale ID for the specified Win32 LCID value. - * - * @param hostID the Win32 LCID to translate - * @param locale the output buffer for the ICU locale ID, which will be NUL-terminated - * if there is room. - * @param localeCapacity the size of the output buffer - * @param status an error is returned if the LCID is unrecognized or the output buffer - * is too small - * @return actual the actual size of the locale ID, not including NUL-termination - * @stable ICU 3.8 - */ -U_STABLE int32_t U_EXPORT2 -uloc_getLocaleForLCID(uint32_t hostID, char *locale, int32_t localeCapacity, - UErrorCode *status); - - -/** - * Add the likely subtags for a provided locale ID, per the algorithm described - * in the following CLDR technical report: - * - * http://www.unicode.org/reports/tr35/#Likely_Subtags - * - * If localeID is already in the maximal form, or there is no data available - * for maximization, it will be copied to the output buffer. For example, - * "und-Zzzz" cannot be maximized, since there is no reasonable maximization. - * - * Examples: - * - * "en" maximizes to "en_Latn_US" - * - * "de" maximizes to "de_Latn_US" - * - * "sr" maximizes to "sr_Cyrl_RS" - * - * "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.) - * - * "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.) - * - * @param localeID The locale to maximize - * @param maximizedLocaleID The maximized locale - * @param maximizedLocaleIDCapacity The capacity of the maximizedLocaleID buffer - * @param err Error information if maximizing the locale failed. If the length - * of the localeID and the null-terminator is greater than the maximum allowed size, - * or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR. - * @return The actual buffer size needed for the maximized locale. If it's - * greater than maximizedLocaleIDCapacity, the returned ID will be truncated. - * On error, the return value is -1. - * @stable ICU 4.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_addLikelySubtags(const char* localeID, - char* maximizedLocaleID, - int32_t maximizedLocaleIDCapacity, - UErrorCode* err); - - -/** - * Minimize the subtags for a provided locale ID, per the algorithm described - * in the following CLDR technical report: - * - * http://www.unicode.org/reports/tr35/#Likely_Subtags - * - * If localeID is already in the minimal form, or there is no data available - * for minimization, it will be copied to the output buffer. Since the - * minimization algorithm relies on proper maximization, see the comments - * for uloc_addLikelySubtags for reasons why there might not be any data. - * - * Examples: - * - * "en_Latn_US" minimizes to "en" - * - * "de_Latn_US" minimizes to "de" - * - * "sr_Cyrl_RS" minimizes to "sr" - * - * "zh_Hant_TW" minimizes to "zh_TW" (The region is preferred to the - * script, and minimizing to "zh" would imply "zh_Hans_CN".) - * - * @param localeID The locale to minimize - * @param minimizedLocaleID The minimized locale - * @param minimizedLocaleIDCapacity The capacity of the minimizedLocaleID buffer - * @param err Error information if minimizing the locale failed. If the length - * of the localeID and the null-terminator is greater than the maximum allowed size, - * or the localeId is not well-formed, the error code is U_ILLEGAL_ARGUMENT_ERROR. - * @return The actual buffer size needed for the minimized locale. If it's - * greater than minimizedLocaleIDCapacity, the returned ID will be truncated. - * On error, the return value is -1. - * @stable ICU 4.0 - */ -U_STABLE int32_t U_EXPORT2 -uloc_minimizeSubtags(const char* localeID, - char* minimizedLocaleID, - int32_t minimizedLocaleIDCapacity, - UErrorCode* err); - -/** - * Returns a locale ID for the specified BCP47 language tag string. - * If the specified language tag contains any ill-formed subtags, - * the first such subtag and all following subtags are ignored. - *

- * This implements the 'Language-Tag' production of BCP47, and so - * supports grandfathered (regular and irregular) as well as private - * use language tags. Private use tags are represented as 'x-whatever', - * and grandfathered tags are converted to their canonical replacements - * where they exist. Note that a few grandfathered tags have no modern - * replacement, these will be converted using the fallback described in - * the first paragraph, so some information might be lost. - * @param langtag the input BCP47 language tag. - * @param localeID the output buffer receiving a locale ID for the - * specified BCP47 language tag. - * @param localeIDCapacity the size of the locale ID output buffer. - * @param parsedLength if not NULL, successfully parsed length - * for the input language tag is set. - * @param err error information if receiving the locald ID - * failed. - * @return the length of the locale ID. - * @stable ICU 4.2 - */ -U_STABLE int32_t U_EXPORT2 -uloc_forLanguageTag(const char* langtag, - char* localeID, - int32_t localeIDCapacity, - int32_t* parsedLength, - UErrorCode* err); - -/** - * Returns a well-formed language tag for this locale ID. - *

- * Note: When strict is FALSE, any locale - * fields which do not satisfy the BCP47 syntax requirement will - * be omitted from the result. When strict is - * TRUE, this function sets U_ILLEGAL_ARGUMENT_ERROR to the - * err if any locale fields do not satisfy the - * BCP47 syntax requirement. - * @param localeID the input locale ID - * @param langtag the output buffer receiving BCP47 language - * tag for the locale ID. - * @param langtagCapacity the size of the BCP47 language tag - * output buffer. - * @param strict boolean value indicating if the function returns - * an error for an ill-formed input locale ID. - * @param err error information if receiving the language - * tag failed. - * @return The length of the BCP47 language tag. - * @stable ICU 4.2 - */ -U_STABLE int32_t U_EXPORT2 -uloc_toLanguageTag(const char* localeID, - char* langtag, - int32_t langtagCapacity, - UBool strict, - UErrorCode* err); - -/** - * Converts the specified keyword (legacy key, or BCP 47 Unicode locale - * extension key) to the equivalent BCP 47 Unicode locale extension key. - * For example, BCP 47 Unicode locale extension key "co" is returned for - * the input keyword "collation". - *

- * When the specified keyword is unknown, but satisfies the BCP syntax, - * then the pointer to the input keyword itself will be returned. - * For example, - * uloc_toUnicodeLocaleKey("ZZ") returns "ZZ". - * - * @param keyword the input locale keyword (either legacy key - * such as "collation" or BCP 47 Unicode locale extension - * key such as "co"). - * @return the well-formed BCP 47 Unicode locale extension key, - * or NULL if the specified locale keyword cannot be - * mapped to a well-formed BCP 47 Unicode locale extension - * key. - * @see uloc_toLegacyKey - * @stable ICU 54 - */ -U_STABLE const char* U_EXPORT2 -uloc_toUnicodeLocaleKey(const char* keyword); - -/** - * Converts the specified keyword value (legacy type, or BCP 47 - * Unicode locale extension type) to the well-formed BCP 47 Unicode locale - * extension type for the specified keyword (category). For example, BCP 47 - * Unicode locale extension type "phonebk" is returned for the input - * keyword value "phonebook", with the keyword "collation" (or "co"). - *

- * When the specified keyword is not recognized, but the specified value - * satisfies the syntax of the BCP 47 Unicode locale extension type, - * or when the specified keyword allows 'variable' type and the specified - * value satisfies the syntax, then the pointer to the input type value itself - * will be returned. - * For example, - * uloc_toUnicodeLocaleType("Foo", "Bar") returns "Bar", - * uloc_toUnicodeLocaleType("variableTop", "00A4") returns "00A4". - * - * @param keyword the locale keyword (either legacy key such as - * "collation" or BCP 47 Unicode locale extension - * key such as "co"). - * @param value the locale keyword value (either legacy type - * such as "phonebook" or BCP 47 Unicode locale extension - * type such as "phonebk"). - * @return the well-formed BCP47 Unicode locale extension type, - * or NULL if the locale keyword value cannot be mapped to - * a well-formed BCP 47 Unicode locale extension type. - * @see uloc_toLegacyType - * @stable ICU 54 - */ -U_STABLE const char* U_EXPORT2 -uloc_toUnicodeLocaleType(const char* keyword, const char* value); - -/** - * Converts the specified keyword (BCP 47 Unicode locale extension key, or - * legacy key) to the legacy key. For example, legacy key "collation" is - * returned for the input BCP 47 Unicode locale extension key "co". - * - * @param keyword the input locale keyword (either BCP 47 Unicode locale - * extension key or legacy key). - * @return the well-formed legacy key, or NULL if the specified - * keyword cannot be mapped to a well-formed legacy key. - * @see toUnicodeLocaleKey - * @stable ICU 54 - */ -U_STABLE const char* U_EXPORT2 -uloc_toLegacyKey(const char* keyword); - -/** - * Converts the specified keyword value (BCP 47 Unicode locale extension type, - * or legacy type or type alias) to the canonical legacy type. For example, - * the legacy type "phonebook" is returned for the input BCP 47 Unicode - * locale extension type "phonebk" with the keyword "collation" (or "co"). - *

- * When the specified keyword is not recognized, but the specified value - * satisfies the syntax of legacy key, or when the specified keyword - * allows 'variable' type and the specified value satisfies the syntax, - * then the pointer to the input type value itself will be returned. - * For example, - * uloc_toLegacyType("Foo", "Bar") returns "Bar", - * uloc_toLegacyType("vt", "00A4") returns "00A4". - * - * @param keyword the locale keyword (either legacy keyword such as - * "collation" or BCP 47 Unicode locale extension - * key such as "co"). - * @param value the locale keyword value (either BCP 47 Unicode locale - * extension type such as "phonebk" or legacy keyword value - * such as "phonebook"). - * @return the well-formed legacy type, or NULL if the specified - * keyword value cannot be mapped to a well-formed legacy - * type. - * @see toUnicodeLocaleType - * @stable ICU 54 - */ -U_STABLE const char* U_EXPORT2 -uloc_toLegacyType(const char* keyword, const char* value); - -#endif /*_ULOC*/ \ No newline at end of file diff --git a/Tweaks/Return-YouTube-Dislikes/unicode/umisc.h b/Tweaks/Return-YouTube-Dislikes/unicode/umisc.h deleted file mode 100644 index a622db3..0000000 --- a/Tweaks/Return-YouTube-Dislikes/unicode/umisc.h +++ /dev/null @@ -1,62 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -********************************************************************** -* Copyright (C) 1999-2006, International Business Machines -* Corporation and others. All Rights Reserved. -********************************************************************** -* file name: umisc.h -* encoding: UTF-8 -* tab size: 8 (not used) -* indentation:4 -* -* created on: 1999oct15 -* created by: Markus W. Scherer -*/ - -#ifndef UMISC_H -#define UMISC_H - -#include "unicode/utypes.h" - -/** - * \file - * \brief C API:misc definitions - * - * This file contains miscellaneous definitions for the C APIs. - */ - -U_CDECL_BEGIN - -/** A struct representing a range of text containing a specific field - * @stable ICU 2.0 - */ -typedef struct UFieldPosition { - /** - * The field - * @stable ICU 2.0 - */ - int32_t field; - /** - * The start of the text range containing field - * @stable ICU 2.0 - */ - int32_t beginIndex; - /** - * The limit of the text range containing field - * @stable ICU 2.0 - */ - int32_t endIndex; -} UFieldPosition; - -#if !UCONFIG_NO_SERVICE -/** - * Opaque type returned by registerInstance, registerFactory and unregister for service registration. - * @stable ICU 2.6 - */ -typedef const void* URegistryKey; -#endif - -U_CDECL_END - -#endif \ No newline at end of file diff --git a/Tweaks/Return-YouTube-Dislikes/unicode/unum.h b/Tweaks/Return-YouTube-Dislikes/unicode/unum.h deleted file mode 100644 index 9e8e824..0000000 --- a/Tweaks/Return-YouTube-Dislikes/unicode/unum.h +++ /dev/null @@ -1,1002 +0,0 @@ -/* -******************************************************************************* -* Copyright (C) 1997-2010, International Business Machines Corporation and others. -* All Rights Reserved. -* Modification History: -* -* Date Name Description -* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes -******************************************************************************* -*/ - -#ifndef _UNUM -#define _UNUM - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/localpointer.h" -#include "uloc.h" -#include "umisc.h" -#include "unicode/parseerr.h" -/** - * \file - * \brief C API: NumberFormat - * - *

Number Format C API

- * - * Number Format C API Provides functions for - * formatting and parsing a number. Also provides methods for - * determining which locales have number formats, and what their names - * are. - *

- * UNumberFormat helps you to format and parse numbers for any locale. - * Your code can be completely independent of the locale conventions - * for decimal points, thousands-separators, or even the particular - * decimal digits used, or whether the number format is even decimal. - * There are different number format styles like decimal, currency, - * percent and spellout. - *

- * To format a number for the current Locale, use one of the static - * factory methods: - *

- * \code
- *    UChar myString[20];
- *    double myNumber = 7.0;
- *    UErrorCode status = U_ZERO_ERROR;
- *    UNumberFormat* nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, &status);
- *    unum_formatDouble(nf, myNumber, myString, 20, NULL, &status);
- *    printf(" Example 1: %s\n", austrdup(myString) ); //austrdup( a function used to convert UChar* to char*)
- * \endcode
- * 
- * If you are formatting multiple numbers, it is more efficient to get - * the format and use it multiple times so that the system doesn't - * have to fetch the information about the local language and country - * conventions multiple times. - *
- * \code
- * uint32_t i, resultlength, reslenneeded;
- * UErrorCode status = U_ZERO_ERROR;
- * UFieldPosition pos;
- * uint32_t a[] = { 123, 3333, -1234567 };
- * const uint32_t a_len = sizeof(a) / sizeof(a[0]);
- * UNumberFormat* nf;
- * UChar* result = NULL;
- *
- * nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, &status);
- * for (i = 0; i < a_len; i++) {
- *    resultlength=0;
- *    reslenneeded=unum_format(nf, a[i], NULL, resultlength, &pos, &status);
- *    result = NULL;
- *    if(status==U_BUFFER_OVERFLOW_ERROR){
- *       status=U_ZERO_ERROR;
- *       resultlength=reslenneeded+1;
- *       result=(UChar*)malloc(sizeof(UChar) * resultlength);
- *       unum_format(nf, a[i], result, resultlength, &pos, &status);
- *    }
- *    printf( " Example 2: %s\n", austrdup(result));
- *    free(result);
- * }
- * \endcode
- * 
- * To format a number for a different Locale, specify it in the - * call to unum_open(). - *
- * \code
- *     UNumberFormat* nf = unum_open(UNUM_DEFAULT, NULL, -1, "fr_FR", NULL, &success)
- * \endcode
- * 
- * You can use a NumberFormat API unum_parse() to parse. - *
- * \code
- *    UErrorCode status = U_ZERO_ERROR;
- *    int32_t pos=0;
- *    int32_t num;
- *    num = unum_parse(nf, str, u_strlen(str), &pos, &status);
- * \endcode
- * 
- * Use UNUM_DECIMAL to get the normal number format for that country. - * There are other static options available. Use UNUM_CURRENCY - * to get the currency number format for that country. Use UNUM_PERCENT - * to get a format for displaying percentages. With this format, a - * fraction from 0.53 is displayed as 53%. - *

- * Use a pattern to create either a DecimalFormat or a RuleBasedNumberFormat - * formatter. The pattern must conform to the syntax defined for those - * formatters. - *

- * You can also control the display of numbers with such function as - * unum_getAttribues() and unum_setAtributes(), which let you set the - * miminum fraction digits, grouping, etc. - * @see UNumberFormatAttributes for more details - *

- * You can also use forms of the parse and format methods with - * ParsePosition and UFieldPosition to allow you to: - *

    - *
  • (a) progressively parse through pieces of a string. - *
  • (b) align the decimal point and other areas. - *
- *

- * It is also possible to change or set the symbols used for a particular - * locale like the currency symbol, the grouping seperator , monetary seperator - * etc by making use of functions unum_setSymbols() and unum_getSymbols(). - */ - -/** A number formatter. - * For usage in C programs. - * @stable ICU 2.0 - */ -typedef void* UNumberFormat; - -/** The possible number format styles. - * @stable ICU 2.0 - */ -typedef enum UNumberFormatStyle { - /** - * Decimal format defined by pattern - * @stable ICU 3.0 - */ - UNUM_PATTERN_DECIMAL=0, - /** Decimal format */ - UNUM_DECIMAL=1, - /** Currency format */ - UNUM_CURRENCY, - /** Percent format */ - UNUM_PERCENT, - /** Scientific format */ - UNUM_SCIENTIFIC, - /** Spellout rule-based format */ - UNUM_SPELLOUT, - /** - * Ordinal rule-based format - * @stable ICU 3.0 - */ - UNUM_ORDINAL, - /** - * Duration rule-based format - * @stable ICU 3.0 - */ - UNUM_DURATION, - /** - * Numbering system rule-based format - * @stable ICU 4.2 - */ - UNUM_NUMBERING_SYSTEM, - /** - * Rule-based format defined by pattern - * @stable ICU 3.0 - */ - UNUM_PATTERN_RULEBASED, - /** Default format */ - UNUM_DEFAULT = UNUM_DECIMAL, - /** (Alias for UNUM_PATTERN_DECIMAL) */ - UNUM_IGNORE = UNUM_PATTERN_DECIMAL, - - UNUM_DECIMAL_COMPACT_SHORT = 14, - UNUM_DECIMAL_COMPACT_LONG = 15, -} UNumberFormatStyle; - -/** The possible number format rounding modes. - * @stable ICU 2.0 - */ -typedef enum UNumberFormatRoundingMode { - UNUM_ROUND_CEILING, - UNUM_ROUND_FLOOR, - UNUM_ROUND_DOWN, - UNUM_ROUND_UP, - /** - * Half-even rounding, misspelled name - * @deprecated, ICU 3.8 - */ - UNUM_FOUND_HALFEVEN, - UNUM_ROUND_HALFDOWN, - UNUM_ROUND_HALFUP, - /** - * Half-even rounding - * @stable, ICU 3.8 - */ - UNUM_ROUND_HALFEVEN = UNUM_FOUND_HALFEVEN -} UNumberFormatRoundingMode; - -/** The possible number format pad positions. - * @stable ICU 2.0 - */ -typedef enum UNumberFormatPadPosition { - UNUM_PAD_BEFORE_PREFIX, - UNUM_PAD_AFTER_PREFIX, - UNUM_PAD_BEFORE_SUFFIX, - UNUM_PAD_AFTER_SUFFIX -} UNumberFormatPadPosition; - -/** - * Create and return a new UNumberFormat for formatting and parsing - * numbers. A UNumberFormat may be used to format numbers by calling - * {@link #unum_format }, and to parse numbers by calling {@link #unum_parse }. - * The caller must call {@link #unum_close } when done to release resources - * used by this object. - * @param style The type of number format to open: one of - * UNUM_DECIMAL, UNUM_CURRENCY, UNUM_PERCENT, UNUM_SCIENTIFIC, UNUM_SPELLOUT, - * UNUM_PATTERN_DECIMAL, UNUM_PATTERN_RULEBASED, or UNUM_DEFAULT. - * If UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED is passed then the - * number format is opened using the given pattern, which must conform - * to the syntax described in DecimalFormat or RuleBasedNumberFormat, - * respectively. - * @param pattern A pattern specifying the format to use. - * This parameter is ignored unless the style is - * UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED. - * @param patternLength The number of characters in the pattern, or -1 - * if null-terminated. This parameter is ignored unless the style is - * UNUM_PATTERN. - * @param locale A locale identifier to use to determine formatting - * and parsing conventions, or NULL to use the default locale. - * @param parseErr A pointer to a UParseError struct to receive the - * details of any parsing errors, or NULL if no parsing error details - * are desired. - * @param status A pointer to an input-output UErrorCode. - * @return A pointer to a newly created UNumberFormat, or NULL if an - * error occurred. - * @see unum_close - * @see DecimalFormat - * @stable ICU 2.0 - */ -U_STABLE UNumberFormat* U_EXPORT2 -unum_open( UNumberFormatStyle style, - const UChar* pattern, - int32_t patternLength, - const char* locale, - UParseError* parseErr, - UErrorCode* status); - - -/** -* Close a UNumberFormat. -* Once closed, a UNumberFormat may no longer be used. -* @param fmt The formatter to close. -* @stable ICU 2.0 -*/ -U_STABLE void U_EXPORT2 -unum_close(UNumberFormat* fmt); - -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUNumberFormatPointer - * "Smart pointer" class, closes a UNumberFormat via unum_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberFormatPointer, UNumberFormat, unum_close); - -U_NAMESPACE_END - -#endif - -/** - * Open a copy of a UNumberFormat. - * This function performs a deep copy. - * @param fmt The format to copy - * @param status A pointer to an UErrorCode to receive any errors. - * @return A pointer to a UNumberFormat identical to fmt. - * @stable ICU 2.0 - */ -U_STABLE UNumberFormat* U_EXPORT2 -unum_clone(const UNumberFormat *fmt, - UErrorCode *status); - -/** -* Format an integer using a UNumberFormat. -* The integer will be formatted according to the UNumberFormat's locale. -* @param fmt The formatter to use. -* @param number The number to format. -* @param result A pointer to a buffer to receive the formatted number. -* @param resultLength The maximum size of result. -* @param pos A pointer to a UFieldPosition. On input, position->field -* is read. On output, position->beginIndex and position->endIndex indicate -* the beginning and ending indices of field number position->field, if such -* a field exists. This parameter may be NULL, in which case no field -* @param status A pointer to an UErrorCode to receive any errors -* @return The total buffer size needed; if greater than resultLength, the output was truncated. -* @see unum_formatInt64 -* @see unum_formatDouble -* @see unum_parse -* @see unum_parseInt64 -* @see unum_parseDouble -* @see UFieldPosition -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_format( const UNumberFormat* fmt, - int32_t number, - UChar* result, - int32_t resultLength, - UFieldPosition *pos, - UErrorCode* status); - -/** -* Format an int64 using a UNumberFormat. -* The int64 will be formatted according to the UNumberFormat's locale. -* @param fmt The formatter to use. -* @param number The number to format. -* @param result A pointer to a buffer to receive the formatted number. -* @param resultLength The maximum size of result. -* @param pos A pointer to a UFieldPosition. On input, position->field -* is read. On output, position->beginIndex and position->endIndex indicate -* the beginning and ending indices of field number position->field, if such -* a field exists. This parameter may be NULL, in which case no field -* @param status A pointer to an UErrorCode to receive any errors -* @return The total buffer size needed; if greater than resultLength, the output was truncated. -* @see unum_format -* @see unum_formatDouble -* @see unum_parse -* @see unum_parseInt64 -* @see unum_parseDouble -* @see UFieldPosition -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_formatInt64(const UNumberFormat *fmt, - int64_t number, - UChar* result, - int32_t resultLength, - UFieldPosition *pos, - UErrorCode* status); - -/** -* Format a double using a UNumberFormat. -* The double will be formatted according to the UNumberFormat's locale. -* @param fmt The formatter to use. -* @param number The number to format. -* @param result A pointer to a buffer to receive the formatted number. -* @param resultLength The maximum size of result. -* @param pos A pointer to a UFieldPosition. On input, position->field -* is read. On output, position->beginIndex and position->endIndex indicate -* the beginning and ending indices of field number position->field, if such -* a field exists. This parameter may be NULL, in which case no field -* @param status A pointer to an UErrorCode to receive any errors -* @return The total buffer size needed; if greater than resultLength, the output was truncated. -* @see unum_format -* @see unum_formatInt64 -* @see unum_parse -* @see unum_parseInt64 -* @see unum_parseDouble -* @see UFieldPosition -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_formatDouble( const UNumberFormat* fmt, - double number, - UChar* result, - int32_t resultLength, - UFieldPosition *pos, /* 0 if ignore */ - UErrorCode* status); - -/** -* Format a decimal number using a UNumberFormat. -* The number will be formatted according to the UNumberFormat's locale. -* The syntax of the input number is a "numeric string" -* as defined in the Decimal Arithmetic Specification, available at -* http://speleotrove.com/decimal -* @param fmt The formatter to use. -* @param number The number to format. -* @param length The length of the input number, or -1 if the input is nul-terminated. -* @param result A pointer to a buffer to receive the formatted number. -* @param resultLength The maximum size of result. -* @param pos A pointer to a UFieldPosition. On input, position->field -* is read. On output, position->beginIndex and position->endIndex indicate -* the beginning and ending indices of field number position->field, if such -* a field exists. This parameter may be NULL, in which case it is ignored. -* @param status A pointer to an UErrorCode to receive any errors -* @return The total buffer size needed; if greater than resultLength, the output was truncated. -* @see unum_format -* @see unum_formatInt64 -* @see unum_parse -* @see unum_parseInt64 -* @see unum_parseDouble -* @see UFieldPosition -* @stable ICU 4.4 -*/ -U_STABLE int32_t U_EXPORT2 -unum_formatDecimal( const UNumberFormat* fmt, - const char * number, - int32_t length, - UChar* result, - int32_t resultLength, - UFieldPosition *pos, /* 0 if ignore */ - UErrorCode* status); - -/** - * Format a double currency amount using a UNumberFormat. - * The double will be formatted according to the UNumberFormat's locale. - * @param fmt the formatter to use - * @param number the number to format - * @param currency the 3-letter null-terminated ISO 4217 currency code - * @param result a pointer to the buffer to receive the formatted number - * @param resultLength the maximum number of UChars to write to result - * @param pos a pointer to a UFieldPosition. On input, - * position->field is read. On output, position->beginIndex and - * position->endIndex indicate the beginning and ending indices of - * field number position->field, if such a field exists. This - * parameter may be NULL, in which case it is ignored. - * @param status a pointer to an input-output UErrorCode - * @return the total buffer size needed; if greater than resultLength, - * the output was truncated. - * @see unum_formatDouble - * @see unum_parseDoubleCurrency - * @see UFieldPosition - * @stable ICU 3.0 - */ -U_STABLE int32_t U_EXPORT2 -unum_formatDoubleCurrency(const UNumberFormat* fmt, - double number, - UChar* currency, - UChar* result, - int32_t resultLength, - UFieldPosition* pos, /* ignored if 0 */ - UErrorCode* status); - -/** -* Parse a string into an integer using a UNumberFormat. -* The string will be parsed according to the UNumberFormat's locale. -* @param fmt The formatter to use. -* @param text The text to parse. -* @param textLength The length of text, or -1 if null-terminated. -* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which -* to begin parsing. If not 0, on output the offset at which parsing ended. -* @param status A pointer to an UErrorCode to receive any errors -* @return The value of the parsed integer -* @see unum_parseInt64 -* @see unum_parseDouble -* @see unum_format -* @see unum_formatInt64 -* @see unum_formatDouble -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_parse( const UNumberFormat* fmt, - const UChar* text, - int32_t textLength, - int32_t *parsePos /* 0 = start */, - UErrorCode *status); - -/** -* Parse a string into an int64 using a UNumberFormat. -* The string will be parsed according to the UNumberFormat's locale. -* @param fmt The formatter to use. -* @param text The text to parse. -* @param textLength The length of text, or -1 if null-terminated. -* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which -* to begin parsing. If not 0, on output the offset at which parsing ended. -* @param status A pointer to an UErrorCode to receive any errors -* @return The value of the parsed integer -* @see unum_parse -* @see unum_parseDouble -* @see unum_format -* @see unum_formatInt64 -* @see unum_formatDouble -* @stable ICU 2.8 -*/ -U_STABLE int64_t U_EXPORT2 -unum_parseInt64(const UNumberFormat* fmt, - const UChar* text, - int32_t textLength, - int32_t *parsePos /* 0 = start */, - UErrorCode *status); - -/** -* Parse a string into a double using a UNumberFormat. -* The string will be parsed according to the UNumberFormat's locale. -* @param fmt The formatter to use. -* @param text The text to parse. -* @param textLength The length of text, or -1 if null-terminated. -* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which -* to begin parsing. If not 0, on output the offset at which parsing ended. -* @param status A pointer to an UErrorCode to receive any errors -* @return The value of the parsed double -* @see unum_parse -* @see unum_parseInt64 -* @see unum_format -* @see unum_formatInt64 -* @see unum_formatDouble -* @stable ICU 2.0 -*/ -U_STABLE double U_EXPORT2 -unum_parseDouble( const UNumberFormat* fmt, - const UChar* text, - int32_t textLength, - int32_t *parsePos /* 0 = start */, - UErrorCode *status); - - -/** -* Parse a number from a string into an unformatted numeric string using a UNumberFormat. -* The input string will be parsed according to the UNumberFormat's locale. -* The syntax of the output is a "numeric string" -* as defined in the Decimal Arithmetic Specification, available at -* http://speleotrove.com/decimal -* @param fmt The formatter to use. -* @param text The text to parse. -* @param textLength The length of text, or -1 if null-terminated. -* @param parsePos If not 0, on input a pointer to an integer specifying the offset at which -* to begin parsing. If not 0, on output the offset at which parsing ended. -* @param outBuf A (char *) buffer to receive the parsed number as a string. The output string -* will be nul-terminated if there is sufficient space. -* @param outBufLength The size of the output buffer. May be zero, in which case -* the outBuf pointer may be NULL, and the function will return the -* size of the output string. -* @param status A pointer to an UErrorCode to receive any errors -* @return the length of the output string, not including any terminating nul. -* @see unum_parse -* @see unum_parseInt64 -* @see unum_format -* @see unum_formatInt64 -* @see unum_formatDouble -* @stable ICU 4.4 -*/ -U_STABLE int32_t U_EXPORT2 -unum_parseDecimal(const UNumberFormat* fmt, - const UChar* text, - int32_t textLength, - int32_t *parsePos /* 0 = start */, - char *outBuf, - int32_t outBufLength, - UErrorCode *status); - -/** - * Parse a string into a double and a currency using a UNumberFormat. - * The string will be parsed according to the UNumberFormat's locale. - * @param fmt the formatter to use - * @param text the text to parse - * @param textLength the length of text, or -1 if null-terminated - * @param parsePos a pointer to an offset index into text at which to - * begin parsing. On output, *parsePos will point after the last - * parsed character. This parameter may be 0, in which case parsing - * begins at offset 0. - * @param currency a pointer to the buffer to receive the parsed null- - * terminated currency. This buffer must have a capacity of at least - * 4 UChars. - * @param status a pointer to an input-output UErrorCode - * @return the parsed double - * @see unum_parseDouble - * @see unum_formatDoubleCurrency - * @stable ICU 3.0 - */ -U_STABLE double U_EXPORT2 -unum_parseDoubleCurrency(const UNumberFormat* fmt, - const UChar* text, - int32_t textLength, - int32_t* parsePos, /* 0 = start */ - UChar* currency, - UErrorCode* status); - -/** - * Set the pattern used by a UNumberFormat. This can only be used - * on a DecimalFormat, other formats return U_ILLEGAL_ARGUMENT_ERROR - * in the status. - * @param format The formatter to set. - * @param localized TRUE if the pattern is localized, FALSE otherwise. - * @param pattern The new pattern - * @param patternLength The length of pattern, or -1 if null-terminated. - * @param parseError A pointer to UParseError to recieve information - * about errors occurred during parsing, or NULL if no parse error - * information is desired. - * @param status A pointer to an input-output UErrorCode. - * @see unum_toPattern - * @see DecimalFormat - * @stable ICU 2.0 - */ -U_STABLE void U_EXPORT2 -unum_applyPattern( UNumberFormat *format, - UBool localized, - const UChar *pattern, - int32_t patternLength, - UParseError *parseError, - UErrorCode *status - ); - -/** -* Get a locale for which decimal formatting patterns are available. -* A UNumberFormat in a locale returned by this function will perform the correct -* formatting and parsing for the locale. The results of this call are not -* valid for rule-based number formats. -* @param localeIndex The index of the desired locale. -* @return A locale for which number formatting patterns are available, or 0 if none. -* @see unum_countAvailable -* @stable ICU 2.0 -*/ -U_STABLE const char* U_EXPORT2 -unum_getAvailable(int32_t localeIndex); - -/** -* Determine how many locales have decimal formatting patterns available. The -* results of this call are not valid for rule-based number formats. -* This function is useful for determining the loop ending condition for -* calls to {@link #unum_getAvailable }. -* @return The number of locales for which decimal formatting patterns are available. -* @see unum_getAvailable -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_countAvailable(void); - -/** The possible UNumberFormat numeric attributes @stable ICU 2.0 */ -typedef enum UNumberFormatAttribute { - /** Parse integers only */ - UNUM_PARSE_INT_ONLY, - /** Use grouping separator */ - UNUM_GROUPING_USED, - /** Always show decimal point */ - UNUM_DECIMAL_ALWAYS_SHOWN, - /** Maximum integer digits */ - UNUM_MAX_INTEGER_DIGITS, - /** Minimum integer digits */ - UNUM_MIN_INTEGER_DIGITS, - /** Integer digits */ - UNUM_INTEGER_DIGITS, - /** Maximum fraction digits */ - UNUM_MAX_FRACTION_DIGITS, - /** Minimum fraction digits */ - UNUM_MIN_FRACTION_DIGITS, - /** Fraction digits */ - UNUM_FRACTION_DIGITS, - /** Multiplier */ - UNUM_MULTIPLIER, - /** Grouping size */ - UNUM_GROUPING_SIZE, - /** Rounding Mode */ - UNUM_ROUNDING_MODE, - /** Rounding increment */ - UNUM_ROUNDING_INCREMENT, - /** The width to which the output of format() is padded. */ - UNUM_FORMAT_WIDTH, - /** The position at which padding will take place. */ - UNUM_PADDING_POSITION, - /** Secondary grouping size */ - UNUM_SECONDARY_GROUPING_SIZE, - /** Use significant digits - * @stable ICU 3.0 */ - UNUM_SIGNIFICANT_DIGITS_USED, - /** Minimum significant digits - * @stable ICU 3.0 */ - UNUM_MIN_SIGNIFICANT_DIGITS, - /** Maximum significant digits - * @stable ICU 3.0 */ - UNUM_MAX_SIGNIFICANT_DIGITS, - /** Lenient parse mode used by rule-based formats. - * @stable ICU 3.0 - */ - UNUM_LENIENT_PARSE -} UNumberFormatAttribute; - -/** -* Get a numeric attribute associated with a UNumberFormat. -* An example of a numeric attribute is the number of integer digits a formatter will produce. -* @param fmt The formatter to query. -* @param attr The attribute to query; one of UNUM_PARSE_INT_ONLY, UNUM_GROUPING_USED, -* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS, -* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER, -* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE. -* @return The value of attr. -* @see unum_setAttribute -* @see unum_getDoubleAttribute -* @see unum_setDoubleAttribute -* @see unum_getTextAttribute -* @see unum_setTextAttribute -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_getAttribute(const UNumberFormat* fmt, - UNumberFormatAttribute attr); - -/** -* Set a numeric attribute associated with a UNumberFormat. -* An example of a numeric attribute is the number of integer digits a formatter will produce. If the -* formatter does not understand the attribute, the call is ignored. Rule-based formatters only understand -* the lenient-parse attribute. -* @param fmt The formatter to set. -* @param attr The attribute to set; one of UNUM_PARSE_INT_ONLY, UNUM_GROUPING_USED, -* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS, -* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER, -* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE, -* or UNUM_LENIENT_PARSE. -* @param newValue The new value of attr. -* @see unum_getAttribute -* @see unum_getDoubleAttribute -* @see unum_setDoubleAttribute -* @see unum_getTextAttribute -* @see unum_setTextAttribute -* @stable ICU 2.0 -*/ -U_STABLE void U_EXPORT2 -unum_setAttribute( UNumberFormat* fmt, - UNumberFormatAttribute attr, - int32_t newValue); - - -/** -* Get a numeric attribute associated with a UNumberFormat. -* An example of a numeric attribute is the number of integer digits a formatter will produce. -* If the formatter does not understand the attribute, -1 is returned. -* @param fmt The formatter to query. -* @param attr The attribute to query; e.g. UNUM_ROUNDING_INCREMENT. -* @return The value of attr. -* @see unum_getAttribute -* @see unum_setAttribute -* @see unum_setDoubleAttribute -* @see unum_getTextAttribute -* @see unum_setTextAttribute -* @stable ICU 2.0 -*/ -U_STABLE double U_EXPORT2 -unum_getDoubleAttribute(const UNumberFormat* fmt, - UNumberFormatAttribute attr); - -/** -* Set a numeric attribute associated with a UNumberFormat. -* An example of a numeric attribute is the number of integer digits a formatter will produce. -* If the formatter does not understand the attribute, this call is ignored. -* @param fmt The formatter to set. -* @param attr The attribute to set; e.g. UNUM_ROUNDING_INCREMENT. -* @param newValue The new value of attr. -* @see unum_getAttribute -* @see unum_setAttribute -* @see unum_getDoubleAttribute -* @see unum_getTextAttribute -* @see unum_setTextAttribute -* @stable ICU 2.0 -*/ -U_STABLE void U_EXPORT2 -unum_setDoubleAttribute( UNumberFormat* fmt, - UNumberFormatAttribute attr, - double newValue); - -/** The possible UNumberFormat text attributes @stable ICU 2.0*/ -typedef enum UNumberFormatTextAttribute { - /** Positive prefix */ - UNUM_POSITIVE_PREFIX, - /** Positive suffix */ - UNUM_POSITIVE_SUFFIX, - /** Negative prefix */ - UNUM_NEGATIVE_PREFIX, - /** Negative suffix */ - UNUM_NEGATIVE_SUFFIX, - /** The character used to pad to the format width. */ - UNUM_PADDING_CHARACTER, - /** The ISO currency code */ - UNUM_CURRENCY_CODE, - /** - * The default rule set. This is only available with rule-based formatters. - * @stable ICU 3.0 - */ - UNUM_DEFAULT_RULESET, - /** - * The public rule sets. This is only available with rule-based formatters. - * This is a read-only attribute. The public rulesets are returned as a - * single string, with each ruleset name delimited by ';' (semicolon). - * @stable ICU 3.0 - */ - UNUM_PUBLIC_RULESETS -} UNumberFormatTextAttribute; - -/** -* Get a text attribute associated with a UNumberFormat. -* An example of a text attribute is the suffix for positive numbers. If the formatter -* does not understand the attributre, U_UNSUPPORTED_ERROR is returned as the status. -* Rule-based formatters only understand UNUM_DEFAULT_RULESET and UNUM_PUBLIC_RULESETS. -* @param fmt The formatter to query. -* @param tag The attribute to query; one of UNUM_POSITIVE_PREFIX, UNUM_POSITIVE_SUFFIX, -* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX, UNUM_PADDING_CHARACTER, UNUM_CURRENCY_CODE, -* UNUM_DEFAULT_RULESET, or UNUM_PUBLIC_RULESETS. -* @param result A pointer to a buffer to receive the attribute. -* @param resultLength The maximum size of result. -* @param status A pointer to an UErrorCode to receive any errors -* @return The total buffer size needed; if greater than resultLength, the output was truncated. -* @see unum_setTextAttribute -* @see unum_getAttribute -* @see unum_setAttribute -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_getTextAttribute( const UNumberFormat* fmt, - UNumberFormatTextAttribute tag, - UChar* result, - int32_t resultLength, - UErrorCode* status); - -/** -* Set a text attribute associated with a UNumberFormat. -* An example of a text attribute is the suffix for positive numbers. Rule-based formatters -* only understand UNUM_DEFAULT_RULESET. -* @param fmt The formatter to set. -* @param tag The attribute to set; one of UNUM_POSITIVE_PREFIX, UNUM_POSITIVE_SUFFIX, -* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX, UNUM_PADDING_CHARACTER, UNUM_CURRENCY_CODE, -* or UNUM_DEFAULT_RULESET. -* @param newValue The new value of attr. -* @param newValueLength The length of newValue, or -1 if null-terminated. -* @param status A pointer to an UErrorCode to receive any errors -* @see unum_getTextAttribute -* @see unum_getAttribute -* @see unum_setAttribute -* @stable ICU 2.0 -*/ -U_STABLE void U_EXPORT2 -unum_setTextAttribute( UNumberFormat* fmt, - UNumberFormatTextAttribute tag, - const UChar* newValue, - int32_t newValueLength, - UErrorCode *status); - -/** - * Extract the pattern from a UNumberFormat. The pattern will follow - * the DecimalFormat pattern syntax. - * @param fmt The formatter to query. - * @param isPatternLocalized TRUE if the pattern should be localized, - * FALSE otherwise. This is ignored if the formatter is a rule-based - * formatter. - * @param result A pointer to a buffer to receive the pattern. - * @param resultLength The maximum size of result. - * @param status A pointer to an input-output UErrorCode. - * @return The total buffer size needed; if greater than resultLength, - * the output was truncated. - * @see unum_applyPattern - * @see DecimalFormat - * @stable ICU 2.0 - */ -U_STABLE int32_t U_EXPORT2 -unum_toPattern( const UNumberFormat* fmt, - UBool isPatternLocalized, - UChar* result, - int32_t resultLength, - UErrorCode* status); - - -/** - * Constants for specifying a number format symbol. - * @stable ICU 2.0 - */ -typedef enum UNumberFormatSymbol { - /** The decimal separator */ - UNUM_DECIMAL_SEPARATOR_SYMBOL = 0, - /** The grouping separator */ - UNUM_GROUPING_SEPARATOR_SYMBOL = 1, - /** The pattern separator */ - UNUM_PATTERN_SEPARATOR_SYMBOL = 2, - /** The percent sign */ - UNUM_PERCENT_SYMBOL = 3, - /** Zero*/ - UNUM_ZERO_DIGIT_SYMBOL = 4, - /** Character representing a digit in the pattern */ - UNUM_DIGIT_SYMBOL = 5, - /** The minus sign */ - UNUM_MINUS_SIGN_SYMBOL = 6, - /** The plus sign */ - UNUM_PLUS_SIGN_SYMBOL = 7, - /** The currency symbol */ - UNUM_CURRENCY_SYMBOL = 8, - /** The international currency symbol */ - UNUM_INTL_CURRENCY_SYMBOL = 9, - /** The monetary separator */ - UNUM_MONETARY_SEPARATOR_SYMBOL = 10, - /** The exponential symbol */ - UNUM_EXPONENTIAL_SYMBOL = 11, - /** Per mill symbol */ - UNUM_PERMILL_SYMBOL = 12, - /** Escape padding character */ - UNUM_PAD_ESCAPE_SYMBOL = 13, - /** Infinity symbol */ - UNUM_INFINITY_SYMBOL = 14, - /** Nan symbol */ - UNUM_NAN_SYMBOL = 15, - /** Significant digit symbol - * @stable ICU 3.0 */ - UNUM_SIGNIFICANT_DIGIT_SYMBOL = 16, - /** The monetary grouping separator - * @stable ICU 3.6 - */ - UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL = 17, - /** One - * @draft ICU 4.6 - */ - UNUM_ONE_DIGIT_SYMBOL = 18, - /** Two - * @draft ICU 4.6 - */ - UNUM_TWO_DIGIT_SYMBOL = 19, - /** Three - * @draft ICU 4.6 - */ - UNUM_THREE_DIGIT_SYMBOL = 20, - /** Four - * @draft ICU 4.6 - */ - UNUM_FOUR_DIGIT_SYMBOL = 21, - /** Five - * @draft ICU 4.6 - */ - UNUM_FIVE_DIGIT_SYMBOL = 22, - /** Six - * @draft ICU 4.6 - */ - UNUM_SIX_DIGIT_SYMBOL = 23, - /** Seven - * @draft ICU 4.6 - */ - UNUM_SEVEN_DIGIT_SYMBOL = 24, - /** Eight - * @draft ICU 4.6 - */ - UNUM_EIGHT_DIGIT_SYMBOL = 25, - /** Nine - * @draft ICU 4.6 - */ - UNUM_NINE_DIGIT_SYMBOL = 26, - /** count symbol constants */ - UNUM_FORMAT_SYMBOL_COUNT = 27 -} UNumberFormatSymbol; - -/** -* Get a symbol associated with a UNumberFormat. -* A UNumberFormat uses symbols to represent the special locale-dependent -* characters in a number, for example the percent sign. This API is not -* supported for rule-based formatters. -* @param fmt The formatter to query. -* @param symbol The UNumberFormatSymbol constant for the symbol to get -* @param buffer The string buffer that will receive the symbol string; -* if it is NULL, then only the length of the symbol is returned -* @param size The size of the string buffer -* @param status A pointer to an UErrorCode to receive any errors -* @return The length of the symbol; the buffer is not modified if -* length>=size -* @see unum_setSymbol -* @stable ICU 2.0 -*/ -U_STABLE int32_t U_EXPORT2 -unum_getSymbol(const UNumberFormat *fmt, - UNumberFormatSymbol symbol, - UChar *buffer, - int32_t size, - UErrorCode *status); - -/** -* Set a symbol associated with a UNumberFormat. -* A UNumberFormat uses symbols to represent the special locale-dependent -* characters in a number, for example the percent sign. This API is not -* supported for rule-based formatters. -* @param fmt The formatter to set. -* @param symbol The UNumberFormatSymbol constant for the symbol to set -* @param value The string to set the symbol to -* @param length The length of the string, or -1 for a zero-terminated string -* @param status A pointer to an UErrorCode to receive any errors. -* @see unum_getSymbol -* @stable ICU 2.0 -*/ -U_STABLE void U_EXPORT2 -unum_setSymbol(UNumberFormat *fmt, - UNumberFormatSymbol symbol, - const UChar *value, - int32_t length, - UErrorCode *status); - - -/** - * Get the locale for this number format object. - * You can choose between valid and actual locale. - * @param fmt The formatter to get the locale from - * @param type type of the locale we're looking for (valid or actual) - * @param status error code for the operation - * @return the locale name - * @stable ICU 2.8 - */ -U_STABLE const char* U_EXPORT2 -unum_getLocaleByType(const UNumberFormat *fmt, - ULocDataLocaleType type, - UErrorCode* status); - -#endif /* #if !UCONFIG_NO_FORMATTING */ - -#endif \ No newline at end of file diff --git a/Tweaks/YTABConfig b/Tweaks/YTABConfig new file mode 160000 index 0000000..ae9d134 --- /dev/null +++ b/Tweaks/YTABConfig @@ -0,0 +1 @@ +Subproject commit ae9d1345f045482b1ab4367ffaec9136e74c84c2 diff --git a/Tweaks/YTABConfig/.gitignore b/Tweaks/YTABConfig/.gitignore deleted file mode 100644 index faf8687..0000000 --- a/Tweaks/YTABConfig/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos/ -packages/ -.DS_Store diff --git a/Tweaks/YTABConfig/LICENSE b/Tweaks/YTABConfig/LICENSE deleted file mode 100644 index f288702..0000000 --- a/Tweaks/YTABConfig/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/Tweaks/YTABConfig/Makefile b/Tweaks/YTABConfig/Makefile deleted file mode 100644 index c1e46b7..0000000 --- a/Tweaks/YTABConfig/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TARGET := iphone:clang:latest:11.0 -INSTALL_TARGET_PROCESSES = YouTube -ARCHS = arm64 -PACKAGE_VERSION = 1.5.0-1 - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YTABConfig - -$(TWEAK_NAME)_FILES = Tweak.xm -$(TWEAK_NAME)_CFLAGS = -fobjc-arc -DTWEAK_VERSION=$(PACKAGE_VERSION) -$(TWEAK_NAME)_FRAMEWORKS = UIKit - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/YTABConfig/README.md b/Tweaks/YTABConfig/README.md deleted file mode 100644 index 5a81c5d..0000000 --- a/Tweaks/YTABConfig/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# YTABConfig - -Configure A/B settings in iOS YouTube app. - -## Supported YouTube versions - -Version 16.42.3 and newer. Lower are either untested or unsupported. diff --git a/Tweaks/YTABConfig/Tweak.xm b/Tweaks/YTABConfig/Tweak.xm deleted file mode 100644 index 08b1474..0000000 --- a/Tweaks/YTABConfig/Tweak.xm +++ /dev/null @@ -1,442 +0,0 @@ -#import -#import "../YouTubeHeader/YTAlertView.h" -#import "../YouTubeHeader/YTAppDelegate.h" -#import "../YouTubeHeader/YTCommonUtils.h" -#import "../YouTubeHeader/YTUIUtils.h" -#import "../YouTubeHeader/YTVersionUtils.h" -#import "../YouTubeHeader/YTGlobalConfig.h" -#import "../YouTubeHeader/YTColdConfig.h" -#import "../YouTubeHeader/YTHotConfig.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../YouTubeHeader/YTSettingsPickerViewController.h" -#import "../YouTubeHeader/YTSettingsViewController.h" -#import "../YouTubeHeader/YTSearchableSettingsViewController.h" -#import "../YouTubeHeader/YTToastResponderEvent.h" - -#define Prefix @"YTABC" -#define EnabledKey @"EnabledYTABC" -#define GroupedKey @"GroupedYTABC" -#define INCLUDED_CLASSES @"Included classes: YTGlobalConfig, YTColdConfig, YTHotConfig" -#define EXCLUDED_METHODS @"Excluded settings: android*, amsterdam*, musicClient* and unplugged*" - -#define _LOC(b, x) [b localizedStringForKey:x value:nil table:nil] -#define LOC(x) _LOC(tweakBundle, x) - -static const NSInteger YTABCSection = 404; - -@interface YTSettingsSectionItemManager (YTABConfig) -- (void)updateYTABCSectionWithEntry:(id)entry; -@end - -NSMutableDictionary *> *cache; -NSUserDefaults *defaults; -NSArray *allKeys; - -static BOOL tweakEnabled() { - return [defaults boolForKey:EnabledKey]; -} - -static BOOL groupedSettings() { - return [defaults boolForKey:GroupedKey]; -} - -static NSString *getKey(NSString *method, NSString *classKey) { - return [NSString stringWithFormat:@"%@.%@.%@", Prefix, classKey, method]; -} - -static NSString *getCacheKey(NSString *method, NSString *classKey) { - return [NSString stringWithFormat:@"%@.%@", classKey, method]; -} - -static BOOL getValue(NSString *methodKey) { - if (![allKeys containsObject:methodKey]) - return [[cache valueForKeyPath:[methodKey substringFromIndex:Prefix.length + 1]] boolValue]; - return [defaults boolForKey:methodKey]; -} - -static void setValue(NSString *method, NSString *classKey, BOOL value) { - [cache setValue:@(value) forKeyPath:getCacheKey(method, classKey)]; - [defaults setBool:value forKey:getKey(method, classKey)]; -} - -static void updateAllKeys() { - allKeys = [defaults dictionaryRepresentation].allKeys; -} - -static BOOL returnFunction(id const self, SEL _cmd) { - NSString *method = NSStringFromSelector(_cmd); - NSString *methodKey = getKey(method, NSStringFromClass([self class])); - return getValue(methodKey); -} - -static BOOL getValueFromInvocation(id target, SEL selector) { - NSInvocationOperation *i = [[NSInvocationOperation alloc] initWithTarget:target selector:selector object:nil]; - [i start]; - BOOL result = NO; - [i.result getValue:&result]; - return result; -} - -NSBundle *YTABCBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YTABC" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YTABC.bundle")]; - }); - return bundle; -} - -%group Search - -%hook YTSettingsViewController - -- (void)loadWithModel:(id)model fromView:(UIView *)view { - %orig; - if ([[self valueForKey:@"_detailsCategoryID"] integerValue] == YTABCSection) - MSHookIvar(self, "_shouldShowSearchBar") = YES; -} - -- (void)setSectionControllers { - %orig; - if (MSHookIvar(self, "_shouldShowSearchBar")) { - YTSettingsSectionController *settingsSectionController = [self settingsSectionControllers][[self valueForKey:@"_detailsCategoryID"]]; - if (settingsSectionController) { - YTSearchableSettingsViewController *searchableVC = [self valueForKey:@"_searchableSettingsViewController"]; - [searchableVC storeCollectionViewSections:@[settingsSectionController]]; - } - } -} - -%end - -%end - -%hook YTSettingsSectionController - -- (void)setSelectedItem:(NSUInteger)selectedItem { - if (selectedItem != NSNotFound) %orig; -} - -%end - -%hook YTAppSettingsPresentationData - -+ (NSArray *)settingsCategoryOrder { - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - [mutableOrder insertObject:@(YTABCSection) atIndex:0]; - return mutableOrder; -} - -%end - -static NSString *getCategory(char c, NSString *method) { - if (c == 'e') { - if ([method hasPrefix:@"elements"]) return @"elements"; - if ([method hasPrefix:@"enable"]) return @"enable"; - } - if (c == 'i') { - if ([method hasPrefix:@"ios"]) return @"ios"; - if ([method hasPrefix:@"is"]) return @"is"; - } - if (c == 's') { - if ([method hasPrefix:@"shorts"]) return @"shorts"; - if ([method hasPrefix:@"should"]) return @"should"; - } - unichar uc = (unichar)c; - return [NSString stringWithCharacters:&uc length:1];; -} - -%hook YTSettingsSectionItemManager - -%new(v@:@) -- (void)updateYTABCSectionWithEntry:(id)entry { - NSMutableArray *sectionItems = [NSMutableArray array]; - int totalSettings = 0; - NSBundle *tweakBundle = YTABCBundle(); - BOOL isPhone = ![%c(YTCommonUtils) isIPad]; - NSString *yesText = _LOC([NSBundle mainBundle], @"settings.yes"); - NSString *cancelText = _LOC([NSBundle mainBundle], @"confirm.cancel"); - NSString *deleteText = _LOC([NSBundle mainBundle], @"search.action.delete"); - Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); - Class YTAlertViewClass = %c(YTAlertView); - if (tweakEnabled()) { - NSMutableDictionary *> *properties = [NSMutableDictionary dictionary]; - for (NSString *classKey in cache) { - for (NSString *method in cache[classKey]) { - char c = tolower([method characterAtIndex:0]); - NSString *category = getCategory(c, method); - if (![properties objectForKey:category]) properties[category] = [NSMutableArray array]; - updateAllKeys(); - BOOL modified = [allKeys containsObject:getKey(method, classKey)]; - NSString *modifiedTitle = modified ? [NSString stringWithFormat:@"%@ *", method] : method; - YTSettingsSectionItem *methodSwitch = [YTSettingsSectionItemClass switchItemWithTitle:modifiedTitle - titleDescription:isPhone && method.length > 26 ? modifiedTitle : nil - accessibilityIdentifier:nil - switchOn:getValue(getKey(method, classKey)) - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - setValue(method, classKey, enabled); - return YES; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSString *content = [NSString stringWithFormat:@"%@.%@", classKey, method]; - YTAlertView *alertView = [YTAlertViewClass confirmationDialog]; - alertView.title = method; - alertView.subtitle = content; - [alertView addTitle:LOC(@"COPY_TO_CLIPBOARD") withAction:^{ - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - pasteboard.string = content; - [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"COPIED_TO_CLIPBOARD") firstResponder:[self parentResponder]] send]; - }]; - updateAllKeys(); - NSString *key = getKey(method, classKey); - if ([allKeys containsObject:key]) { - [alertView addTitle:deleteText withAction:^{ - [defaults removeObjectForKey:key]; - updateAllKeys(); - }]; - } - [alertView addCancelButton:NULL]; - [alertView show]; - return NO; - } - settingItemId:0]; - [properties[category] addObject:methodSwitch]; - } - } - YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; - BOOL grouped = groupedSettings(); - for (NSString *category in properties) { - NSMutableArray *rows = properties[category]; - totalSettings += rows.count; - if (grouped) { - NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]; - [rows sortUsingDescriptors:@[sort]]; - NSString *shortTitle = [NSString stringWithFormat:@"\"%@\" (%ld)", category, rows.count]; - NSString *title = [NSString stringWithFormat:@"%@ %@", LOC(@"SETTINGS_START_WITH"), shortTitle]; - YTSettingsSectionItem *sectionItem = [YTSettingsSectionItemClass itemWithTitle:title accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:shortTitle pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:sectionItem]; - } else { - [sectionItems addObjectsFromArray:rows]; - } - } - NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]; - [sectionItems sortUsingDescriptors:@[sort]]; - YTSettingsSectionItem *copyAll = [YTSettingsSectionItemClass itemWithTitle:LOC(@"COPY_CURRENT_SETTINGS") - titleDescription:LOC(@"COPY_CURRENT_SETTINGS_DESC") - accessibilityIdentifier:nil - detailTextBlock:nil - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - NSMutableArray *content = [NSMutableArray array]; - for (NSString *classKey in cache) { - [cache[classKey] enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *value, BOOL* stop) { - [content addObject:[NSString stringWithFormat:@"%@: %d", key, [value boolValue]]]; - }]; - } - [content sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; - [content insertObject:[NSString stringWithFormat:@"Device model: %@", [%c(YTCommonUtils) hardwareModel]] atIndex:0]; - [content insertObject:[NSString stringWithFormat:@"App version: %@", [%c(YTVersionUtils) appVersion]] atIndex:0]; - [content insertObject:EXCLUDED_METHODS atIndex:0]; - [content insertObject:INCLUDED_CLASSES atIndex:0]; - [content insertObject:[NSString stringWithFormat:@"YTABConfig version: %@", @(OS_STRINGIFY(TWEAK_VERSION))] atIndex:0]; - pasteboard.string = [content componentsJoinedByString:@"\n"]; - [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"COPIED_TO_CLIPBOARD") firstResponder:[self parentResponder]] send]; - return YES; - }]; - [sectionItems insertObject:copyAll atIndex:0]; - YTSettingsSectionItem *modified = [YTSettingsSectionItemClass itemWithTitle:LOC(@"VIEW_MODIFIED_SETTINGS") - titleDescription:LOC(@"VIEW_MODIFIED_SETTINGS_DESC") - accessibilityIdentifier:nil - detailTextBlock:nil - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSMutableArray *features = [NSMutableArray array]; - updateAllKeys(); - for (NSString *key in allKeys) { - if ([key hasPrefix:Prefix]) { - NSString *displayKey = [key substringFromIndex:Prefix.length + 1]; - [features addObject:[NSString stringWithFormat:@"%@: %d", displayKey, [defaults boolForKey:key]]]; - } - } - [features sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; - [features insertObject:[NSString stringWithFormat:LOC(@"TOTAL_MODIFIED_SETTINGS"), features.count] atIndex:0]; - NSString *content = [features componentsJoinedByString:@"\n"]; - YTAlertView *alertView = [YTAlertViewClass confirmationDialogWithAction:^{ - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - pasteboard.string = content; - [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"COPIED_TO_CLIPBOARD") firstResponder:[self parentResponder]] send]; - } actionTitle:LOC(@"COPY_TO_CLIPBOARD")]; - alertView.title = LOC(@"MODIFIED_SETTINGS_TITLE"); - alertView.subtitle = content; - [alertView show]; - return YES; - }]; - [sectionItems insertObject:modified atIndex:0]; - YTSettingsSectionItem *reset = [YTSettingsSectionItemClass itemWithTitle:LOC(@"RESET_KILL") - titleDescription:LOC(@"RESET_KILL_DESC") - accessibilityIdentifier:nil - detailTextBlock:nil - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - YTAlertView *alertView = [YTAlertViewClass confirmationDialogWithAction:^{ - updateAllKeys(); - for (NSString *key in allKeys) { - if ([key hasPrefix:Prefix]) - [defaults removeObjectForKey:key]; - } - exit(0); - } actionTitle:yesText]; - alertView.title = LOC(@"WARNING"); - alertView.subtitle = LOC(@"APPLY_DESC"); - [alertView show]; - return YES; - }]; - [sectionItems insertObject:reset atIndex:0]; - YTSettingsSectionItem *group = [YTSettingsSectionItemClass switchItemWithTitle:LOC(@"GROUPED") - titleDescription:nil - accessibilityIdentifier:nil - switchOn:groupedSettings() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - YTAlertView *alertView = [YTAlertViewClass confirmationDialogWithAction:^{ - [defaults setBool:enabled forKey:GroupedKey]; - exit(0); - } - actionTitle:yesText - cancelAction:^{ - [cell setSwitchOn:!enabled animated:YES]; - } - cancelTitle:cancelText]; - alertView.title = LOC(@"WARNING"); - alertView.subtitle = LOC(@"APPLY_DESC"); - [alertView show]; - return YES; - } - settingItemId:0]; - [sectionItems insertObject:group atIndex:0]; - } - YTSettingsSectionItem *thread = [YTSettingsSectionItemClass itemWithTitle:LOC(@"OPEN_MEGATHREAD") - titleDescription:LOC(@"OPEN_MEGATHREAD_DESC") - accessibilityIdentifier:nil - detailTextBlock:nil - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/PoomSmart/YTABConfig/discussions"]]; - }]; - [sectionItems insertObject:thread atIndex:0]; - YTSettingsSectionItem *master = [YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLED") - titleDescription:LOC(@"ENABLED_DESC") - accessibilityIdentifier:nil - switchOn:tweakEnabled() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [defaults setBool:enabled forKey:EnabledKey]; - YTAlertView *alertView = [YTAlertViewClass confirmationDialogWithAction:^{ exit(0); } - actionTitle:yesText - cancelAction:^{ - [cell setSwitchOn:!enabled animated:YES]; - } - cancelTitle:cancelText]; - alertView.title = LOC(@"WARNING"); - alertView.subtitle = LOC(@"APPLY_DESC"); - [alertView show]; - return YES; - } - settingItemId:0]; - [sectionItems insertObject:master atIndex:0]; - YTSettingsViewController *delegate = [self valueForKey:@"_dataDelegate"]; - [delegate setSectionItems:sectionItems - forCategory:YTABCSection - title:@"A/B" - titleDescription:tweakEnabled() ? [NSString stringWithFormat:@"YTABConfig %@, %d feature flags.", @(OS_STRINGIFY(TWEAK_VERSION)), totalSettings] : nil - headerHidden:NO]; -} - -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { - if (category == YTABCSection) { - [self updateYTABCSectionWithEntry:entry]; - return; - } - %orig; -} - -%end - -static NSMutableArray *getBooleanMethods(Class clz) { - NSMutableArray *allMethods = [NSMutableArray array]; - unsigned int methodCount = 0; - Method *methods = class_copyMethodList(clz, &methodCount); - for (unsigned int i = 0; i < methodCount; ++i) { - Method method = methods[i]; - const char *name = sel_getName(method_getName(method)); - if (strstr(name, "ndroid") || strstr(name, "musicClient") || strstr(name, "amsterdam") || strstr(name, "unplugged")) continue; - const char *encoding = method_getTypeEncoding(method); - if (strcmp(encoding, "B16@0:8")) continue; - NSString *selector = [NSString stringWithUTF8String:name]; - if (![allMethods containsObject:selector]) - [allMethods addObject:selector]; - } - free(methods); - return allMethods; -} - -static void hookClass(NSObject *instance) { - if (!instance) [NSException raise:@"hookClass Invalid argument exception" format:@"Hooking the class of a non-existing instance"]; - Class instanceClass = [instance class]; - NSMutableArray *methods = getBooleanMethods(instanceClass); - NSString *classKey = NSStringFromClass(instanceClass); - NSMutableDictionary *classCache = cache[classKey] = [NSMutableDictionary new]; - for (NSString *method in methods) { - SEL selector = NSSelectorFromString(method); - BOOL result = getValueFromInvocation(instance, selector); - classCache[method] = @(result); - MSHookMessageEx(instanceClass, selector, (IMP)returnFunction, NULL); - } -} - -%hook YTAppDelegate - -- (BOOL)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2 { - defaults = [NSUserDefaults standardUserDefaults]; - if (tweakEnabled()) { - updateAllKeys(); - YTGlobalConfig *globalConfig; - YTColdConfig *coldConfig; - YTHotConfig *hotConfig; - @try { - globalConfig = [self valueForKey:@"_globalConfig"]; - coldConfig = [self valueForKey:@"_coldConfig"]; - hotConfig = [self valueForKey:@"_hotConfig"]; - } @catch (id ex) { - id settings = [self valueForKey:@"_settings"]; - globalConfig = [settings valueForKey:@"_globalConfig"]; - coldConfig = [settings valueForKey:@"_coldConfig"]; - hotConfig = [settings valueForKey:@"_hotConfig"]; - } - hookClass(globalConfig); - hookClass(coldConfig); - hookClass(hotConfig); - if (!groupedSettings()) { - %init(Search); - } - } - return %orig; -} - -%end - -%ctor { - NSBundle *bundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/Frameworks/Module_Framework.framework", [[NSBundle mainBundle] bundlePath]]]; - if (!bundle.loaded) [bundle load]; - cache = [NSMutableDictionary new]; - %init; -} - -%dtor { - [cache removeAllObjects]; -} diff --git a/Tweaks/YTABConfig/YTABConfig.plist b/Tweaks/YTABConfig/YTABConfig.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/YTABConfig/YTABConfig.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/YTABConfig/control b/Tweaks/YTABConfig/control deleted file mode 100644 index b6d0800..0000000 --- a/Tweaks/YTABConfig/control +++ /dev/null @@ -1,11 +0,0 @@ -Package: com.ps.ytabconfig -Name: YTABConfig -Version: 1.0.0 -Architecture: iphoneos-arm -Description: Configure A/B features in iOS YouTube app. -Maintainer: PoomSmart -Author: PoomSmart -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 11.0) -Depiction: https://poomsmart.github.io/repo/depictions/ytabconfig.html -SileoDepiction: https://poomsmart.github.io/repo/sileodepictions/ytabconfig.json diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/Info.plist b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/Info.plist deleted file mode 100644 index 32d0326..0000000 Binary files a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/Info.plist and /dev/null differ diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ar.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ar.lproj/Localizable.strings deleted file mode 100644 index 42564de..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ar.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "مفعَّل"; -"ENABLED_DESC" = "فعّل لإظهار إعدادات A/B."; -"GROUPED" = "الإعدادات مجمَّعة حسب البادئات"; -"RESET_KILL" = "إعادة التعيين والخروج من التطبيق"; -"RESET_KILL_DESC" = "المس هنا للتراجع عن كل تغييراتك والخروج من التطبيق."; -"COPY_CURRENT_SETTINGS" = "نسخ الإعدادات الحالية"; -"COPY_CURRENT_SETTINGS_DESC" = "المس لنسخ إعداداتك الحالية."; -"VIEW_MODIFIED_SETTINGS" = "إظهار الإعدادات المعدَّلة"; -"VIEW_MODIFIED_SETTINGS_DESC" = "المس لعرض جميع التغييرات التي أجريتها يدويَّاً."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "التغييرات"; -"TOTAL_MODIFIED_SETTINGS" = "المجموع: %ld"; - -// Quit app alert -"WARNING" = "تحذير"; -"APPLY_DESC" = "سيؤدي هذا الإجراء إلى إغلاق التطبيق. هل أنت متأكد أنك تَوَد الاستمرار؟"; - -"OPEN_MEGATHREAD" = "فتح موضوع المناقشات"; -"OPEN_MEGATHREAD_DESC" = "فتح موضوع YTABConfig على موقع GitHub حيث يمكنك مشاركة ومناقشة تأثير تفعيل وإلغاء كل خيار."; -"SETTINGS_START_WITH" = "الإعدادات التي تبدأ بـ"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "نسخ"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "تم النسخ."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/de.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/de.lproj/Localizable.strings deleted file mode 100644 index 6ea8431..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/de.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Aktiviert"; -"ENABLED_DESC" = "Aktivieren, um A/B-Einstellungen zu sehen."; -"GROUPED" = "Gruppierte Einstellungen bei Prefix"; -"RESET_KILL" = "Zurücksetzen und crashen"; -"RESET_KILL_DESC" = "Tippe hier, um alle Einstellungen zurückzusetzen und um YouTube zum Abstürzen zu bringen."; -"COPY_CURRENT_SETTINGS" = "Aktuelle Einstellungen kopieren"; -"COPY_CURRENT_SETTINGS_DESC" = "Tippe hier, um alle Einstellungen in die Zwischenablage zu kopieren."; -"VIEW_MODIFIED_SETTINGS" = "Modifizierte Einstellungen anzeigen"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Tippe hier, um alle manuelle Änderungen zu sehen."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Änderungen"; -"TOTAL_MODIFIED_SETTINGS" = "Total: %ld"; - -// Quit app alert -"WARNING" = "Warning"; -"APPLY_DESC" = "This action will quit YouTube. Are you sure you want to continue?"; - -"OPEN_MEGATHREAD" = "Megathread öffnen"; -"OPEN_MEGATHREAD_DESC" = "Öffne den YTABConfig Megathread auf GitHub, in dem Sie sich über die Auswirkungen der Aktivierung bzw. Deaktivierung der einzelnen Einstellungen austauschen und diskutieren können."; -"SETTINGS_START_WITH" = "Einstellungen beginnend mit"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "In die Zwischenablage kopieren"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "In die Zwischenablage kopiert."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/en.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 20ce9f8..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Enabled"; -"ENABLED_DESC" = "Enable to show A/B settings."; -"GROUPED" = "Grouped settings by prefixes"; -"RESET_KILL" = "Reset and Kill"; -"RESET_KILL_DESC" = "Tap to undo all of your changes and kill the app."; -"COPY_CURRENT_SETTINGS" = "Copy current settings"; -"COPY_CURRENT_SETTINGS_DESC" = "Tap to copy the current settings to clipboard."; -"VIEW_MODIFIED_SETTINGS" = "View modified settings"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Tap to view all the changes you made manually."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Changes"; -"TOTAL_MODIFIED_SETTINGS" = "Total: %ld"; - -// Quit app alert -"WARNING" = "Warning"; -"APPLY_DESC" = "This action will quit YouTube. Are you sure you want to continue?"; - -"OPEN_MEGATHREAD" = "Open megathread"; -"OPEN_MEGATHREAD_DESC" = "Open YTABConfig megathread on GitHub where you can share and discuss the effect of each flag being enabled or disabled."; -"SETTINGS_START_WITH" = "Settings starting with"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Copy to clipboard"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Copied to clipboard."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/es.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/es.lproj/Localizable.strings deleted file mode 100644 index 21302d5..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/es.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Activado"; -"ENABLED_DESC" = "Activar para mostrar ajustes A/B"; -"GROUPED" = "Ajustes agrupados por prefijos"; -"RESET_KILL" = "Reiniciar y matar"; -"RESET_KILL_DESC" = "Toque para deshacer todos los cambios y matar la aplicación"; -"COPY_CURRENT_SETTINGS" = "Copiar ajustes actuales"; -"COPY_CURRENT_SETTINGS_DESC" = "Toque para copiar la configuración actual en el portapapeles"; -"VIEW_MODIFIED_SETTINGS" = "Ver ajustes modificados"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Pulse para ver todos los cambios realizados manualmente"; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Cambios"; -"TOTAL_MODIFIED_SETTINGS" = "Total: %ld"; - -// Quit app alert -"WARNING" = "Advertencia"; -"APPLY_DESC" = "Esta acción cerrará YouTube. ¿Está seguro de que desea continuar?"; - -"OPEN_MEGATHREAD" = "Abrir megahilo"; -"OPEN_MEGATHREAD_DESC" = "Abrir megahilo de YTABConfig en GitHub donde se puede compartir y discutir el efecto de cada bandera activada o desactivada"; -"SETTINGS_START_WITH" = "Configuración que comienza con"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Copiar al portapapeles"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Copiado al portapapeles"; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/hu.lproj/localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/hu.lproj/localizable.strings deleted file mode 100644 index 16da137..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/hu.lproj/localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Engedélyezve"; -"ENABLED_DESC" = "Engedélyezze az A/B beállítások megjelenítését."; -"GROUPED" = "A beállítások előtagok szerint csoportosítva"; -"RESET_KILL" = "Visszaállítás és Leállítás"; -"RESET_KILL_DESC" = "Koppintson az összes módosítás visszavonásához és az alkalmazás leállításához."; -"COPY_CURRENT_SETTINGS" = "Az aktuális beállítások másolása"; -"COPY_CURRENT_SETTINGS_DESC" = "Érintse meg az aktuális beállítások vágólapra másolásához."; -"VIEW_MODIFIED_SETTINGS" = "A módosított beállítások megtekintése"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Érintse meg az összes manuális módosítás megtekintéséhez."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Változtatások"; -"TOTAL_MODIFIED_SETTINGS" = "Teljes: %ld"; - -// Quit app alert -"WARNING" = "Warning"; -"APPLY_DESC" = "This action will quit YouTube. Are you sure you want to continue?"; - -"OPEN_MEGATHREAD" = "Megaszál megnyitása"; -"OPEN_MEGATHREAD_DESC" = "Nyissa meg az YTABConfig megaszálat a GitHubon, ahol megoszthatja és megvitathatja az egyes jelzők engedélyezésének vagy letiltásának hatását."; -"SETTINGS_START_WITH" = "A következővel kezdődő beállítások:"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Másolás a vágólapra"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Vágólapra másolva."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ja.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ja.lproj/Localizable.strings deleted file mode 100644 index 6568f08..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ja.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "有効"; -"ENABLED_DESC" = "A/Bの設定を表示します"; -"GROUPED" = "プレフィックスで設定をグループ化します"; -"RESET_KILL" = "リセットして終了します"; -"RESET_KILL_DESC" = "タップして変更を全て取り消し、アプリを終了する"; -"COPY_CURRENT_SETTINGS" = "現在の設定をコピーします"; -"COPY_CURRENT_SETTINGS_DESC" = "タップして現在の設定をクリップボードにコピーします"; -"VIEW_MODIFIED_SETTINGS" = "変更された設定を表示します"; -"VIEW_MODIFIED_SETTINGS_DESC" = "タップすると手動で行った全ての変更を表示します"; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "変更点"; -"TOTAL_MODIFIED_SETTINGS" = "合計: %ld"; - -// Quit app alert -"WARNING" = "警告"; -"APPLY_DESC" = "この操作でYouTubeアプリが終了します。本当に続けますか?"; - -"OPEN_MEGATHREAD" = "メガスレッドを開きます"; -"OPEN_MEGATHREAD_DESC" = "各フラグの有効,無効の効果を共有,議論できるGitHubのYTABConfig メガスレッドを開きます"; -"SETTINGS_START_WITH" = "から始まる設定"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "クリップボードにコピーします"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "クリップボードにコピーしました"; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ko.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ko.lproj/Localizable.strings deleted file mode 100644 index 45a505f..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ko.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "활성화"; -"ENABLED_DESC" = "A/B 설정 표시를 활성화합니다."; -"GROUPED" = "접두사별로 그룹화된 설정"; -"RESET_KILL" = "재설정 후 종료"; -"RESET_KILL_DESC" = "모든 변경 사항을 실행 취소하고 앱을 종료하려면 탭하세요."; -"COPY_CURRENT_SETTINGS" = "현재 설정 복사"; -"COPY_CURRENT_SETTINGS_DESC" = "현재 설정을 클립보드로 복사하려면 탭하세요."; -"VIEW_MODIFIED_SETTINGS" = "수정된 설정 보기"; -"VIEW_MODIFIED_SETTINGS_DESC" = "수동으로 변경한 모든 내용을 보려면 탭하세요."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "변경 사항"; -"TOTAL_MODIFIED_SETTINGS" = "총합: %ld"; - -// Quit app alert -"WARNING" = "Warning"; -"APPLY_DESC" = "This action will quit YouTube. Are you sure you want to continue?"; - -"OPEN_MEGATHREAD" = "메가스레드 열기"; -"OPEN_MEGATHREAD_DESC" = "GitHub에서 YTABConfig 메가스레드를 열어 각 플래그가 활성화 또는 비활성화되는 효과를 공유하고 논의할 수 있습니다."; -"SETTINGS_START_WITH" = "다음 글자로 시작하는 설정들 : "; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "클립보드에 복사"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "클립보드에 복사됨."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/pt.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/pt.lproj/Localizable.strings deleted file mode 100644 index 1737557..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/pt.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Ativado"; -"ENABLED_DESC" = "Ative para mostrar as configurações A/B."; -"GROUPED" = "Configurações agrupadas por prefixos"; -"RESET_KILL" = "Redefinir e Encerrar"; -"RESET_KILL_DESC" = "Toque para desfazer todas as suas alterações e encerrar o app."; -"COPY_CURRENT_SETTINGS" = "Copiar configurações atuais"; -"COPY_CURRENT_SETTINGS_DESC" = "Toque para copiar as configurações atuais para a área de transferência."; -"VIEW_MODIFIED_SETTINGS" = "Ver configurações modificadas"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Toque para ver todas as alterações feitas manualmente."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Mudanças"; -"TOTAL_MODIFIED_SETTINGS" = "Total: %ld"; - -// Quit app alert -"WARNING" = "Aviso"; -"APPLY_DESC" = "Esta ação encerrará o YouTube. Você tem certeza que quer continuar?"; - -"OPEN_MEGATHREAD" = "Abrir discussão"; -"OPEN_MEGATHREAD_DESC" = "Abre a discussão do YTABConfig no GitHub, onde você pode compartilhar e discutir o efeito de cada sinalizador(flag) sendo habilitado ou desabilitado."; -"SETTINGS_START_WITH" = "Configurações começando com"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Copiar para a área de transferência"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Copiado para a área de transferência."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ru.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index dfee6e0..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Активировать"; -"ENABLED_DESC" = "Активируйте для отображения настроек твика."; -"GROUPED" = "Группировать по префиксам"; -"RESET_KILL" = "Сбросить настройки"; -"RESET_KILL_DESC" = "Нажмите для сброса всех изменений."; -"COPY_CURRENT_SETTINGS" = "Копировать настройки"; -"COPY_CURRENT_SETTINGS_DESC" = "Нажмите, чтобы скопировать текущие настройки в буфер обмена."; -"VIEW_MODIFIED_SETTINGS" = "Отобразить изменения"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Нажмите, чтобы увидеть примененные вами изменения."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Настройки"; -"TOTAL_MODIFIED_SETTINGS" = "Всего: %ld"; - -// Quit app alert -"WARNING" = "Внимание"; -"APPLY_DESC" = "Данное действие приведет к принудительному закрытию YouTube. Продолжить?"; - -"OPEN_MEGATHREAD" = "Дискуссии и рекомендации"; -"OPEN_MEGATHREAD_DESC" = "Перенаправит вас на страницу дискуссий и рекомендаций по YTABConfig на GitHub, где вы можете обсудить настройки и поделиться своим опытом о настройках твика."; -"SETTINGS_START_WITH" = "Настройки, начинающиеся на"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Скопировать в буфер обмена"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Скопировано в буфер обмена"; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/tr.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/tr.lproj/Localizable.strings deleted file mode 100644 index 49b634b..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/tr.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Etkinleştir"; -"ENABLED_DESC" = "A/B ayarlarını göstermeyi etkinleştirir."; -"GROUPED" = "Öneklere göre gruplandırılmış ayarlar"; -"RESET_KILL" = "Sıfırla ve Kapat"; -"RESET_KILL_DESC" = "Tüm değişikliklerini geri almak ve uygulamayı kapatmak için dokun."; -"COPY_CURRENT_SETTINGS" = "Mevcut ayarları kopyala."; -"COPY_CURRENT_SETTINGS_DESC" = "Mevcut ayarları panoya kopyalamak için dokun."; -"VIEW_MODIFIED_SETTINGS" = "Değiştirilen ayarları görüntüle"; -"VIEW_MODIFIED_SETTINGS_DESC" = "El ile yaptığın tüm değişiklikleri görüntülemek için dokun."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Değişiklikler"; -"TOTAL_MODIFIED_SETTINGS" = "Toplam: %ld"; - -// Quit app alert -"WARNING" = "Uyarı"; -"APPLY_DESC" = "Bu eylem YouTube'u kapatacak. Devam etmek istediğine emin misin?"; - -"OPEN_MEGATHREAD" = "Megabaşlığı Aç"; -"OPEN_MEGATHREAD_DESC" = "Etkinleştirilen veya devre dışı bırakılan her ayarın etkisini paylaşabileceğin ve tartışabileceğin YTABConfig megabaşlığını(megathread) GitHub'da açar."; -"SETTINGS_START_WITH" = "Yazılan ile başlayan ayarlar"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Panoya kopyala"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Panoya kopyalandı."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/vi.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/vi.lproj/Localizable.strings deleted file mode 100644 index b11d9d8..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/vi.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "Kích hoạt"; -"ENABLED_DESC" = "Kích hoạt tinh chỉnh để hiện cài đặt của các thử nghiệm A/B (flag)."; -"GROUPED" = "Gộp các cài đặt lại theo vần"; -"RESET_KILL" = "Khôi phục các thay đổi"; -"RESET_KILL_DESC" = "Chạm để khôi phục các thay đổi và đóng ứng dụng."; -"COPY_CURRENT_SETTINGS" = "Sao chép các thay đổi"; -"COPY_CURRENT_SETTINGS_DESC" = "Sao chép các thay đổi hiện tại của bạn vào bộ nhớ tạm."; -"VIEW_MODIFIED_SETTINGS" = "Xem các thay đổi"; -"VIEW_MODIFIED_SETTINGS_DESC" = "Chạm để xem tất cả các thay đổi mà bạn đã áp dụng."; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "Các thay đổi"; -"TOTAL_MODIFIED_SETTINGS" = "Tổng cộng: %ld"; - -// Quit app alert -"WARNING" = "Chú ý"; -"APPLY_DESC" = "Áp dụng thay đổi này sẽ khởi động lại YouTube. Bạn có muốn tiếp tục không?"; - -"OPEN_MEGATHREAD" = "Mở megathread"; -"OPEN_MEGATHREAD_DESC" = "Mở megathread của YTABConfig trên Github, nơi bạn có thể chia sẻ và thảo luận về công dụng của các flag khi bật/tắt."; -"SETTINGS_START_WITH" = "Các flag bắt đầu với vần"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "Copy vào bộ nhớ tạm"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "Đã copy vào bộ nhớ tạm."; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/zh_cn.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/zh_cn.lproj/Localizable.strings deleted file mode 100644 index e4fbd63..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/zh_cn.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "启用"; -"ENABLED_DESC" = "显示和应用 A/B 测试选项。"; -"GROUPED" = "按首字母或前缀词分组"; -"RESET_KILL" = "恢复默认并退出"; -"RESET_KILL_DESC" = "将所有选项重置为默认值并关闭 App。"; -"COPY_CURRENT_SETTINGS" = "复制当前设置"; -"COPY_CURRENT_SETTINGS_DESC" = "将当前所有设置复制到剪贴板。"; -"VIEW_MODIFIED_SETTINGS" = "查看已改动的选项"; -"VIEW_MODIFIED_SETTINGS_DESC" = "查看您已手动更改的选项。"; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "已改动的选项"; -"TOTAL_MODIFIED_SETTINGS" = "共计:%ld项"; - -// Quit app alert -"WARNING" = "警告"; -"APPLY_DESC" = "执行此操作需要关闭 YouTube,是否继续?"; - -"OPEN_MEGATHREAD" = "进入集中讨论贴"; -"OPEN_MEGATHREAD_DESC" = "前往 GitHub 上的 YTABConfig 集中讨论贴来与其他用户分享和讨论各个选项的效果。"; -"SETTINGS_START_WITH" = "查看以此开头的选项:"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "复制到剪贴板"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "已复制到剪贴板。"; diff --git a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/zh_tw.lproj/Localizable.strings b/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/zh_tw.lproj/Localizable.strings deleted file mode 100644 index 10ec18c..0000000 --- a/Tweaks/YTABConfig/layout/Library/Application Support/YTABC.bundle/zh_tw.lproj/Localizable.strings +++ /dev/null @@ -1,30 +0,0 @@ -// Settings -"ENABLED" = "啟用"; -"ENABLED_DESC" = "啟用並顯示 A/B 設定"; -"GROUPED" = "將設定以前綴分組"; -"RESET_KILL" = "重置並重新啟動應用程式"; -"RESET_KILL_DESC" = "點擊還原所有設定並重新啟動應用程式"; -"COPY_CURRENT_SETTINGS" = "複製目前的設定"; -"COPY_CURRENT_SETTINGS_DESC" = "點擊將目前的設定複製到剪貼簿"; -"VIEW_MODIFIED_SETTINGS" = "查看修改的設定"; -"VIEW_MODIFIED_SETTINGS_DESC" = "點擊查看您修改的所有設定"; - -// Shown in alert -"MODIFIED_SETTINGS_TITLE" = "已變更的"; -"TOTAL_MODIFIED_SETTINGS" = "總共: %ld"; - -// Quit app alert -"WARNING" = "警告"; -"APPLY_DESC" = "需要重新啟動 Youtube,是否繼續?"; - -"OPEN_MEGATHREAD" = "打開討論區"; -"OPEN_MEGATHREAD_DESC" = "打開 YTABConfig 在 GitHub 上的討論區,您可以在此討論或分享每項設定的作用。"; -"SETTINGS_START_WITH" = "以下列前綴開頭的設定"; - -// Clipboard - -// Shown in alert -"COPY_TO_CLIPBOARD" = "複製到剪貼簿"; - -// Shown in toast -"COPIED_TO_CLIPBOARD" = "已複製到剪貼簿"; diff --git a/Tweaks/YTHoldForSpeed b/Tweaks/YTHoldForSpeed new file mode 160000 index 0000000..4166be9 --- /dev/null +++ b/Tweaks/YTHoldForSpeed @@ -0,0 +1 @@ +Subproject commit 4166be9befde53da8bbbcbfd99f723f664536ffb diff --git a/Tweaks/YTHoldForSpeed/.gitignore b/Tweaks/YTHoldForSpeed/.gitignore deleted file mode 100644 index 9c04476..0000000 --- a/Tweaks/YTHoldForSpeed/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos -.DS_Store -packages diff --git a/Tweaks/YTHoldForSpeed/Makefile b/Tweaks/YTHoldForSpeed/Makefile deleted file mode 100644 index bf945f9..0000000 --- a/Tweaks/YTHoldForSpeed/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TARGET := iphone:clang:15.5:14.0 -INSTALL_TARGET_PROCESSES = YouTube - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = ytholdforspeed - -ytholdforspeed_FILES = YTHFSTweak.x YTHFSSettings.x YTHFSPrefsManager.m -ytholdforspeed_CFLAGS = -fobjc-arc - -THEOS_PACKAGE_BASE_VERSION = 1.0.3 -_THEOS_INTERNAL_PACKAGE_VERSION = 1.0.3 - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/YTHoldForSpeed/YTHFSHeaders.h b/Tweaks/YTHoldForSpeed/YTHFSHeaders.h deleted file mode 100644 index c2dac59..0000000 --- a/Tweaks/YTHoldForSpeed/YTHFSHeaders.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// YTHFSHeaders.h -// -// Created by Joshua Seltzer on 12/5/22. -// -// - -#import -#import - -@interface YTDoubleTapToSeekView : UIView - -// shows feedback with the given title text and direction -- (void)showCenteredSeekFeedbackWithTitle:(NSString *)title direction:(NSInteger)direction; - -@end - -@interface YTMainAppVideoPlayerOverlayView : UIView - -// the view that is used to display that the double tap to seek gesture was invoked -@property (readonly, nonatomic) YTDoubleTapToSeekView *doubleTapToSeekView; - -@end - -// the controller responsible for handling changes to the playback speed -@interface YTVarispeedSwitchController : NSObject -@end - -@interface YTPlayerView : UIView - -// the overlay view which includes the double tap to seek view -@property (retain, nonatomic) UIView *overlayView; - -@end - -@interface YTPlayerViewController : UIViewController - -// the main view for viewing videos -@property (readonly, nonatomic) YTPlayerView *playerView; - -// the controller responsible for allowing the user to switch the playback speed -@property (readonly, nonatomic) YTVarispeedSwitchController *varispeedController; - -// the overlay controller that will be used to potentially hide the player controls -@property (readonly, nonatomic) UIViewController *contentVideoPlayerOverlay; - -// returns whether or not the play controls are currently hidden or visible -- (BOOL)arePlayerControlsHidden; - -// returns the current playback speed -- (float)currentPlaybackRateForVarispeedSwitchController:(YTVarispeedSwitchController *)varispeedSwitchController; - -// invoked whenever the playback speed selection is changed -- (void)varispeedSwitchController:(YTVarispeedSwitchController *)varispeedSwitchController didSelectRate:(float)rate; - -@end - -@interface YTMainAppVideoPlayerOverlayViewController : UIViewController - -// indicates whether or not the playback speed of the video can be changed -@property (readonly, nonatomic) BOOL isVarispeedAvailable; - -// hide the player controls programatically -- (void)hidePlayerControlsAnimated:(BOOL)animated; - -@end - -// controller which is updated with the launch and dismissal of the player view controller -@interface YTWatchController : NSObject -@end - -// manager responsible for handling the app's preferences -@interface YTSettingsSectionItemManager : NSObject - -// required when creating setting sections that have user selection -- (id)parentResponder; - -@end - -// view controller that displays settings information -@interface YTStyledViewController -@end -@interface YTSettingsViewController : YTStyledViewController - -// reloads the setting sections in the settings view controller -- (void)reloadData; - -// push a new controller on the navigation stack -- (void)pushViewController:(id)viewController; - -// sets the array of section items for a given settings category -- (void)setSectionItems:(NSArray *)sectionItems forCategory:(NSInteger)categoryId title:(NSString *)title titleDescription:(NSString *)titleDescription headerHidden:(BOOL)hidden; - -@end - -// view controller that displays selectable settings -@interface YTSettingsPickerViewController : YTStyledViewController - -// initialize a new picker view controller -- (id)initWithNavTitle:(NSString *)navTitle pickerSectionTitle:(NSString *)pickerSectionTitle rows:(NSArray *)rows selectedItemIndex:(NSUInteger)index parentResponder:(id)responder; - -@end - -// a cell in the settings view controller -@interface YTSettingsCell -@end - -// an item which defines a section inside a settings controller -@interface YTSettingsSectionItem : NSObject - -// create a new setting item with an on/off switch, title, and optional description -+ (id)switchItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(id)identifier switchOn:(BOOL)enabled switchBlock:(id)switchBlock settingItemId:(NSInteger)itemId; - -// create a new item with a title, selected detail text, and a selection block which can push another instance of a settings controller -+ (id)itemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(id)identifier detailTextBlock:(id)detailTextBlock selectBlock:(id)selectBlock; - -// create a checkmark item with a title and select block -+ (id)checkmarkItemWithTitle:(NSString *)title selectBlock:(id)selectBlock; - -@end diff --git a/Tweaks/YTHoldForSpeed/YTHFSPrefsManager.h b/Tweaks/YTHoldForSpeed/YTHFSPrefsManager.h deleted file mode 100644 index 2c52e58..0000000 --- a/Tweaks/YTHoldForSpeed/YTHFSPrefsManager.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// YTHFSPrefsManager.h -// -// Created by Joshua Seltzer on 12/5/22. -// -// - -#import -#import - -// enum to define the options for the hold duration -typedef enum YTHFSHoldDurationOption : NSInteger { - kYTHFSHoldDurationOption025, - kYTHFSHoldDurationOption050, - kYTHFSHoldDurationOption075, - kYTHFSHoldDurationOption100, - kYTHFSHoldDurationOption125, - kYTHFSHoldDurationOption150, - kYTHFSHoldDurationOption175, - kYTHFSHoldDurationOption200 -} YTHFSHoldDurationOption; - -// enum to define the options for the playback rate -typedef enum YTHFSPlaybackRateOption : NSInteger { - kYTHFSPlaybackRateOption025, - kYTHFSPlaybackRateOption050, - kYTHFSPlaybackRateOption075, - kYTHFSPlaybackRateOption125, - kYTHFSPlaybackRateOption150, - kYTHFSPlaybackRateOption175, - kYTHFSPlaybackRateOption200 -} YTHFSPlaybackRateOption; - -// manager that manages the preferences for the tweak -@interface YTHFSPrefsManager : NSObject - -// return a localized string with a given default value from the localization files in the tweak bundle -+ (NSString *)localizedStringForKey:(NSString *)key withDefaultValue:(NSString *)defaultValue; - -// intended to be invoked when the tweak is initialized to ensure all of the default values are available -+ (void)registerDefaults; - -// returns whether or not the device supports haptic feedback -+ (BOOL)supportsHapticFeedback; - -// return the value that corresponds to the given hold duration option -+ (CGFloat)holdDurationValueForOption:(YTHFSHoldDurationOption)holdDurationOption; - -// return the value that corresponds to the given playback rate option -+ (CGFloat)playbackRateValueForOption:(YTHFSPlaybackRateOption)playbackRateOption; - -// return the hold playback option for the given value -+ (YTHFSHoldDurationOption)holdDurationOptionForValue:(CGFloat)value; - -// return the playback rate option for the given value -+ (YTHFSPlaybackRateOption)playbackRateOptionForValue:(CGFloat)value; - -// return the appropriate string representation of the hold duration for the given value -+ (NSString *)holdDurationStringForValue:(CGFloat)value; - -// return the appropriate string representation of the playback rate for the given value -+ (NSString *)playbackRateStringForValue:(CGFloat)value; - -// setters and getters for the tweak preferences -+ (BOOL)holdGestureEnabled; -+ (void)setHoldGestureEnabled:(BOOL)enabled; -+ (BOOL)autoApplyRateEnabled; -+ (void)setAutoApplyRateEnabled:(BOOL)enabled; -+ (CGFloat)togglePlaybackRate; -+ (void)setTogglePlaybackRate:(CGFloat)playbackRate; -+ (CGFloat)holdDuration; -+ (void)setHoldDuration:(CGFloat)holdDuration; -+ (BOOL)hapticFeedbackEnabled; -+ (void)setHapticFeedbackEnabled:(BOOL)enabled; - -@end diff --git a/Tweaks/YTHoldForSpeed/YTHFSPrefsManager.m b/Tweaks/YTHoldForSpeed/YTHFSPrefsManager.m deleted file mode 100644 index 54ccc21..0000000 --- a/Tweaks/YTHoldForSpeed/YTHFSPrefsManager.m +++ /dev/null @@ -1,194 +0,0 @@ -// -// YTHFSPrefsManager.m -// -// Created by Joshua Seltzer on 12/5/22. -// -// - -#import "YTHFSPrefsManager.h" -#import -#import -#import - -// define constants for the keys used to interact with the settings within user defaults -#define kYTHFSHoldGestureEnabledKey @"YTHFSHoldGestureEnabled" -#define kYTHFSAutoApplyRateEnabledKey @"YTHFSAutoApplyRateEnabled" -#define kYTHFSTogglePlaybackRateKey @"YTHFSTogglePlaybackRate" -#define kYTHFSHoldDurationKey @"YTHFSHoldDuration" -#define kYTHFSHapticFeedbackEnabledKey @"YTHFSHapticFeedbackEnabled" - -// define some constants to define the default preference values -#define kYTHFSDefaultHoldGestureEnabled YES -#define kYTHFSDefaultAutoApplyRateEnabled NO -#define kYTHFSDefaultTogglePlaybackRate 1.5 -#define kYTHFSDefaultHoldDuration 1.0 - -// create static variables that will be determined once -static NSBundle *sYTHFSBundle; -static BOOL sYTHFSSupportsHapticFeedback; -static NSNumberFormatter *sYTHFSDecimalNumberFormatter; - -@implementation YTHFSPrefsManager - -// return a localized string with a given default value from the localization files in the tweak bundle -+ (NSString *)localizedStringForKey:(NSString *)key withDefaultValue:(NSString *)defaultValue -{ - NSBundle *tweakBundle = [YTHFSPrefsManager bundle]; - if (tweakBundle != nil) { - return [tweakBundle localizedStringForKey:key value:defaultValue table:@"Localizable"]; - } else { - return defaultValue; - } -} - -// intended to be invoked when the tweak is initialized to ensure all of the default values are available -+ (void)registerDefaults -{ - [[NSUserDefaults standardUserDefaults] registerDefaults:@{kYTHFSHoldGestureEnabledKey:[NSNumber numberWithBool:kYTHFSDefaultHoldGestureEnabled], - kYTHFSAutoApplyRateEnabledKey:[NSNumber numberWithBool:kYTHFSDefaultAutoApplyRateEnabled], - kYTHFSTogglePlaybackRateKey:[NSNumber numberWithFloat:kYTHFSDefaultTogglePlaybackRate], - kYTHFSHoldDurationKey:[NSNumber numberWithFloat:kYTHFSDefaultHoldDuration], - kYTHFSHapticFeedbackEnabledKey:[NSNumber numberWithBool:[YTHFSPrefsManager supportsHapticFeedback]]}]; -} - -// returns whether or not the device supports haptic feedback -+ (BOOL)supportsHapticFeedback -{ - static dispatch_once_t pred; - dispatch_once(&pred, ^{ - // determine if the current device is able to support haptic feedback - if (!CHHapticEngine.capabilitiesForHardware.supportsHaptics) { - // ensure we are not on an iPhone 7 family device, since those devices are not covered under - // the supportsHaptics call as of 2022-12-08 / iOS 16.1 SDK - struct utsname systemInfo; - uname(&systemInfo); - NSString *currentDeviceIdentifier = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; - if ([currentDeviceIdentifier isEqualToString:@"iPhone9,1"] || - [currentDeviceIdentifier isEqualToString:@"iPhone9,3"] || - [currentDeviceIdentifier isEqualToString:@"iPhone9,2"] || - [currentDeviceIdentifier isEqualToString:@"iPhone9,4"]) { - sYTHFSSupportsHapticFeedback = YES; - } else { - sYTHFSSupportsHapticFeedback = NO; - } - } else { - sYTHFSSupportsHapticFeedback = YES; - } - }); - return sYTHFSSupportsHapticFeedback; -} - -// return the value that corresponds to the given hold duration option -+ (CGFloat)holdDurationValueForOption:(YTHFSHoldDurationOption)holdDurationOption -{ - return (holdDurationOption + 1) * 0.25; -} - -// return the value that corresponds to the given playback rate option -+ (CGFloat)playbackRateValueForOption:(YTHFSPlaybackRateOption)playbackRateOption -{ - CGFloat playbackRateOffset = 0.25; - if (playbackRateOption > kYTHFSPlaybackRateOption075) { - playbackRateOffset = playbackRateOffset * 2; - } - return playbackRateOption * 0.25 + playbackRateOffset; -} - -// return the hold playback option for the given value -+ (YTHFSHoldDurationOption)holdDurationOptionForValue:(CGFloat)value -{ - return MAX(MIN((NSInteger)(value / 0.25) - 1, kYTHFSHoldDurationOption200), kYTHFSHoldDurationOption025); -} - -// return the playback rate option for the given value -+ (YTHFSPlaybackRateOption)playbackRateOptionForValue:(CGFloat)value -{ - NSInteger playbackRateOptionOffset = 1; - if (value > 1.00) { - ++playbackRateOptionOffset; - } - return MAX(MIN((NSInteger)(value / 0.25) - playbackRateOptionOffset, kYTHFSPlaybackRateOption200), kYTHFSPlaybackRateOption025); -} - -// return the appropriate string representation of the hold duration for the given value -+ (NSString *)holdDurationStringForValue:(CGFloat)value -{ - return [NSString stringWithFormat:[YTHFSPrefsManager localizedStringForKey:@"X_SECONDS" withDefaultValue:@"%@ seconds"], [[YTHFSPrefsManager decimalNumberFormatter] stringFromNumber:[NSNumber numberWithFloat:value]]]; -} - -// return the appropriate string representation of the playback rate for the given value -+ (NSString *)playbackRateStringForValue:(CGFloat)value -{ - return [NSString stringWithFormat:@"%@x", [[YTHFSPrefsManager decimalNumberFormatter] stringFromNumber:[NSNumber numberWithFloat:value]]]; -} - -// setters and getters for the tweak preferences -+ (BOOL)holdGestureEnabled -{ - return [[NSUserDefaults standardUserDefaults] boolForKey:kYTHFSHoldGestureEnabledKey]; -} -+ (void)setHoldGestureEnabled:(BOOL)enabled -{ - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kYTHFSHoldGestureEnabledKey]; -} -+ (BOOL)autoApplyRateEnabled -{ - return [[NSUserDefaults standardUserDefaults] boolForKey:kYTHFSAutoApplyRateEnabledKey]; -} -+ (void)setAutoApplyRateEnabled:(BOOL)enabled -{ - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kYTHFSAutoApplyRateEnabledKey]; -} -+ (CGFloat)togglePlaybackRate -{ - return [[NSUserDefaults standardUserDefaults] floatForKey:kYTHFSTogglePlaybackRateKey]; -} -+ (void)setTogglePlaybackRate:(CGFloat)playbackRate -{ - [[NSUserDefaults standardUserDefaults] setFloat:playbackRate forKey:kYTHFSTogglePlaybackRateKey]; -} -+ (CGFloat)holdDuration -{ - return [[NSUserDefaults standardUserDefaults] floatForKey:kYTHFSHoldDurationKey]; -} -+ (void)setHoldDuration:(CGFloat)holdDuration -{ - [[NSUserDefaults standardUserDefaults] setFloat:holdDuration forKey:kYTHFSHoldDurationKey]; -} -+ (BOOL)hapticFeedbackEnabled -{ - return [[NSUserDefaults standardUserDefaults] boolForKey:kYTHFSHapticFeedbackEnabledKey]; -} -+ (void)setHapticFeedbackEnabled:(BOOL)hapticFeedbackEnabled -{ - [[NSUserDefaults standardUserDefaults] setBool:hapticFeedbackEnabled forKey:kYTHFSHapticFeedbackEnabledKey]; -} - -// return the bundle for the tweak which can be different depending on the jailbreak / installation method -+ (NSBundle *)bundle -{ - static dispatch_once_t pred; - dispatch_once(&pred, ^{ - NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"YTHoldForSpeed" ofType:@"bundle"]; - if (bundlePath) { - sYTHFSBundle = [NSBundle bundleWithPath:bundlePath]; - } else { - sYTHFSBundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YTHoldForSpeed.bundle")]; - } - }); - return sYTHFSBundle; -} - -// return the number formatter that will be used to create strings for the playback rate and hold duration -+ (NSNumberFormatter *)decimalNumberFormatter -{ - static dispatch_once_t pred; - dispatch_once(&pred, ^{ - sYTHFSDecimalNumberFormatter = [[NSNumberFormatter alloc] init]; - [sYTHFSDecimalNumberFormatter setMinimumFractionDigits:1]; - [sYTHFSDecimalNumberFormatter setMaximumFractionDigits:2]; - }); - return sYTHFSDecimalNumberFormatter; -} - -@end diff --git a/Tweaks/YTHoldForSpeed/YTHFSSettings.x b/Tweaks/YTHoldForSpeed/YTHFSSettings.x deleted file mode 100644 index 4c911eb..0000000 --- a/Tweaks/YTHoldForSpeed/YTHFSSettings.x +++ /dev/null @@ -1,164 +0,0 @@ -// -// YTHFSSettings.x -// -// Created by Joshua Seltzer on 12/11/22. -// -// - -#import "YTHFSHeaders.h" -#import "YTHFSPrefsManager.h" - -@interface YTSettingsSectionItemManager (YTHFS) - -// create a new method that will be used to add the tweak's settings -- (void)YTHFSUpdateHoldForSpeedSectionWithEntry:(id)entry; - -@end - -// define the section number that is used to indicate the tweak's settings -#define kYTHFSHoldForSpeedSection 2168 - -%hook YTAppSettingsPresentationData - -// set the order of the settings and insert our custom settings for the tweak -+ (NSArray *)settingsCategoryOrder -{ - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - NSUInteger insertIndex = [order indexOfObject:@(1)]; - if (insertIndex != NSNotFound) { - [mutableOrder insertObject:@(kYTHFSHoldForSpeedSection) atIndex:insertIndex + 1]; - } - return [mutableOrder copy]; -} - -%end - -%hook YTSettingsSectionItemManager - -// override to add our custom entries for the hold for speed section in the settings -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry -{ - if (category == kYTHFSHoldForSpeedSection) { - [self YTHFSUpdateHoldForSpeedSectionWithEntry:entry]; - return; - } - %orig; -} - -// logic which creates the section items for the tweak's preferences -%new -- (void)YTHFSUpdateHoldForSpeedSectionWithEntry:(id)entry { - NSMutableArray *mainSectionItems = [NSMutableArray array]; - Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); - YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; - - // create a settings section to enable or disable the hold gesture - YTSettingsSectionItem *holdGestureSection = [YTSettingsSectionItemClass switchItemWithTitle:[YTHFSPrefsManager localizedStringForKey:@"HOLD_GESTURE" withDefaultValue:@"Hold gesture"] - titleDescription:[YTHFSPrefsManager localizedStringForKey:@"HOLD_GESTURE_DESC" withDefaultValue:@"Tap and hold anywhere in the video player to toggle the playback speed between \"Normal\" (i.e. 1.0x) and the selected toggle speed.\n\nPlease be aware that by enabling this feature, the stock \"seek anywhere\" gesture will be disabled."] - accessibilityIdentifier:nil - switchOn:[YTHFSPrefsManager holdGestureEnabled] - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [YTHFSPrefsManager setHoldGestureEnabled:enabled]; - return YES; - } - settingItemId:0]; - [mainSectionItems addObject:holdGestureSection]; - - // create a settings section to enable or disable the hold gesture - YTSettingsSectionItem *autoApplySpeedSection = [YTSettingsSectionItemClass switchItemWithTitle:[YTHFSPrefsManager localizedStringForKey:@"AUTO_APPLY_SPEED" withDefaultValue:@"Automatically apply speed"] - titleDescription:[YTHFSPrefsManager localizedStringForKey:@"AUTO_APPLY_SPEED_DESC" withDefaultValue:@"When enabled, the selected playback speed will automatically be applied when a new video player is launched."] - accessibilityIdentifier:nil - switchOn:[YTHFSPrefsManager autoApplyRateEnabled] - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [YTHFSPrefsManager setAutoApplyRateEnabled:enabled]; - return YES; - } - settingItemId:1]; - [mainSectionItems addObject:autoApplySpeedSection]; - - // create a settings section that allows the selection of the playback rate - NSString *playbackRateTitle = [YTHFSPrefsManager localizedStringForKey:@"TOGGLE_SPEED" withDefaultValue:@"Toggle speed"]; - YTSettingsSectionItem *toggleRateSection = [YTSettingsSectionItemClass itemWithTitle:playbackRateTitle - titleDescription:[YTHFSPrefsManager localizedStringForKey:@"TOGGLE_SPEED_DESC" withDefaultValue:@"The speed that the video player will toggle between when the hold gesture is invoked."] - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return [YTHFSPrefsManager playbackRateStringForValue:[YTHFSPrefsManager togglePlaybackRate]]; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - // create a new section item for each toggle rate option that the user can select - NSMutableArray *playbackRateSectionRows = [NSMutableArray array]; - for (NSInteger currentRow = kYTHFSPlaybackRateOption025; currentRow <= kYTHFSPlaybackRateOption200; ++currentRow) { - CGFloat playbackRateForRow = [YTHFSPrefsManager playbackRateValueForOption:currentRow]; - YTSettingsSectionItem *rateSection = [YTSettingsSectionItemClass checkmarkItemWithTitle:[YTHFSPrefsManager playbackRateStringForValue:playbackRateForRow] - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - [YTHFSPrefsManager setTogglePlaybackRate:playbackRateForRow]; - [settingsViewController reloadData]; - return YES; - }]; - [playbackRateSectionRows addObject:rateSection]; - } - YTSettingsPickerViewController *playbackRatePicker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:playbackRateTitle - pickerSectionTitle:[playbackRateTitle uppercaseString] - rows:playbackRateSectionRows - selectedItemIndex:[YTHFSPrefsManager playbackRateOptionForValue:[YTHFSPrefsManager togglePlaybackRate]] - parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:playbackRatePicker]; - return YES; - }]; - [mainSectionItems addObject:toggleRateSection]; - - // create a settings section that allows the selection of the hold duration - NSString *holdDurationTitle = [YTHFSPrefsManager localizedStringForKey:@"HOLD_DURATION" withDefaultValue:@"Hold duration"]; - YTSettingsSectionItem *holdDurationSection = [YTSettingsSectionItemClass itemWithTitle:holdDurationTitle - titleDescription:[YTHFSPrefsManager localizedStringForKey:@"HOLD_DURATION_DESC" withDefaultValue:@"The amount of time (in seconds) that is required for the hold gesture to toggle the speed of the video player."] - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return [YTHFSPrefsManager holdDurationStringForValue:[YTHFSPrefsManager holdDuration]]; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - // create a new section item for each hold duration option that the user can select - NSMutableArray *holdDurationSectionRows = [NSMutableArray array]; - for (NSInteger currentRow = kYTHFSHoldDurationOption025; currentRow <= kYTHFSHoldDurationOption200; ++currentRow) { - CGFloat holdDurationForRow = [YTHFSPrefsManager holdDurationValueForOption:currentRow]; - YTSettingsSectionItem *holdDurationSection = [YTSettingsSectionItemClass checkmarkItemWithTitle:[YTHFSPrefsManager holdDurationStringForValue:holdDurationForRow] - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - [YTHFSPrefsManager setHoldDuration:holdDurationForRow]; - [settingsViewController reloadData]; - return YES; - }]; - [holdDurationSectionRows addObject:holdDurationSection]; - } - YTSettingsPickerViewController *holdDurationPicker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:holdDurationTitle - pickerSectionTitle:[holdDurationTitle uppercaseString] - rows:holdDurationSectionRows - selectedItemIndex:[YTHFSPrefsManager holdDurationOptionForValue:[YTHFSPrefsManager holdDuration]] - parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:holdDurationPicker]; - return YES; - }]; - [mainSectionItems addObject:holdDurationSection]; - - // if available, add a settings section to enable or disable haptic feedback - if ([YTHFSPrefsManager supportsHapticFeedback]) { - YTSettingsSectionItem *hapticFeedbackSection = [YTSettingsSectionItemClass switchItemWithTitle:[YTHFSPrefsManager localizedStringForKey:@"HAPTIC_FEEDBACK" withDefaultValue:@"Haptic feedback"] - titleDescription:[YTHFSPrefsManager localizedStringForKey:@"HAPTIC_FEEDBACK_DESC" withDefaultValue:@"Use haptic feedback to indicate that the speed of the video player was toggled."] - accessibilityIdentifier:nil - switchOn:[YTHFSPrefsManager hapticFeedbackEnabled] - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [YTHFSPrefsManager setHapticFeedbackEnabled:enabled]; - return YES; - } - settingItemId:4]; - [mainSectionItems addObject:hapticFeedbackSection]; - } - - // add all of our settings item to the main settings list - [settingsViewController setSectionItems:mainSectionItems - forCategory:kYTHFSHoldForSpeedSection - title:[YTHFSPrefsManager localizedStringForKey:@"HOLD_FOR_SPEED" withDefaultValue:@"Hold for speed"] - titleDescription:nil - headerHidden:NO]; -} - -%end diff --git a/Tweaks/YTHoldForSpeed/YTHFSTweak.x b/Tweaks/YTHoldForSpeed/YTHFSTweak.x deleted file mode 100644 index fff6085..0000000 --- a/Tweaks/YTHoldForSpeed/YTHFSTweak.x +++ /dev/null @@ -1,195 +0,0 @@ -// -// YTHFSTweak.x -// -// Created by Joshua Seltzer on 12/5/22. -// -// - -#import "YTHFSHeaders.h" -#import "YTHFSPrefsManager.h" - -@interface YTPlayerViewController (YTHFS) - -// the long press gesture that will be created and added to the player view -@property (nonatomic, retain) UILongPressGestureRecognizer *YTHFSLongPressGesture; - -// switch between the user-selected playback rate and the normal playback rate, invoked either via the hold gesture or -// automatically when the video starts (dependent on settings) -- (void)YTHFSSwitchPlaybackRate; - -@end - -// define some non-configurable defaults for the long press gesture -#define kYTHFSNormalPlaybackRate 1.0 -#define kYTHFSNumTouchesRequired 1 -#define kYTHFSAllowableMovement 50 - -// the static variables to keep track of the settings which shall persist until the YTPlayerViewController is recreated -static CGFloat sYTHFSTogglePlaybackRate; -static BOOL sYTHFSHapticFeedbackEnabled; -static BOOL sYTHFSAutoApplyRateEnabled; - -// enum to define the direction of the playback rate feedback indicator -typedef enum YTHFSFeedbackDirection : NSInteger { - kYTHFSFeedbackDirectionForward, - kYTHFSFeedbackDirectionBackward -} YTHFSFeedbackDirection; - -%hook YTWatchLayerViewController - -// invoked when the player view controller is either created or destroyed -- (void)watchController:(YTWatchController *)watchController didSetPlayerViewController:(YTPlayerViewController *)playerViewController -{ - if (playerViewController) { - // grab the state of the settings for this instance of the player view controller - sYTHFSTogglePlaybackRate = [YTHFSPrefsManager togglePlaybackRate]; - sYTHFSHapticFeedbackEnabled = [YTHFSPrefsManager hapticFeedbackEnabled]; - - // check to see if the toggle rate should automatically be applied when the video starts - sYTHFSAutoApplyRateEnabled = [YTHFSPrefsManager autoApplyRateEnabled]; - - // add a long press gesture to configure the playback rate - if ([YTHFSPrefsManager holdGestureEnabled]) { - // check to see if the long press gesture is already created - if (!playerViewController.YTHFSLongPressGesture) { - playerViewController.YTHFSLongPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:playerViewController - action:@selector(YTHFSHandleLongPressGesture:)]; - playerViewController.YTHFSLongPressGesture.numberOfTouchesRequired = kYTHFSNumTouchesRequired; - playerViewController.YTHFSLongPressGesture.allowableMovement = kYTHFSAllowableMovement; - [playerViewController.playerView addGestureRecognizer:playerViewController.YTHFSLongPressGesture]; - } - - // update the minimum press duration with whatever the user set in the settings - playerViewController.YTHFSLongPressGesture.minimumPressDuration = [YTHFSPrefsManager holdDuration]; - } - } - - %orig; -} - -%end - -%hook YTPlayerViewController - -// the long press gesture that will be created and added to the player view -%property (nonatomic, retain) UILongPressGestureRecognizer *YTHFSLongPressGesture; - -%new -- (void)YTHFSHandleLongPressGesture:(UILongPressGestureRecognizer *)longPressGestureRecognizer -{ - if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan && [self.contentVideoPlayerOverlay isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayViewController")]) { - YTMainAppVideoPlayerOverlayViewController *overlayViewController = (YTMainAppVideoPlayerOverlayViewController *)self.contentVideoPlayerOverlay; - if (overlayViewController.isVarispeedAvailable) { - [self YTHFSSwitchPlaybackRate]; - } - } -} - -%new -- (void)YTHFSSwitchPlaybackRate -{ - NSString *feedbackTitle = nil; - YTHFSFeedbackDirection feedbackDirection = kYTHFSFeedbackDirectionForward; - CGFloat currentPlaybackRate = [self currentPlaybackRateForVarispeedSwitchController:self.varispeedController]; - if (currentPlaybackRate != sYTHFSTogglePlaybackRate) { - // change to the toggle rate if the current playback rate is any other speed - [self varispeedSwitchController:self.varispeedController didSelectRate:sYTHFSTogglePlaybackRate]; - feedbackTitle = [YTHFSPrefsManager playbackRateStringForValue:sYTHFSTogglePlaybackRate]; - if (currentPlaybackRate > sYTHFSTogglePlaybackRate) { - feedbackDirection = kYTHFSFeedbackDirectionBackward; - } - } else { - // otherwise switch back to the default rate - [self varispeedSwitchController:self.varispeedController didSelectRate:kYTHFSNormalPlaybackRate]; - feedbackTitle = [YTHFSPrefsManager localizedStringForKey:@"NORMAL" withDefaultValue:@"Normal"]; - if (currentPlaybackRate > kYTHFSNormalPlaybackRate) { - feedbackDirection = kYTHFSFeedbackDirectionBackward; - } - } - - // if the overlay controls are displayed, ensure to hide them before displaying the visual indicator - if (![self arePlayerControlsHidden] && [self.contentVideoPlayerOverlay isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayViewController")]) { - YTMainAppVideoPlayerOverlayViewController *overlayViewController = (YTMainAppVideoPlayerOverlayViewController *)self.contentVideoPlayerOverlay; - [overlayViewController hidePlayerControlsAnimated:YES]; - } - - // trigger the double tap to seek view to visibly indicate that the playback rate has changed - if ([self.playerView.overlayView isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayView")]) { - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)self.playerView.overlayView; - [overlayView.doubleTapToSeekView showCenteredSeekFeedbackWithTitle:feedbackTitle direction:feedbackDirection]; - } - - // fire off haptic feedback to indicate that the playback rate changed (only applies to supported devices if enabled) - if (sYTHFSHapticFeedbackEnabled) { - UINotificationFeedbackGenerator *feedbackGenerator = [[UINotificationFeedbackGenerator alloc] init]; - [feedbackGenerator notificationOccurred:UINotificationFeedbackTypeSuccess]; - feedbackGenerator = nil; - } -} - -// invoked when a video (or ad) is activated inside the player -- (void)playbackController:(id)localPlaybackController didActivateVideo:(id)singleVideoController withPlaybackData:(id)playbackData -{ - %orig; - - if (sYTHFSAutoApplyRateEnabled && [self.contentVideoPlayerOverlay isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayViewController")]) { - YTMainAppVideoPlayerOverlayViewController *overlayViewController = (YTMainAppVideoPlayerOverlayViewController *)self.contentVideoPlayerOverlay; - if (overlayViewController.isVarispeedAvailable) { - // regardless of the current playback rate, at this point we know that the toggle rate will be applied - sYTHFSAutoApplyRateEnabled = NO; - - // compare whether or not the current playback rate is what the user selected and if not, change to it now - if ([self currentPlaybackRateForVarispeedSwitchController:self.varispeedController] != sYTHFSTogglePlaybackRate) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [self YTHFSSwitchPlaybackRate]; - }); - } - } - } -} - -- (void)dealloc -{ - // remove and destroy the gesture recognizer if it exists - if (self.YTHFSLongPressGesture) { - [self.playerView removeGestureRecognizer:self.YTHFSLongPressGesture]; - self.YTHFSLongPressGesture = nil; - } - - %orig; -} - -%end - -%hook YTMainAppVideoPlayerOverlayView - -// override the long press gesture recognizer that is used to invoke the seek gesture -- (void)setSeekAnywhereLongPressGestureRecognizer:(UILongPressGestureRecognizer *)longPressGestureRecognizer -{ - if (![YTHFSPrefsManager holdGestureEnabled]) { - %orig; - } -} - -// override the pan gesture recognizer that is used to invoke the seek gesture -- (void)setSeekAnywherePanGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognzier -{ - if (![YTHFSPrefsManager holdGestureEnabled]) { - %orig; - } -} - -// override the long press gesture recognizer that is used to invoke the seek gesture (introduced with YouTube 18.05.2) -- (void)setLongPressGestureRecognizer:(UILongPressGestureRecognizer *)longPressGestureRecognizer -{ - if (![YTHFSPrefsManager holdGestureEnabled]) { - %orig; - } -} - -%end - -%ctor { - // ensure that the default preferences are available - [YTHFSPrefsManager registerDefaults]; -} \ No newline at end of file diff --git a/Tweaks/YTHoldForSpeed/assets/Screenshot_1.png b/Tweaks/YTHoldForSpeed/assets/Screenshot_1.png deleted file mode 100644 index 19fc225..0000000 Binary files a/Tweaks/YTHoldForSpeed/assets/Screenshot_1.png and /dev/null differ diff --git a/Tweaks/YTHoldForSpeed/assets/Screenshot_2.png b/Tweaks/YTHoldForSpeed/assets/Screenshot_2.png deleted file mode 100644 index 309554e..0000000 Binary files a/Tweaks/YTHoldForSpeed/assets/Screenshot_2.png and /dev/null differ diff --git a/Tweaks/YTHoldForSpeed/assets/banner.psd b/Tweaks/YTHoldForSpeed/assets/banner.psd deleted file mode 100644 index ac6829a..0000000 Binary files a/Tweaks/YTHoldForSpeed/assets/banner.psd and /dev/null differ diff --git a/Tweaks/YTHoldForSpeed/assets/forward.svg b/Tweaks/YTHoldForSpeed/assets/forward.svg deleted file mode 100644 index d161455..0000000 --- a/Tweaks/YTHoldForSpeed/assets/forward.svg +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tweaks/YTHoldForSpeed/assets/icon.psd b/Tweaks/YTHoldForSpeed/assets/icon.psd deleted file mode 100644 index 63c34d5..0000000 Binary files a/Tweaks/YTHoldForSpeed/assets/icon.psd and /dev/null differ diff --git a/Tweaks/YTHoldForSpeed/build_release.sh b/Tweaks/YTHoldForSpeed/build_release.sh deleted file mode 100644 index 2816ec0..0000000 --- a/Tweaks/YTHoldForSpeed/build_release.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# rootful (iphoneos-arm) -export PREFIX=$THEOS/toolchain/Xcode11.xctoolchain/usr/bin/ -make clean -make package FINALPACKAGE=1 - -# rootless (iphoneos-arm64) -export -n PREFIX -make clean -make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless \ No newline at end of file diff --git a/Tweaks/YTHoldForSpeed/control b/Tweaks/YTHoldForSpeed/control deleted file mode 100644 index 7e66791..0000000 --- a/Tweaks/YTHoldForSpeed/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: com.joshuaseltzer.ytholdforspeed -Name: YTHoldForSpeed -Version: 1.0.3 -Architecture: iphoneos-arm -Description: Tap and hold on the YouTube video player to toggle a selected playback speed. Preferences for the tweak are configured within the YouTube app. -Maintainer: Joshua Seltzer -Author: Joshua Seltzer -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000) diff --git a/Tweaks/YTHoldForSpeed/layout/Library/Application Support/YTHoldForSpeed.bundle/en.lproj/Localizable.strings b/Tweaks/YTHoldForSpeed/layout/Library/Application Support/YTHoldForSpeed.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 505c031..0000000 --- a/Tweaks/YTHoldForSpeed/layout/Library/Application Support/YTHoldForSpeed.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,13 +0,0 @@ -"HOLD_FOR_SPEED" = "Hold for speed"; -"NORMAL" = "Normal"; -"X_SECONDS" = "%@ seconds"; -"HOLD_GESTURE" = "Hold gesture"; -"HOLD_GESTURE_DESC" = "Tap and hold anywhere in the video player to toggle the playback speed between \"Normal\" (i.e. 1.0x) and the selected toggle speed.\n\nPlease be aware that by enabling this feature, the stock \"seek anywhere\" gesture will be disabled."; -"AUTO_APPLY_SPEED" = "Automatically apply speed"; -"AUTO_APPLY_SPEED_DESC" = "When enabled, the selected playback speed will automatically be applied when a new video player is launched."; -"TOGGLE_SPEED" = "Toggle speed"; -"TOGGLE_SPEED_DESC" = "The speed that the video player will toggle between when the hold gesture is invoked."; -"HOLD_DURATION" = "Hold duration"; -"HOLD_DURATION_DESC" = "The amount of time (in seconds) that is required for the hold gesture to toggle the speed of the video player."; -"HAPTIC_FEEDBACK" = "Haptic feedback"; -"HAPTIC_FEEDBACK_DESC" = "Use haptic feedback to indicate that the speed of the video player was toggled."; diff --git a/Tweaks/YTHoldForSpeed/ytholdforspeed.plist b/Tweaks/YTHoldForSpeed/ytholdforspeed.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/YTHoldForSpeed/ytholdforspeed.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/YTLite b/Tweaks/YTLite new file mode 160000 index 0000000..0a98d61 --- /dev/null +++ b/Tweaks/YTLite @@ -0,0 +1 @@ +Subproject commit 0a98d61920c4d383a57f4dea7e1f4e949835166b diff --git a/Tweaks/YTLite/.gitattributes b/Tweaks/YTLite/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Tweaks/YTLite/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Tweaks/YTLite/LICENSE b/Tweaks/YTLite/LICENSE deleted file mode 100644 index 7055c6a..0000000 --- a/Tweaks/YTLite/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 dayanch96 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Tweaks/YTLite/Makefile b/Tweaks/YTLite/Makefile deleted file mode 100644 index 35d8758..0000000 --- a/Tweaks/YTLite/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -ifeq ($(ROOTLESS),1) -THEOS_PACKAGE_SCHEME=rootless -endif - -DEBUG=0 -FINALPACKAGE=1 -ARCHS = arm64 -PACKAGE_VERSION = 2.1 -TARGET := iphone:clang:latest:11.0 - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YTLite -$(TWEAK_NAME)_FRAMEWORKS = UIKit Foundation -$(TWEAK_NAME)_CFLAGS = -fobjc-arc -DTWEAK_VERSION=$(PACKAGE_VERSION) -$(TWEAK_NAME)_FILES = YTLite.x Settings.x Sideloading.x - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/YTLite/README.md b/Tweaks/YTLite/README.md deleted file mode 100644 index 17dd527..0000000 --- a/Tweaks/YTLite/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# YTLite -Lightweight YouTube Enhancer - -Advanced mode can be activated inside **Version cell**. Then simply reopen YTLite settings - -# How to build it yourself -Clone this repo and __[YouTubeHeader by PoomSmart](https://github.com/PoomSmart/YouTubeHeader/)__ - -cd YTLite folder and run - -• '**make clean package**' to build deb for rootful device - -• '**make clean package ROOTLESS=1**' to build deb for rootless device - - -

- -

diff --git a/Tweaks/YTLite/Settings.x b/Tweaks/YTLite/Settings.x deleted file mode 100644 index 3866676..0000000 --- a/Tweaks/YTLite/Settings.x +++ /dev/null @@ -1,392 +0,0 @@ -#import "YTLite.h" - -@interface YTSettingsSectionItemManager (YTLite) -- (void)updateYTLiteSectionWithEntry:(id)entry; -@end - -static const NSInteger YTLiteSection = 789; - -static void resetYTLiteSettings() { - NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - [fileManager removeItemAtPath:prefsPath error:nil]; -} - -NSBundle *YTLiteBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YTLite" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS("/Library/Application Support/YTLite.bundle")]; - }); - return bundle; -} - -// Settings -%hook YTAppSettingsPresentationData -+ (NSArray *)settingsCategoryOrder { - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - NSUInteger insertIndex = [order indexOfObject:@(1)]; - if (insertIndex != NSNotFound) - [mutableOrder insertObject:@(YTLiteSection) atIndex:insertIndex + 1]; - return mutableOrder; -} -%end - -%hook YTSettingsSectionController -- (void)setSelectedItem:(NSUInteger)selectedItem { - if (selectedItem != NSNotFound) %orig; -} -%end - -%hook YTSettingsSectionItemManager -%new -- (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled { - NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"]; - NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:prefsPath]; - - if (!prefs) prefs = [NSMutableDictionary dictionary]; - - [prefs setObject:@(enabled) forKey:key]; - [prefs writeToFile:prefsPath atomically:NO]; - - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES); -} - -%new -- (void)updateIntegerPrefsForKey:(NSString *)key intValue:(NSInteger)intValue { - NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"]; - NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:prefsPath]; - - if (!prefs) prefs = [NSMutableDictionary dictionary]; - - [prefs setObject:@(intValue) forKey:key]; - [prefs writeToFile:prefsPath atomically:NO]; - - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES); -} - -static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleDescription, NSString *key, BOOL *value, id selfObject) { - Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); - YTSettingsSectionItem *item = [YTSettingsSectionItemClass switchItemWithTitle:title - titleDescription:titleDescription - accessibilityIdentifier:nil - switchOn:*value - switchBlock:^BOOL(YTSettingsCell *cell, BOOL enabled) { - [selfObject updatePrefsForKey:key enabled:enabled]; - return YES; - } - settingItemId:0]; - return item; -} - -%new(v@:@) -- (void)updateYTLiteSectionWithEntry:(id)entry { - NSMutableArray *sectionItems = [NSMutableArray array]; - Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); - YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; - id selfObject = self; - - YTSettingsSectionItem *space = [%c(YTSettingsSectionItem) itemWithTitle:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { return YES; }]; - - YTSettingsSectionItem *general = [YTSettingsSectionItemClass itemWithTitle:LOC(@"General") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"RemoveAds"), LOC(@"RemoveAdsDesc"), @"noAds", &kNoAds, selfObject), - createSwitchItem(LOC(@"BackgroundPlayback"), LOC(@"BackgroundPlaybackDesc"), @"backgroundPlayback", &kBackgroundPlayback, selfObject) - ]; - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"General") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:general]; - - YTSettingsSectionItem *navbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Navbar") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"RemoveCast"), LOC(@"RemoveCastDesc"), @"noCast", &kNoCast, selfObject), - createSwitchItem(LOC(@"RemoveNotifications"), LOC(@"RemoveNotificationsDesc"), @"removeNotifsButton", &kNoNotifsButton, selfObject), - createSwitchItem(LOC(@"RemoveSearch"), LOC(@"RemoveSearchDesc"), @"removeSearchButton", &kNoSearchButton, selfObject), - createSwitchItem(LOC(@"RemoveVoiceSearch"), LOC(@"RemoveVoiceSearchDesc"), @"removeVoiceSearchButton", &kNoVoiceSearchButton, selfObject) - ]; - - if (kAdvancedMode) { - YTSettingsSectionItem *addStickyNavbar = createSwitchItem(LOC(@"StickyNavbar"), LOC(@"StickyNavbarDesc"), @"stickyNavbar", &kStickyNavbar, selfObject); - rows = [rows arrayByAddingObject:addStickyNavbar]; - - YTSettingsSectionItem *addNoSubbar = createSwitchItem(LOC(@"NoSubbar"), LOC(@"NoSubbarDesc"), @"noSubbar", &kNoSubbar, selfObject); - rows = [rows arrayByAddingObject:addNoSubbar]; - - YTSettingsSectionItem *addNoYTLogo = createSwitchItem(LOC(@"NoYTLogo"), LOC(@"NoYTLogoDesc"), @"noYTLogo", &kNoYTLogo, selfObject); - rows = [rows arrayByAddingObject:addNoYTLogo]; - } - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Navbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:navbar]; - - if (kAdvancedMode) { - YTSettingsSectionItem *overlay = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Overlay") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"HideAutoplay"), LOC(@"HideAutoplayDesc"), @"hideAutoplay", &kHideAutoplay, selfObject), - createSwitchItem(LOC(@"HideSubs"), LOC(@"HideSubsDesc"), @"hideSubs", &kHideSubs, selfObject), - createSwitchItem(LOC(@"NoHUDMsgs"), LOC(@"NoHUDMsgsDesc"), @"noHUDMsgs", &kNoHUDMsgs, selfObject), - createSwitchItem(LOC(@"HidePrevNext"), LOC(@"HidePrevNextDesc"), @"hidePrevNext", &kHidePrevNext, selfObject), - createSwitchItem(LOC(@"ReplacePrevNext"), LOC(@"ReplacePrevNextDesc"), @"replacePrevNext", &kReplacePrevNext, selfObject), - createSwitchItem(LOC(@"NoDarkBg"), LOC(@"NoDarkBgDesc"), @"noDarkBg", &kNoDarkBg, selfObject), - createSwitchItem(LOC(@"NoEndScreenCards"), LOC(@"NoEndScreenCardsDesc"), @"endScreenCards", &kEndScreenCards, selfObject), - createSwitchItem(LOC(@"NoFullscreenActions"), LOC(@"NoFullscreenActionsDesc"), @"noFullscreenActions", &kNoFullscreenActions, selfObject), - createSwitchItem(LOC(@"NoRelatedVids"), LOC(@"NoRelatedVidsDesc"), @"noRelatedVids", &kNoRelatedVids, selfObject), - createSwitchItem(LOC(@"NoPromotionCards"), LOC(@"NoPromotionCardsDesc"), @"noPromotionCards", &kNoPromotionCards, selfObject), - createSwitchItem(LOC(@"NoWatermarks"), LOC(@"NoWatermarksDesc"), @"noWatermarks", &kNoWatermarks, selfObject) - ]; - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Overlay") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:overlay]; - - YTSettingsSectionItem *player = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Player") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"Miniplayer"), LOC(@"MiniplayerDesc"), @"miniplayer", &kMiniplayer, selfObject), - createSwitchItem(LOC(@"DisableAutoplay"), LOC(@"DisableAutoplayDesc"), @"disableAutoplay", &kDisableAutoplay, selfObject), - createSwitchItem(LOC(@"NoContentWarning"), LOC(@"NoContentWarningDesc"), @"noContentWarning", &kNoContentWarning, selfObject), - createSwitchItem(LOC(@"ClassicQuality"), LOC(@"ClassicQualityDesc"), @"classicQuality", &kClassicQuality, selfObject), - createSwitchItem(LOC(@"DontSnap2Chapter"), LOC(@"DontSnap2ChapterDesc"), @"dontSnapToChapter", &kDontSnapToChapter, selfObject), - createSwitchItem(LOC(@"RedProgressBar"), LOC(@"RedProgressBarDesc"), @"redProgressBar", &kRedProgressBar, selfObject), - createSwitchItem(LOC(@"NoHints"), LOC(@"NoHintsDesc"), @"noHints", &kNoHints, selfObject), - createSwitchItem(LOC(@"NoFreeZoom"), LOC(@"NoFreeZoomDesc"), @"noFreeZoom", &kNoFreeZoom, selfObject), - createSwitchItem(LOC(@"ExitFullscreen"), LOC(@"ExitFullscreenDesc"), @"exitFullscreen", &kExitFullscreen, selfObject), - createSwitchItem(LOC(@"NoDoubleTap2Seek"), LOC(@"NoDoubleTap2SeekDesc"), @"noDoubleTapToSeek", &kNoDoubleTapToSeek, selfObject) - ]; - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Player") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:player]; - - YTSettingsSectionItem *shorts = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Shorts") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"HideShorts"), LOC(@"HideShortsDesc"), @"hideShorts", &kHideShorts, selfObject), - createSwitchItem(LOC(@"ShortsProgress"), LOC(@"ShortsProgressDesc"), @"shortsProgress", &kShortsProgress, selfObject), - createSwitchItem(LOC(@"ResumeShorts"), LOC(@"ResumeShortsDesc"), @"resumeShorts", &kResumeShorts, selfObject), - createSwitchItem(LOC(@"HideShortsLogo"), LOC(@"HideShortsLogoDesc"), @"hideShortsLogo", &kHideShortsLogo, selfObject), - createSwitchItem(LOC(@"HideShortsSearch"), LOC(@"HideShortsSearchDesc"), @"hideShortsSearch", &kHideShortsSearch, selfObject), - createSwitchItem(LOC(@"HideShortsCamera"), LOC(@"HideShortsCameraDesc"), @"hideShortsCamera", &kHideShortsCamera, selfObject), - createSwitchItem(LOC(@"HideShortsMore"), LOC(@"HideShortsMoreDesc"), @"hideShortsMore", &kHideShortsMore, selfObject), - createSwitchItem(LOC(@"HideShortsSubscriptions"), LOC(@"HideShortsSubscriptionsDesc"), @"hideShortsSubscriptions", &kHideShortsSubscriptions, selfObject), - createSwitchItem(LOC(@"HideShortsLike"), LOC(@"HideShortsLikeDesc"), @"hideShortsLike", &kHideShortsLike, selfObject), - createSwitchItem(LOC(@"HideShortsDislike"), LOC(@"HideShortsDislikeDesc"), @"hideShortsDislike", &kHideShortsDislike, selfObject), - createSwitchItem(LOC(@"HideShortsComments"), LOC(@"HideShortsCommentsDesc"), @"hideShortsComments", &kHideShortsComments, selfObject), - createSwitchItem(LOC(@"HideShortsRemix"), LOC(@"HideShortsRemixDesc"), @"hideShortsRemix", &kHideShortsRemix, selfObject), - createSwitchItem(LOC(@"HideShortsShare"), LOC(@"HideShortsShareDesc"), @"hideShortsShare", &kHideShortsShare, selfObject), - createSwitchItem(LOC(@"HideShortsAvatars"), LOC(@"HideShortsAvatarsDesc"), @"hideShortsAvatars", &kHideShortsAvatars, selfObject), - createSwitchItem(LOC(@"HideShortsThanks"), LOC(@"HideShortsThanksDesc"), @"hideShortsThanks", &kHideShortsThanks, selfObject), - createSwitchItem(LOC(@"HideShortsChannelName"), LOC(@"HideShortsChannelNameDesc"), @"hideShortsChannelName", &kHideShortsChannelName, selfObject), - createSwitchItem(LOC(@"HideShortsDescription"), LOC(@"HideShortsDescriptionDesc"), @"hideShortsDescription", &kHideShortsDescription, selfObject), - createSwitchItem(LOC(@"HideShortsAudioTrack"), LOC(@"HideShortsAudioTrackDesc"), @"hideShortsAudioTrack", &kHideShortsAudioTrack, selfObject) - ]; - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Shorts") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:shorts]; - } - - YTSettingsSectionItem *tabbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Tabbar") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"RemoveLabels"), LOC(@"RemoveLabelsDesc"), @"removeLabels", &kRemoveLabels, selfObject), - createSwitchItem(LOC(@"ReExplore"), LOC(@"ReExploreDesc"), @"reExplore", &kReExplore, selfObject), - createSwitchItem(LOC(@"HideShortsTab"), LOC(@"HideShortsTabDesc"), @"removeShorts", &kRemoveShorts, selfObject), - createSwitchItem(LOC(@"HideSubscriptionsTab"), LOC(@"HideSubscriptionsTabDesc"), @"removeSubscriptions", &kRemoveSubscriptions, selfObject), - createSwitchItem(LOC(@"HideUploadButton"), LOC(@"HideUploadButtonDesc"), @"removeUploads", &kRemoveUploads, selfObject), - createSwitchItem(LOC(@"HideLibraryTab"), LOC(@"HideLibraryTabDesc"), @"removeLibrary", &kRemoveLibrary, selfObject) - ]; - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Tabbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:tabbar]; - - if (kAdvancedMode) { - YTSettingsSectionItem *other = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Other") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @"‣"; - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - createSwitchItem(LOC(@"RemovePlayNext"), LOC(@"RemovePlayNextDesc"), @"removePlayNext", &kRemovePlayNext, selfObject), - createSwitchItem(LOC(@"NoContinueWatching"), LOC(@"NoContinueWatchingDesc"), @"noContinueWatching", &kNoContinueWatching, selfObject) - ]; - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Other") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:other]; - - [sectionItems addObject:space]; - - YTSettingsSectionItem *startup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Startup") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - switch (kPivotIndex) { - case 1: - return LOC(@"ShortsTab"); - case 2: - return LOC(@"Subscriptions"); - case 3: - return LOC(@"Library"); - case 0: - default: - return LOC(@"Home"); - } - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Home") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *home, NSUInteger arg1) { - kPivotIndex = 0; - [settingsViewController reloadData]; - [self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex]; - return YES; - }], - [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"ShortsTab") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *shorts, NSUInteger arg1) { - if (kRemoveShorts) { - YTAlertView *alertView = [%c(YTAlertView) infoDialog]; - alertView.title = LOC(@"Warning"); - alertView.subtitle = LOC(@"TabIsHidden"); - [alertView show]; - return NO; - } else { - kPivotIndex = 1; - [settingsViewController reloadData]; - [self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex]; - return YES; - } - }], - [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Subscriptions") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *subscriptions, NSUInteger arg1) { - if (kRemoveSubscriptions) { - YTAlertView *alertView = [%c(YTAlertView) infoDialog]; - alertView.title = LOC(@"Warning"); - alertView.subtitle = LOC(@"TabIsHidden"); - [alertView show]; - return NO; - } else { - kPivotIndex = 2; - [settingsViewController reloadData]; - [self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex]; - return YES; - } - }], - [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Library") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *library, NSUInteger arg1) { - if (kRemoveLibrary) { - YTAlertView *alertView = [%c(YTAlertView) infoDialog]; - alertView.title = LOC(@"Warning"); - alertView.subtitle = LOC(@"TabIsHidden"); - [alertView show]; - return NO; - } else { - kPivotIndex = 3; - [settingsViewController reloadData]; - [self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex]; - return YES; - } - }] - ]; - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Startup") pickerSectionTitle:nil rows:rows selectedItemIndex:kPivotIndex parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:startup]; - } - - [sectionItems addObject:space]; - - YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YTClassicVideoQuality, YTShortsProgress, YTReExplore, SkipContentWarning, YouTubeHeaders" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/PoomSmart/"]]; - }]; - - YTSettingsSectionItem *miro = [%c(YTSettingsSectionItem) itemWithTitle:@"MiRO92" titleDescription:@"YTNoShorts" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/MiRO92/"]]; - }]; - - YTSettingsSectionItem *dayanch96 = [%c(YTSettingsSectionItem) itemWithTitle:@"Dayanch96" titleDescription:LOC(@"Developer") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Dayanch96/"]]; - }]; - - YTSettingsSectionItem *reset = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ResetSettings") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ - resetYTLiteSettings(); - exit(0); - } - actionTitle:LOC(@"Yes") - cancelTitle:LOC(@"No")]; - alertView.title = LOC(@"Warning"); - alertView.subtitle = LOC(@"ResetMessage"); - [alertView show]; - return YES; - }]; - - YTSettingsSectionItem *version = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Version") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return @(OS_STRINGIFY(TWEAK_VERSION)); - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ps, miro, dayanch96, space, createSwitchItem(LOC(@"Advanced"), nil, @"advancedMode", &kAdvancedMode, selfObject), reset]; - - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"About") pickerSectionTitle:LOC(@"Credits") rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:version]; - - [settingsViewController setSectionItems:sectionItems forCategory:YTLiteSection title:@"YTLite" titleDescription:nil headerHidden:NO]; -} - -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { - if (category == YTLiteSection) { - [self updateYTLiteSectionWithEntry:entry]; - return; - } %orig; -} -%end \ No newline at end of file diff --git a/Tweaks/YTLite/Sideloading.x b/Tweaks/YTLite/Sideloading.x deleted file mode 100644 index 561457b..0000000 --- a/Tweaks/YTLite/Sideloading.x +++ /dev/null @@ -1,138 +0,0 @@ -#import -#import -#import - -#define YT_BUNDLE_ID @"com.google.ios.youtube" -#define YT_NAME @"YouTube" - -@interface SSOConfiguration : NSObject -@end - -%group gSideloading -// Keychain patching -static NSString *accessGroupID() { - NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: - (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass, - @"bundleSeedID", kSecAttrAccount, - @"", kSecAttrService, - (id)kCFBooleanTrue, kSecReturnAttributes, - nil]; - CFDictionaryRef result = nil; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); - if (status == errSecItemNotFound) - status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); - if (status != errSecSuccess) - return nil; - NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup]; - - return accessGroup; -} - -// IAmYouTube (https://github.com/PoomSmart/IAmYouTube/) -%hook YTVersionUtils -+ (NSString *)appName { return YT_NAME; } -+ (NSString *)appID { return YT_BUNDLE_ID; } -%end - -%hook GCKBUtils -+ (NSString *)appIdentifier { return YT_BUNDLE_ID; } -%end - -%hook GPCDeviceInfo -+ (NSString *)bundleId { return YT_BUNDLE_ID; } -%end - -%hook OGLBundle -+ (NSString *)shortAppName { return YT_NAME; } -%end - -%hook GVROverlayView -+ (NSString *)appName { return YT_NAME; } -%end - -%hook OGLPhenotypeFlagServiceImpl -- (NSString *)bundleId { return YT_BUNDLE_ID; } -%end - -%hook APMAEU -+ (BOOL)isFAS { return YES; } -%end - -%hook GULAppEnvironmentUtil -+ (BOOL)isFromAppStore { return YES; } -%end - -%hook SSOConfiguration -- (id)initWithClientID:(id)clientID supportedAccountServices:(id)supportedAccountServices { - self = %orig; - [self setValue:YT_NAME forKey:@"_shortAppName"]; - [self setValue:YT_BUNDLE_ID forKey:@"_applicationIdentifier"]; - return self; -} -%end - -%hook NSBundle -- (NSString *)bundleIdentifier { - NSArray *address = [NSThread callStackReturnAddresses]; - Dl_info info = {0}; - if (dladdr((void *)[address[2] longLongValue], &info) == 0) - return %orig; - NSString *path = [NSString stringWithUTF8String:info.dli_fname]; - if ([path hasPrefix:NSBundle.mainBundle.bundlePath]) - return YT_BUNDLE_ID; - return %orig; -} -- (id)objectForInfoDictionaryKey:(NSString *)key { - if ([key isEqualToString:@"CFBundleIdentifier"]) - return YT_BUNDLE_ID; - if ([key isEqualToString:@"CFBundleDisplayName"] || [key isEqualToString:@"CFBundleName"]) - return YT_NAME; - return %orig; -} -// Fix Google Sign in by @PoomSmart and @level3tjg (qnblackcat/uYouPlus#684) -- (NSDictionary *)infoDictionary { - NSMutableDictionary *info = %orig.mutableCopy; - NSString *altBundleIdentifier = info[@"ALTBundleIdentifier"]; - if (altBundleIdentifier) info[@"CFBundleIdentifier"] = altBundleIdentifier; - return info; -} -%end - -// Fix login for YouTube 18.13.2 and higher -%hook SSOKeychainHelper -+ (NSString *)accessGroup { - return accessGroupID(); -} -+ (NSString *)sharedAccessGroup { - return accessGroupID(); -} -%end - -// Fix login for YouTube 17.33.2 and higher -%hook SSOKeychainCore -+ (NSString *)accessGroup { - return accessGroupID(); -} - -+ (NSString *)sharedAccessGroup { - return accessGroupID(); -} -%end - -// Fix App Group Directory by moving it to documents directory -%hook NSFileManager -- (NSURL *)containerURLForSecurityApplicationGroupIdentifier:(NSString *)groupIdentifier { - if (groupIdentifier != nil) { - NSArray *paths = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; - NSURL *documentsURL = [paths lastObject]; - return [documentsURL URLByAppendingPathComponent:@"AppGroup"]; - } - return %orig(groupIdentifier); -} -%end -%end - -%ctor { - NSString *embeddedMobileProvisionPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]; - if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedMobileProvisionPath]) %init(gSideloading); -} diff --git a/Tweaks/YTLite/YTLite.h b/Tweaks/YTLite/YTLite.h deleted file mode 100644 index c8bce1b..0000000 --- a/Tweaks/YTLite/YTLite.h +++ /dev/null @@ -1,153 +0,0 @@ -#import -#import -#import -#import "../YouTubeHeader/YTIGuideResponse.h" -#import "../YouTubeHeader/YTIGuideResponseSupportedRenderers.h" -#import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h" -#import "../YouTubeHeader/YTIPivotBarRenderer.h" -#import "../YouTubeHeader/YTIBrowseRequest.h" -#import "../YouTubeHeader/YTISectionListRenderer.h" -#import "../YouTubeHeader/YTQTMButton.h" -#import "../YouTubeHeader/YTVideoQualitySwitchOriginalController.h" -#import "../YouTubeHeader/YTPlayerViewController.h" -#import "../YouTubeHeader/YTPlayerOverlay.h" -#import "../YouTubeHeader/YTPlayerOverlayProvider.h" -#import "../YouTubeHeader/YTSettingsViewController.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../YouTubeHeader/YTSettingsPickerViewController.h" -#import "../YouTubeHeader/YTUIUtils.h" -#import "../YouTubeHeader/YTIMenuConditionalServiceItemRenderer.h" - -extern NSBundle *YTLiteBundle(); - -static inline NSString *LOC(NSString *key) { - NSBundle *tweakBundle = YTLiteBundle(); - return [tweakBundle localizedStringForKey:key value:nil table:nil]; -} - -BOOL kNoAds; -BOOL kBackgroundPlayback; -BOOL kNoCast; -BOOL kNoNotifsButton; -BOOL kNoSearchButton; -BOOL kNoVoiceSearchButton; -BOOL kStickyNavbar; -BOOL kNoSubbar; -BOOL kNoYTLogo; -BOOL kHideAutoplay; -BOOL kHideSubs; -BOOL kNoHUDMsgs; -BOOL kHidePrevNext; -BOOL kReplacePrevNext; -BOOL kNoDarkBg; -BOOL kEndScreenCards; -BOOL kNoFullscreenActions; -BOOL kNoRelatedVids; -BOOL kNoPromotionCards; -BOOL kNoWatermarks; -BOOL kMiniplayer; -BOOL kDisableAutoplay; -BOOL kNoContentWarning; -BOOL kClassicQuality; -BOOL kDontSnapToChapter; -BOOL kRedProgressBar; -BOOL kNoHints; -BOOL kNoFreeZoom; -BOOL kExitFullscreen; -BOOL kNoDoubleTapToSeek; -BOOL kHideShorts; -BOOL kShortsProgress; -BOOL kResumeShorts; -BOOL kHideShortsLogo; -BOOL kHideShortsSearch; -BOOL kHideShortsCamera; -BOOL kHideShortsMore; -BOOL kHideShortsSubscriptions; -BOOL kHideShortsLike; -BOOL kHideShortsDislike; -BOOL kHideShortsComments; -BOOL kHideShortsRemix; -BOOL kHideShortsShare; -BOOL kHideShortsAvatars; -BOOL kHideShortsThanks; -BOOL kHideShortsChannelName; -BOOL kHideShortsDescription; -BOOL kHideShortsAudioTrack; -BOOL kRemoveLabels; -BOOL kReExplore; -BOOL kRemoveShorts; -BOOL kRemoveSubscriptions; -BOOL kRemoveUploads; -BOOL kRemoveLibrary; -BOOL kRemovePlayNext; -BOOL kNoContinueWatching; -BOOL kAdvancedMode; -int kPivotIndex; - -@interface YTSettingsSectionItemManager (Custom) -@property (nonatomic, strong) NSMutableDictionary *prefs; -@property (nonatomic, strong) NSString *prefsPath; -- (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled; -- (void)updateIntegerPrefsForKey:(NSString *)key intValue:(NSInteger)intValue; -@end - -@interface YTPivotBarView : UIView -@end - -@interface YTPivotBarItemView : UIView -@end - -@interface YTPivotBarViewController : UIViewController -- (void)selectItemWithPivotIdentifier:(id)pivotIndentifier; -@end - -@interface YTRightNavigationButtons : UIView -@property (nonatomic, strong) YTQTMButton *notificationButton; -@property (nonatomic, strong) YTQTMButton *searchButton; -@end - -@interface YTNavigationBarTitleView : UIView -@end - -@interface YTChipCloudCell : UICollectionViewCell -@end - -@interface YTSegmentableInlinePlayerBarView -@property (nonatomic, assign, readwrite) BOOL enableSnapToChapter; -@end - -@interface YTPlayabilityResolutionUserActionUIController : NSObject -- (void)confirmAlertDidPressConfirm; -@end - -@interface YTReelPlayerButton : UIButton -@end - -@interface ELMCellNode -@end - -@interface _ASCollectionViewCell : UICollectionViewCell -- (id)node; -@end - -@interface YTAsyncCollectionView : UICollectionView -- (void)removeCellsAtIndexPath:(NSIndexPath *)indexPath; -@end - -@interface YTReelWatchPlaybackOverlayView : UIView -@end - -@interface YTReelTransparentStackView : UIView -@end - -@interface YTReelWatchHeaderView : UIView -@end - -@interface YTAlertView : UIView -@property (nonatomic, copy, readwrite) NSString *title; -@property (nonatomic, copy, readwrite) NSString *subtitle; -+ (instancetype)infoDialog; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelTitle:(NSString *)cancelTitle; -- (void)show; -@end \ No newline at end of file diff --git a/Tweaks/YTLite/YTLite.plist b/Tweaks/YTLite/YTLite.plist deleted file mode 100644 index d036024..0000000 --- a/Tweaks/YTLite/YTLite.plist +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Filter - - Bundles - - com.google.ios.youtube - - - - diff --git a/Tweaks/YTLite/YTLite.x b/Tweaks/YTLite/YTLite.x deleted file mode 100644 index a39e0df..0000000 --- a/Tweaks/YTLite/YTLite.x +++ /dev/null @@ -1,699 +0,0 @@ -#import "YTLite.h" - -// YouTube-X (https://github.com/PoomSmart/YouTube-X/) -// Background Playback -%hook YTIPlayabilityStatus -- (BOOL)isPlayableInBackground { return kBackgroundPlayback ? YES : NO; } -%end - -%hook MLVideo -- (BOOL)playableInBackground { return kBackgroundPlayback ? YES : NO; } -%end - -// Disable Ads -%hook YTIPlayerResponse -- (BOOL)isMonetized { return kNoAds ? NO : YES; } -%end - -%hook YTDataUtils -+ (id)spamSignalsDictionary { return kNoAds ? nil : %orig; } -+ (id)spamSignalsDictionaryWithoutIDFA { return kNoAds ? nil : %orig; } -%end - -%hook YTAdsInnerTubeContextDecorator -- (void)decorateContext:(id)context { if (!kNoAds) %orig; } -%end - -%hook YTAccountScopedAdsInnerTubeContextDecorator -- (void)decorateContext:(id)context { if (!kNoAds) %orig; } -%end - -%hook YTIElementRenderer -- (NSData *)elementData { - if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData) - return nil; - NSString *description = [self description]; - if (([description containsString:@"brand_promo"] - || [description containsString:@"product_carousel"] - || [description containsString:@"product_engagement_panel"] - || [description containsString:@"product_item"]) && kNoAds) - return [NSData data]; - return %orig; -} -%end - -%hook YTSectionListViewController -- (void)loadWithModel:(YTISectionListRenderer *)model { - if (kNoAds) { - NSMutableArray *contentsArray = model.contentsArray; - NSIndexSet *removeIndexes = [contentsArray indexesOfObjectsPassingTest:^BOOL(YTISectionListSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer; - YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject]; - return firstObject.hasPromotedVideoRenderer || firstObject.hasCompactPromotedVideoRenderer || firstObject.hasPromotedVideoInlineMutedRenderer; - }]; - [contentsArray removeObjectsAtIndexes:removeIndexes]; - } %orig; -} -%end - -// NOYTPremium (https://github.com/PoomSmart/NoYTPremium) -// Alert -%hook YTCommerceEventGroupHandler -- (void)addEventHandlers {} -%end - -// Full-screen -%hook YTInterstitialPromoEventGroupHandler -- (void)addEventHandlers {} -%end - -%hook YTPromosheetEventGroupHandler -- (void)addEventHandlers {} -%end - -%hook YTPromoThrottleController -- (BOOL)canShowThrottledPromo { return NO; } -- (BOOL)canShowThrottledPromoWithFrequencyCap:(id)arg1 { return NO; } -- (BOOL)canShowThrottledPromoWithFrequencyCaps:(id)arg1 { return NO; } -%end - -%hook YTIShowFullscreenInterstitialCommand -- (BOOL)shouldThrottleInterstitial { return YES; } -%end - -// "Try new features" in settings -%hook YTSettingsSectionItemManager -- (void)updatePremiumEarlyAccessSectionWithEntry:(id)arg1 {} -%end - -// Survey -%hook YTSurveyController -- (void)showSurveyWithRenderer:(id)arg1 surveyParentResponder:(id)arg2 {} -%end - -// Navbar Stuff -// Disable Cast -%hook MDXPlaybackRouteButtonController -- (BOOL)isPersistentCastIconEnabled { return kNoCast ? NO : YES; } -- (void)updateRouteButton:(id)arg1 { if (!kNoCast) %orig; } -- (void)updateAllRouteButtons { if (!kNoCast) %orig; } -%end - -%hook YTSettings -- (void)setDisableMDXDeviceDiscovery:(BOOL)arg1 { %orig(kNoCast); } -%end - -// Hide Cast, Notifications and Search Buttons -%hook YTRightNavigationButtons -- (void)layoutSubviews { - %orig; - if (kNoCast && self.subviews.count > 1 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.mdx.playbackroute.button"]) self.subviews[1].hidden = YES; // Hide icon immediately - if (kNoNotifsButton) self.notificationButton.hidden = YES; - if (kNoSearchButton) self.searchButton.hidden = YES; - if (kNoVoiceSearchButton && self.subviews.count >= 4 && [self.subviews[2].accessibilityIdentifier isEqualToString:@"id.settings.overflow.button"]) self.subviews[3].hidden = YES; -} -%end - -// Hide YouTube Logo -%hook YTNavigationBarTitleView -- (void)layoutSubviews { %orig; if (kNoYTLogo && self.subviews.count > 1 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.yoodle.logo"]) self.subviews[1].hidden = YES; } -%end - -// Stick Navigation bar -%hook YTHeaderView -- (BOOL)stickyNavHeaderEnabled { return kStickyNavbar ? YES : NO; } -%end - -// Remove Subbar -%hook YTMySubsFilterHeaderView -- (void)setChipFilterView:(id)arg1 { if (!kNoSubbar) %orig; } -%end - -%hook YTHeaderContentComboView -- (void)enableSubheaderBarWithView:(id)arg1 { if (!kNoSubbar) %orig; } -- (void)setFeedHeaderScrollMode:(int)arg1 { kNoSubbar ? %orig(0) : %orig; } -%end - -%hook YTChipCloudCell -- (void)layoutSubviews { - if (self.superview && kNoSubbar) { - [self removeFromSuperview]; - } %orig; -} -%end - -// Hide Autoplay Switch and Subs Button -%hook YTMainAppControlsOverlayView -- (void)setAutoplaySwitchButtonRenderer:(id)arg1 { if (!kHideAutoplay) %orig; } -- (void)setClosedCaptionsOrSubtitlesButtonAvailable:(BOOL)arg1 { kHideSubs ? %orig(NO) : %orig; } -%end - -// Remove HUD Messages -%hook YTHUDMessageView -- (id)initWithMessage:(id)arg1 dismissHandler:(id)arg2 { return kNoHUDMsgs ? nil : %orig; } -%end - - -%hook YTColdConfig -// Hide Next & Previous buttons -- (BOOL)removeNextPaddleForSingletonVideos { return kHidePrevNext ? YES : NO; } -- (BOOL)removePreviousPaddleForSingletonVideos { return kHidePrevNext ? YES : NO; } -// Replace Next & Previous with Fast Forward & Rewind buttons -- (BOOL)replaceNextPaddleWithFastForwardButtonForSingletonVods { return kReplacePrevNext ? YES : NO; } -- (BOOL)replacePreviousPaddleWithRewindButtonForSingletonVods { return kReplacePrevNext ? YES : NO; } -// Disable Free Zoom -- (BOOL)videoZoomFreeZoomEnabledGlobalConfig { return kNoFreeZoom ? NO : YES; } -// Use System Theme -- (BOOL)shouldUseAppThemeSetting { return YES; } -// Dismiss Panel By Swiping in Fullscreen Mode -- (BOOL)isLandscapeEngagementPanelSwipeRightToDismissEnabled { return YES; } -// Remove Video in Playlist By Swiping To The Right -- (BOOL)enableSwipeToRemoveInPlaylistWatchEp { return YES; } -%end - -// Remove Dark Background in Overlay -%hook YTMainAppVideoPlayerOverlayView -- (void)setBackgroundVisible:(BOOL)arg1 { kNoDarkBg ? %orig(NO) : %orig; } -%end - -// No Endscreen Cards -%hook YTCreatorEndscreenView -- (void)setHidden:(BOOL)arg1 { kEndScreenCards ? %orig(YES) : %orig; } -%end - -// Disable Fullscreen Actions -%hook YTFullscreenActionsView -- (BOOL)enabled { return kNoFullscreenActions ? NO : YES; } -- (void)setEnabled:(BOOL)arg1 { kNoFullscreenActions ? %orig(NO) : %orig; } -%end - -// Dont Show Related Videos on Finish -%hook YTFullscreenEngagementOverlayController -- (void)setRelatedVideosVisible:(BOOL)arg1 { kNoRelatedVids ? %orig(NO) : %orig; } -%end - -// Hide Paid Promotion Cards -%hook YTMainAppVideoPlayerOverlayViewController -- (void)setPaidContentWithPlayerData:(id)data { if (!kNoPromotionCards) %orig; } -- (void)playerOverlayProvider:(YTPlayerOverlayProvider *)provider didInsertPlayerOverlay:(YTPlayerOverlay *)overlay { - if ([[overlay overlayIdentifier] isEqualToString:@"player_overlay_paid_content"] && kNoPromotionCards) return; - %orig; -} -%end - -%hook YTInlineMutedPlaybackPlayerOverlayViewController -- (void)setPaidContentWithPlayerData:(id)data { if (!kNoPromotionCards) %orig; } -%end - -// Remove Watermarks -%hook YTAnnotationsViewController -- (void)loadFeaturedChannelWatermark { if (!kNoWatermarks) %orig; } -%end - -// Forcibly Enable Miniplayer -%hook YTWatchMiniBarViewController -- (void)updateMiniBarPlayerStateFromRenderer { if (!kMiniplayer) %orig; } -%end - -// Disable Autoplay -%hook YTPlaybackConfig -- (void)setStartPlayback:(BOOL)arg1 { kDisableAutoplay ? %orig(NO) : %orig; } -%end - -// Skip Content Warning (https://github.com/qnblackcat/uYouPlus/blob/main/uYouPlus.xm#L452-L454) -%hook YTPlayabilityResolutionUserActionUIController -- (void)showConfirmAlert { if (kNoContentWarning) [self confirmAlertDidPressConfirm]; } -%end - -// Classic Video Quality (https://github.com/PoomSmart/YTClassicVideoQuality) -%hook YTVideoQualitySwitchControllerFactory -- (id)videoQualitySwitchControllerWithParentResponder:(id)responder { - Class originalClass = %c(YTVideoQualitySwitchOriginalController); - if (kClassicQuality) { - return originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig; - } return %orig; -} -%end - -// Disable Snap To Chapter (https://github.com/qnblackcat/uYouPlus/blob/main/uYouPlus.xm#L457-464) -%hook YTSegmentableInlinePlayerBarView -- (void)didMoveToWindow { %orig; if (kDontSnapToChapter) self.enableSnapToChapter = NO; } -%end - -// Red Progress Bar and Gray Buffer Progress -%hook YTInlinePlayerBarContainerView -- (id)quietProgressBarColor { return kRedProgressBar ? [UIColor redColor] : %orig; } -%end - -%hook YTSegmentableInlinePlayerBarView -- (void)setBufferedProgressBarColor:(id)arg1 { if (kNoRelatedVids) %orig([UIColor colorWithRed:0.65 green:0.65 blue:0.65 alpha:0.60]); } -%end - -// Disable Hints -%hook YTSettings -- (BOOL)areHintsDisabled { return kNoHints ? YES : NO; } -- (void)setHintsDisabled:(BOOL)arg1 { kNoHints ? %orig(YES) : %orig; } -%end - -%hook YTUserDefaults -- (BOOL)areHintsDisabled { return kNoHints ? YES : NO; } -- (void)setHintsDisabled:(BOOL)arg1 { kNoHints ? %orig(YES) : %orig; } -%end - -// Exit Fullscreen on Finish -%hook YTWatchFlowController -- (BOOL)shouldExitFullScreenOnFinish { return kExitFullscreen ? YES : NO; } -%end - -// Disable Double Tap To Seek -%hook YTDoubleTapToSeekController -- (void)enableDoubleTapToSeek:(BOOL)arg1 { kNoDoubleTapToSeek ? %orig(NO) : %orig; } -%end - -// Fit 'Play All' Buttons Text For Localizations -%hook YTQTMButton -- (void)layoutSubviews { - if ([self.accessibilityIdentifier isEqualToString:@"id.playlist.playall.button"]) { - self.titleLabel.adjustsFontSizeToFitWidth = YES; - } %orig; -} -%end - -// Fix Playlist Mini-bar Height For Small Screens -%hook YTPlaylistMiniBarView -- (void)setFrame:(CGRect)frame { - if (frame.size.height < 54.0) frame.size.height = 54.0; - %orig(frame); -} -%end - -// Remove "Play next in queue" from the menu @PoomSmart (https://github.com/qnblackcat/uYouPlus/issues/1138#issuecomment-1606415080) -%hook YTMenuItemVisibilityHandler -- (BOOL)shouldShowServiceItemRenderer:(YTIMenuConditionalServiceItemRenderer *)renderer { - if (kRemovePlayNext && renderer.icon.iconType == 251) { - return NO; - } return %orig; -} -%end - -// Remove Premium Pop-up, Horizontal Video Carousel and Shorts (https://github.com/MiRO92/YTNoShorts) -%hook YTAsyncCollectionView -- (id)cellForItemAtIndexPath:(NSIndexPath *)indexPath { - UICollectionViewCell *cell = %orig; - - if ([cell isKindOfClass:objc_lookUpClass("_ASCollectionViewCell")]) { - _ASCollectionViewCell *cell = %orig; - if ([cell respondsToSelector:@selector(node)]) { - NSString *idToRemove = [[cell node] accessibilityIdentifier]; - if ([idToRemove isEqualToString:@"statement_banner.view"] || - (([idToRemove isEqualToString:@"eml.shorts-grid"] || [idToRemove isEqualToString:@"eml.shorts-shelf"]) && kHideShorts)) { - [self removeCellsAtIndexPath:indexPath]; - } - } - } else if (([cell isKindOfClass:objc_lookUpClass("YTReelShelfCell")] && kHideShorts) || - ([cell isKindOfClass:objc_lookUpClass("YTHorizontalCardListCell")] && kNoContinueWatching)) { - [self removeCellsAtIndexPath:indexPath]; - } return %orig; -} - -%new -- (void)removeCellsAtIndexPath:(NSIndexPath *)indexPath { - [self deleteItemsAtIndexPaths:@[indexPath]]; -} -%end - -// Shorts Progress Bar (https://github.com/PoomSmart/YTShortsProgress) -%hook YTReelPlayerViewController -- (BOOL)shouldEnablePlayerBar { return kShortsProgress ? YES : NO; } -- (BOOL)shouldAlwaysEnablePlayerBar { return kShortsProgress ? YES : NO; } -- (BOOL)shouldEnablePlayerBarOnlyOnPause { return kShortsProgress ? NO : YES; } -%end - -%hook YTReelPlayerViewControllerSub -- (BOOL)shouldEnablePlayerBar { return kShortsProgress ? YES : NO; } -- (BOOL)shouldAlwaysEnablePlayerBar { return kShortsProgress ? YES : NO; } -- (BOOL)shouldEnablePlayerBarOnlyOnPause { return kShortsProgress ? NO : YES; } -%end - -%hook YTColdConfig -- (BOOL)iosEnableVideoPlayerScrubber { return kShortsProgress ? YES : NO; } -- (BOOL)mobileShortsTabInlined { return kShortsProgress ? YES : NO; } -%end - -%hook YTHotConfig -- (BOOL)enablePlayerBarForVerticalVideoWhenControlsHiddenInFullscreen { return kShortsProgress ? YES : NO; } -%end - -// Dont Startup Shorts -%hook YTShortsStartupCoordinator -- (id)evaluateResumeToShorts { return kResumeShorts ? nil : %orig; } -%end - -// Hide Shorts Elements -%hook YTReelPausedStateCarouselView -- (void)setPausedStateCarouselVisible:(BOOL)arg1 animated:(BOOL)arg2 { kHideShortsSubscriptions ? %orig(arg1 = NO, arg2) : %orig; } -%end - -%hook YTReelWatchPlaybackOverlayView -- (void)setReelLikeButton:(id)arg1 { if (!kHideShortsLike) %orig; } -- (void)setReelDislikeButton:(id)arg1 { if (!kHideShortsDislike) %orig; } -- (void)setViewCommentButton:(id)arg1 { if (!kHideShortsComments) %orig; } -- (void)setRemixButton:(id)arg1 { if (!kHideShortsRemix) %orig; } -- (void)setShareButton:(id)arg1 { if (!kHideShortsShare) %orig; } -- (void)layoutSubviews { - %orig; - - for (UIView *subview in self.subviews) { - if (kHideShortsAvatars && [NSStringFromClass([subview class]) isEqualToString:@"YTELMView"]) { - subview.hidden = YES; - break; - } - } -} -%end - -%hook YTReelHeaderView -- (void)setTitleLabelVisible:(BOOL)arg1 animated:(BOOL)arg2 { kHideShortsLogo ? %orig(arg1 = NO, arg2) : %orig; } -%end - -%hook YTReelTransparentStackView -- (void)layoutSubviews { - %orig; - if (kHideShortsSearch && self.subviews.count >= 3 && [self.subviews[0].accessibilityIdentifier isEqualToString:@"id.ui.generic.button"]) self.subviews[0].hidden = YES; - if (kHideShortsCamera && self.subviews.count >= 3 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.ui.generic.button"]) self.subviews[1].hidden = YES; - if (kHideShortsMore && self.subviews.count >= 3 && [self.subviews[2].accessibilityIdentifier isEqualToString:@"id.ui.generic.button"]) self.subviews[2].hidden = YES; -} -%end - -%hook YTReelWatchHeaderView -- (void)layoutSubviews { - %orig; - if (kHideShortsDescription && [self.subviews[2].accessibilityIdentifier isEqualToString:@"id.reels_smv_player_title_label"]) self.subviews[2].hidden = YES; - if (kHideShortsThanks && [self.subviews[self.subviews.count - 3].accessibilityIdentifier isEqualToString:@"id.elements.components.suggested_action"]) self.subviews[self.subviews.count - 3].hidden = YES; - if (kHideShortsChannelName) self.subviews[self.subviews.count - 2].hidden = YES; - if (kHideShortsAudioTrack) self.subviews.lastObject.hidden = YES; -} -%end - -// Remove Tabs -%hook YTPivotBarView -- (void)setRenderer:(YTIPivotBarRenderer *)renderer { - NSMutableArray *items = [renderer itemsArray]; - - NSDictionary *identifiersToRemove = @{ - @"FEshorts": @(kRemoveShorts), - @"FEsubscriptions": @(kRemoveSubscriptions), - @"FEuploads": @(kRemoveUploads), - @"FElibrary": @(kRemoveLibrary) - }; - - for (NSString *identifier in identifiersToRemove) { - BOOL shouldRemoveItem = [identifiersToRemove[identifier] boolValue]; - NSUInteger index = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - if ([identifier isEqualToString:@"FEuploads"]) { - return shouldRemoveItem && [[[renderers pivotBarIconOnlyItemRenderer] pivotIdentifier] isEqualToString:identifier]; - } else { - return shouldRemoveItem && [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:identifier]; - } - }]; - - if (index != NSNotFound) { - [items removeObjectAtIndex:index]; - } - } %orig; -} -%end - -// Replace Shorts with Explore tab (https://github.com/PoomSmart/YTReExplore) -static void replaceTab(YTIGuideResponse *response) { - NSMutableArray *renderers = [response itemsArray]; - for (YTIGuideResponseSupportedRenderers *guideRenderers in renderers) { - YTIPivotBarRenderer *pivotBarRenderer = [guideRenderers pivotBarRenderer]; - NSMutableArray *items = [pivotBarRenderer itemsArray]; - NSUInteger shortIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - return [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:@"FEshorts"]; - }]; - if (shortIndex != NSNotFound) { - [items removeObjectAtIndex:shortIndex]; - NSUInteger exploreIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - return [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:[%c(YTIBrowseRequest) browseIDForExploreTab]]; - }]; - if (exploreIndex == NSNotFound) { - YTIPivotBarSupportedRenderers *exploreTab = [%c(YTIPivotBarRenderer) pivotSupportedRenderersWithBrowseId:[%c(YTIBrowseRequest) browseIDForExploreTab] title:LOC(@"Explore") iconType:292]; - [items insertObject:exploreTab atIndex:1]; - } - } - } -} - -%hook YTGuideServiceCoordinator -- (void)handleResponse:(YTIGuideResponse *)response withCompletion:(id)completion { - if (kReExplore) replaceTab(response); - %orig(response, completion); -} -- (void)handleResponse:(YTIGuideResponse *)response error:(id)error completion:(id)completion { - if (kReExplore) replaceTab(response); - %orig(response, error, completion); -} -%end - -// Hide Tab Labels -BOOL hasHomeBar = NO; -CGFloat pivotBarViewHeight; - -%hook YTPivotBarView -- (void)layoutSubviews { - %orig; - pivotBarViewHeight = self.frame.size.height; -} -%end - -%hook YTPivotBarItemView -- (void)layoutSubviews { - %orig; - - CGFloat pivotBarAccessibilityControlWidth; - - if (kRemoveLabels) { - for (UIView *subview in self.subviews) { - if ([subview isKindOfClass:objc_lookUpClass("YTPivotBarItemViewAccessibilityControl")]) { - pivotBarAccessibilityControlWidth = CGRectGetWidth(subview.frame); - break; - } - } - - for (UIView *subview in self.subviews) { - if ([subview isKindOfClass:objc_lookUpClass("YTQTMButton")]) { - for (UIView *buttonSubview in subview.subviews) { - if ([buttonSubview isKindOfClass:[UILabel class]]) { - [buttonSubview removeFromSuperview]; - break; - } - } - - UIImageView *imageView = nil; - for (UIView *buttonSubview in subview.subviews) { - if ([buttonSubview isKindOfClass:[UIImageView class]]) { - imageView = (UIImageView *)buttonSubview; - break; - } - } - - if (imageView) { - CGFloat imageViewHeight = imageView.image.size.height; - CGFloat imageViewWidth = imageView.image.size.width; - CGRect buttonFrame = subview.frame; - - if (@available(iOS 13.0, *)) { - UIWindowScene *mainWindowScene = (UIWindowScene *)[[[UIApplication sharedApplication] connectedScenes] anyObject]; - if (mainWindowScene) { - UIEdgeInsets safeAreaInsets = mainWindowScene.windows.firstObject.safeAreaInsets; - if (safeAreaInsets.bottom > 0) { - hasHomeBar = YES; - } - } - } - - CGFloat yOffset = hasHomeBar ? 15.0 : 0.0; - CGFloat xOffset = (pivotBarAccessibilityControlWidth - imageViewWidth) / 2.0; - - buttonFrame.origin.y = (pivotBarViewHeight - imageViewHeight - yOffset) / 2.0; - buttonFrame.origin.x = xOffset; - - buttonFrame.size.height = imageViewHeight; - buttonFrame.size.width = imageViewWidth; - - subview.frame = buttonFrame; - subview.bounds = CGRectMake(0, 0, imageViewWidth, imageViewHeight); - } - } - } - } -} -%end - -// Startup Tab -BOOL isTabSelected = NO; -%hook YTPivotBarViewController -- (void)viewDidAppear:(BOOL)animated { - %orig(); - - if (!isTabSelected) { - NSString *pivotIdentifier; - switch (kPivotIndex) { - case 0: - pivotIdentifier = @"FEwhat_to_watch"; - break; - case 1: - pivotIdentifier = @"FEshorts"; - break; - case 2: - pivotIdentifier = @"FEsubscriptions"; - break; - case 3: - pivotIdentifier = @"FElibrary"; - break; - default: - return; - } - [self selectItemWithPivotIdentifier:pivotIdentifier]; - isTabSelected = YES; - } -} -%end - -static void reloadPrefs() { - NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"YTLite.plist"]; - NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:path]; - - kNoAds = (prefs[@"noAds"] != nil) ? [prefs[@"noAds"] boolValue] : YES; - kBackgroundPlayback = (prefs[@"backgroundPlayback"] != nil) ? [prefs[@"backgroundPlayback"] boolValue] : YES; - kNoCast = [prefs[@"noCast"] boolValue] ?: NO; - kNoNotifsButton = [prefs[@"removeNotifsButton"] boolValue] ?: NO; - kNoSearchButton = [prefs[@"removeSearchButton"] boolValue] ?: NO; - kNoVoiceSearchButton = [prefs[@"removeVoiceSearchButton"] boolValue] ?: NO; - kStickyNavbar = [prefs[@"stickyNavbar"] boolValue] ?: NO; - kNoSubbar = [prefs[@"noSubbar"] boolValue] ?: NO; - kNoYTLogo = [prefs[@"noYTLogo"] boolValue] ?: NO; - kHideAutoplay = [prefs[@"hideAutoplay"] boolValue] ?: NO; - kHideSubs = [prefs[@"hideSubs"] boolValue] ?: NO; - kNoHUDMsgs = [prefs[@"noHUDMsgs"] boolValue] ?: NO; - kHidePrevNext = [prefs[@"hidePrevNext"] boolValue] ?: NO; - kReplacePrevNext = [prefs[@"replacePrevNext"] boolValue] ?: NO; - kNoDarkBg = [prefs[@"noDarkBg"] boolValue] ?: NO; - kEndScreenCards = [prefs[@"endScreenCards"] boolValue] ?: NO; - kNoFullscreenActions = [prefs[@"noFullscreenActions"] boolValue] ?: NO; - kNoRelatedVids = [prefs[@"noRelatedVids"] boolValue] ?: NO; - kNoPromotionCards = [prefs[@"noPromotionCards"] boolValue] ?: NO; - kNoWatermarks = [prefs[@"noWatermarks"] boolValue] ?: NO; - kMiniplayer = [prefs[@"miniplayer"] boolValue] ?: NO; - kDisableAutoplay = [prefs[@"disableAutoplay"] boolValue] ?: NO; - kNoContentWarning = [prefs[@"noContentWarning"] boolValue] ?: NO; - kClassicQuality = [prefs[@"classicQuality"] boolValue] ?: NO; - kDontSnapToChapter = [prefs[@"dontSnapToChapter"] boolValue] ?: NO; - kRedProgressBar = [prefs[@"redProgressBar"] boolValue] ?: NO; - kNoHints = [prefs[@"noHints"] boolValue] ?: NO; - kNoFreeZoom = [prefs[@"noFreeZoom"] boolValue] ?: NO; - kExitFullscreen = [prefs[@"exitFullscreen"] boolValue] ?: NO; - kNoDoubleTapToSeek = [prefs[@"noDoubleTapToSeek"] boolValue] ?: NO; - kHideShorts = [prefs[@"hideShorts"] boolValue] ?: NO; - kShortsProgress = [prefs[@"shortsProgress"] boolValue] ?: NO; - kResumeShorts = [prefs[@"resumeShorts"] boolValue] ?: NO; - kHideShortsLogo = [prefs[@"hideShortsLogo"] boolValue] ?: NO; - kHideShortsSearch = [prefs[@"hideShortsSearch"] boolValue] ?: NO; - kHideShortsCamera = [prefs[@"hideShortsCamera"] boolValue] ?: NO; - kHideShortsMore = [prefs[@"hideShortsMore"] boolValue] ?: NO; - kHideShortsSubscriptions = [prefs[@"hideShortsSubscriptions"] boolValue] ?: NO; - kHideShortsLike = [prefs[@"hideShortsLike"] boolValue] ?: NO; - kHideShortsDislike = [prefs[@"hideShortsDislike"] boolValue] ?: NO; - kHideShortsComments = [prefs[@"hideShortsComments"] boolValue] ?: NO; - kHideShortsRemix = [prefs[@"hideShortsRemix"] boolValue] ?: NO; - kHideShortsShare = [prefs[@"hideShortsShare"] boolValue] ?: NO; - kHideShortsAvatars = [prefs[@"hideShortsAvatars"] boolValue] ?: NO; - kHideShortsThanks = [prefs[@"hideShortsThanks"] boolValue] ?: NO; - kHideShortsChannelName = [prefs[@"hideShortsChannelName"] boolValue] ?: NO; - kHideShortsDescription = [prefs[@"hideShortsDescription"] boolValue] ?: NO; - kHideShortsAudioTrack = [prefs[@"hideShortsAudioTrack"] boolValue] ?: NO; - kRemoveLabels = [prefs[@"removeLabels"] boolValue] ?: NO; - kReExplore = [prefs[@"reExplore"] boolValue] ?: NO; - kRemoveShorts = [prefs[@"removeShorts"] boolValue] ?: NO; - kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO; - kRemoveUploads = (prefs[@"removeUploads"] != nil) ? [prefs[@"removeUploads"] boolValue] : YES; - kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO; - kRemovePlayNext = [prefs[@"removePlayNext"] boolValue] ?: NO; - kNoContinueWatching = [prefs[@"noContinueWatching"] boolValue] ?: NO; - kPivotIndex = (prefs[@"pivotIndex"] != nil) ? [prefs[@"pivotIndex"] intValue] : 0; - kAdvancedMode = [prefs[@"advancedMode"] boolValue] ?: NO; - - NSDictionary *newSettings = @{ - @"noAds" : @(kNoAds), - @"backgroundPlayback" : @(kBackgroundPlayback), - @"noCast" : @(kNoCast), - @"removeNotifsButton" : @(kNoNotifsButton), - @"removeSearchButton" : @(kNoSearchButton), - @"removeVoiceSearchButton" : @(kNoVoiceSearchButton), - @"stickyNavbar" : @(kStickyNavbar), - @"noSubbar" : @(kNoSubbar), - @"noYTLogo" : @(kNoYTLogo), - @"hideAutoplay" : @(kHideAutoplay), - @"hideSubs" : @(kHideSubs), - @"noHUDMsgs" : @(kNoHUDMsgs), - @"hidePrevNext" : @(kHidePrevNext), - @"replacePrevNext" : @(kReplacePrevNext), - @"noDarkBg" : @(kNoDarkBg), - @"endScreenCards" : @(kEndScreenCards), - @"noFullscreenActions" : @(kNoFullscreenActions), - @"noRelatedVids" : @(kNoRelatedVids), - @"noPromotionCards" : @(kNoPromotionCards), - @"noWatermarks" : @(kNoWatermarks), - @"miniplayer" : @(kMiniplayer), - @"disableAutoplay" : @(kDisableAutoplay), - @"noContentWarning" : @(kNoContentWarning), - @"classicQuality" : @(kClassicQuality), - @"dontSnapToChapter" : @(kDontSnapToChapter), - @"redProgressBar" : @(kRedProgressBar), - @"noHints" : @(kNoHints), - @"noFreeZoom" : @(kNoFreeZoom), - @"exitFullscreen" : @(kExitFullscreen), - @"noDoubleTapToSeek" : @(kNoDoubleTapToSeek), - @"hideShorts" : @(kHideShorts), - @"shortsProgress" : @(kShortsProgress), - @"resumeShorts" : @(kResumeShorts), - @"hideShortsLogo" : @(kHideShortsLogo), - @"hideShortsSearch" : @(kHideShortsSearch), - @"hideShortsCamera" : @(kHideShortsCamera), - @"hideShortsMore" : @(kHideShortsMore), - @"hideShortsSubscriptions" : @(kHideShortsSubscriptions), - @"hideShortsLike" : @(kHideShortsLike), - @"hideShortsDislike" : @(kHideShortsDislike), - @"hideShortsComments" : @(kHideShortsComments), - @"hideShortsRemix" : @(kHideShortsRemix), - @"hideShortsShare" : @(kHideShortsShare), - @"hideShortsAvatars" : @(kHideShortsAvatars), - @"hideShortsThanks" : @(kHideShortsThanks), - @"hideShortsChannelName" : @(kHideShortsChannelName), - @"hideShortsDescription" : @(kHideShortsDescription), - @"hideShortsAudioTrack" : @(kHideShortsAudioTrack), - @"removeLabels" : @(kRemoveLabels), - @"reExplore" : @(kReExplore), - @"removeShorts" : @(kRemoveShorts), - @"removeSubscriptions" : @(kRemoveSubscriptions), - @"removeUploads" : @(kRemoveUploads), - @"removeLibrary" : @(kRemoveLibrary), - @"removePlayNext" : @(kRemovePlayNext), - @"noContinueWatching" : @(kNoContinueWatching), - @"pivotIndex" : @(kPivotIndex), - @"advancedMode" : @(kAdvancedMode) - }; - - if (![newSettings isEqualToDictionary:prefs]) [newSettings writeToFile:path atomically:NO]; -} - -static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { - reloadPrefs(); -} - -%ctor { - CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.dvntm.ytlite.prefschanged"), NULL, CFNotificationSuspensionBehaviorCoalesce); - reloadPrefs(); -} diff --git a/Tweaks/YTLite/control b/Tweaks/YTLite/control deleted file mode 100644 index bcca9d9..0000000 --- a/Tweaks/YTLite/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: com.dvntm.ytlite -Name: YTLite -Depends: mobilesubstrate -Version: 0.0.1 -Architecture: iphoneos-arm -Description: Lightweight YouTube Enhancer -Maintainer: dvntm -Author: dvntm -Section: Tweaks diff --git a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/Info.plist b/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/Info.plist deleted file mode 100644 index fa80b7d..0000000 --- a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleShortVersionString - 1.0.0 - CFBundleIdentifier - com.dvntm.ytlite - CFBundleSignature - ???? - CFBundleInfoDictionaryVersion - 6.0 - CFBundleDevelopmentRegion - English - CFBundleExecutable - YTLite - CFBundlePackageType - BNDL - CFBundleVersion - 1.0 - NSPrincipalClass - YTLite - - diff --git a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings b/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings deleted file mode 100644 index bb77d1a..0000000 --- a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,144 +0,0 @@ -"General" = "General"; -"RemoveAds" = "Remove ads"; -"RemoveAdsDesc" = "Removes in-app ads."; -"BackgroundPlayback" = "Background playback"; -"BackgroundPlaybackDesc" = "Enables background playback."; - -"Navbar" = "Navigation bar"; -"RemoveCast" = "Hide Cast button"; -"RemoveCastDesc" = "Hides Cast button from the Navigation bar."; -"RemoveNotifications" = "Hide Notifications button"; -"RemoveNotificationsDesc" = "Hides Notifications button from the Navigation bar."; -"RemoveSearch" = "Hide Search button"; -"RemoveSearchDesc" = "Hides Search button from the Navigation bar."; -"RemoveVoiceSearch" = "Hide Voice search button"; -"RemoveVoiceSearchDesc" = "Hides Voice search button from the Navigation bar."; -"StickyNavbar" = "Sticky Navigation bar"; -"StickyNavbarDesc" = "Pins the Navigation bar so that it remains visible when scrolling down."; -"NoSubbar" = "Hide Subbar"; -"NoSubbarDesc" = "Hides Subbar (All, New to you, Live etc.) under the Navigation bar."; -"NoYTLogo" = "Remove YouTube logo"; -"NoYTLogoDesc" = "Removes YouTube logo in the Navigation bar."; - -"Overlay" = "Overlay"; -"HideAutoplay" = "Hide Autoplay switch"; -"HideAutoplayDesc" = "Hides Autoplay switch from the overlay."; -"HideSubs" = "Hide Subtitles button"; -"HideSubsDesc" = "Hides Subtitles button from the overlay."; -"NoHUDMsgs" = "Hide HUD Messages"; -"NoHUDMsgsDesc" = "Hides all feature messages from the player. Example: CC is turned on/off, Video loop is on, etc."; -"HidePrevNext" = "Hide Previous and Next buttons"; -"HidePrevNextDesc" = "Hides Previous and Next video buttons from overlay."; -"ReplacePrevNext" = "Fast forward and Rewind buttons"; -"ReplacePrevNextDesc" = "Replaces Previous and Next video buttons to Fast forward and Rewind buttons in overlay."; -"NoDarkBg" = "Remove dark background"; -"NoDarkBgDesc" = "Removes overlay dark background."; -"NoEndScreenCards" = "Hide End screens hover cards"; -"NoEndScreenCardsDesc" = "Hides End screens (thumbnails) at the end of videos."; -"NoFullscreenActions" = "Disable fullscreen actions"; -"NoFullscreenActionsDesc" = "Disables actions panel in fullscreen mode."; -"NoRelatedVids" = "No related videos in overlay"; -"NoRelatedVidsDesc" = "Removes related videos displayed in the overlay by swiping up."; -"NoPromotionCards" = "Hide Paid Promotion cards"; -"NoPromotionCardsDesc" = "Hides \"Includes Paid Promotions\" card in promotions included videos."; -"NoWatermarks" = "Hide Watermarks"; -"NoWatermarksDesc" = "Hides channel watermarks from the player."; - -"Player" = "Player"; -"Miniplayer" = "Enable mini player"; -"MiniplayerDesc" = "Enables the mini player for videos that were not originally designed for it, such as videos targeted for children."; -"DisableAutoplay" = "Disable Autoplay videos"; -"DisableAutoplayDesc" = "Prevents video playback after opening."; -"NoContentWarning" = "Skip content warning"; -"NoContentWarningDesc" = "Skips sensitive content warning message."; -"ClassicQuality" = "Classic video quality"; -"ClassicQualityDesc" = "Brings back classic video quality selection menu."; -"DontSnap2Chapter" = "Disable snap to chapter"; -"DontSnap2ChapterDesc" = "Disables skipping to the next episode by double-tap gesture."; -"RedProgressBar" = "Red progress bar"; -"RedProgressBarDesc" = "Brings back red progress bar."; -"NoHints" = "Disable hints"; -"NoHintsDesc" = "Disables hints by author which appears at the top-right corner during playback."; -"NoFreeZoom" = "Disable free zoom gesture"; -"NoFreeZoomDesc" = "Disables new free zoom gestures."; -"ExitFullscreen" = "Exit fullscreen mode on finish"; -"ExitFullscreenDesc" = "Exits fullscreen mode at the end of video playback."; -"NoDoubleTap2Seek" = "Disable double tap to seek"; -"NoDoubleTap2SeekDesc" = "Disables double tap to seek gesture."; - -"Tabbar" = "Tab bar"; -"RemoveLabels" = "Remove labels"; -"RemoveLabelsDesc" = "Removes tab labels."; -"ReExplore" = "Replace Shorts tab with Explore tab"; -"ReExploreDesc" = "Shows Explore tab instead of Shorts tab as on old YouTube versions."; -"HideShortsTab" = "Hide Shorts tab"; -"HideShortsTabDesc" = "Hides Shorts tab from the Tab bar"; -"HideSubscriptionsTab" = "Hide Subscriptions tab"; -"HideSubscriptionsTabDesc" = "Hides Subscriptions tab from the Tab bar"; -"HideUploadButton" = "Hide Upload button"; -"HideUploadButtonDesc" = "Hides Upload button from the Tab bar"; -"HideLibraryTab" = "Hide Library tab"; -"HideLibraryTabDesc" = "Hides Library tab from the Tab bar"; - -"Shorts" = "Shorts"; -"HideShorts" = "Hide Shorts videos"; -"HideShortsDesc" = "Hides Shorts videos from Homepage, Recommended etc. (Not applied to Watch history)"; -"ShortsProgress" = "Enable progress bar"; -"ShortsProgressDesc" = "Displays progress bar in the Shorts overlay."; -"ResumeShorts" = "Don't start from Shorts tab"; -"ResumeShortsDesc" = "Prevents starting from Shorts videos at the opening app, which happens if YouTube was closed while watching Shorts."; -"HideShortsLogo" = "Hide Shorts logo"; -"HideShortsLogoDesc" = "Hides Shorts logo in the top left corner."; -"HideShortsSearch" = "Hide Search button"; -"HideShortsSearchDesc" = "Hides Search button from the Shorts overlay."; -"HideShortsCamera" = "Hide Camera button"; -"HideShortsCameraDesc" = "Hides Camera button from the Shorts overlay."; -"HideShortsMore" = "Hide More (⋮) button"; -"HideShortsMoreDesc" = "Hides More (⋮) button from the Shorts overlay. It's also accessible by long-pressing the screen."; -"HideShortsSubscriptions" = "Hide Subscriptions button"; -"HideShortsSubscriptionsDesc" = "Hides Subscriptions button which appears when Shorts paused."; -"HideShortsLike" = "Hide Like button"; -"HideShortsLikeDesc" = "Hides Like button from the Shorts overlay."; -"HideShortsDislike" = "Hide Dislike button"; -"HideShortsDislikeDesc" = "Hides Dislike button from the Shorts overlay."; -"HideShortsComments" = "Hide Comments button"; -"HideShortsCommentsDesc" = "Hides Comments button from the Shorts overlay."; -"HideShortsRemix" = "Hide Remix button"; -"HideShortsRemixDesc" = "Hides Remix button from the Shorts overlay."; -"HideShortsShare" = "Hide Share button"; -"HideShortsShareDesc" = "Hides Share button from the Shorts overlay."; -"HideShortsAvatars" = "Hide channels avatar"; -"HideShortsAvatarsDesc" = "Hides profile picture in the bottom right corner."; -"HideShortsThanks" = "Hide Superthanks button"; -"HideShortsThanksDesc" = "Hides Superthanks (Donate) button from the Shorts overlay."; -"HideShortsChannelName" = "Hide Channel name"; -"HideShortsChannelNameDesc" = "Hides Channel name and Subscribe button from the Shorts overlay."; -"HideShortsDescription" = "Hide Description"; -"HideShortsDescriptionDesc" = "Hides Shorts description under channel name."; -"HideShortsAudioTrack" = "Hide AudioTrack"; -"HideShortsAudioTrackDesc" = "Hides AudioTrack under Shorts description."; - -"Other" = "Other"; -"RemovePlayNext" = "Remove \"Play next in queue\""; -"RemovePlayNextDesc" = "Removes \"Play next in queue\" option from menu."; -"NoContinueWatching" = "Remove \"Continue watching\""; -"NoContinueWatchingDesc" = "Removes the \"Continue watching\" section containing unfinished videos from the Home page."; - -"Startup" = "Startup page"; -"Home" = "Home"; -"Explore" = "Explore"; -"ShortsTab" = "Shorts"; -"Subscriptions" = "Subscriptions"; -"Library" = "Library"; -"Warning" = "Warning"; -"TabIsHidden" = "Hidden tab cannot be selected as startup page"; - -"Version" = "Version"; -"About" = "About"; -"Credits" = "Credits"; -"Developer" = "YTLite developer"; -"Advanced" = "Advanced mode"; -"ResetSettings" = "Reset YTLite settings"; -"ResetMessage" = "This option will reset YTLite settings to default and close YouTube.\n\nAre you sure you want to continue?"; -"Yes" = "Yes"; -"No" = "No"; \ No newline at end of file diff --git a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings b/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index 7a8c1e0..0000000 --- a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,144 +0,0 @@ -"General" = "Основные"; -"RemoveAds" = "Убрать рекламу"; -"RemoveAdsDesc" = "Убирает рекламу в приложении."; -"BackgroundPlayback" = "Фоновое воспроизведение"; -"BackgroundPlaybackDesc" = "Активирует фоновое воспроизведение."; - -"Navbar" = "Панель навигации"; -"RemoveCast" = "Скрыть «Трансляция»"; -"RemoveCastDesc" = "Скрывает кнопку трансляции с панели навигации."; -"RemoveNotifications" = "Скрыть «Уведомления»"; -"RemoveNotificationsDesc" = "Скрывает кнопку уведомлений с панели навигации."; -"RemoveSearch" = "Скрыть «Поиск»"; -"RemoveSearchDesc" = "Скрывает кнопку поиска с панели навигации."; -"RemoveVoiceSearch" = "Скрыть «Голосовой поиск»"; -"RemoveVoiceSearchDesc" = "Скрывает кнопку голосового поиска с панели навигации."; -"StickyNavbar" = "Закрепить панель навигации"; -"StickyNavbarDesc" = "Закрепляет панель навигации в верхней части экрана, запрещая ему скрываться во время скролла страницы вниз."; -"NoSubbar" = "Скрыть наклейки"; -"NoSubbarDesc" = "Скрывает панель с наклейками (Все, Новое для вас, Сейчас в эфире и т.д.) под панелью навигации."; -"NoYTLogo" = "Скрыть логотип YouTube"; -"NoYTLogoDesc" = "Убирает логотип YouTube с панели навигации."; - -"Overlay" = "Настройки оверлея"; -"HideAutoplay" = "Скрыть «Автовоспроизведение»"; -"HideAutoplayDesc" = "Скрывает тумблер «Автовоспроизведение» с оверлея плеера."; -"HideSubs" = "Скрыть «Субтитры»"; -"HideSubsDesc" = "Скрывает кнопку субтитров с оверлея плеера."; -"NoHUDMsgs" = "Скрыть сообщения плеера"; -"NoHUDMsgsDesc" = "Скрывает надписи YouTube, появляющиеся поверх видео."; -"HidePrevNext" = "Скрыть «След.» и «Пред.»"; -"HidePrevNextDesc" = "Убирает переключатели «Следующий» и «Предыдущий» с плеера"; -"ReplacePrevNext" = "Перемотка вместо «След.» и «Пред.»"; -"ReplacePrevNextDesc" = "Заменяет переключатели «Следующий» и «Предыдущий» на перемотку на 10 сек. в окне плеера."; -"NoDarkBg" = "Не затемнять фон плеера"; -"NoDarkBgDesc" = "Убирает затемнение экрана под кнопками управления плеером."; -"NoEndScreenCards" = "Скрыть рекомендации"; -"NoEndScreenCardsDesc" = "Скрывает эскизы, отображаемые по окончанию видеоролика."; -"NoFullscreenActions" = "Отключить панель действий"; -"NoFullscreenActionsDesc" = "Отключает панель действий, отображающуюся под прогресс-баром плеера."; -"NoRelatedVids" = "Скрыть рекомендации в оверлее"; -"NoRelatedVidsDesc" = "Скрывает рекомендации, отображаемые по свайпу вверх в плеере."; -"NoPromotionCards" = "Скрыть сообщение «Есть реклама»"; -"NoPromotionCardsDesc" = "Скрывает всплывающее сообщение «Есть реклама» в роликах со спонсорской рекламой."; -"NoWatermarks" = "Скрыть водяные знаки"; -"NoWatermarksDesc" = "Скрывает значки каналов в плеере."; - -"Player" = "Настройки плеера"; -"Miniplayer" = "Разрешить миниплеер"; -"MiniplayerDesc" = "Принудительно активирует миниплеер для видео, в которых изначально не был предназначен (например, видеоролики для детей)."; -"DisableAutoplay" = "Запретить автовоспроизведение"; -"DisableAutoplayDesc" = "Принудительно запрещает автовоспроизведение видео при его открытии."; -"NoContentWarning" = "Пропускать предупреждения"; -"NoContentWarningDesc" = "Пропускает предупреждения, всплывающие перед воспроизведением некоторого контента."; -"ClassicQuality" = "Классический выбор качества"; -"ClassicQualityDesc" = "Возвращает классическое меню выбора качества в меню плеера."; -"DontSnap2Chapter" = "Не перематывать эпизоды"; -"DontSnap2ChapterDesc" = "Отключает жест перемотки к следующему эпизоду двойным нажатием."; -"RedProgressBar" = "Красный прогресс-бар"; -"RedProgressBarDesc" = "Возвращает красный прогресс-бар вместо нового, серого цвета."; -"NoHints" = "Отключить подсказки"; -"NoHintsDesc" = "Скрывает подсказки от авторов видео, появляющиеся в правом верхнем углу."; -"NoFreeZoom" = "Отключить жесты для зума"; -"NoFreeZoomDesc" = "Отключает жесты приближения для нового зума."; -"ExitFullscreen" = "Автовыход из полноэкранного режима"; -"ExitFullscreenDesc" = "Выходит из полноэкранного режима по окончанию воспроизведения."; -"NoDoubleTap2Seek" = "Отключить перемотку двойным тапом"; -"NoDoubleTap2SeekDesc" = "Отключает перемотку двойным тапом в плеере."; - -"Tabbar" = "Панель вкладок"; -"RemoveLabels" = "Скрыть названия"; -"RemoveLabelsDesc" = "Скрывает названия вкладок."; -"ReExplore" = "Вкладка «Навигация» вместо «Shorts»"; -"ReExploreDesc" = "Заменяет вкладку «Shorts» на привычную нам «Навигацию»."; -"HideShortsTab" = "Скрыть «Shorts»"; -"HideShortsTabDesc" = "Скрывает вкладку «Shorts» с панели вкладок."; -"HideSubscriptionsTab" = "Скрыть «Подписки»"; -"HideSubscriptionsTabDesc" = "Скрывает вкладку «Подписки» с панели вкладок."; -"HideUploadButton" = "Скрыть «Создать» (+)"; -"HideUploadButtonDesc" = "Скрывает кнопку «Создать» с панели вкладок."; -"HideLibraryTab" = "Скрыть «Библиотеку»"; -"HideLibraryTabDesc" = "Скрывает вкладку «Библиотека» с панели вкладок."; - -"Shorts" = "Настройки Shorts"; -"HideShorts" = "Скрыть видеоролики Shorts"; -"HideShortsDesc" = "Скрывает видеоролики, помеченные как Shorts с Главного экрана, Рекомендаций и т.д. (Не применяется к истории просмотров)"; -"ShortsProgress" = "Показывать прогресс-бар"; -"ShortsProgressDesc" = "Отображает прогресс-бар в плеере Shorts."; -"ResumeShorts" = "Всегда запускать с Главной страницы"; -"ResumeShortsDesc" = "Предотвращает запуск видеороликов Shorts при открытии YouTube. Это происходит, если закрыть YouTube при просмотре Shorts."; -"HideShortsLogo" = "Скрыть логотип Shorts"; -"HideShortsLogoDesc" = "Скрывает логотип Shorts, расположенный в верхнем левом углу."; -"HideShortsSearch" = "Скрыть кнопку «Поиск»"; -"HideShortsSearchDesc" = "Скрывает кнопку поиска с плеера Shorts."; -"HideShortsCamera" = "Скрыть кнопку «Камера»"; -"HideShortsCameraDesc" = "Скрывает кнопку камеры с плеера Shorts."; -"HideShortsMore" = "Скрыть кнопку «⋮»"; -"HideShortsMoreDesc" = "Скрывает кнопку «Еще» (⋮) с плеера Shorts. Данное меню также доступно долгим нажатием по экрану."; -"HideShortsSubscriptions" = "Скрыть «Подписки»"; -"HideShortsSubscriptionsDesc" = "Скрывает кнопку «Подписки», появляющуюся при остановке воспроизведения."; -"HideShortsLike" = "Скрыть кнопку «Лайк»"; -"HideShortsLikeDesc" = "Скрывает кнопку лайка с плеера Shorts."; -"HideShortsDislike" = "Скрыть кнопку «Дизлайк»"; -"HideShortsDislikeDesc" = "Скрывает кнопку дизлайка с плеера Shorts."; -"HideShortsComments" = "Скрыть кнопку «Комментарии»"; -"HideShortsCommentsDesc" = "Скрывает кнопку комментариев с плеера Shorts."; -"HideShortsRemix" = "Скрыть кнопку «Ремикс»"; -"HideShortsRemixDesc" = "Скрывает кнопку для создания ремикса с плеера Shorts."; -"HideShortsShare" = "Скрыть кнопку «Поделиться»"; -"HideShortsShareDesc" = "Скрывает кнопку поделиться с плеера Shorts."; -"HideShortsAvatars" = "Скрыть аватарку"; -"HideShortsAvatarsDesc" = "Скрывает аватарку пользователя в правом нижнем углу."; -"HideShortsThanks" = "Скрыть «Суперспасибо»"; -"HideShortsThanksDesc" = "Скрывает кнопку отправки доната (суперспасибо) с плеера Shorts."; -"HideShortsChannelName" = "Скрыть название канала"; -"HideShortsChannelNameDesc" = "Скрывает название канала и кнопку «Подписаться» с плеера Shorts."; -"HideShortsDescription" = "Скрыть описание ролика"; -"HideShortsDescriptionDesc" = "Скрывает описание ролика, отображающееся под названием канала."; -"HideShortsAudioTrack" = "Скрыть аудиодорожку"; -"HideShortsAudioTrackDesc" = "Скрывает информацию об аудиодорожке в нижней части плеера."; - -"Other" = "Другие настройки"; -"RemovePlayNext" = "Убрать «Добавить в начало очереди»"; -"RemovePlayNextDesc" = "Убирает опцию «Добавить в начало очереди» из меню видео."; -"NoContinueWatching" = "Отключить «Продолжить просмотр»"; -"NoContinueWatchingDesc" = "Удаляет блок «Продолжить просмотр» содержащий недосмотренные видео с Главной страницы."; - -"Startup" = "Начальная страница"; -"Home" = "Главная"; -"Explore" = "Навигация"; -"ShortsTab" = "Shorts"; -"Subscriptions" = "Подписки"; -"Library" = "Библиотека"; -"Warning" = "Внимание"; -"TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы"; - -"Version" = "Версия"; -"About" = "О твике"; -"Credits" = "Авторы"; -"Developer" = "Разработчик твика"; -"Advanced" = "Расширенный режим"; -"ResetSettings" = "Сбросить настройки твика"; -"ResetMessage" = "Данное действие сбросит настройки YTLite к значениям по умолчанию и закроет YouTube.\n\nУверены, что хотите продолжить?"; -"Yes" = "Да"; -"No" = "Нет"; diff --git a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings b/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings deleted file mode 100644 index 18800f3..0000000 --- a/Tweaks/YTLite/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings +++ /dev/null @@ -1,136 +0,0 @@ -"General" = "常规"; -"RemoveAds" = "移除广告"; -"RemoveAdsDesc" = "删除程序内的广告。"; -"BackgroundPlayback" = "后台播放"; -"BackgroundPlaybackDesc" = "启用后台播放。"; - -"Navbar" = "导航栏"; -"RemoveCast" = "隐藏投射按钮"; -"RemoveCastDesc" = "从导航栏中隐藏投射按钮。"; -"RemoveNotifications" = "隐藏通知按钮"; -"RemoveNotificationsDesc" = "从导航栏中隐藏通知按钮。"; -"RemoveSearch" = "隐藏搜索按钮"; -"RemoveSearchDesc" = "从导航栏中隐藏搜索按钮。"; -"StickyNavbar" = "固定导航栏"; -"StickyNavbarDesc" = "固定导航栏,使其在向下滚动时保持可见。"; -"NoSubbar" = "隐藏子栏"; -"NoSubbarDesc" = "隐藏导航栏下的子栏(全部、新内容、实时等)。"; -"NoYTLogo" = "删除 YouTube Logo"; -"NoYTLogoDesc" = "删除导航栏中的 YouTube Logo。"; - -"Overlay" = "播放界面"; -"HideAutoplay" = "隐藏自动播放开关"; -"HideAutoplayDesc" = "从播放界面隐藏自动播放开关。"; -"HideSubs" = "隐藏字幕按钮"; -"HideSubsDesc" = "从播放界面隐藏字幕按钮。"; -"NoHUDMsgs" = "隐藏屏显信息"; -"NoHUDMsgsDesc" = "隐藏播放界面的所有功能信息。示例:CC按钮打开/关闭、视频循环等。"; -"HidePrevNext" = "隐藏上一个和下一个按钮"; -"HidePrevNextDesc" = "从播放界面中隐藏上一个和下一个视频按钮。"; -"ReplacePrevNext" = "快进和快退按钮"; -"ReplacePrevNextDesc" = "将上一个和下一个视频按钮替换为快进和快退按钮。"; -"NoDarkBg" = "删除深色背景"; -"NoDarkBgDesc" = "删除播放界面的深色背景。"; -"NoEndScreenCards" = "隐藏片尾画面"; -"NoEndScreenCardsDesc" = "隐藏视频结尾处的片尾屏幕(缩略图)。"; -"NoFullscreenActions" = "禁用全屏操作"; -"NoFullscreenActionsDesc" = "在全屏模式下禁用操作面板。"; -"NoRelatedVids" = "没有相关视频"; -"NoRelatedVidsDesc" = "通过向上滑动删除播放界面中显示的相关视频。"; -"NoPromotionCards" = "隐藏付费"; -"NoPromotionCardsDesc" = "在付费视频中隐藏“付费内容”。"; -"NoWatermarks" = "隐藏水印"; -"NoWatermarksDesc" = "隐藏播放器的频道水印。"; - -"Player" = "播放器"; -"Miniplayer" = "启用迷你播放器"; -"MiniplayerDesc" = "启用迷你播放器来播放最初不是为其设计的视频,例如针对儿童的视频。"; -"DisableAutoplay" = "禁用自动播放视频"; -"DisableAutoplayDesc" = "打开后防止视频自动播放。"; -"NoContentWarning" = "跳过内容警告"; -"NoContentWarningDesc" = "跳过敏感内容警告消息。"; -"ClassicQuality" = "经典视频质量"; -"ClassicQualityDesc" = "加回经典的视频质量选择菜单。"; -"DontSnap2Chapter" = "禁用双击跳转"; -"DontSnap2ChapterDesc" = "禁用通过双击手势跳到下一集。"; -"RedProgressBar" = "红色进度条"; -"RedProgressBarDesc" = "加回红色进度条。"; -"NoHints" = "禁用提示"; -"NoHintsDesc" = "禁用播放期间出现在右上角的作者提示。"; -"NoFreeZoom" = "禁用自由缩放手势"; -"NoFreeZoomDesc" = "禁用新的自由缩放手势。"; -"ExitFullscreen" = "完成后退出全屏模式"; -"ExitFullscreenDesc" = "在视频播放结束时退出全屏模式。"; -"NoDoubleTap2Seek" = "禁用双击搜索"; -"NoDoubleTap2SeekDesc" = "禁用双击搜索手势。"; - -"Tabbar" = "选项卡栏"; -"RemoveLabels" = "移除标签"; -"RemoveLabelsDesc" = "删除选项卡标签。"; -"ReExplore" = "将短视频选项卡替换为“探索”选项卡"; -"ReExploreDesc" = "显示“探索”选项卡,而不是旧版 本中的“短视频”选项卡。"; -"HideShortsTab" = "隐藏短视频"; -"HideShortsTabDesc" = "从选项卡栏中隐藏短视频。"; -"HideSubscriptionsTab" = "隐藏订阅内容"; -"HideSubscriptionsTabDesc" = "从选项卡栏中隐藏订阅内容。"; -"HideUploadButton" = "隐藏上传按钮"; -"HideUploadButtonDesc" = "从选项卡栏中隐藏上传按钮。"; -"HideLibraryTab" = "隐藏媒体库"; -"HideLibraryTabDesc" = "从选项卡栏中隐藏媒体库。"; - -"Shorts" = "短视频"; -"HideShorts" = "隐藏短视频"; -"HideShortsDesc" = "从首页、推荐等隐藏短视频(不适用于观看历史记录)。"; -"ShortsProgress" = "启用进度条"; -"ShortsProgressDesc" = "在短视频播放器中显示进度条。"; -"ResumeShorts" = "不要从短视频开始"; -"ResumeShortsDesc" = "防止在打开应用程序时首先启动短视频,如果在观看短视频时关闭,就会发生这种情况。"; -"HideShortsLogo" = "隐藏短视频Logo"; -"HideShortsLogoDesc" = "隐藏左上角的短视频Logo。"; -"HideShortsSearch" = "隐藏搜索按钮"; -"HideShortsSearchDesc" = "从短视频播放器中隐藏搜索按钮。"; -"HideShortsCamera" = "隐藏相机按钮"; -"HideShortsCameraDesc" = "从短视频播放器中隐藏相机按钮。"; -"HideShortsMore" = "隐藏更多 (⋮) 按钮"; -"HideShortsMoreDesc" = "从短视频播放器中隐藏更多 (⋮) 按钮 。也可以通过长按屏幕来访问它。"; -"HideShortsSubscriptions" = "隐藏订阅按钮"; -"HideShortsSubscriptionsDesc" = "隐藏短视频暂停时显示的订阅按钮。"; -"HideShortsLike" = "隐藏喜欢按钮"; -"HideShortsLikeDesc" = "从短视频播放器中隐藏喜欢按钮。"; -"HideShortsDislike" = "隐藏不喜欢按钮"; -"HideShortsDislikeDesc" = "从短视频播放器中隐藏不喜欢按钮。"; -"HideShortsComments" = "隐藏评论按钮"; -"HideShortsCommentsDesc" = "从短视频播放器中隐藏评论按钮。"; -"HideShortsRemix" = "隐藏混剪按钮"; -"HideShortsRemixDesc" = "从短视频播放器中隐藏混剪按钮。"; -"HideShortsShare" = "隐藏分享按钮"; -"HideShortsShareDesc" = "从短视频播放器中隐藏分享按钮。"; -"HideShortsAvatars" = "隐藏发布者头像"; -"HideShortsAvatarsDesc" = "隐藏右下角的发布者个人资料头像。"; -"HideShortsThanks" = "隐藏捐赠按钮"; -"HideShortsThanksDesc" = "从短视频播放器中隐藏捐赠按钮。"; -"HideShortsChannelName" = "隐藏发布者名称"; -"HideShortsChannelNameDesc" = "从短视频播放器中隐藏发布者名称和订阅按钮。"; -"HideShortsDescription" = "隐藏说明"; -"HideShortsDescriptionDesc" = "在频道名称下隐藏短视频描述。"; -"HideShortsAudioTrack" = "隐藏音频音轨"; -"HideShortsAudioTrackDesc" = "从短视频描述下隐藏音频音轨。"; - -"Startup" = "启动页"; -"Home" = "首页"; -"Explore" = "探索"; -"ShortsTab" = "短视频"; -"Subscriptions" = "订阅"; -"Library" = "媒体库"; -"Warning" = "警告"; -"TabIsHidden" = "无法选择隐藏选项卡作为启动页。"; - -"Version" = "版本"; -"About" = "关于"; -"Credits" = "信息"; -"Developer" = "YTLite开发者"; -"Advanced" = "高级模式"; -"ResetSettings" = "重置YTLite设置"; -"ResetMessage" = "此选项会将YTLite设置重置为默认值并关闭YouTube。\n\n确定要继续吗?"; -"Yes" = "是"; -"No" = "不"; diff --git a/Tweaks/YTUHD b/Tweaks/YTUHD new file mode 160000 index 0000000..ed71ce0 --- /dev/null +++ b/Tweaks/YTUHD @@ -0,0 +1 @@ +Subproject commit ed71ce0dbbcb2246defdd2198014846572baea35 diff --git a/Tweaks/YTUHD/.gitignore b/Tweaks/YTUHD/.gitignore deleted file mode 100644 index 9c04476..0000000 --- a/Tweaks/YTUHD/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos -.DS_Store -packages diff --git a/Tweaks/YTUHD/Common.x b/Tweaks/YTUHD/Common.x deleted file mode 100644 index a11eb62..0000000 --- a/Tweaks/YTUHD/Common.x +++ /dev/null @@ -1,74 +0,0 @@ -#import "Header.h" -#import -#import -#import - -extern BOOL UseVP9(); - -%hook YTSettings - -- (BOOL)isWebMEnabled { - return YES; -} - -%end - -%group Spoofing - -%hook UIDevice - -- (NSString *)systemVersion { - return @"15.7.6"; -} - -%end - -%hook NSProcessInfo - -- (NSOperatingSystemVersion)operatingSystemVersion { - NSOperatingSystemVersion version; - version.majorVersion = 15; - version.minorVersion = 7; - version.patchVersion = 6; - return version; -} - -%end - -%hookf(int, sysctlbyname, const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - if (strcmp(name, "kern.osversion") == 0) { - if (oldp) - strcpy((char *)oldp, IOS_BUILD); - *oldlenp = strlen(IOS_BUILD); - } - return %orig(name, oldp, oldlenp, newp, newlen); -} - -%end - -// #ifdef SIDELOADED - -// #import "../PSHeader/Misc.h" - -// typedef struct OpaqueVTVideoDecoder VTVideoDecoderRef; -// extern OSStatus VTSelectAndCreateVideoDecoderInstance(CMVideoCodecType codecType, CFAllocatorRef allocator, CFDictionaryRef videoDecoderSpecification, VTVideoDecoderRef *decoderInstanceOut); - -// #endif - -%ctor { - if (UseVP9()) { - %init; -// #ifdef SIDELOADED -// CFMutableDictionaryRef payload = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); -// if (payload) { -// CFDictionarySetValue(payload, CFSTR("RequireHardwareAcceleratedVideoDecoder"), kCFBooleanTrue); -// CFDictionarySetValue(payload, CFSTR("AllowAlternateDecoderSelection"), kCFBooleanTrue); -// VTSelectAndCreateVideoDecoderInstance(kCMVideoCodecType_VP9, kCFAllocatorDefault, payload, NULL); -// CFRelease(payload); -// } -// #endif - if (!IS_IOS_OR_NEWER(iOS_15_0)) { - %init(Spoofing); - } - } -} diff --git a/Tweaks/YTUHD/Header.h b/Tweaks/YTUHD/Header.h deleted file mode 100644 index 41ef171..0000000 --- a/Tweaks/YTUHD/Header.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef YTUHD_H_ -#define YTUHD_H_ - -#import "../YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h" -#import "../YouTubeHeader/YTIHamplayerConfig.h" -#import "../YouTubeHeader/MLABRPolicyNew.h" -#import "../YouTubeHeader/MLABRPolicyOld.h" -#import "../YouTubeHeader/MLVideo.h" -#import "../YouTubeHeader/MLHAMPlayerItem.h" - -#define IOS_BUILD "19H349" -#define MAX_FPS 60 -#define MAX_HEIGHT 2160 // 4k -#define MAX_PIXELS 8294400 // 3840 x 2160 (4k) - -#define UseVP9Key @"EnableVP9" - -#endif \ No newline at end of file diff --git a/Tweaks/YTUHD/LICENSE b/Tweaks/YTUHD/LICENSE deleted file mode 100644 index b3819a1..0000000 --- a/Tweaks/YTUHD/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 - 2023 PoomSmart - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Tweaks/YTUHD/Makefile b/Tweaks/YTUHD/Makefile deleted file mode 100644 index 480145e..0000000 --- a/Tweaks/YTUHD/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -TARGET := iphone:clang:latest:11.0 -ARCHS = arm64 -INSTALL_TARGET_PROCESSES = YouTube - -EXTRA_CFLAGS = -ifeq ($(SIDELOADED),1) -EXTRA_CFLAGS += -DSIDELOADED -endif - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YTUHD -$(TWEAK_NAME)_FILES = Common.x Tweak.x Settings.x -$(TWEAK_NAME)_CFLAGS = -fobjc-arc $(EXTRA_CFLAGS) -$(TWEAK_NAME)_FRAMEWORKS = VideoToolbox - -# SUBPROJECTS = YTUHD-AVD - -include $(THEOS_MAKE_PATH)/tweak.mk -# include $(THEOS_MAKE_PATH)/aggregate.mk diff --git a/Tweaks/YTUHD/README.md b/Tweaks/YTUHD/README.md deleted file mode 100644 index 1a41ed0..0000000 --- a/Tweaks/YTUHD/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# YTUHD - -Unlock 1440p (2K) and 2160p (4K) resolutions in iOS YouTube app. - -## Backstory - -For a few years, YouTube has been testing 2K/4K resolutions on iOS as A/B (Alpha/Beta testing). The first group of users will see 2K/4K options while the other won't. -There are certain prerequisites for those options to show; (1) Whether a device support VP9 video decoding (which implies on Apple's end to be at least on iOS 14) and -(2) Whether YouTube decides on their end to include those options for that particular device. -YTUHD attemps to bypass those restrictions for all 64-bit devices running iOS 11 or higher, as the performance points of those devices are at most reasonable to be able to keep up with 2K/4K, at least, optimistically. - -## VP9 - -Hardware accelerated VP9 decoder is technically added as of iOS 14 and YouTube has been utilizing it through a private entitlement `com.apple.coremedia.allow-alternate-video-decoder-selection` (All apps are equal is a lie). -This decoder handles the resolutions up to 4K, although not all devices that can run iOS 14 get this decoder. iPhone SE (1st gen) is one example that hardware VP9 decoder is entirely absent from the firmware. - -Also, for those old devices they don't get `AppleAVD` driver which is essential for VP9 decoding to work. Such attempt to load VP9 decoder (inside `AppleAVD` driver) from `/System/Library/VideoDecoders/AVD.videodecoder` (provided that you can extract that from dyld_shared_cache of a new device) will result in `AVDRegister - AppleAVDCheckPlatform() returned FALSE`. - -## Server ABR - -If you look at the source code, there is an enforcement to not use server ABR. The author has yet to figure out what ABR stands for but its purpose is to fetch the available formats (resolutions) of a video. -When the flag is set to true, it's entirely up to YouTube server to respond to YouTube app of the video formats the user can be served. -YTUHD has no control over that and has to disable it and relies on the client code that allows for 2K/4K formats. - -## iOS version - -The history has shaped YTUHD to spoof the device as iOS 14 (or higher) for those running lower. The user agent gets changed for this for YouTube server to respond with VP9 formats and all. - -## Sideloading - -It's been reported that the sideloaded version of YouTube will not get 2K/4K even with YTUHD included. This is because of a big reason: VP9. -Normally when an app is sideloaded, the private entitlements get removed (`com.apple.coremedia.allow-alternate-video-decoder-selection`, too) and the app won't be allowed to access hardware VP9 decoder. No known solution for bypassing this, unless you use [TrollStore](https://github.com/opa334/TrollStore) which allows for practically any entitlements, including the aforementioned, to be in your sideloaded app. diff --git a/Tweaks/YTUHD/Settings.x b/Tweaks/YTUHD/Settings.x deleted file mode 100644 index 1758e19..0000000 --- a/Tweaks/YTUHD/Settings.x +++ /dev/null @@ -1,64 +0,0 @@ -#import "Header.h" -#import -#import -#import "../YouTubeHeader/YTHotConfig.h" -#import "../YouTubeHeader/YTSettingsViewController.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" - -#define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] - -extern BOOL UseVP9(); - -NSBundle *YTUHDBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YTUHD" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YTUHD.bundle")]; - }); - return bundle; -} - -%hook YTSettingsSectionItemManager - -- (void)updateVideoQualitySectionWithEntry:(id)entry { - YTHotConfig *hotConfig; - @try { - hotConfig = [self valueForKey:@"_hotConfig"]; - } @catch (id ex) { - hotConfig = [self.gimme instanceForType:%c(YTHotConfig)]; - } - YTIMediaQualitySettingsHotConfig *mediaQualitySettingsHotConfig = [hotConfig hotConfigGroup].mediaHotConfig.mediaQualitySettingsHotConfig; - BOOL defaultValue = mediaQualitySettingsHotConfig.enablePersistentVideoQualitySettings; - mediaQualitySettingsHotConfig.enablePersistentVideoQualitySettings = YES; - %orig; - mediaQualitySettingsHotConfig.enablePersistentVideoQualitySettings = defaultValue; -} - -%end - -%hook YTSettingsViewController - -- (void)setSectionItems:(NSMutableArray *)sectionItems forCategory:(NSInteger)category title:(NSString *)title titleDescription:(NSString *)titleDescription headerHidden:(BOOL)headerHidden { - if (category == 14) { - NSBundle *tweakBundle = YTUHDBundle(); - BOOL hasVP9 = VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9); - YTSettingsSectionItem *vp9 = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"USE_VP9") - titleDescription:[NSString stringWithFormat:@"%@\n\n%@: %d", LOC(@"USE_VP9_DESC"), LOC(@"HW_VP9_SUPPORT"), hasVP9] - accessibilityIdentifier:nil - switchOn:UseVP9() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:UseVP9Key]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:vp9]; - } - %orig; -} - -%end \ No newline at end of file diff --git a/Tweaks/YTUHD/Tweak.x b/Tweaks/YTUHD/Tweak.x deleted file mode 100644 index fa3b9b4..0000000 --- a/Tweaks/YTUHD/Tweak.x +++ /dev/null @@ -1,71 +0,0 @@ -#import "Header.h" - -BOOL UseVP9() { - return [[NSUserDefaults standardUserDefaults] boolForKey:UseVP9Key]; -} - -// Remove any <= 1080p VP9 formats -NSArray *filteredFormats(NSArray *formats) { - NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(MLFormat *format, NSDictionary *bindings) { - return [format height] > 1080 || [[format MIMEType] videoCodec] != 'vp09'; - }]; - return [formats filteredArrayUsingPredicate:predicate]; -} - -%hook MLHAMPlayerItem - -- (void)load { - MLInnerTubePlayerConfig *config = [self config]; - YTIMediaCommonConfig *mediaCommonConfig = [config mediaCommonConfig]; - mediaCommonConfig.useServerDrivenAbr = NO; - %orig; -} - -%end - -static void hookFormats(MLABRPolicy *self) { - YTIHamplayerConfig *config = [self valueForKey:@"_hamplayerConfig"]; - config.videoAbrConfig.preferSoftwareHdrOverHardwareSdr = YES; - if ([config respondsToSelector:@selector(setDisableResolveOverlappingQualitiesByCodec:)]) - config.disableResolveOverlappingQualitiesByCodec = NO; - YTIHamplayerStreamFilter *filter = config.streamFilter; - filter.enableVideoCodecSplicing = YES; - filter.vp9.maxArea = MAX_PIXELS; - filter.vp9.maxFps = MAX_FPS; -} - -%hook MLABRPolicy - -- (void)setFormats:(NSArray *)formats { - hookFormats(self); - %orig(filteredFormats(formats)); -} - -%end - -%hook MLABRPolicyOld - -- (void)setFormats:(NSArray *)formats { - hookFormats(self); - %orig(filteredFormats(formats)); -} - -%end - -%hook YTHotConfig - -- (BOOL)iosClientGlobalConfigEnableNewMlabrpolicy { - return NO; -} - -- (BOOL)iosPlayerClientSharedConfigEnableNewMlabrpolicy { - return NO; -} - -%end - -%ctor { - if (UseVP9()) { - %init; - } -} diff --git a/Tweaks/YTUHD/YTUHD-AVD/AVD.x b/Tweaks/YTUHD/YTUHD-AVD/AVD.x deleted file mode 100644 index 3a4ac2d..0000000 --- a/Tweaks/YTUHD/YTUHD-AVD/AVD.x +++ /dev/null @@ -1,21 +0,0 @@ -#import -#import - -%hookf(kern_return_t, IOServiceGetMatchingServices, mach_port_t mainPort, CFDictionaryRef matching, io_iterator_t *existing) { - if (CFDictionaryGetValue(matching, CFSTR("AppleAVD"))) - return 0; - return %orig(mainPort, matching, existing); -} - -%hookf(BOOL, AppleAVDCheckPlatform) { - return YES; -} - -%ctor { - const char *avdPath = "/System/Library/VideoDecoders/AVD.videodecoder"; - void *avd = dlopen(avdPath, RTLD_LAZY); - MSImageRef ref = MSGetImageByName(avdPath); - void *AppleAVDCheckPlatform_p = MSFindSymbol(ref, "_AppleAVDCheckPlatform"); - HBLogDebug(@"AVD open: %d, pointer: %d", avd != NULL, AppleAVDCheckPlatform_p != NULL); - %init(AppleAVDCheckPlatform = (void *)AppleAVDCheckPlatform_p); -} diff --git a/Tweaks/YTUHD/YTUHD-AVD/Makefile b/Tweaks/YTUHD/YTUHD-AVD/Makefile deleted file mode 100644 index 09da61b..0000000 --- a/Tweaks/YTUHD/YTUHD-AVD/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -TARGET := iphone:clang:latest:14.0 -ARCHS = arm64 - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YTUHD-AVD -$(TWEAK_NAME)_FILES = AVD.x -$(TWEAK_NAME)_CFLAGS = -fobjc-arc -$(TWEAK_NAME)_FRAMEWORKS = IOKit - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/YTUHD/YTUHD-AVD/YTUHD-AVD.plist b/Tweaks/YTUHD/YTUHD-AVD/YTUHD-AVD.plist deleted file mode 100644 index 1176124..0000000 --- a/Tweaks/YTUHD/YTUHD-AVD/YTUHD-AVD.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Filter - - Bundles - - com.google.ios.youtube - - Executables - - mediaserverd - - CoreFoundationVersion - - 1751.108 - - - - \ No newline at end of file diff --git a/Tweaks/YTUHD/YTUHD.plist b/Tweaks/YTUHD/YTUHD.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/YTUHD/YTUHD.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/YTUHD/control b/Tweaks/YTUHD/control deleted file mode 100644 index f1d6ddb..0000000 --- a/Tweaks/YTUHD/control +++ /dev/null @@ -1,11 +0,0 @@ -Package: com.ps.ytuhd -Name: YTUHD -Version: 1.4.0 -Architecture: iphoneos-arm -Description: Unlock 1440p and 2160p resolutions in iOS YouTube app. -Maintainer: PoomSmart -Author: PoomSmart -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 11.0) -Depiction: https://poomsmart.github.io/repo/depictions/ytuhd.html -SileoDepiction: https://poomsmart.github.io/repo/sileodepictions/ytuhd.json diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/Info.plist b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/Info.plist deleted file mode 100644 index a110aa7..0000000 Binary files a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/Info.plist and /dev/null differ diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ar.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ar.lproj/Localizable.strings deleted file mode 100644 index 25d76cc..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ar.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "استخدام VP9"; -"USE_VP9_DESC" = "تفعيل كوديك VP9 والذي يدعم الأبعاد حتى 4K. يعمل بكفاءة أكثر في الأجهزة ذات معالح A11 فأعلى. يتطلب إعادة تشغيل التطبيق."; -"HW_VP9_SUPPORT" = "دعم العتاد لكوديك VP9 المطلوب"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/de.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/de.lproj/Localizable.strings deleted file mode 100644 index 5267650..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/de.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "VP9 verwenden"; -"USE_VP9_DESC" = "Aktiviert den VP9-Codec, welcher bis zu 4k-Auflösungen unterstützt. Funktioniert am besten bei Geräten mit Apple CPU A11 und höher. App-Neustart erforderlich!"; -"HW_VP9_SUPPORT" = "Hardware VP9 Support"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/en.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 06ef184..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Use VP9"; -"USE_VP9_DESC" = "Enable VP9 codec that supports up to 4K resolutions. Works best with devices with Apple CPU A11 and higher. App restart is required."; -"HW_VP9_SUPPORT" = "Hardware VP9 Support"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/es.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/es.lproj/Localizable.strings deleted file mode 100644 index 9e48f39..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/es.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Utilizar VP9"; -"USE_VP9_DESC" = "Activa el códec VP9 que admite resoluciones de hasta 4K. Funciona mejor con dispositivos con CPU Apple A11 y superior. Es necesario reiniciar la aplicación"; -"HW_VP9_SUPPORT" = "Soporte de hardware VP9"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/fr.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/fr.lproj/Localizable.strings deleted file mode 100644 index b79b1f9..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/fr.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Utiliser VP9"; -"USE_VP9_DESC" = "Active le codec VP9 qui prend en charge les résolutions jusqu'à 4K. Fonctionne mieux avec les appareils dotés d'un processeur Apple A11 ou supérieur. Le redémarrage de l'application est nécessaire."; -"HW_VP9_SUPPORT" = "Support matériel de VP9"; \ No newline at end of file diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/hu.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/hu.lproj/Localizable.strings deleted file mode 100644 index 3a84a8d..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/hu.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Használja a VP9-et"; -"USE_VP9_DESC" = "Engedélyezze az akár 4K felbontást támogató VP9 kodeket. A legjobban az Apple CPU A11 vagy újabb CPU-val rendelkező eszközökkel működik. Az alkalmazás újraindítása szükséges."; -"HW_VP9_SUPPORT" = "Hardveres VP9 támogatás"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/it.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/it.lproj/Localizable.strings deleted file mode 100644 index a33f76a..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/it.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Usa VP9"; -"USE_VP9_DESC" = "Attiva il codec VP9 che supporta risoluzione fino a 4K. Funziona meglio con dispositivi con CPU Apple A11 o superiore. È richiesto un riavvio dell'app."; -"HW_VP9_SUPPORT" = "Supporto Hardware VP9"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ja.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ja.lproj/Localizable.strings deleted file mode 100644 index d6d3bfb..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ja.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "VP9を使用"; -"USE_VP9_DESC" = "最大で4K解像度に対応するVP9コーデックを有効にします。Apple CPU A11以降のチップを搭載した端末で最適に動作します。アプリの再起動が必要です。"; -"HW_VP9_SUPPORT" = "ハードウェアVP9への対応"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ko.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ko.lproj/Localizable.strings deleted file mode 100644 index 5cfab5d..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ko.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "VP9 사용"; -"USE_VP9_DESC" = "VP9 코덱을 활성화하면 최대 4K 해상도를 지원합니다. Apple CPU A11 이상이 탑재된 기기에서 가장 잘 작동합니다. 앱 재시작이 필요합니다."; -"HW_VP9_SUPPORT" = "VP9 하드웨어 지원"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/nl.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/nl.lproj/Localizable.strings deleted file mode 100644 index f2242b9..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/nl.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Gebruik VP9"; -"USE_VP9_DESC" = "Schakel het VP9-codec in die tot 4K resoluties ondersteunt. Werkt het beste met apparaten met Apple CPU A11 of hoger. App herstart is vereist."; -"HW_VP9_SUPPORT" = "Hardware VP9-ondersteuning"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/pt.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/pt.lproj/Localizable.strings deleted file mode 100644 index 5993d48..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/pt.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Usar VP9"; -"USE_VP9_DESC" = "Ative o codec VP9 que suporta resoluções de até 4K. Funciona melhor com dispositivos com Apple CPU A11 e superior. A reinicialização do app é necessária."; -"HW_VP9_SUPPORT" = "Suporte de Hardware VP9"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ro.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ro.lproj/Localizable.strings deleted file mode 100644 index 1133a53..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ro.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Utilizare VP9"; -"USE_VP9_DESC" = "Activare codec VP9, care suportă rezoluții până la 4K. Funcționează ideal cu dispozitive cu procesor Apple A11 sau ulterior. Este necesară repornirea aplicației."; -"HW_VP9_SUPPORT" = "Suport VP9 Hardware"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ru.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index eec1d98..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Включить кодек VP9"; -"USE_VP9_DESC" = "Активирует кодек VP9, поддерживающий разрешения до 4K. Не рекомендуется включение на устройствах с процессором ниже A11. Потребуется перезапуск приложения."; -"HW_VP9_SUPPORT" = "Поддержка VP9 железом"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/tr.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/tr.lproj/Localizable.strings deleted file mode 100644 index 24f6480..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/tr.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "VP9'u etkinleştir"; -"USE_VP9_DESC" = "4K çözünürlüğe kadar destekleyen VP9 kodek bileşenini etkinleştirin. Apple CPU A11 ve üzeri cihazlarla en iyi şekilde çalışır. Uygulamanın yeniden başlatılması gerekir."; -"HW_VP9_SUPPORT" = "Donanımsal VP9 Desteği"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/vi.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/vi.lproj/Localizable.strings deleted file mode 100644 index defe9ac..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/vi.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "Sử dụng bộ giải mã VP9"; -"USE_VP9_DESC" = "Sử dụng bộ giải mã VP9 để có thể tải video với chất lượng 2K/4K. Hoạt động tốt nhất với chip A11 trở lên và ứng dụng được cài đặt bằng TrollStore. Cần khởi động lại ứng dụng."; -"HW_VP9_SUPPORT" = "Hỗ trợ bộ giải mã VP9"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/zh_cn.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/zh_cn.lproj/Localizable.strings deleted file mode 100644 index b0856e4..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/zh_cn.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "使用 VP9 编码"; -"USE_VP9_DESC" = "启用最高支持 4K 分辨率的 VP9 编解码器。推荐使用搭载 A11 芯片或以上的机型(如:iPhone 8/X 或以上)。更改本设置后需要重启 App。"; -"HW_VP9_SUPPORT" = "硬件 VP9 编码支持状态"; diff --git a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/zh_tw.lproj/Localizable.strings b/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/zh_tw.lproj/Localizable.strings deleted file mode 100644 index a8c6a2c..0000000 --- a/Tweaks/YTUHD/layout/Library/Application Support/YTUHD.bundle/zh_tw.lproj/Localizable.strings +++ /dev/null @@ -1,5 +0,0 @@ -// Settings - -"USE_VP9" = "使用 VP9 編碼"; -"USE_VP9_DESC" = "支援 4K 解析度的 VP9 編解碼器並且建議使用 A11 晶片(含)以上的機型。需重新啟動應用程式。"; -"HW_VP9_SUPPORT" = "硬體 VP9 編碼支援狀態"; diff --git a/Tweaks/YouMute b/Tweaks/YouMute new file mode 160000 index 0000000..2c28090 --- /dev/null +++ b/Tweaks/YouMute @@ -0,0 +1 @@ +Subproject commit 2c28090b038955f73f35437cffa908f9e53c84ca diff --git a/Tweaks/YouMute/.gitattributes b/Tweaks/YouMute/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Tweaks/YouMute/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Tweaks/YouMute/.gitignore b/Tweaks/YouMute/.gitignore deleted file mode 100644 index 94b0b64..0000000 --- a/Tweaks/YouMute/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos -.DS_Store -packages \ No newline at end of file diff --git a/Tweaks/YouMute/LICENSE b/Tweaks/YouMute/LICENSE deleted file mode 100644 index a420437..0000000 --- a/Tweaks/YouMute/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 - 2023 PoomSmart - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Tweaks/YouMute/Makefile b/Tweaks/YouMute/Makefile deleted file mode 100644 index d01245b..0000000 --- a/Tweaks/YouMute/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -TARGET := iphone:clang:latest:11.0 -PACKAGE_VERSION = 1.1.1-1 -INSTALL_TARGET_PROCESSES = YouTube -ARCHS = arm64 - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YouMute - -$(TWEAK_NAME)_FILES = Tweak.x -$(TWEAK_NAME)_CFLAGS = -fobjc-arc -$(TWEAK_NAME)_FRAMEWORKS = UIKit - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/YouMute/README.md b/Tweaks/YouMute/README.md deleted file mode 100644 index 2e943a4..0000000 --- a/Tweaks/YouMute/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# YouMute -Mute/unmute videos in YouTube directly. - -## Supported YouTube versions -Version 16.42.3 and newer. Lower are either untested or unsupported. diff --git a/Tweaks/YouMute/Tweak.x b/Tweaks/YouMute/Tweak.x deleted file mode 100644 index 3c34e81..0000000 --- a/Tweaks/YouMute/Tweak.x +++ /dev/null @@ -1,320 +0,0 @@ -#import -#import "../YouTubeHeader/YTColor.h" -#import "../YouTubeHeader/YTCommonUtils.h" -#import "../YouTubeHeader/YTInlinePlayerBarContainerView.h" -#import "../YouTubeHeader/YTMainAppControlsOverlayView.h" -#import "../YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h" -#import "../YouTubeHeader/YTSingleVideoController.h" -#import "../YouTubeHeader/YTSettingsPickerViewController.h" -#import "../YouTubeHeader/YTSettingsViewController.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../YouTubeHeader/YTQTMButton.h" -#import "../YouTubeHeader/QTMIcon.h" -#import "../YouTubeHeader/UIView+YouTube.h" - -#define EnabledKey @"YouMuteEnabled" -#define PositionKey @"YouMutePosition" - -#define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] - -static const NSInteger YouMuteSection = 521; - -@interface YTSettingsSectionItemManager (YouMute) -- (void)updateYouMuteSectionWithEntry:(id)entry; -@end - -@interface YTMainAppControlsOverlayView (YouMute) -@property (retain, nonatomic) YTQTMButton *muteButton; -- (void)didPressMute:(id)arg; -@end - -@interface YTInlinePlayerBarContainerView (YouMute) -@property (retain, nonatomic) YTQTMButton *muteButton; -- (void)didPressMute:(id)arg; -@end - -static BOOL TweakEnabled() { - return [[NSUserDefaults standardUserDefaults] boolForKey:EnabledKey]; -} - -static int MuteButtonPosition() { - return [[NSUserDefaults standardUserDefaults] integerForKey:PositionKey]; -} - -static BOOL UseTopMuteButton() { - return TweakEnabled() && MuteButtonPosition() == 0; -} - -static BOOL UseBottomMuteButton() { - return TweakEnabled() && MuteButtonPosition() == 1; -} - -static BOOL isMutedTop(YTMainAppControlsOverlayView *self) { - YTMainAppVideoPlayerOverlayViewController *c = [self valueForKey:@"_eventsDelegate"]; - YTSingleVideoController *video = [c valueForKey:@"_currentSingleVideoObservable"]; - return [video isMuted]; -} - -static BOOL isMutedBottom(YTInlinePlayerBarContainerView *self) { - YTSingleVideoController *video = [self.delegate valueForKey:@"_currentSingleVideo"]; - return [video isMuted]; -} - -static NSBundle *YTEditResourcesBundle() { - Class YTCommonUtilsClass = %c(YTCommonUtils); - return [YTCommonUtilsClass resourceBundleForModuleName:@"Edit" appBundle:[YTCommonUtilsClass bundleForClass:%c(YTEditBundleIdentifier)]]; -} - -static UIImage *muteImage(BOOL muted) { - return [%c(QTMIcon) tintImage:[UIImage imageNamed:muted ? @"ic_volume_off" : @"ic_volume_up" inBundle:YTEditResourcesBundle() compatibleWithTraitCollection:nil] color:[%c(YTColor) white1]]; -} - -static void createMuteButtonTop(YTMainAppControlsOverlayView *self) { - if (!self) return; - CGFloat padding = [[self class] topButtonAdditionalPadding]; - UIImage *image = muteImage(isMutedTop(self)); - self.muteButton = [self buttonWithImage:image accessibilityLabel:@"Mute" verticalContentPadding:padding]; - self.muteButton.hidden = YES; - self.muteButton.alpha = 0; - [self.muteButton addTarget:self action:@selector(didPressMute:) forControlEvents:UIControlEventTouchUpInside]; - @try { - [[self valueForKey:@"_topControlsAccessibilityContainerView"] addSubview:self.muteButton]; - } @catch (id ex) { - [self addSubview:self.muteButton]; - } -} - -static void createMuteButtonBottom(YTInlinePlayerBarContainerView *self) { - if (!self) return; - UIImage *image = muteImage(isMutedBottom(self)); - self.muteButton = [%c(YTQTMButton) iconButton]; - self.muteButton.hidden = YES; - self.muteButton.exclusiveTouch = YES; - self.muteButton.alpha = 0; - self.muteButton.minHitTargetSize = 60; - self.muteButton.accessibilityLabel = @"Mute"; - [self.muteButton setImage:image forState:0]; - [self.muteButton sizeToFit]; - [self.muteButton addTarget:self action:@selector(didPressMute:) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:self.muteButton]; -} - -static NSMutableArray *topControls(YTMainAppControlsOverlayView *self, NSMutableArray *controls) { - if (UseTopMuteButton()) - [controls insertObject:self.muteButton atIndex:0]; - return controls; -} - -NSBundle *YouMuteBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YouMute" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YouMute.bundle")]; - }); - return bundle; -} - -%group Top - -%hook YTMainAppVideoPlayerOverlayViewController - -- (void)updateTopRightButtonAvailability { - %orig; - YTMainAppVideoPlayerOverlayView *v = [self videoPlayerOverlayView]; - YTMainAppControlsOverlayView *c = [v valueForKey:@"_controlsOverlayView"]; - c.muteButton.hidden = !UseTopMuteButton(); - [c setNeedsLayout]; -} - -%end - -%hook YTMainAppControlsOverlayView - -%property (retain, nonatomic) YTQTMButton *muteButton; - -- (id)initWithDelegate:(id)delegate { - self = %orig; - createMuteButtonTop(self); - return self; -} - -- (id)initWithDelegate:(id)delegate autoplaySwitchEnabled:(BOOL)autoplaySwitchEnabled { - self = %orig; - createMuteButtonTop(self); - return self; -} - -- (NSMutableArray *)topButtonControls { - return topControls(self, %orig); -} - -- (NSMutableArray *)topControls { - return topControls(self, %orig); -} - -- (void)setTopOverlayVisible:(BOOL)visible isAutonavCanceledState:(BOOL)canceledState { - if (UseTopMuteButton()) - self.muteButton.alpha = canceledState || !visible ? 0.0 : 1.0; - %orig; -} - -%new(v@:@) -- (void)didPressMute:(id)arg { - YTMainAppVideoPlayerOverlayViewController *c = [self valueForKey:@"_eventsDelegate"]; - YTSingleVideoController *video = [c valueForKey:@"_currentSingleVideoObservable"]; - [video setMuted:![video isMuted]]; - [self.muteButton setImage:muteImage([video isMuted]) forState:0]; -} - -%end - -%end - -%group Bottom - -%hook YTInlinePlayerBarContainerView - -%property (retain, nonatomic) YTQTMButton *muteButton; - -- (id)init { - self = %orig; - createMuteButtonBottom(self); - return self; -} - -- (NSMutableArray *)rightIcons { - NSMutableArray *icons = %orig; - if (UseBottomMuteButton() && ![icons containsObject:self.muteButton]) - [icons insertObject:self.muteButton atIndex:0]; - return icons; -} - -- (void)updateIconVisibility { - %orig; - if (UseBottomMuteButton()) - self.muteButton.hidden = NO; -} - -- (void)hideScrubber { - %orig; - if (UseBottomMuteButton()) - self.muteButton.alpha = 0; -} - -- (void)setPeekableViewVisible:(BOOL)visible fullscreenButtonVisibleShouldMatchPeekableView:(BOOL)match { - %orig; - if (UseBottomMuteButton()) - self.muteButton.alpha = visible ? 1 : 0; -} - -- (void)layoutSubviews { - %orig; - if (!UseBottomMuteButton()) return; - CGFloat multiFeedWidth = [self respondsToSelector:@selector(multiFeedElementView)] ? [self multiFeedElementView].frame.size.width : 0; - YTQTMButton *enter = [self enterFullscreenButton]; - if ([enter yt_isVisible]) { - CGRect frame = enter.frame; - frame.origin.x -= multiFeedWidth + enter.frame.size.width + 16; - self.muteButton.frame = frame; - } else { - YTQTMButton *exit = [self exitFullscreenButton]; - if ([exit yt_isVisible]) { - CGRect frame = exit.frame; - frame.origin.x -= multiFeedWidth + exit.frame.size.width + 16; - self.muteButton.frame = frame; - } - } -} - -%new(v@:@) -- (void)didPressMute:(id)arg { - YTSingleVideoController *video = [self.delegate valueForKey:@"_currentSingleVideo"]; - [video setMuted:![video isMuted]]; - [self.muteButton setImage:muteImage([video isMuted]) forState:0]; -} - -%end - -%end - -%group Settings - -%hook YTAppSettingsPresentationData - -+ (NSArray *)settingsCategoryOrder { - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - NSUInteger insertIndex = [order indexOfObject:@(1)]; - if (insertIndex != NSNotFound) - [mutableOrder insertObject:@(YouMuteSection) atIndex:insertIndex + 1]; - return mutableOrder; -} - -%end - -%hook YTSettingsSectionItemManager - -%new(v@:@) -- (void)updateYouMuteSectionWithEntry:(id)entry { - NSMutableArray *sectionItems = [NSMutableArray array]; - NSBundle *tweakBundle = YouMuteBundle(); - Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); - YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; - YTSettingsSectionItem *master = [YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLED") - titleDescription:nil - accessibilityIdentifier:nil - switchOn:TweakEnabled() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:EnabledKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:master]; - YTSettingsSectionItem *position = [YTSettingsSectionItemClass itemWithTitle:LOC(@"POSITION") - accessibilityIdentifier:nil - detailTextBlock:^NSString *() { - return MuteButtonPosition() ? LOC(@"BOTTOM") : LOC(@"TOP"); - } - selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ - [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"TOP") titleDescription:LOC(@"TOP_DESC") selectBlock:^BOOL (YTSettingsCell *top, NSUInteger arg1) { - [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:PositionKey]; - [settingsViewController reloadData]; - return YES; - }], - [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"BOTTOM") titleDescription:LOC(@"BOTTOM_DESC") selectBlock:^BOOL (YTSettingsCell *bottom, NSUInteger arg1) { - [[NSUserDefaults standardUserDefaults] setInteger:1 forKey:PositionKey]; - [settingsViewController reloadData]; - return YES; - }] - ]; - YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"POSITION") pickerSectionTitle:nil rows:rows selectedItemIndex:MuteButtonPosition() parentResponder:[self parentResponder]]; - [settingsViewController pushViewController:picker]; - return YES; - }]; - [sectionItems addObject:position]; - [settingsViewController setSectionItems:sectionItems forCategory:YouMuteSection title:@"YouMute" titleDescription:nil headerHidden:NO]; -} - -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { - if (category == YouMuteSection) { - [self updateYouMuteSectionWithEntry:entry]; - return; - } - %orig; -} - -%end - -%end - -%ctor { - %init(Settings); - %init(Top); - %init(Bottom); -} diff --git a/Tweaks/YouMute/YouMute.plist b/Tweaks/YouMute/YouMute.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/YouMute/YouMute.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/YouMute/control b/Tweaks/YouMute/control deleted file mode 100644 index c902211..0000000 --- a/Tweaks/YouMute/control +++ /dev/null @@ -1,11 +0,0 @@ -Package: com.ps.youmute -Name: YouMute -Version: 1.0.0 -Architecture: iphoneos-arm -Description: Mute/unmute videos in YouTube directly. -Maintainer: PoomSmart -Author: PoomSmart -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 11.0) -Depiction: https://poomsmart.github.io/repo/depictions/youmute.html -SileoDepiction: https://poomsmart.github.io/repo/sileodepictions/youmute.json diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/Info.plist b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/Info.plist deleted file mode 100644 index 15f81a9..0000000 Binary files a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/Info.plist and /dev/null differ diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ar.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ar.lproj/Localizable.strings deleted file mode 100644 index 87ce7eb..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ar.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "إظهار زر كتم الصوت"; -"POSITION" = "مكان زر كتم الصوت"; -"TOP" = "الأعلى"; -"TOP_DESC" = "في الجزء العلوي الأيمن، حيث يوجد زر التشغيل التلقائي وزر البث وغيرها."; -"BOTTOM" = "الأسفل"; -"BOTTOM_DESC" = "في الجزء السفلي الأيمن، حيث يوجد زر ملء الشاشة."; diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/en.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 3969cc8..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "Show mute button"; -"POSITION" = "Mute button position"; -"TOP" = "Top"; -"TOP_DESC" = "At the top-right, where autoplay, captions, cast and overflow menu are."; -"BOTTOM" = "Bottom"; -"BOTTOM_DESC" = "At the bottom-right, where fullscreen button is."; diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/es.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/es.lproj/Localizable.strings deleted file mode 100644 index f3c005a..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/es.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "Mostrar botón de silencio"; -"POSITION" = "Posición del botón Silencio"; -"TOP" = "Arriba"; -"TOP_DESC" = "En la parte superior derecha, donde están la reproducción automática, los subtítulos, el reparto y el menú de desbordamiento."; -"BOTTOM" = "Abajo"; -"BOTTOM_DESC" = "En la parte inferior derecha, donde está el botón de pantalla completa."; diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ja.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ja.lproj/Localizable.strings deleted file mode 100644 index 0c171ff..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ja.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "ミュートボタンを表示"; -"POSITION" = "ミュートボタンの位置"; -"TOP" = "上部"; -"TOP_DESC" = "右上, 自動再生, キャプション, キャストとオーバーフローメニューがある場所."; -"BOTTOM" = "下部"; -"BOTTOM_DESC" = "右下, フルスクリーンボタンがある場所."; diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ru.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index 892f03f..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "Отображать кнопку «Без звука»"; -"POSITION" = "Место расположения кнопки"; -"TOP" = "Сверху"; -"TOP_DESC" = "В правом верхнем углу, рядом с кнопками Автовоспроизведения, Субтитров и выпадающего меню."; -"BOTTOM" = "Снизу"; -"BOTTOM_DESC" = "В правом нижнем углу, рядом с кнопкой Полноэкранного режима."; diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/zh_TW.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/zh_TW.lproj/Localizable.strings deleted file mode 100644 index 9468ec7..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/zh_TW.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "顯示靜音按鈕"; -"POSITION" = "靜音按鈕位置"; -"TOP" = "頂部"; -"TOP_DESC" = "在右上方,也就是自動播放、字幕、投放和選項所在的位置。"; -"BOTTOM" = "底部"; -"BOTTOM_DESC" = "在右下方,也就是全螢幕按鈕所在的位置。"; \ No newline at end of file diff --git a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/zh_cn.lproj/Localizable.strings b/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/zh_cn.lproj/Localizable.strings deleted file mode 100644 index 22b28db..0000000 --- a/Tweaks/YouMute/layout/Library/Application Support/YouMute.bundle/zh_cn.lproj/Localizable.strings +++ /dev/null @@ -1,8 +0,0 @@ -// Settings - -"ENABLED" = "显示静音按钮"; -"POSITION" = "静音按钮位置"; -"TOP" = "顶部"; -"TOP_DESC" = "在右上角,自动播放、字幕等按钮所在位置。"; -"BOTTOM" = "底部"; -"BOTTOM_DESC" = "在右下角,全屏按钮所在的位置。"; diff --git a/Tweaks/YouPiP b/Tweaks/YouPiP new file mode 160000 index 0000000..bd04bf3 --- /dev/null +++ b/Tweaks/YouPiP @@ -0,0 +1 @@ +Subproject commit bd04bf37be3d01540db418061164ae17a8f0298e diff --git a/Tweaks/YouPiP/.gitattributes b/Tweaks/YouPiP/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Tweaks/YouPiP/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Tweaks/YouPiP/.gitignore b/Tweaks/YouPiP/.gitignore deleted file mode 100644 index 94b0b64..0000000 --- a/Tweaks/YouPiP/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.theos -.DS_Store -packages \ No newline at end of file diff --git a/Tweaks/YouPiP/AVKit-Header.h b/Tweaks/YouPiP/AVKit-Header.h deleted file mode 100644 index 4bf304e..0000000 --- a/Tweaks/YouPiP/AVKit-Header.h +++ /dev/null @@ -1,18 +0,0 @@ -#import -#import -#import - -@interface AVPlayerController : UIResponder -@end - -@interface AVPictureInPictureControllerContentSource (Private) -@property(assign) bool hasInitialRenderSize; -@end - -@interface AVPictureInPictureController (Private) -@property(nonatomic, retain) AVPictureInPictureControllerContentSource *contentSource API_AVAILABLE(ios(15.0)); // retain -> strong on iOS 15 -- (instancetype)initWithContentSource:(AVPictureInPictureControllerContentSource *)contentSource API_AVAILABLE(ios(15.0)); -- (void)sampleBufferDisplayLayerRenderSizeDidChangeToSize:(CGSize)renderSize; -- (void)sampleBufferDisplayLayerDidAppear; -- (void)sampleBufferDisplayLayerDidDisappear; -@end \ No newline at end of file diff --git a/Tweaks/YouPiP/Header.h b/Tweaks/YouPiP/Header.h deleted file mode 100644 index 14f2cf3..0000000 --- a/Tweaks/YouPiP/Header.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef YOUPIP_H_ -#define YOUPIP_H_ - -#import "AVKit-Header.h" - -#define TweakName @"YouPiP" - -#define EnabledKey @"YouPiPEnabled" -#define CompatibilityModeKey @"CompatibilityModeKey" -#define PiPActivationMethodKey @"PiPActivationMethodKey" -#define PiPActivationMethod2Key @"PiPActivationMethod2Key" -#define NoMiniPlayerPiPKey @"NoMiniPlayerPiPKey" -#define NonBackgroundableKey @"NonBackgroundableKey" -#define FakeVersionKey @"FakeVersionKey" - -#endif \ No newline at end of file diff --git a/Tweaks/YouPiP/LICENSE b/Tweaks/YouPiP/LICENSE deleted file mode 100644 index a159d16..0000000 --- a/Tweaks/YouPiP/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2018 - 2020 SpicaT -Copyright (c) 2020 - 2023 PoomSmart - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/Tweaks/YouPiP/LegacyPiPCompat.x b/Tweaks/YouPiP/LegacyPiPCompat.x deleted file mode 100644 index 73af655..0000000 --- a/Tweaks/YouPiP/LegacyPiPCompat.x +++ /dev/null @@ -1,357 +0,0 @@ -#import "Header.h" -#import -#import "../YouTubeHeader/MLAVPlayer.h" -#import "../YouTubeHeader/MLHAMQueuePlayer.h" -#import "../YouTubeHeader/MLPIPController.h" -#import "../YouTubeHeader/MLPlayerPool.h" -#import "../YouTubeHeader/MLPlayerPoolImpl.h" -#import "../YouTubeHeader/MLVideoDecoderFactory.h" -#import "../YouTubeHeader/MLDefaultPlayerViewFactory.h" -#import "../YouTubeHeader/YTHotConfig.h" -#import "../YouTubeHeader/YTPlayerPIPController.h" -#import "../YouTubeHeader/YTBackgroundabilityPolicy.h" -#import "../YouTubeHeader/YTPlayerViewControllerConfig.h" -#import "../YouTubeHeader/YTSystemNotifications.h" -#import "../YouTubeHeader/YTAutonavEndscreenController.h" - -extern BOOL TweakEnabled(); -extern BOOL isPictureInPictureActive(MLPIPController *); - -BOOL hasSampleBufferPiP; -BOOL isLegacyVersion; - -BOOL LegacyPiP() { - return isLegacyVersion ? YES : [[NSUserDefaults standardUserDefaults] boolForKey:CompatibilityModeKey]; -} - -static void forceRenderViewTypeBase(YTIHamplayerConfig *hamplayerConfig) { - if (!LegacyPiP()) return; - hamplayerConfig.renderViewType = 2; -} - -static void forceRenderViewTypeHot(YTIHamplayerHotConfig *hamplayerHotConfig) { - if (!LegacyPiP()) return; - hamplayerHotConfig.renderViewType = 2; -} - -static void forceRenderViewType(YTHotConfig *hotConfig) { - YTIHamplayerHotConfig *hamplayerHotConfig = [hotConfig hamplayerHotConfig]; - forceRenderViewTypeHot(hamplayerHotConfig); -} - -static MLPIPController *(*InjectMLPIPController)(void); -static YTSystemNotifications *(*InjectYTSystemNotifications)(void); -static YTBackgroundabilityPolicy *(*InjectYTBackgroundabilityPolicy)(void); -static YTPlayerViewControllerConfig *(*InjectYTPlayerViewControllerConfig)(void); -YTHotConfig *(*InjectYTHotConfig)(void); - -%group WithInjection - -YTPlayerPIPController *initPlayerPiPControllerIfNeeded(YTPlayerPIPController *controller, id delegate, id parentResponder) { - if (controller) return controller; - controller = [[%c(YTPlayerPIPController) alloc] init]; - MLPIPController *pip = InjectMLPIPController(); - YTSystemNotifications *systemNotifications = InjectYTSystemNotifications(); - YTBackgroundabilityPolicy *bgPolicy = InjectYTBackgroundabilityPolicy(); - YTPlayerViewControllerConfig *playerConfig = InjectYTPlayerViewControllerConfig(); - [controller setValue:pip forKey:@"_pipController"]; - [controller setValue:bgPolicy forKey:@"_backgroundabilityPolicy"]; - [controller setValue:playerConfig forKey:@"_config"]; - @try { - YTHotConfig *config = InjectYTHotConfig(); - [controller setValue:config forKey:@"_hotConfig"]; - } @catch (id ex) {} - if (parentResponder) { - @try { - [controller setValue:parentResponder forKey:@"_parentResponder"]; - } @catch (id ex) {} - } - [controller setValue:delegate forKey:@"_delegate"]; - [bgPolicy addBackgroundabilityPolicyObserver:controller]; - [pip addPIPControllerObserver:controller]; - [systemNotifications addSystemNotificationsObserver:controller]; - return controller; -} - -%hook YTPlayerPIPController - -- (instancetype)initWithDelegate:(id)delegate { - return initPlayerPiPControllerIfNeeded(%orig, delegate, nil); -} - -- (instancetype)initWithDelegate:(id)delegate parentResponder:(id)parentResponder { - return initPlayerPiPControllerIfNeeded(%orig, delegate, parentResponder); -} - -%end - -%hook YTAutonavEndscreenController - -- (instancetype)initWithParentResponder:(id)arg1 config:(id)arg2 imageService:(id)arg3 lastActionController:(id)arg4 reachabilityController:(id)arg5 endscreenDelegate:(id)arg6 { - self = %orig; - if ([self valueForKey:@"_pipController"] == nil) - [self setValue:InjectMLPIPController() forKey:@"_pipController"]; - return self; -} - -%end - -%hook MLHAMQueuePlayer - -- (instancetype)initWithStickySettings:(MLPlayerStickySettings *)stickySettings playerViewProvider:(MLPlayerPoolImpl *)playerViewProvider playerConfiguration:(void *)playerConfiguration { - self = %orig; - if ([self valueForKey:@"_pipController"] == nil) - [self setValue:InjectMLPIPController() forKey:@"_pipController"]; - return self; -} - -%end - -%hook MLAVPlayer - -- (bool)isPictureInPictureActive { - return isPictureInPictureActive(InjectMLPIPController()); -} - -%end - -%hook MLPlayerPoolImpl - -- (instancetype)init { - self = %orig; - if (self) - [self setValue:InjectMLPIPController() forKey:@"_pipController"]; - return self; -} - -%end - -%hook MLAVPIPPlayerLayerView - -- (id)initWithPlaceholderPlayerItem:(AVPlayerItem *)playerItem { - self = %orig; - if ([self valueForKey:@"_pipController"] == nil) - [self setValue:InjectMLPIPController() forKey:@"_pipController"]; - return self; -} - -%end - -%end - -%group Legacy - -static MLAVPlayer *makeAVPlayer(id self, MLVideo *video, MLInnerTubePlayerConfig *playerConfig, MLPlayerStickySettings *stickySettings, BOOL gimmeAlloc) { - BOOL externalPlaybackActive = [(MLAVPlayer *)[self valueForKey:@"_activePlayer"] externalPlaybackActive]; - MLAVPlayer *player = gimmeAlloc ? [((MLPlayerPool *)self).gimme allocOf:%c(MLAVPlayer)] : [%c(MLAVPlayer) alloc]; - player = [player initWithVideo:video playerConfig:playerConfig stickySettings:stickySettings externalPlaybackActive:externalPlaybackActive]; - if (stickySettings) - player.rate = stickySettings.rate; - return player; -} - -%hook MLPIPController - -- (void)activatePiPController { - if (!isPictureInPictureActive(self)) { - AVPictureInPictureController *pip = [self valueForKey:@"_pictureInPictureController"]; - if (!pip) { - MLAVPIPPlayerLayerView *avpip = [self valueForKey:@"_AVPlayerView"]; - if (avpip) { - AVPlayerLayer *playerLayer = [avpip playerLayer]; - pip = [[AVPictureInPictureController alloc] initWithPlayerLayer:playerLayer]; - [self setValue:pip forKey:@"_pictureInPictureController"]; - pip.delegate = self; - } - } - } -} - -- (void)deactivatePiPController { - AVPictureInPictureController *pip = [self valueForKey:@"_pictureInPictureController"]; - [pip stopPictureInPicture]; -} - -%end - -%hook MLPlayerPoolImpl - -- (id)acquirePlayerForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings { - return makeAVPlayer(self, video, playerConfig, stickySettings, NO); -} - -- (id)acquirePlayerForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings latencyLogger:(id)latencyLogger { - return makeAVPlayer(self, video, playerConfig, stickySettings, NO); -} - -- (id)acquirePlayerForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings latencyLogger:(id)latencyLogger reloadContext:(id)reloadContext { - return makeAVPlayer(self, video, playerConfig, stickySettings, NO); -} - -- (MLAVPlayerLayerView *)playerViewForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - MLDefaultPlayerViewFactory *factory = [self valueForKey:@"_playerViewFactory"]; - return [factory AVPlayerViewForVideo:video playerConfig:playerConfig]; -} - -- (BOOL)canQueuePlayerPlayVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - return NO; -} - -%end - -%hook MLPlayerPool - -- (id)acquirePlayerForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings { - return makeAVPlayer(self, video, playerConfig, stickySettings, YES); -} - -- (id)acquirePlayerForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings latencyLogger:(id)latencyLogger { - return makeAVPlayer(self, video, playerConfig, stickySettings, YES); -} - -- (MLAVPlayerLayerView *)playerViewForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - MLDefaultPlayerViewFactory *factory = [self valueForKey:@"_playerViewFactory"]; - return [factory AVPlayerViewForVideo:video playerConfig:playerConfig]; -} - -- (BOOL)canUsePlayerView:(id)playerView forVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - forceRenderViewTypeBase([playerConfig hamplayerConfig]); - return %orig; -} - -- (BOOL)canQueuePlayerPlayVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - return NO; -} - -%end - -%hook MLDefaultPlayerViewFactory - -- (id)hamPlayerViewForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - forceRenderViewType([self valueForKey:@"_hotConfig"]); - forceRenderViewTypeBase([playerConfig hamplayerConfig]); - return %orig; -} - -- (BOOL)canUsePlayerView:(id)playerView forVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - forceRenderViewTypeBase([playerConfig hamplayerConfig]); - return %orig; -} - -%end - -%hook MLVideoDecoderFactory - -- (void)prepareDecoderForFormatDescription:(id)formatDescription delegateQueue:(id)delegateQueue { - forceRenderViewTypeHot([self valueForKey:@"_hotConfig"]); - %orig; -} - -%end - -%end - -%group Compat - -%hook AVPictureInPictureController - -%new(v@:) -- (void)invalidatePlaybackState {} - -%new(v@:) -- (void)sampleBufferDisplayLayerDidDisappear {} - -%new(v@:) -- (void)sampleBufferDisplayLayerDidAppear {} - -%new -- (void)sampleBufferDisplayLayerRenderSizeDidChangeToSize:(CGSize)size {} - -%new -- (void)setRequiresLinearPlayback:(BOOL)linear {} - -%new(v@:) -- (void)reloadPrerollAttributes {} - -%end - -%end - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - -%group AVKit_iOS14_2_Up - -%hook AVPictureInPictureControllerContentSource - -%property (assign) bool hasInitialRenderSize; - -- (id)initWithSampleBufferDisplayLayer:(AVSampleBufferDisplayLayer *)sampleBufferDisplayLayer initialRenderSize:(CGSize)initialRenderSize playbackDelegate:(id)playbackDelegate { - self = %orig; - if (self) - self.hasInitialRenderSize = true; - return self; -} - -%end - -%end - -%group AVKit_preiOS14_2 - -%hook AVPictureInPictureControllerContentSource - -%property (assign) bool hasInitialRenderSize; - -%new -- (instancetype)initWithSampleBufferDisplayLayer:(AVSampleBufferDisplayLayer *)sampleBufferDisplayLayer initialRenderSize:(CGSize)initialRenderSize playbackDelegate:(id )playbackDelegate { - return [self initWithSampleBufferDisplayLayer:sampleBufferDisplayLayer playbackDelegate:playbackDelegate]; -} - -%end - -%hook AVPictureInPictureController - -%new -- (void)setCanStartPictureInPictureAutomaticallyFromInline:(BOOL)canStartFromInline {} - -%end - -%end - -#pragma clang diagnostic pop - -%ctor { - if (!TweakEnabled()) return; - NSString *frameworkPath = [NSString stringWithFormat:@"%@/Frameworks/Module_Framework.framework/Module_Framework", NSBundle.mainBundle.bundlePath]; - NSBundle *bundle = [NSBundle bundleWithPath:frameworkPath]; - if (!bundle.loaded) [bundle load]; - MSImageRef ref = MSGetImageByName([frameworkPath UTF8String]); - InjectMLPIPController = MSFindSymbol(ref, "_InjectMLPIPController"); - if (InjectMLPIPController) { - InjectYTSystemNotifications = MSFindSymbol(ref, "_InjectYTSystemNotifications"); - InjectYTBackgroundabilityPolicy = MSFindSymbol(ref, "_InjectYTBackgroundabilityPolicy"); - InjectYTPlayerViewControllerConfig = MSFindSymbol(ref, "_InjectYTPlayerViewControllerConfig"); - InjectYTHotConfig = MSFindSymbol(ref, "_InjectYTHotConfig"); - %init(WithInjection); - } else { - NSString *currentVersion = [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey]; - hasSampleBufferPiP = isLegacyVersion = [currentVersion compare:@"15.33.4" options:NSNumericSearch] == NSOrderedDescending; - hasSampleBufferPiP &= IS_IOS_OR_NEWER(iOS_13_0); - } - if (!IS_IOS_OR_NEWER(iOS_14_0)) { - %init(Compat); - if (!IS_IOS_OR_NEWER(iOS_13_0)) - isLegacyVersion = YES; - } - if (LegacyPiP()) { - %init(Legacy); - } - if (!IS_IOS_OR_NEWER(iOS_14_0) || IS_IOS_OR_NEWER(iOS_15_0)) - return; - if (IS_IOS_OR_NEWER(iOS_14_2)) { - %init(AVKit_iOS14_2_Up); - } else { - %init(AVKit_preiOS14_2); - } -} \ No newline at end of file diff --git a/Tweaks/YouPiP/Makefile b/Tweaks/YouPiP/Makefile deleted file mode 100644 index d627bec..0000000 --- a/Tweaks/YouPiP/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -TARGET = iphone:clang:latest:11.0 -ARCHS = arm64 -PACKAGE_VERSION = 1.7.19-2 -MIN_YOUTUBE_VERSION = 15.10.4 - -EXTRA_CFLAGS = -DMIN_YOUTUBE_VERSION=$(MIN_YOUTUBE_VERSION) - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = YouPiP -$(TWEAK_NAME)_FILES = Tweak.x Settings.x LegacyPiPCompat.x -$(TWEAK_NAME)_CFLAGS = -fobjc-arc $(EXTRA_CFLAGS) -$(TWEAK_NAME)_FRAMEWORKS = AVFoundation AVKit UIKit - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/YouPiP/README.md b/Tweaks/YouPiP/README.md deleted file mode 100644 index f7d7d9c..0000000 --- a/Tweaks/YouPiP/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# YouPiP - -Enable native Picture-in-Picture feature for videos in YouTube app. - -Activate PiP by playing the video and dismissing the app, or tapping PiP button in video tab bar or control overlay. - -## Build it yourself - -Use iOS 15+ SDK and latest THEOS. diff --git a/Tweaks/YouPiP/Settings.x b/Tweaks/YouPiP/Settings.x deleted file mode 100644 index a05ed8f..0000000 --- a/Tweaks/YouPiP/Settings.x +++ /dev/null @@ -1,186 +0,0 @@ -#import -#import "Header.h" -#import "../YouTubeHeader/YTAlertView.h" -#import "../YouTubeHeader/YTHotConfig.h" -#import "../YouTubeHeader/YTSettingsViewController.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../YouTubeHeader/YTAppSettingsSectionItemActionController.h" - -#define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] - -#define FEATURE_CUTOFF_VERSION @"16.46.5" - -static const NSInteger YouPiPSection = 200; - -@interface YTSettingsSectionItemManager (YouPiP) -- (void)updateYouPiPSectionWithEntry:(id)entry; -@end - -extern BOOL TweakEnabled(); -extern BOOL UsePiPButton(); -extern BOOL UseTabBarPiPButton(); -extern BOOL NoMiniPlayerPiP(); -extern BOOL LegacyPiP(); -extern BOOL NonBackgroundable(); -extern BOOL FakeVersion(); - -extern NSBundle *YouPiPBundle(); - -NSString *currentVersion; - -static NSString *YouPiPWarnVersionKey = @"YouPiPWarnVersionKey"; - -%hook YTAppSettingsPresentationData - -+ (NSArray *)settingsCategoryOrder { - NSArray *order = %orig; - NSMutableArray *mutableOrder = [order mutableCopy]; - NSUInteger insertIndex = [order indexOfObject:@(1)]; - if (insertIndex != NSNotFound) - [mutableOrder insertObject:@(YouPiPSection) atIndex:insertIndex + 1]; // Add YouPiP under General (ID: 1) section - return mutableOrder; -} - -%end - -%hook YTSettingsSectionItemManager - -%new(v@:@) -- (void)updateYouPiPSectionWithEntry:(id)entry { - YTSettingsViewController *delegate = [self valueForKey:@"_dataDelegate"]; - NSMutableArray *sectionItems = [NSMutableArray array]; - NSBundle *tweakBundle = YouPiPBundle(); - YTSettingsSectionItem *enabled = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"ENABLED") - titleDescription:LOC(@"ENABLED_DESC") - accessibilityIdentifier:nil - switchOn:TweakEnabled() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:EnabledKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:enabled]; - YTSettingsSectionItem *activationMethod = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"USE_PIP_BUTTON") - titleDescription:LOC(@"USE_PIP_BUTTON_DESC") - accessibilityIdentifier:nil - switchOn:UsePiPButton() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:PiPActivationMethodKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:activationMethod]; - YTSettingsSectionItem *activationMethod2 = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"USE_TAB_BAR_PIP_BUTTON") - titleDescription:LOC(@"USE_TAB_BAR_PIP_BUTTON_DESC") - accessibilityIdentifier:nil - switchOn:UseTabBarPiPButton() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:PiPActivationMethod2Key]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:activationMethod2]; - YTSettingsSectionItem *miniPlayer = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"DISABLE_PIP_MINI_PLAYER") - titleDescription:LOC(@"DISABLE_PIP_MINI_PLAYER_DESC") - accessibilityIdentifier:nil - switchOn:NoMiniPlayerPiP() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:NoMiniPlayerPiPKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:miniPlayer]; - if (IS_IOS_OR_NEWER(iOS_13_0) && [currentVersion compare:@"15.33.4" options:NSNumericSearch] == NSOrderedDescending) { - YTSettingsSectionItem *legacyPiP = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"LEGACY_PIP") - titleDescription:LOC(@"LEGACY_PIP_DESC") - accessibilityIdentifier:nil - switchOn:LegacyPiP() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:CompatibilityModeKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:legacyPiP]; - } - YTAppSettingsSectionItemActionController *sectionItemActionController = [delegate valueForKey:@"_sectionItemActionController"]; - YTSettingsSectionItemManager *sectionItemManager = [sectionItemActionController valueForKey:@"_sectionItemManager"]; - YTHotConfig *hotConfig; - @try { - hotConfig = [sectionItemManager valueForKey:@"_hotConfig"]; - } @catch (id ex) { - hotConfig = [sectionItemManager.gimme instanceForType:%c(YTHotConfig)]; - } - YTIIosMediaHotConfig *iosMediaHotConfig = hotConfig.hotConfigGroup.mediaHotConfig.iosMediaHotConfig; - if ([iosMediaHotConfig respondsToSelector:@selector(setEnablePipForNonBackgroundableContent:)]) { - YTSettingsSectionItem *nonBackgroundable = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"NON_BACKGROUNDABLE_PIP") - titleDescription:LOC(@"NON_BACKGROUNDABLE_PIP_DESC") - accessibilityIdentifier:nil - switchOn:NonBackgroundable() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:NonBackgroundableKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:nonBackgroundable]; - } - if ([currentVersion compare:FEATURE_CUTOFF_VERSION options:NSNumericSearch] == NSOrderedDescending) { - YTSettingsSectionItem *fakeVersion = [%c(YTSettingsSectionItem) switchItemWithTitle:LOC(@"FAKE_YT_VERSION") - titleDescription:[NSString stringWithFormat:LOC(@"FAKE_YT_VERSION_DESC"), FEATURE_CUTOFF_VERSION] - accessibilityIdentifier:nil - switchOn:FakeVersion() - switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:FakeVersionKey]; - return YES; - } - settingItemId:0]; - [sectionItems addObject:fakeVersion]; - } - [delegate setSectionItems:sectionItems forCategory:YouPiPSection title:TweakName titleDescription:nil headerHidden:NO]; -} - -- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { - if (category == YouPiPSection) { - [self updateYouPiPSectionWithEntry:entry]; - return; - } - %orig; -} - -%end - -BOOL loadWatchNextRequest = NO; - -%hook YTVersionUtils - -+ (NSString *)appVersion { - return FakeVersion() && loadWatchNextRequest ? FEATURE_CUTOFF_VERSION : %orig; -} - -%end - -%hook YTWatchNextViewController - -- (void)loadWatchNextRequest:(id)arg1 withInitialWatchNextResponse:(id)arg2 disableUnloadModel:(BOOL)arg3 { - loadWatchNextRequest = YES; - %orig; - loadWatchNextRequest = NO; -} - -%end - -%ctor { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - currentVersion = [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey]; - if (![defaults boolForKey:YouPiPWarnVersionKey] && [currentVersion compare:@(OS_STRINGIFY(MIN_YOUTUBE_VERSION)) options:NSNumericSearch] != NSOrderedDescending) { - [defaults setBool:YES forKey:YouPiPWarnVersionKey]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - NSBundle *tweakBundle = YouPiPBundle(); - YTAlertView *alertView = [%c(YTAlertView) infoDialog]; - alertView.title = TweakName; - alertView.subtitle = [NSString stringWithFormat:LOC(@"UNSUPPORTED_YT_VERSION"), currentVersion, @(OS_STRINGIFY(MIN_YOUTUBE_VERSION))]; - [alertView show]; - }); - } - %init; -} diff --git a/Tweaks/YouPiP/Tweak.x b/Tweaks/YouPiP/Tweak.x deleted file mode 100644 index ba1dfc4..0000000 --- a/Tweaks/YouPiP/Tweak.x +++ /dev/null @@ -1,600 +0,0 @@ -#import -#import -#import "Header.h" -#import "../YouTubeHeader/GIMBindingBuilder.h" -#import "../YouTubeHeader/GPBExtensionRegistry.h" -#import "../YouTubeHeader/MLPIPController.h" -#import "../YouTubeHeader/MLDefaultPlayerViewFactory.h" -#import "../YouTubeHeader/YTBackgroundabilityPolicy.h" -#import "../YouTubeHeader/YTMainAppControlsOverlayView.h" -#import "../YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h" -#import "../YouTubeHeader/YTHotConfig.h" -#import "../YouTubeHeader/YTLocalPlaybackController.h" -#import "../YouTubeHeader/YTPlayerPIPController.h" -#import "../YouTubeHeader/YTSettingsSectionItem.h" -#import "../YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../YouTubeHeader/YTIPictureInPictureRendererRoot.h" -#import "../YouTubeHeader/YTColor.h" -#import "../YouTubeHeader/QTMIcon.h" -#import "../YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h" -#import "../YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h" -#import "../YouTubeHeader/YTSlimVideoDetailsActionView.h" -#import "../YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h" -#import "../YouTubeHeader/YTPageStyleController.h" -#import "../YouTubeHeader/YTPlayerStatus.h" -#import "../YouTubeHeader/YTWatchViewController.h" - -#define PiPButtonType 801 - -@interface YTMainAppControlsOverlayView (YP) -@property (retain, nonatomic) YTQTMButton *pipButton; -- (void)didPressPiP:(id)arg; -- (UIImage *)pipImage; -@end - -BOOL FromUser = NO; -BOOL PiPDisabled = NO; - -extern BOOL LegacyPiP(); -extern YTHotConfig *(*InjectYTHotConfig)(void); - -BOOL TweakEnabled() { - return [[NSUserDefaults standardUserDefaults] boolForKey:EnabledKey]; -} - -BOOL UsePiPButton() { - return [[NSUserDefaults standardUserDefaults] boolForKey:PiPActivationMethodKey]; -} - -BOOL NoMiniPlayerPiP() { - return [[NSUserDefaults standardUserDefaults] boolForKey:NoMiniPlayerPiPKey]; -} - -BOOL UseTabBarPiPButton() { - return [[NSUserDefaults standardUserDefaults] boolForKey:PiPActivationMethod2Key]; -} - -BOOL NonBackgroundable() { - return [[NSUserDefaults standardUserDefaults] boolForKey:NonBackgroundableKey]; -} - -BOOL FakeVersion() { - return [[NSUserDefaults standardUserDefaults] boolForKey:FakeVersionKey]; -} - -BOOL isPictureInPictureActive(MLPIPController *pip) { - return [pip respondsToSelector:@selector(pictureInPictureActive)] ? [pip pictureInPictureActive] : [pip isPictureInPictureActive]; -} - -static NSString *PiPIconPath; -static NSString *TabBarPiPIconPath; -static NSString *PiPVideoPath; - -static void forcePictureInPicture(YTHotConfig *hotConfig, BOOL value) { - [hotConfig mediaHotConfig].enablePictureInPicture = value; - YTIIosMediaHotConfig *iosMediaHotConfig = hotConfig.hotConfigGroup.mediaHotConfig.iosMediaHotConfig; - iosMediaHotConfig.enablePictureInPicture = value; - if ([iosMediaHotConfig respondsToSelector:@selector(setEnablePipForNonBackgroundableContent:)]) - iosMediaHotConfig.enablePipForNonBackgroundableContent = value && NonBackgroundable(); - if ([iosMediaHotConfig respondsToSelector:@selector(setEnablePipForNonPremiumUsers:)]) - iosMediaHotConfig.enablePipForNonPremiumUsers = value; -} - -static void activatePiPBase(YTPlayerPIPController *controller, BOOL playPiP) { - MLPIPController *pip = [controller valueForKey:@"_pipController"]; - if ([controller respondsToSelector:@selector(maybeEnablePictureInPicture)]) - [controller maybeEnablePictureInPicture]; - else if ([controller respondsToSelector:@selector(maybeInvokePictureInPicture)]) - [controller maybeInvokePictureInPicture]; - else { - BOOL canPiP = [controller respondsToSelector:@selector(canEnablePictureInPicture)] && [controller canEnablePictureInPicture]; - if (!canPiP) - canPiP = [controller respondsToSelector:@selector(canInvokePictureInPicture)] && [controller canInvokePictureInPicture]; - if (canPiP) { - if ([pip respondsToSelector:@selector(activatePiPController)]) - [pip activatePiPController]; - else - [pip startPictureInPicture]; - } - } - AVPictureInPictureController *avpip = [pip valueForKey:@"_pictureInPictureController"]; - if (playPiP) { - if ([avpip isPictureInPicturePossible]) - [avpip startPictureInPicture]; - } else { - if ([pip respondsToSelector:@selector(deactivatePiPController)]) - [pip deactivatePiPController]; - else - [avpip stopPictureInPicture]; - } -} - -static void activatePiP(YTLocalPlaybackController *local, BOOL playPiP) { - if (![local isKindOfClass:%c(YTLocalPlaybackController)]) - return; - YTPlayerPIPController *controller = [local valueForKey:@"_playerPIPController"]; - activatePiPBase(controller, playPiP); -} - -static void bootstrapPiP(YTPlayerViewController *self, BOOL playPiP) { - YTHotConfig *hotConfig; - @try { - if (InjectYTHotConfig) - hotConfig = InjectYTHotConfig(); - else - hotConfig = [self valueForKey:@"_hotConfig"]; - } @catch (id ex) { - hotConfig = [[self gimme] instanceForType:%c(YTHotConfig)]; - } - forcePictureInPicture(hotConfig, YES); - YTLocalPlaybackController *local = [self valueForKey:@"_playbackController"]; - activatePiP(local, playPiP); -} - -#pragma mark - Video tab bar PiP Button - -static YTISlimMetadataButtonSupportedRenderers *makeUnderPlayerButton(NSString *title, int iconType, NSString *browseId) { - YTISlimMetadataButtonSupportedRenderers *supportedRenderer = [[%c(YTISlimMetadataButtonSupportedRenderers) alloc] init]; - YTISlimMetadataButtonRenderer *metadataButtonRenderer = [[%c(YTISlimMetadataButtonRenderer) alloc] init]; - YTIButtonSupportedRenderers *buttonSupportedRenderer = [[%c(YTIButtonSupportedRenderers) alloc] init]; - YTIBrowseEndpoint *endPoint = [[%c(YTIBrowseEndpoint) alloc] init]; - YTICommand *command = [[%c(YTICommand) alloc] init]; - YTIButtonRenderer *button = [[%c(YTIButtonRenderer) alloc] init]; - YTIIcon *icon = [[%c(YTIIcon) alloc] init]; - endPoint.browseId = browseId; - command.browseEndpoint = endPoint; - icon.iconType = iconType; - button.style = 8; // Opacity style - button.tooltip = title; - button.size = 1; // Default size - button.isDisabled = NO; - button.text = [%c(YTIFormattedString) formattedStringWithString:title]; - button.icon = icon; - button.navigationEndpoint = command; - buttonSupportedRenderer.buttonRenderer = button; - metadataButtonRenderer.button = buttonSupportedRenderer; - supportedRenderer.slimMetadataButtonRenderer = metadataButtonRenderer; - return supportedRenderer; -} - -%hook YTIIcon - -- (UIImage *)iconImageWithColor:(UIColor *)color { - if (self.iconType == PiPButtonType) { - UIImage *image = [%c(QTMIcon) tintImage:[UIImage imageWithContentsOfFile:TabBarPiPIconPath] color:[[%c(YTPageStyleController) currentColorPalette] textPrimary]]; - if ([image respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)]) - image = [image imageFlippedForRightToLeftLayoutDirection]; - return image; - } - return %orig; -} -%end - -%hook YTSlimVideoScrollableDetailsActionsView - -- (void)createActionViewsFromSupportedRenderers:(NSMutableArray *)renderers { // for old YouTube version - if (UseTabBarPiPButton()) { - YTISlimMetadataButtonSupportedRenderers *PiPButton = makeUnderPlayerButton(@"PiP", PiPButtonType, @"YouPiP.pip.command"); - if (![renderers containsObject:PiPButton]) - [renderers addObject:PiPButton]; - } - %orig; -} - -- (void)createActionViewsFromSupportedRenderers:(NSMutableArray *)renderers withElementsContextBlock:(id)arg2 { - if (UseTabBarPiPButton()) { - YTISlimMetadataButtonSupportedRenderers *PiPButton = makeUnderPlayerButton(@"PiP", PiPButtonType, @"YouPiP.pip.command"); - if (![renderers containsObject:PiPButton]) - [renderers addObject:PiPButton]; - } - %orig; -} - -%end - -%hook YTSlimVideoDetailsActionView - -- (void)didTapButton:(id)arg1 { - if ([self.label.attributedText.string isEqualToString:@"PiP"]) { - YTSlimVideoScrollableActionBarCellController *_delegate = self.delegate; - YTPlayerViewController *playerViewController = nil; - @try { - if ([[_delegate valueForKey:@"_metadataPanelStateProvider"] isKindOfClass:%c(YTWatchController)]) { - id provider = [_delegate valueForKey:@"_metadataPanelStateProvider"]; - @try { - YTWatchViewController *watchViewController = [provider valueForKey:@"_watchViewController"]; - playerViewController = [watchViewController valueForKey:@"_playerViewController"]; - } @catch (id ex) { - playerViewController = [provider valueForKey:@"_playerViewController"]; - } - } - } @catch (id ex) { // for old YouTube version - if ([[_delegate valueForKey:@"_ngwMetadataPanelStateProvider"] isKindOfClass:%c(YTNGWatchController)]) { - id provider = [_delegate valueForKey:@"_ngwMetadataPanelStateProvider"]; - playerViewController = [provider valueForKey:@"_playerViewController"]; - } - } - if (playerViewController && [playerViewController isKindOfClass:%c(YTPlayerViewController)]) { - FromUser = YES; - bootstrapPiP(playerViewController, YES); - } - return; - } - %orig; -} - -%end - -#pragma mark - Overlay PiP Button - -%hook YTMainAppVideoPlayerOverlayViewController - -- (void)updateTopRightButtonAvailability { - %orig; - YTMainAppVideoPlayerOverlayView *v = [self videoPlayerOverlayView]; - YTMainAppControlsOverlayView *c = [v valueForKey:@"_controlsOverlayView"]; - c.pipButton.hidden = !UsePiPButton(); - [c setNeedsLayout]; -} - -%end - -static void createPiPButton(YTMainAppControlsOverlayView *self) { - if (self) { - CGFloat padding = [[self class] topButtonAdditionalPadding]; - UIImage *image = [self pipImage]; - self.pipButton = [self buttonWithImage:image accessibilityLabel:@"pip" verticalContentPadding:padding]; - self.pipButton.hidden = YES; - self.pipButton.alpha = 0; - [self.pipButton addTarget:self action:@selector(didPressPiP:) forControlEvents:UIControlEventTouchUpInside]; - @try { - [[self valueForKey:@"_topControlsAccessibilityContainerView"] addSubview:self.pipButton]; - } @catch (id ex) { - [self addSubview:self.pipButton]; - } - } -} - -static NSMutableArray *topControls(YTMainAppControlsOverlayView *self, NSMutableArray *controls) { - if (UsePiPButton()) - [controls insertObject:self.pipButton atIndex:0]; - return controls; -} - -%hook YTMainAppControlsOverlayView - -%property (retain, nonatomic) YTQTMButton *pipButton; - -- (id)initWithDelegate:(id)delegate { - self = %orig; - createPiPButton(self); - return self; -} - -- (id)initWithDelegate:(id)delegate autoplaySwitchEnabled:(BOOL)autoplaySwitchEnabled { - self = %orig; - createPiPButton(self); - return self; -} - -- (NSMutableArray *)topButtonControls { - return topControls(self, %orig); -} - -- (NSMutableArray *)topControls { - return topControls(self, %orig); -} - -- (void)setTopOverlayVisible:(BOOL)visible isAutonavCanceledState:(BOOL)canceledState { - if (UsePiPButton()) - self.pipButton.alpha = canceledState || !visible ? 0.0 : 1.0; - %orig; -} - -%new(@:) -- (UIImage *)pipImage { - static UIImage *image = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - UIColor *color = [%c(YTColor) white1]; - image = [%c(QTMIcon) tintImage:[UIImage imageWithContentsOfFile:PiPIconPath] color:color]; - if ([image respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)]) - image = [image imageFlippedForRightToLeftLayoutDirection]; - }); - return image; -} - -%new(v@:@) -- (void)didPressPiP:(id)arg { - YTMainAppVideoPlayerOverlayViewController *c = [self valueForKey:@"_eventsDelegate"]; - FromUser = YES; - bootstrapPiP([c delegate], YES); -} - -%end - -#pragma mark - PiP Support - -%hook AVPictureInPictureController - -+ (BOOL)isPictureInPictureSupported { - return YES; -} - -%end - -%hook AVPlayerController - -- (BOOL)isPictureInPictureSupported { - return YES; -} - -%end - -%hook AVSampleBufferDisplayLayerPlayerController - -- (void)setPictureInPictureAvailable:(BOOL)available { - %orig(YES); -} - -%end - -%hook MLPIPController - -- (void)activatePiPController { - %orig; - if (!IS_IOS_OR_NEWER(iOS_15_0) && !LegacyPiP()) { - MLHAMSBDLSampleBufferRenderingView *view = [self valueForKey:@"_HAMPlayerView"]; - CGSize size = [self renderSizeForView:view]; - AVPictureInPictureController *avpip = [self valueForKey:@"_pictureInPictureController"]; - [avpip sampleBufferDisplayLayerRenderSizeDidChangeToSize:size]; - [avpip sampleBufferDisplayLayerDidAppear]; - } -} - -- (BOOL)isPictureInPictureSupported { - return YES; -} - -%new(v@:@) -- (BOOL)pictureInPictureControllerPlaybackPaused:(AVPictureInPictureController *)pictureInPictureController { - return [self pictureInPictureControllerIsPlaybackPaused:pictureInPictureController]; -} - -%new(v@:@) -- (void)pictureInPictureControllerStartPlayback:(id)arg1 { - [self pictureInPictureControllerStartPlayback]; -} - -%new(v@:@) -- (void)pictureInPictureControllerStopPlayback:(id)arg1 { - [self pictureInPictureControllerStopPlayback]; -} - -%new -- (void)renderingViewSampleBufferFrameSizeDidChange:(CGSize)size { - if (!IS_IOS_OR_NEWER(iOS_15_0) && size.width && size.height) { - AVPictureInPictureController *avpip = [self valueForKey:@"_pictureInPictureController"]; - [avpip sampleBufferDisplayLayerRenderSizeDidChangeToSize:size]; - } -} - -%new(v@:@) -- (void)appWillEnterForeground:(id)arg1 { - if (!IS_IOS_OR_NEWER(iOS_15_0) && !LegacyPiP()) { - AVPictureInPictureController *avpip = [self valueForKey:@"_pictureInPictureController"]; - [avpip sampleBufferDisplayLayerDidAppear]; - } -} - -%new(v@:@) -- (void)appWillEnterBackground:(id)arg1 { - if (!IS_IOS_OR_NEWER(iOS_15_0) && !LegacyPiP()) { - AVPictureInPictureController *avpip = [self valueForKey:@"_pictureInPictureController"]; - [avpip sampleBufferDisplayLayerDidDisappear]; - } -} - -%end - -%hook MLDefaultPlayerViewFactory - -- (MLAVPlayerLayerView *)AVPlayerViewForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig { - forcePictureInPicture([self valueForKey:@"_hotConfig"], YES); - return %orig; -} - -%end - -#pragma mark - PiP Support, Backgroundable - -%hook YTIHamplayerConfig - -- (BOOL)enableBackgroundable { - return YES; -} - -%end - -%hook YTIBackgroundOfflineSettingCategoryEntryRenderer - -- (BOOL)isBackgroundEnabled { - return YES; -} - -%end - -%hook YTBackgroundabilityPolicy - -- (void)updateIsBackgroundableByUserSettings { - %orig; - [self setValue:@(YES) forKey:@"_backgroundableByUserSettings"]; -} - -%end - -%hook YTSettingsSectionItemManager - -- (YTSettingsSectionItem *)pictureInPictureSectionItem { - forcePictureInPicture([self valueForKey:@"_hotConfig"], YES); - return %orig; -} - -- (YTSettingsSectionItem *)pictureInPictureSectionItem:(id)arg1 { - forcePictureInPicture([self valueForKey:@"_hotConfig"], YES); - return %orig; -} - -%end - -#pragma mark - Hacks - -BOOL YTSingleVideo_isLivePlayback_override = NO; - -%hook YTSingleVideo - -- (BOOL)isLivePlayback { - return YTSingleVideo_isLivePlayback_override ? NO : %orig; -} - -%end - -static YTHotConfig *getHotConfig(YTPlayerPIPController *self) { - @try { - return [self valueForKey:@"_hotConfig"]; - } @catch (id ex) { - return [[self valueForKey:@"_config"] valueForKey:@"_hotConfig"]; - } -} - -%hook YTPlayerPIPController - -- (BOOL)canInvokePictureInPicture { - forcePictureInPicture(getHotConfig(self), YES); - YTSingleVideo_isLivePlayback_override = YES; - BOOL value = %orig; - YTSingleVideo_isLivePlayback_override = NO; - return value; -} - -- (BOOL)canEnablePictureInPicture { - forcePictureInPicture(getHotConfig(self), YES); - YTSingleVideo_isLivePlayback_override = YES; - BOOL value = %orig; - YTSingleVideo_isLivePlayback_override = NO; - return value; -} - -- (void)didStopPictureInPicture { - FromUser = NO; - %orig; -} - -- (void)appWillResignActive:(id)arg1 { - // If PiP button on, PiP doesn't activate on app resign unless it's from user - BOOL hasPiPButton = UsePiPButton() || UseTabBarPiPButton(); - BOOL disablePiP = hasPiPButton && !FromUser; - if (disablePiP) { - MLPIPController *pip = [self valueForKey:@"_pipController"]; - [pip setValue:nil forKey:@"_pictureInPictureController"]; - } else { - if (LegacyPiP()) - activatePiPBase(self, YES); - %orig; - } -} - -%end - -%hook YTSingleVideoController - -- (void)playerStatusDidChange:(YTPlayerStatus *)playerStatus { - %orig; - PiPDisabled = NoMiniPlayerPiP() && playerStatus.visibility == 1; -} - -%end - -%hook AVPictureInPicturePlatformAdapter - -- (BOOL)isSystemPictureInPicturePossible { - return PiPDisabled ? NO : %orig; -} - -%end - -%hook YTIPlayabilityStatus - -- (BOOL)isPlayableInBackground { - return YES; -} - -- (BOOL)isPlayableInPictureInPicture { - return YES; -} - -- (BOOL)hasPictureInPicture { - return YES; -} - -%end - -#pragma mark - PiP Support, Binding - -%hook YTAppModule - -- (void)configureWithBinder:(GIMBindingBuilder *)binder { - %orig; - [[binder bindType:%c(MLPIPController)] initializedWith:^(id a) { - MLPIPController *pip = [%c(MLPIPController) alloc]; - if ([pip respondsToSelector:@selector(initWithPlaceholderPlayerItemResourcePath:)]) - pip = [pip initWithPlaceholderPlayerItemResourcePath:PiPVideoPath]; - else if ([pip respondsToSelector:@selector(initWithPlaceholderPlayerItem:)]) - pip = [pip initWithPlaceholderPlayerItem:[AVPlayerItem playerItemWithURL:[NSURL URLWithString:PiPVideoPath]]]; - return pip; - }]; -} - -%end - -%hook YTIInnertubeResourcesIosRoot - -- (GPBExtensionRegistry *)extensionRegistry { - GPBExtensionRegistry *registry = %orig; - [registry addExtension:[%c(YTIPictureInPictureRendererRoot) pictureInPictureRenderer]]; - return registry; -} - -%end - -%hook GoogleGlobalExtensionRegistry - -- (GPBExtensionRegistry *)extensionRegistry { - GPBExtensionRegistry *registry = %orig; - [registry addExtension:[%c(YTIPictureInPictureRendererRoot) pictureInPictureRenderer]]; - return registry; -} - -%end - -NSBundle *YouPiPBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YouPiP" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YouPiP.bundle")]; - }); - return bundle; -} - -%ctor { - if (!TweakEnabled()) return; - NSBundle *tweakBundle = YouPiPBundle(); - PiPVideoPath = [tweakBundle pathForResource:@"PiPPlaceholderAsset" ofType:@"mp4"]; - PiPIconPath = [tweakBundle pathForResource:@"yt-pip-overlay" ofType:@"png"]; - TabBarPiPIconPath = [tweakBundle pathForResource:@"yt-pip-tabbar" ofType:@"png"]; - %init; -} diff --git a/Tweaks/YouPiP/YouPiP.plist b/Tweaks/YouPiP/YouPiP.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/YouPiP/YouPiP.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/YouPiP/control b/Tweaks/YouPiP/control deleted file mode 100644 index fbf5414..0000000 --- a/Tweaks/YouPiP/control +++ /dev/null @@ -1,14 +0,0 @@ -Package: com.ps.youpip -Name: YouPiP -Depends: mobilesubstrate, firmware (>= 11.0), firmware (>= 14.0) | gsc.ipad | com.ps.forceinpicture | com.cabralcole.forceinpicture -Version: 1.0.0 -Architecture: iphoneos-arm -Description: Enable native PiP in YouTube app. -Maintainer: PoomSmart -Author: PoomSmart -Section: Tweaks -Replaces: com.spicat.youpip -Provides: com.spicat.youpip -Conflicts: com.spicat.youpip -Depiction: https://poomsmart.github.io/repo/depictions/youpip.html -SileoDepiction: https://poomsmart.github.io/repo/sileodepictions/youpip.json diff --git a/Tweaks/YouPiP/layout/DEBIAN/postinst b/Tweaks/YouPiP/layout/DEBIAN/postinst deleted file mode 100755 index 9f5854a..0000000 --- a/Tweaks/YouPiP/layout/DEBIAN/postinst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -killall -9 YouTube || true \ No newline at end of file diff --git a/Tweaks/YouPiP/layout/DEBIAN/postrm b/Tweaks/YouPiP/layout/DEBIAN/postrm deleted file mode 100755 index 9f5854a..0000000 --- a/Tweaks/YouPiP/layout/DEBIAN/postrm +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -killall -9 YouTube || true \ No newline at end of file diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/Info.plist b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/Info.plist deleted file mode 100644 index 5c7a6fe..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/Info.plist and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/PiPPlaceholderAsset.mp4 b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/PiPPlaceholderAsset.mp4 deleted file mode 100644 index 0b6976a..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/PiPPlaceholderAsset.mp4 and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ar.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ar.lproj/Localizable.strings deleted file mode 100644 index ed6d2a6..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ar.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "مفعَّل"; -"ENABLED_DESC" = "يجب إعادة تشغيل التطبيق."; - -"USE_PIP_BUTTON" = "استخدم زر PiP"; -"USE_PIP_BUTTON_DESC" = "إضافة زر PiP مع الأزرار على الفيديو لتفعيل PiP عند الخروج من التطبيق."; - -"USE_TAB_BAR_PIP_BUTTON" = "إضافة زر PiP أسفل الفيديو"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "إضافة زر PiP مع شريط الأزرار أسفل الفيديو لتفعيل PiP عند الخروج من التطبيق. يجب إعادة تشغيل التطبيق لتفعيل الميزة."; - -"DISABLE_PIP_MINI_PLAYER" = "منع PiP في المشغّل المصغر"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "منع PiP من العمل أثناء تشغيل فيديو عبرالمشغّل المصغّر."; - -"LEGACY_PIP" = "نمط PiP القديم"; -"LEGACY_PIP_DESC" = "استخدام AVPlayerLayer لـ PiP. النمط هذا يصلح مشكلة التسريع ولكن قد يمنع خيارات UHD (2K/4K) من جميع الفيديوهات. إعادة تشغيل التطبيق مطلوبة لتفعيل هذا النمط."; - -"NON_BACKGROUNDABLE_PIP" = "PiP للفيديوهات التي لا تعمل في الخلفية"; -"NON_BACKGROUNDABLE_PIP_DESC" = "تفعيل PiP للفيديوهات التي لا تعمل في الخلفية."; - -"FAKE_YT_VERSION" = "إصدار يوتيوب مزيف"; -"FAKE_YT_VERSION_DESC" = "تغيير إصدار اليوتيوب إلى %@ لكي يظهر زر PiP أسفل الفيديو."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "إصدار يوتيوب رقم %@ لم يتم اختباره، وقد لا يكون مدعوماً من YouPiP. رجاءً قم بتحديث يوتيوب إلى إصدار %@ على الأقل."; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/de.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/de.lproj/Localizable.strings deleted file mode 100644 index cc32303..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/de.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Aktiviert"; -"ENABLED_DESC" = "App-Neustart erforderlich!"; - -"USE_PIP_BUTTON" = "PiP-Taste im Video anzeigen"; -"USE_PIP_BUTTON_DESC" = "Fügt im Videoplayer eine PiP-Taste hinzu, um PiP auch ohne verlassen der App zu verwenden."; - -"USE_TAB_BAR_PIP_BUTTON" = "PiP-Taste unter dem Video anzeigen"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Fügt unter dem Video eine PiP-Taste hinzu, um PiP auch ohne verlassen der App zu verwenden. App-Neustart erforderlich!"; - -"DISABLE_PIP_MINI_PLAYER" = "PiP für Miniplayer deaktivieren"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Deaktiviert PiP während videos im Miniplayer laufen."; - -"LEGACY_PIP" = "Legacy PiP"; -"LEGACY_PIP_DESC" = "Verwendet AVPlayerLayer für PiP. Dies behebt das Geschwindigkeitsproblem, entfernt aber auch die UHD-Optionen (2K/4K) aus allen Videos. App-Neustart erforderlich!"; - -"NON_BACKGROUNDABLE_PIP" = "Nicht-hintergrundfähiges PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Aktiviert PiP für nicht im Hintergrund laufende Videos."; - -"FAKE_YT_VERSION" = "Fake YouTube-Version"; -"FAKE_YT_VERSION_DESC" = "Setzt die YouTube-Version auf %@, sodass die PiP-Taste unter dem Videoplayer eventuell angezeigt wird."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube-Version %@ wurde nicht getestet und wird eventuell nicht von YouPiP unterstützt, bitte upgrade YouTube mindestens zur Version %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/en.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/en.lproj/Localizable.strings deleted file mode 100644 index c96914b..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Enabled"; -"ENABLED_DESC" = "App restart is required."; - -"USE_PIP_BUTTON" = "Use PiP Button"; -"USE_PIP_BUTTON_DESC" = "Adds a PiP button over the video control overlay to activate PiP instead of dismissing the app."; - -"USE_TAB_BAR_PIP_BUTTON" = "Use Video Tab Bar PiP Button"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Adds a PiP button in video tab bar to activate PiP instead of dismissing the app. App restart is required."; - -"DISABLE_PIP_MINI_PLAYER" = "Disable PiP for Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Disables PiP while playing a video in the mini player."; - -"LEGACY_PIP" = "Legacy PiP"; -"LEGACY_PIP_DESC" = "Uses AVPlayerLayer for PiP. This fixes speedup bug but may remove UHD options (2K/4K) from any videos. App restart is required."; - -"NON_BACKGROUNDABLE_PIP" = "Non-backgroundable PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Enables PiP for non-backgroundable video."; - -"FAKE_YT_VERSION" = "Fake YouTube version"; -"FAKE_YT_VERSION_DESC" = "Set YouTube version to %@ so that PiP button under video player may show."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube version %@ is not tested and may not be supported by YouPiP, please upgrade YouTube to at least version %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/es.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/es.lproj/Localizable.strings deleted file mode 100644 index 4195cf4..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/es.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Activado"; -"ENABLED_DESC" = "Es necesario reiniciar la aplicación"; - -"USE_PIP_BUTTON" = "Utilizar botón PiP"; -"USE_PIP_BUTTON_DESC" = "Añade un botón PiP sobre la superposición de control de vídeo para activar PiP en lugar de cerrar la aplicación"; - -"USE_TAB_BAR_PIP_BUTTON" = "Utiliza el botón PiP de la barra de pestañas de vídeo"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Añade un botón PiP en la barra de pestañas de vídeo para activar PiP en lugar de cerrar la aplicación. Es necesario reiniciar la aplicación"; - -"DISABLE_PIP_MINI_PLAYER" = "Desactiva PiP para Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Desactiva PiP mientras se reproduce un vídeo en el minirreproductor"; - -"LEGACY_PIP" = "PiP heredado"; -"LEGACY_PIP_DESC" = "Utiliza AVPlayerLayer para PiP. Esto corrige el error de velocidad, pero puede eliminar las opciones UHD (2K/4K) de cualquier vídeo. Es necesario reiniciar la aplicación"; - -"NON_BACKGROUNDABLE_PIP" = "PiP sin segundo plano"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Habilita PiP para videos sin segundo plano."; - -"FAKE_YT_VERSION" = "Versión falsa de YouTube"; -"FAKE_YT_VERSION_DESC" = "Establece la versión de YouTube en %@ para que se muestre el botón PiP bajo el reproductor de vídeo"; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "La versión %@ de YouTube no ha sido probada y puede no ser compatible con YouPiP, por favor actualice YouTube al menos a la versión %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/fr.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/fr.lproj/Localizable.strings deleted file mode 100644 index 5e3215b..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/fr.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Enabled"; -"ENABLED_DESC" = "Le redémarrage de l'application est nécessaire."; - -"USE_PIP_BUTTON" = "Utiliser le bouton PiP"; -"USE_PIP_BUTTON_DESC" = "Ajoute un bouton PiP sur la superposition de contrôle vidéo pour activer le PiP au lieu de quitter l'application"; - -"USE_TAB_BAR_PIP_BUTTON" = "Utilise le bouton PiP de la barre d'onglets vidéo"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Ajoute un bouton PiP dans la barre d'onglets vidéo pour activer le PiP au lieu de quitter l'application. Le redémarrage de l'application est nécessaire."; - -"DISABLE_PIP_MINI_PLAYER" = "Désactive le PiP pour le Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Désactive le PiP pendant la lecture d'une vidéo dans le mini-lecteur"; - -"LEGACY_PIP" = "PiP hérité"; -"LEGACY_PIP_DESC" = "Utilise AVPlayerLayer pour le PiP. Cela corrige le bug d'accélération mais supprime également les options UHD (2K/4K) de toutes les vidéos. Un redémarrage de l'application est nécessaire."; - -"NON_BACKGROUNDABLE_PIP" = "PiP non rétroactif"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Active le PiP pour les vidéos qui ne sont pas en arrière-plan"; - -"FAKE_YT_VERSION" = "Fausse version YouTube"; -"FAKE_YT_VERSION_DESC" = "Définir la version de YouTube à %@ pour que le bouton PiP sous le lecteur vidéo puisse s'afficher"; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "La version %@ de YouTube n'a pas été testée et peut ne pas être prise en charge par YouPiP, veuillez mettre à jour YouTube vers au moins la version %@"; \ No newline at end of file diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/hu.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/hu.lproj/Localizable.strings deleted file mode 100644 index d58bf91..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/hu.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Engedélyezve"; -"ENABLED_DESC" = "Az alkalmazás újraindítása szükséges."; - -"USE_PIP_BUTTON" = "Használja a PiP gombot"; -"USE_PIP_BUTTON_DESC" = "Adjon hozzá egy PiP gombot a videovezérlő fedvényéhez, hogy aktiválja a kép a képben funkciót az alkalmazás elvetése helyett."; - -"USE_TAB_BAR_PIP_BUTTON" = "Használja a Video Tab Bar PiP gombot"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Hozzáad egy PiP gombot a videó lap sávjához a kép a képben funkció aktiválásához az alkalmazás elvetése helyett. Az alkalmazás újraindítása szükséges."; - -"DISABLE_PIP_MINI_PLAYER" = "A PiP letiltása a Mini Player számára"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Letiltja a PiP-t videó lejátszása közben a minilejátszóban."; - -"LEGACY_PIP" = "Legacy PiP"; -"LEGACY_PIP_DESC" = "AVPlayerLayert használ a képben. Ez javítja a gyorsítási hibát, de eltávolíthatja az UHD opciókat (2K/4K) minden videóból. Az alkalmazás újraindítása szükséges."; - -"NON_BACKGROUNDABLE_PIP" = "Háttérben nem használható PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Engedélyezi a PiP-t a nem háttérrel ellátott videókhoz."; - -"FAKE_YT_VERSION" = "Hamis YouTube-verzió"; -"FAKE_YT_VERSION_DESC" = "Állítsa a YouTube verziót %@ értékre, hogy megjelenjen a videólejátszó alatti PiP gomb."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "A YouTube %@ verziója nincs tesztelve, és előfordulhat, hogy a YouPiP nem támogatja. Kérjük, frissítse a YouTube-ot legalább %@ verzióra"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/it.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/it.lproj/Localizable.strings deleted file mode 100644 index 13ace82..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/it.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Enabled"; -"ENABLED_DESC" = "È richiesto un riavvio dell'app."; - -"USE_PIP_BUTTON" = "Usa Bottone PiP"; -"USE_PIP_BUTTON_DESC" = "Aggiunge un bottone PiP tra i controlli in sovrimpressione al video per attivare il PiP invece di chiudere l'app."; - -"USE_TAB_BAR_PIP_BUTTON" = "Usa Bottone PiP nella Barra dei Tab"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Aggiunge un bottone PiP nella Barra dei Tab per attivare il PiP invece di chiudere l'app. È richiesto un riavvio dell'app."; - -"DISABLE_PIP_MINI_PLAYER" = "Disattiva PiP per Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Disattiva PiP durante la riproduzione nel mini player."; - -"LEGACY_PIP" = "Legacy PiP"; -"LEGACY_PIP_DESC" = "Usa AVPlayerLayer per PiP. Questo ripara il bug relativo all'accelerazione ma rimuove anche le opzioni UHD (2K/4K) da qualsiasi video. È richiesto un riavvio dell'app."; - -"NON_BACKGROUNDABLE_PIP" = "Non sullo sfondo PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Attiva PiP per i video che non possono essere messi sullo sfondo."; - -"FAKE_YT_VERSION" = "Versione YouTube falsa"; -"FAKE_YT_VERSION_DESC" = "Imposta la versione di Youtube a %@ in modo tale da poter mostrare il bottone PiP sotto al video."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube versione %@ non è stato testato e potrebbe non essere supportato da YouPiP, ti preghiamo di aggiorare YouTube almeno alla versione %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ja.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ja.lproj/Localizable.strings deleted file mode 100644 index f37c75e..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ja.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "有効"; -"ENABLED_DESC" = "アプリの再起動が必要です。"; - -"USE_PIP_BUTTON" = "PiPボタンを使用"; -"USE_PIP_BUTTON_DESC" = "ビデオコントロールオーバーレイの上にPiPボタンを追加しアプリを終了する代わりにPiPを起動できるようにします。"; - -"USE_TAB_BAR_PIP_BUTTON" = "動画タブバーPiPボタンを使用"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "ビデオタブバーにPiPボタンを追加しアプリを終了する代わりにPiPを起動できるようにします。アプリの再起動が必要です。"; - -"DISABLE_PIP_MINI_PLAYER" = "ミニプレーヤーでのPiPを無効化"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "ミニプレーヤーで再生している際にはPiPを無効化します。"; - -"LEGACY_PIP" = "レガシーPiP"; -"LEGACY_PIP_DESC" = "AVPlayerLayerをPiPに使用します。スピードアップのバグを修正しますが全ての動画からUHDオプション(2K/4K)を削除されます。アプリの再起動が必要です。"; - -"NON_BACKGROUNDABLE_PIP" = "非バックグラウンドPiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "非バックグラウンドのビデオのPiPを有効化します。"; - -"FAKE_YT_VERSION" = "YouTubeのバージョンを偽装"; -"FAKE_YT_VERSION_DESC" = "YouTubeをバージョン %@ に設定し、ビデオプレーヤー下のPiPボタンに表示させます。"; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTubeバージョン %@ はテストされておらずYouPiPがサポートされていません、YouTubeを最低でもバージョン %@ 以上にアップグレードしてください。"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ko.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ko.lproj/Localizable.strings deleted file mode 100644 index cbbc4e9..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ko.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "활성화"; -"ENABLED_DESC" = "앱 재시작이 필요합니다."; - -"USE_PIP_BUTTON" = "PiP 버튼 사용"; -"USE_PIP_BUTTON_DESC" = "영상 제어 오버레이 위에 PiP 버튼을 직접 추가하여 기존 PiP 방식과는 다른 방법으로 PiP를 활성화합니다."; - -"USE_TAB_BAR_PIP_BUTTON" = "비디오 툴바 PiP 버튼 사용"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "앱을 해제하는 대신 PiP를 활성화하기 위해 영상 탭 표시줄에 PiP 버튼을 추가합니다. 앱 재시작이 필요합니다."; - -"DISABLE_PIP_MINI_PLAYER" = "미니플레이어 PiP 비활성화"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "미니 플레이어에서 영상을 재생하고 있는동안 PiP를 비활성화 합니다."; - -"LEGACY_PIP" = "레거시 PiP"; -"LEGACY_PIP_DESC" = "PiP용 AVPlayerLayer를 사용합니다. 이것은 속도향상 버그를 수정하지만 모든 영상에서 UHD 옵션(2K/4K)이 제거됩니다. 앱 재시작이 필요합니다."; - -"NON_BACKGROUNDABLE_PIP" = "강제 백그라운드 PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "백그라운드가 되지 않는 영상에 PiP를 활성화합니다."; - -"FAKE_YT_VERSION" = "가짜 유튜브 버전"; -"FAKE_YT_VERSION_DESC" = "영상 플레이어 아래에 PiP 버튼이 나타날 수 있도록 YouTube 버전을 16.46.5로 설정합니다."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube 버전 %@는 테스트되지 않았으며 YouPiP에서 지원하지 않을 수 있습니다. YouTube를 버전 %@ 이상으로 업그레이드하세요."; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/nl.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/nl.lproj/Localizable.strings deleted file mode 100644 index 219942d..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/nl.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Enabled"; -"ENABLED_DESC" = "App herstart is vereist."; - -"USE_PIP_BUTTON" = "Gebruik PiP Knop"; -"USE_PIP_BUTTON_DESC" = "Voegt een PiP knop toe aan de Video Control Overlay om PiP te activeren in plaats van de app af te sluiten."; - -"USE_TAB_BAR_PIP_BUTTON" = "Gebruik de knop PiP van de Video-tabbalk"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Voegt een PiP-knop toe in de videotabbalk om PiP te activeren in plaats van de app af te sluiten. App herstart is vereist."; - -"DISABLE_PIP_MINI_PLAYER" = "Schakel PiP uit voor Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Schakelt PiP uit tijdens het afspelen van een video in de minispeler."; - -"LEGACY_PIP" = "Verouderd PiP"; -"LEGACY_PIP_DESC" = "Gebruikt AVPlayerLayer voor PiP. Dit lost versnellingsfouten op, maar verwijdert mogelijke UHD-opties (2K/4K) van alle video's. App herstart is vereist."; - -"NON_BACKGROUNDABLE_PIP" = "Niet-achtergrondgebonden PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Schakelt PiP in voor niet-achtergrondgebonden video."; - -"FAKE_YT_VERSION" = "Vals YouTube versie"; -"FAKE_YT_VERSION_DESC" = "Stel de YouTube-versie in op %@ zodat de PiP-knop onder de videospeler kan worden weergegeven."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube versie %@ is niet getest en wordt waarschijnlijk niet ondersteunt door YouPiP, gelieve YouTube te upgraden naar het nieuwste versie %@."; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/pt.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/pt.lproj/Localizable.strings deleted file mode 100644 index 9744393..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/pt.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Ativado"; -"ENABLED_DESC" = "A reinicialização do app é necessária."; - -"USE_PIP_BUTTON" = "Usar o Botão PiP"; -"USE_PIP_BUTTON_DESC" = "Adiciona um botão PiP sobre a sobreposição de controle de vídeo para ativar o PiP em vez de dispensar o aplicativo."; - -"USE_TAB_BAR_PIP_BUTTON" = "Usar o Botão PiP da Barra de Guia de Vídeo"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Adiciona um botão PiP na barra de guia de vídeo para ativar o PiP em vez de dispensar o aplicativo. A reinicialização do app é necessária."; - -"DISABLE_PIP_MINI_PLAYER" = "Desativar PiP para Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Desativa o PiP durante a reprodução de um vídeo no mini player."; - -"LEGACY_PIP" = "PiP Legado"; -"LEGACY_PIP_DESC" = "Usa AVPlayerLayer para o PiP. Isso corrige o bug de aceleração, mas também remove as opções UHD (2K/4K) de qualquer vídeo. A reinicialização do app é necessária."; - -"NON_BACKGROUNDABLE_PIP" = "PiP sem segundo plano"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Habilita PiP para vídeo sem segundo plano."; - -"FAKE_YT_VERSION" = "Versão Fake do YouTube"; -"FAKE_YT_VERSION_DESC" = "Define a versão do YouTube para %@ para que o botão PiP no player de vídeo possa ser exibido."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "A versão do YouTube %@ não foi testado e pode não ser compatível com o YouPiP, porfavor atualize o YouTube para pelo menos a versão %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ro.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ro.lproj/Localizable.strings deleted file mode 100644 index a49e272..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ro.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Enabled"; -"ENABLED_DESC" = "Este necesară repornirea aplicației."; - -"USE_PIP_BUTTON" = "Utilizare buton PiP"; -"USE_PIP_BUTTON_DESC" = "Adaugă un buton PiP deasupra controalelor video pentru a activa PiP, în loc să închideți aplicația."; - -"USE_TAB_BAR_PIP_BUTTON" = "Utilizare buton PiP în bara filei video"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Adaugă un buton PiP în bara filei video pentru a activa PiP, în loc să închideți aplicația. Este necesară repornirea aplicației."; - -"DISABLE_PIP_MINI_PLAYER" = "Dezactivare PiP pentru Mini Player"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Dezactivează PiP în timp ce este redat un videoclip în mini player."; - -"LEGACY_PIP" = "PiP Legacy"; -"LEGACY_PIP_DESC" = "Utilizează AVPlayerLayer pentru PiP. Acesta rezolvă bug-ul legat de viteza de redare, dar poate elimina opțiunile de calitate UHD (2K/4K) de la videoclip. Este necesară repornirea aplicației."; - -"NON_BACKGROUNDABLE_PIP" = "PiP neredabil în fundal"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Activează PiP pentru videoclipuri ce nu pot fi redate în fundal."; - -"FAKE_YT_VERSION" = "Versiune YouTube falsă"; -"FAKE_YT_VERSION_DESC" = "Setare versiune YouTube la %@ pentru a permite apariția butonului PiP sub player-ul video."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "Această versiune YouTube (%@) nu a fost testată și este posibil să nu fie suportată de YouPiP. Vă rugăm să actualizați YouTube cel puțin la versiunea %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ru.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index e35602b..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Активировать"; -"ENABLED_DESC" = "Потребуется перезапуск YouTube."; - -"USE_PIP_BUTTON" = "Активировать PiP вручную"; -"USE_PIP_BUTTON_DESC" = "Добавляет кнопку PiP (Картинка в Картинке) в панель навигации для активации PiP вручную. Включите данную опцию, чтобы PiP не срабатывал автоматически."; - -"USE_TAB_BAR_PIP_BUTTON" = "Использовать кнопку PiP под плеером"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Добавляет кнопку PiP (Картинка в Картинке) в панель под видео для активации PiP вручную. Включите данную опцию, чтобы PiP не срабатывал автоматически. Потребуется перезапуск YouTube."; - -"DISABLE_PIP_MINI_PLAYER" = "Отключить PiP для мини-плеера"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Предотвращает включение режима Картинка в Картинке, если видео проигрывается в мини-плеере."; - -"LEGACY_PIP" = "Старый вариант PiP"; -"LEGACY_PIP_DESC" = "На основе AVPlayerLayer, в котором нет багов со скоростью воспроизведения. Данный режим отключает воспроизведение видео в ультра высоком разрешении (2K/4K). Потребуется перезапуск YouTube."; - -"NON_BACKGROUNDABLE_PIP" = "Принудительный PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Активирует PiP (Картинка в Картинке) для контента, не поддерживающего PiP изначально."; - -"FAKE_YT_VERSION" = "Имитация старой версии YouTube"; -"FAKE_YT_VERSION_DESC" = "Понижает версию YouTube до %@, в которой корректно отображаются кнопки под плеером."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "Данная версия YouTube (%@) еще не протестирована и, возможно, неподдерживается YouPiP-ом. Понизьте YouTube, как минимум, до версии %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/tr.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/tr.lproj/Localizable.strings deleted file mode 100644 index a77a834..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/tr.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Etkinleştir"; -"ENABLED_DESC" = "Uygulamanın yeniden başlatılması gerekir."; - -"USE_PIP_BUTTON" = "PiP Düğmesini Kullan"; -"USE_PIP_BUTTON_DESC" = "Uygulamayı kapatmak yerine PiP'yi etkinleştirmek için video kontrol katmanının üzerine bir PiP düğmesi ekler."; - -"USE_TAB_BAR_PIP_BUTTON" = "Video Sekme Çubuğu PiP Düğmesini Kullan"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Uygulamayı arkaplana almak yerine PiP'yi etkinleştirmek için video sekme çubuğuna bir PiP düğmesi ekler. Uygulamanın yeniden başlatılması gerekir."; - -"DISABLE_PIP_MINI_PLAYER" = "Mini Oynatıcı için PiP'yi Devre Dışı Bırak"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "Mini oynatıcıda video oynatırken PiP'yi devre dışı bırakır."; - -"LEGACY_PIP" = "Eski PiP"; -"LEGACY_PIP_DESC" = "PiP için AVPlayerLayer'ı kullanır. Bu, hızlandırma hatasını düzeltir ancak herhangi bir videodan UHD seçeneklerini (2K/4K) kaldırabilir. Uygulamanın yeniden başlatılması gerekir."; - -"NON_BACKGROUNDABLE_PIP" = "Arkaplansız PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Arkaplansız video için PiP'yi etkinleştirir."; - -"FAKE_YT_VERSION" = "Sahte YouTube sürümü"; -"FAKE_YT_VERSION_DESC" = "Video oynatıcının altındaki PiP düğmesinin gösterilebilmesi için YouTube sürümünü %@ olarak ayarlayın."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube %@ sürümü test edilmemiştir ve YouPiP tarafından desteklenmeyebilir, lütfen YouTube'u en az %@ sürümüne yükseltin"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/vi.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/vi.lproj/Localizable.strings deleted file mode 100644 index 3312734..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/vi.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "Kích hoạt"; -"ENABLED_DESC" = "Cần khởi động lại ứng dụng."; - -"USE_PIP_BUTTON" = "Thêm nút kích hoạt PiP"; -"USE_PIP_BUTTON_DESC" = "Thêm một nút để kích hoạt PiP thủ công vào trong trình phát video, thay vì để PiP kích hoạt tự động khi ẩn ứng dụng."; - -"USE_TAB_BAR_PIP_BUTTON" = "Thêm nút kích hoạt PiP vào thanh Tab"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "Thêm một nút để kích hoạt PiP thủ công vào thanh Tab dưới video, thay vì để PiP kích hoạt tự động khi ẩn ứng dụng (chỉ hoạt động khi bạn bật tính năng Fake phiên bản của YouTube ở dưới)."; - -"DISABLE_PIP_MINI_PLAYER" = "Vô hiệu hóa PiP khi trình phát thu nhỏ đang chạy"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "PiP sẽ không tự động kích hoạt khi video đang chạy ở dạng trình phát thủ nhỏ."; - -"LEGACY_PIP" = "Legacy PiP"; -"LEGACY_PIP_DESC" = "Sử dụng AVPlayerLayer cho PiP. Bật tính năng này để sửa lỗi speed-up của YouPiP. Tuy nhiên, video sẽ bị mất chất lượng 2K/4K (nếu có), đồng thời tính năng lựa chọn chất lượng video mặc định của uYou cũng sẽ không hoạt động. Cần khởi động lại ứng dụng."; - -"NON_BACKGROUNDABLE_PIP" = "Non-backgroundable PiP"; -"NON_BACKGROUNDABLE_PIP_DESC" = "Cho phép PiP hoạt động với những video không cho chạy nền (không khuyến khích)."; - -"FAKE_YT_VERSION" = "Fake phiên bản của YouTube"; -"FAKE_YT_VERSION_DESC" = "Đánh lừa phiên bản của YouTube hiện tại thành phiên bản %@ để tính năng Thêm nút kích hoạt PiP vào thanh Tab có thể hoạt động."; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube phiên bản dưới %@ chưa được test và có thể không được hỗ trợ bởi YouPiP, vui lòng cập nhật YouTube lên ít nhất phiên bản %@"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay.png b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay.png deleted file mode 100644 index a23be8b..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay.png and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay@2x.png b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay@2x.png deleted file mode 100644 index 52b6c4e..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay@2x.png and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay@3x.png b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay@3x.png deleted file mode 100644 index c58cde7..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-overlay@3x.png and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar.png b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar.png deleted file mode 100644 index cd466a3..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar.png and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar@2x.png b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar@2x.png deleted file mode 100644 index e0fd0ed..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar@2x.png and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar@3x.png b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar@3x.png deleted file mode 100644 index cb6724a..0000000 Binary files a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/yt-pip-tabbar@3x.png and /dev/null differ diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/zh_cn.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/zh_cn.lproj/Localizable.strings deleted file mode 100644 index edb0c8f..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/zh_cn.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "启用"; -"ENABLED_DESC" = "更改本设置后需要重启App。"; - -"USE_PIP_BUTTON" = "使用画中画按钮"; -"USE_PIP_BUTTON_DESC" = "在视频播放器控制界面上显示用于手动启动画中画的按钮。开启本设置后,返回主屏幕时将不会启动画中画。"; - -"USE_TAB_BAR_PIP_BUTTON" = "使用视频标签栏画中画按钮"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "在视频标签栏处显示用于手动启动画中画的按钮。开启本设置后,返回主屏幕时将不会启动画中画。"; - -"DISABLE_PIP_MINI_PLAYER" = "禁用迷你播放器画中画"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "在使用迷你播放器时禁用画中画。"; - -"LEGACY_PIP" = "使用传统视频框架"; -"LEGACY_PIP_DESC" = "使用 AVPlayerLayer 来进行画中画以修复视频加速播放的问题,但同时也将禁用所有视频的 UHD (2K/4K)画质选项。更改本设置后需要重启App。"; - -"NON_BACKGROUNDABLE_PIP" = "强制画中画"; -"NON_BACKGROUNDABLE_PIP_DESC" = "为不支持后台播放的视频启用画中画。"; - -"FAKE_YT_VERSION" = "伪装 YouTube 版本"; -"FAKE_YT_VERSION_DESC" = "将 YouTube App 的版本设为 %@ 以尝试显示播放器下方的画中画按钮。"; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube App 版本 %@ 未经测试,可能不支持 YouPiP 画中画插件。请将 YouTube 更新至版本 %@ 或以上。"; diff --git a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/zh_tw.lproj/Localizable.strings b/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/zh_tw.lproj/Localizable.strings deleted file mode 100644 index 8d1b791..0000000 --- a/Tweaks/YouPiP/layout/Library/Application Support/YouPiP.bundle/zh_tw.lproj/Localizable.strings +++ /dev/null @@ -1,25 +0,0 @@ -// Settings - -"ENABLED" = "啟用"; -"ENABLED_DESC" = "需要重新啟動應用程式。"; - -"USE_PIP_BUTTON" = "使用子母畫面按鈕"; -"USE_PIP_BUTTON_DESC" = "在影片控制層上增加子母畫面按鈕以啟用子母畫面而不是關閉應用程式。"; - -"USE_TAB_BAR_PIP_BUTTON" = "使用影片標籤欄子母畫面按鈕"; -"USE_TAB_BAR_PIP_BUTTON_DESC" = "在影片標籤欄中增加子母畫面按鈕以啟用子母畫面而不是關閉應用程式。需要重新啟動應用程式。"; - -"DISABLE_PIP_MINI_PLAYER" = "為迷你播放器停用子母畫面"; -"DISABLE_PIP_MINI_PLAYER_DESC" = "在迷你播放器中播放影片時停用子母畫面。"; - -"LEGACY_PIP" = "傳統子母畫面(不建議使用)"; -"LEGACY_PIP_DESC" = "使用 AVPlayerLayer 進行子母畫面。這修復了加速錯誤,但也同時從影片中刪除了 UHD 選項(2K/4K)。需要重新啟動應用程式。"; - -"NON_BACKGROUNDABLE_PIP" = "非背景子母畫面"; -"NON_BACKGROUNDABLE_PIP_DESC" = "為非背景影片啟用子母畫面。"; - -"FAKE_YT_VERSION" = "假 YouTube 版本"; -"FAKE_YT_VERSION_DESC" = "將 YouTube 版本設定為 %@,讓子母畫面按鈕正常顯示。"; - -// Compatibility warning -"UNSUPPORTED_YT_VERSION" = "YouTube 版本 %@ 未經測試,YouPiP 可能不支援,請將 YouTube 升級 %@ 版本"; diff --git a/Tweaks/YouTubeHeader b/Tweaks/YouTubeHeader new file mode 160000 index 0000000..922e4e7 --- /dev/null +++ b/Tweaks/YouTubeHeader @@ -0,0 +1 @@ +Subproject commit 922e4e781083f808af6a5c42f575fda496bd52fa diff --git a/Tweaks/YouTubeHeader/.gitattributes b/Tweaks/YouTubeHeader/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Tweaks/YouTubeHeader/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Tweaks/YouTubeHeader/.gitignore b/Tweaks/YouTubeHeader/.gitignore deleted file mode 100644 index 9bea433..0000000 --- a/Tweaks/YouTubeHeader/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ - -.DS_Store diff --git a/Tweaks/YouTubeHeader/ASCollectionElement.h b/Tweaks/YouTubeHeader/ASCollectionElement.h deleted file mode 100644 index d1743f0..0000000 --- a/Tweaks/YouTubeHeader/ASCollectionElement.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface ASCollectionElement : NSObject -@end diff --git a/Tweaks/YouTubeHeader/ASCollectionView.h b/Tweaks/YouTubeHeader/ASCollectionView.h deleted file mode 100644 index f7d41ea..0000000 --- a/Tweaks/YouTubeHeader/ASCollectionView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface ASCollectionView : UICollectionView -@end diff --git a/Tweaks/YouTubeHeader/ASControlNode.h b/Tweaks/YouTubeHeader/ASControlNode.h deleted file mode 100644 index 56c0a7e..0000000 --- a/Tweaks/YouTubeHeader/ASControlNode.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "ASDisplayNode.h" - -@interface ASControlNode : ASDisplayNode -@end diff --git a/Tweaks/YouTubeHeader/ASDisplayNode.h b/Tweaks/YouTubeHeader/ASDisplayNode.h deleted file mode 100644 index c0d84b8..0000000 --- a/Tweaks/YouTubeHeader/ASDisplayNode.h +++ /dev/null @@ -1,21 +0,0 @@ -#import -#import "ASLayoutElementStyleYoga.h" - -@interface ASDisplayNode : NSObject -@property (atomic, copy, readwrite) NSArray *yogaChildren; -@property (nonatomic, copy, readwrite) NSString *accessibilityIdentifier; -@property (atomic, weak, readonly) ASDisplayNode *yogaParent; -@property (atomic, strong, readwrite) id contents; -@property (atomic, assign, readwrite) CGFloat alpha; -@property (atomic, assign, readwrite) CGRect frame; -@property (atomic, assign, readwrite) CGRect bounds; -@property (atomic, assign, readonly) unsigned char interfaceState; -@property (atomic, assign, readwrite, getter=isHidden) BOOL hidden; -@property (atomic, assign, readwrite, getter=isLayerBacked) BOOL layerBacked; -@property (atomic, assign, readwrite) BOOL automaticallyManagesSubnodes; -- (id)controller; -- (ASLayoutElementStyleYoga *)style; -- (UIViewController *)closestViewController; -- (UIView *)view; -- (BOOL)isNodeLoaded; -@end diff --git a/Tweaks/YouTubeHeader/ASLayoutElementStyleYoga.h b/Tweaks/YouTubeHeader/ASLayoutElementStyleYoga.h deleted file mode 100644 index f498d5f..0000000 --- a/Tweaks/YouTubeHeader/ASLayoutElementStyleYoga.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface ASLayoutElementStyleYoga : NSObject -@property (nonatomic, assign, readwrite) CGFloat spacingBefore; -@property (nonatomic, assign, readwrite) CGFloat spacingAfter; -@property (nonatomic, assign, readwrite) CGFloat flexGrow; -@property (nonatomic, assign, readwrite) CGFloat flexShrink; -@end diff --git a/Tweaks/YouTubeHeader/ASNodeContext.h b/Tweaks/YouTubeHeader/ASNodeContext.h deleted file mode 100644 index 72bd1cc..0000000 --- a/Tweaks/YouTubeHeader/ASNodeContext.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ASNodeContext : NSObject -- (instancetype)initWithOptions:(unsigned char)options; -- (unsigned char)options; -@end diff --git a/Tweaks/YouTubeHeader/ASNodeController.h b/Tweaks/YouTubeHeader/ASNodeController.h deleted file mode 100644 index 54190b6..0000000 --- a/Tweaks/YouTubeHeader/ASNodeController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface ASNodeController : NSObject -@end diff --git a/Tweaks/YouTubeHeader/ASTextNode.h b/Tweaks/YouTubeHeader/ASTextNode.h deleted file mode 100644 index 3af155f..0000000 --- a/Tweaks/YouTubeHeader/ASTextNode.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "ASControlNode.h" - -@interface ASTextNode : ASControlNode -@property (atomic, copy, readwrite) NSAttributedString *attributedText; -@end diff --git a/Tweaks/YouTubeHeader/ELMCellNode.h b/Tweaks/YouTubeHeader/ELMCellNode.h deleted file mode 100644 index b1e7272..0000000 --- a/Tweaks/YouTubeHeader/ELMCellNode.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "ASCellNode.h" -#import "ELMElement.h" - -@interface ELMCellNode : ASCellNode -@property (atomic, strong, readwrite) ELMElement *element; -@end diff --git a/Tweaks/YouTubeHeader/ELMContainerNode.h b/Tweaks/YouTubeHeader/ELMContainerNode.h deleted file mode 100644 index 3da5283..0000000 --- a/Tweaks/YouTubeHeader/ELMContainerNode.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "ELMElement.h" -#import "ASDisplayNode.h" - -@interface ELMContainerNode : ASDisplayNode -@property (atomic, strong, readwrite) ELMElement *element; -- (void)addYogaChild:(id)child; -- (void)addSubnode:(id)subnode; -@end diff --git a/Tweaks/YouTubeHeader/ELMElement.h b/Tweaks/YouTubeHeader/ELMElement.h deleted file mode 100644 index 4829cd4..0000000 --- a/Tweaks/YouTubeHeader/ELMElement.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ELMElement : NSObject -- (id)newChildElementWithInstance:(const void *)instance; -- (const void *)instance; -@end diff --git a/Tweaks/YouTubeHeader/ELMNodeController.h b/Tweaks/YouTubeHeader/ELMNodeController.h deleted file mode 100644 index 80c4b5c..0000000 --- a/Tweaks/YouTubeHeader/ELMNodeController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "ASNodeController.h" - -@interface ELMNodeController : ASNodeController -- (const void *)materializationContext; -@end diff --git a/Tweaks/YouTubeHeader/ELMNodeFactory.h b/Tweaks/YouTubeHeader/ELMNodeFactory.h deleted file mode 100644 index f0359ec..0000000 --- a/Tweaks/YouTubeHeader/ELMNodeFactory.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ELMNodeFactory : NSObject -+ (instancetype)sharedInstance; -- (id)nodeWithElement:(id)element materializationContext:(const void *)context; -@end diff --git a/Tweaks/YouTubeHeader/ELMTextNode.h b/Tweaks/YouTubeHeader/ELMTextNode.h deleted file mode 100644 index 0226c9f..0000000 --- a/Tweaks/YouTubeHeader/ELMTextNode.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "ASTextNode.h" -#import "ELMElement.h" - -@interface ELMTextNode : ASTextNode -@property (atomic, strong, readwrite) ELMElement *element; -- (instancetype)initWithElement:(ELMElement *)element context:(id)context; -@end diff --git a/Tweaks/YouTubeHeader/GIMBindingBuilder.h b/Tweaks/YouTubeHeader/GIMBindingBuilder.h deleted file mode 100644 index f7629bf..0000000 --- a/Tweaks/YouTubeHeader/GIMBindingBuilder.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface GIMBindingBuilder : NSObject -- (instancetype)bindType:(Class)typeClass; -- (instancetype)initializedWith:(id (^)(id))block; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/GIMMe.h b/Tweaks/YouTubeHeader/GIMMe.h deleted file mode 100644 index c6d5aed..0000000 --- a/Tweaks/YouTubeHeader/GIMMe.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface GIMMe : NSObject -+ (instancetype)gimme; -- (instancetype)allocOf:(Class)cls; -- (id)nullableInstanceForType:(id)type; -- (id)instanceForType:(id)type; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/GOOAlertView.h b/Tweaks/YouTubeHeader/GOOAlertView.h deleted file mode 100644 index 00ebf1f..0000000 --- a/Tweaks/YouTubeHeader/GOOAlertView.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GOOModalView.h" - -@interface GOOAlertView : GOOModalView -@property (nonatomic, copy, readwrite) NSString *title; -@property (nonatomic, readonly, strong) UILabel *titleLabel; -@property (nonatomic, copy, readwrite) NSString *subtitle; -@property (nonatomic, readonly, strong) UILabel *subtitleLabel; -@property (nonatomic, readwrite, copy) UIImage *icon; -+ (instancetype)dialog; -+ (instancetype)infoDialog; -+ (instancetype)confirmationDialog; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelTitle:(NSString *)cancelTitle; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelAction:(void (^)(void))cancelAction cancelTitle:(NSString *)cancelTitle; -+ (instancetype)confirmationDialogWithSelector:(SEL)selector actionTitle:(NSString *)actionTitle; -+ (instancetype)confirmationDialogWithSelector:(SEL)selector actionTitle:(NSString *)actionTitle showsCancelButton:(BOOL)showsCancelButton; -- (void)addCancelButton:(SEL)selector; -- (void)addCancelButtonWithAction:(void (^)(void))action; -@end diff --git a/Tweaks/YouTubeHeader/GOOModalView.h b/Tweaks/YouTubeHeader/GOOModalView.h deleted file mode 100644 index b1c929e..0000000 --- a/Tweaks/YouTubeHeader/GOOModalView.h +++ /dev/null @@ -1,18 +0,0 @@ -#import - -@interface GOOModalView : UIView -@property (nonatomic, readwrite, weak) id target; -@property (nonatomic, readwrite, assign) BOOL shouldDismissOnBackgroundTap; -@property (nonatomic, readwrite, assign) BOOL shouldDismissOnApplicationBackground; -- (instancetype)initWithTarget:(id)target; -- (void)addTitle:(NSString *)title withAction:(void (^)(void))action; -- (void)addTitle:(NSString *)title withDestructiveAction:(void (^)(void))action; -- (void)addTitle:(NSString *)title withSelector:(SEL)selector; -- (void)addTitle:(NSString *)title withCancelSelector:(SEL)cancelSelector; -- (void)addTitle:(NSString *)title withDestructiveSelector:(SEL)cancelSelector; -- (void)addTitle:(NSString *)title iconImage:(UIImage *)iconImage withAction:(void (^)(void))action; -- (void)addTitle:(NSString *)title iconImage:(UIImage *)iconImage withSelector:(SEL)selector; -- (void)show; -- (void)cancel; -- (void)dismiss; -@end diff --git a/Tweaks/YouTubeHeader/GPBExtensionDescriptor.h b/Tweaks/YouTubeHeader/GPBExtensionDescriptor.h deleted file mode 100644 index c3d5e49..0000000 --- a/Tweaks/YouTubeHeader/GPBExtensionDescriptor.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface GPBExtensionDescriptor : NSObject -- (Class)msgClass; -@end diff --git a/Tweaks/YouTubeHeader/GPBExtensionRegistry.h b/Tweaks/YouTubeHeader/GPBExtensionRegistry.h deleted file mode 100644 index 87850c8..0000000 --- a/Tweaks/YouTubeHeader/GPBExtensionRegistry.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface GPBExtensionRegistry : NSObject -- (void)addExtension:(id)extension; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/GPBMessage.h b/Tweaks/YouTubeHeader/GPBMessage.h deleted file mode 100644 index 4bd822e..0000000 --- a/Tweaks/YouTubeHeader/GPBMessage.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface GPBMessage : NSObject -- (id)firstSubmessage; -@end diff --git a/Tweaks/YouTubeHeader/HAMAsyncVTVideoDecoder.h b/Tweaks/YouTubeHeader/HAMAsyncVTVideoDecoder.h deleted file mode 100644 index fb53cfd..0000000 --- a/Tweaks/YouTubeHeader/HAMAsyncVTVideoDecoder.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface HAMAsyncVTVideoDecoder : NSObject -- (instancetype)initWithDelegate:(id)delegate delegateQueue:(id)delegateQueue decodeQueue:(id)decodeQueue formatDescription:(id)formatDescription pixelBufferAttributes:(id)pixelBufferAttributes; -@end diff --git a/Tweaks/YouTubeHeader/HAMMIMEType.h b/Tweaks/YouTubeHeader/HAMMIMEType.h deleted file mode 100644 index 1af1157..0000000 --- a/Tweaks/YouTubeHeader/HAMMIMEType.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface HAMMIMEType : NSObject -- (unsigned int)audioCodec; -- (unsigned int)videoCodec; -@end diff --git a/Tweaks/YouTubeHeader/HAMPixelBufferRenderingView.h b/Tweaks/YouTubeHeader/HAMPixelBufferRenderingView.h deleted file mode 100644 index 3c5b9c5..0000000 --- a/Tweaks/YouTubeHeader/HAMPixelBufferRenderingView.h +++ /dev/null @@ -1,2 +0,0 @@ -@protocol HAMPixelBufferRenderingView -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/HAMSBDLSampleBufferRenderingView.h b/Tweaks/YouTubeHeader/HAMSBDLSampleBufferRenderingView.h deleted file mode 100644 index 6796c65..0000000 --- a/Tweaks/YouTubeHeader/HAMSBDLSampleBufferRenderingView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface HAMSBDLSampleBufferRenderingView : UIView -@property (retain, nonatomic, readonly) AVSampleBufferDisplayLayer *displayLayer; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/LICENSE b/Tweaks/YouTubeHeader/LICENSE deleted file mode 100644 index 94533be..0000000 --- a/Tweaks/YouTubeHeader/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 - 2022 PoomSmart - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Tweaks/YouTubeHeader/MLABRPolicy.h b/Tweaks/YouTubeHeader/MLABRPolicy.h deleted file mode 100644 index 959ff3e..0000000 --- a/Tweaks/YouTubeHeader/MLABRPolicy.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface MLABRPolicy : NSObject -- (void)requestFormatReselection; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLABRPolicyFormatData.h b/Tweaks/YouTubeHeader/MLABRPolicyFormatData.h deleted file mode 100644 index ab122c1..0000000 --- a/Tweaks/YouTubeHeader/MLABRPolicyFormatData.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLFormat.h" - -@interface MLABRPolicyFormatData : NSObject -- (instancetype)initWithFormat:(MLFormat *)format; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLABRPolicyNew.h b/Tweaks/YouTubeHeader/MLABRPolicyNew.h deleted file mode 100644 index bc3cd18..0000000 --- a/Tweaks/YouTubeHeader/MLABRPolicyNew.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLABRPolicy.h" - -// YouTube 17.30.3 and higher -@interface MLABRPolicyNew : MLABRPolicy -@end diff --git a/Tweaks/YouTubeHeader/MLABRPolicyOld.h b/Tweaks/YouTubeHeader/MLABRPolicyOld.h deleted file mode 100644 index f036b2b..0000000 --- a/Tweaks/YouTubeHeader/MLABRPolicyOld.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLABRPolicy.h" - -// YouTube 17.30.3 and higher -@interface MLABRPolicyOld : MLABRPolicy -@end diff --git a/Tweaks/YouTubeHeader/MLAVAssetPlayer.h b/Tweaks/YouTubeHeader/MLAVAssetPlayer.h deleted file mode 100644 index 020d83c..0000000 --- a/Tweaks/YouTubeHeader/MLAVAssetPlayer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface MLAVAssetPlayer : NSObject -- (AVPlayerItem *)playerItem; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLAVPIPPlayerLayerView.h b/Tweaks/YouTubeHeader/MLAVPIPPlayerLayerView.h deleted file mode 100644 index bea392e..0000000 --- a/Tweaks/YouTubeHeader/MLAVPIPPlayerLayerView.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "MLAVPlayerLayerView.h" -#import "MLAVPlayer.h" -#import "MLAVPlayerViewDelegate.h" - -@interface MLAVPIPPlayerLayerView : MLAVPlayerLayerView -@property (nonatomic, readonly, strong) AVPlayerLayer *playerLayer; -@property (nonatomic, readwrite, weak) NSObject *delegate; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLAVPlayer.h b/Tweaks/YouTubeHeader/MLAVPlayer.h deleted file mode 100644 index 21e7270..0000000 --- a/Tweaks/YouTubeHeader/MLAVPlayer.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "MLAVAssetPlayer.h" -#import "MLInnerTubePlayerConfig.h" -#import "MLPlayerViewProtocol.h" -#import "MLPlayerStickySettings.h" - -@interface MLAVPlayer : NSObject -@property (nonatomic, readwrite, assign) BOOL active; -@property (nonatomic, readonly, assign) BOOL externalPlaybackActive; -@property (nonatomic, readwrite, assign) float rate; -@property (nonatomic, readonly, strong) MLVideo *video; -@property (nonatomic, readonly, strong) MLInnerTubePlayerConfig *config; -@property (nonatomic, readonly, strong) MLAVAssetPlayer *assetPlayer; -@property (nonatomic, readwrite, strong) UIView *renderingView; -- (instancetype)initWithVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings externalPlaybackActive:(BOOL)externalPlaybackActive; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLAVPlayerLayerView.h b/Tweaks/YouTubeHeader/MLAVPlayerLayerView.h deleted file mode 100644 index cc2a684..0000000 --- a/Tweaks/YouTubeHeader/MLAVPlayerLayerView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLPlayerViewProtocol.h" -#import "HAMPixelBufferRenderingView.h" - -@interface MLAVPlayerLayerView : UIView -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLAVPlayerViewDelegate.h b/Tweaks/YouTubeHeader/MLAVPlayerViewDelegate.h deleted file mode 100644 index 85c6e00..0000000 --- a/Tweaks/YouTubeHeader/MLAVPlayerViewDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@protocol MLAVPlayerViewDelegate -@required -- (void)playerViewErrorDidOccur:(id)arg1; -@end diff --git a/Tweaks/YouTubeHeader/MLDefaultPlayerViewFactory.h b/Tweaks/YouTubeHeader/MLDefaultPlayerViewFactory.h deleted file mode 100644 index 7c3523f..0000000 --- a/Tweaks/YouTubeHeader/MLDefaultPlayerViewFactory.h +++ /dev/null @@ -1,10 +0,0 @@ -#include "GIMMe.h" -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" -#import "MLAVPlayerLayerView.h" - -@interface MLDefaultPlayerViewFactory : NSObject -@property (nonatomic, weak, readwrite) GIMMe *gimme; -- (BOOL)canUsePlayerView:(UIView *)playerView forVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)config; -- (MLAVPlayerLayerView *)AVPlayerViewForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)config; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLFormat.h b/Tweaks/YouTubeHeader/MLFormat.h deleted file mode 100644 index 8cdf045..0000000 --- a/Tweaks/YouTubeHeader/MLFormat.h +++ /dev/null @@ -1,17 +0,0 @@ -#import -#import "HAMMIMEType.h" -#import "YTIFormatStream.h" - -@interface MLFormat : NSObject -- (HAMMIMEType *)MIMEType; -- (YTIFormatStream *)formatStream; -- (NSURL *)URL; -- (int)width; -- (int)height; -- (int)singleDimensionResolution; -- (CGFloat)FPS; -- (BOOL)isAudio; -- (BOOL)isVideo; -- (BOOL)isText; -- (NSInteger)compareByQuality:(MLFormat *)format; -@end diff --git a/Tweaks/YouTubeHeader/MLHAMPlayer.h b/Tweaks/YouTubeHeader/MLHAMPlayer.h deleted file mode 100644 index 240626b..0000000 --- a/Tweaks/YouTubeHeader/MLHAMPlayer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" -#import "MLPlayerStickySettings.h" - -@interface MLHAMPlayer : NSObject -- (instancetype)initWithVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings playerViewProvider:(id)playerViewProvider; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLHAMPlayerItem.h b/Tweaks/YouTubeHeader/MLHAMPlayerItem.h deleted file mode 100644 index 125640d..0000000 --- a/Tweaks/YouTubeHeader/MLHAMPlayerItem.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "MLABRPolicy.h" -#import "MLFormat.h" -#import "MLInnerTubePlayerConfig.h" - -@interface MLHAMPlayerItem : NSObject -@property (nonatomic, readonly, strong) MLInnerTubePlayerConfig *config; -- (void)ABRPolicy:(MLABRPolicy *)policy selectableFormatsDidChange:(NSArray *)formats; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLHAMPlayerViewProtocol.h b/Tweaks/YouTubeHeader/MLHAMPlayerViewProtocol.h deleted file mode 100644 index 449dc58..0000000 --- a/Tweaks/YouTubeHeader/MLHAMPlayerViewProtocol.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" - -@protocol MLHAMPlayerViewProtocol -- (void)makeActivePlayer; -- (void)setVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLHAMQueuePlayer.h b/Tweaks/YouTubeHeader/MLHAMQueuePlayer.h deleted file mode 100644 index 9d9b16a..0000000 --- a/Tweaks/YouTubeHeader/MLHAMQueuePlayer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "MLHAMPlayer.h" - -@interface MLHAMQueuePlayer : MLHAMPlayer -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLHAMSBDLSampleBufferRenderingView.h b/Tweaks/YouTubeHeader/MLHAMSBDLSampleBufferRenderingView.h deleted file mode 100644 index 374db3c..0000000 --- a/Tweaks/YouTubeHeader/MLHAMSBDLSampleBufferRenderingView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "HAMSBDLSampleBufferRenderingView.h" - -@interface MLHAMSBDLSampleBufferRenderingView : HAMSBDLSampleBufferRenderingView -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLInnerTubePlayerConfig.h b/Tweaks/YouTubeHeader/MLInnerTubePlayerConfig.h deleted file mode 100644 index 669f452..0000000 --- a/Tweaks/YouTubeHeader/MLInnerTubePlayerConfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIMediaCommonConfig.h" -#import "YTIHamplayerConfig.h" - -@interface MLInnerTubePlayerConfig : NSObject -@property (nonatomic, readonly, strong) YTIMediaCommonConfig *mediaCommonConfig; -@property (nonatomic, readonly, strong) YTIHamplayerConfig *hamplayerConfig; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLOnesieVideoData.h b/Tweaks/YouTubeHeader/MLOnesieVideoData.h deleted file mode 100644 index 2a595af..0000000 --- a/Tweaks/YouTubeHeader/MLOnesieVideoData.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLOnesieVideoData : NSObject -@end diff --git a/Tweaks/YouTubeHeader/MLPIPController.h b/Tweaks/YouTubeHeader/MLPIPController.h deleted file mode 100644 index 7e9182a..0000000 --- a/Tweaks/YouTubeHeader/MLPIPController.h +++ /dev/null @@ -1,24 +0,0 @@ -#import -#import "MLAVPIPPlayerLayerView.h" -#import "MLHAMSBDLSampleBufferRenderingView.h" - -@interface MLPIPController : NSObject -@property (nonatomic, strong, readwrite) MLAVPIPPlayerLayerView *AVPlayerView; -@property (nonatomic, strong, readwrite) MLHAMSBDLSampleBufferRenderingView *HAMPlayerView; -- (instancetype)initWithPlaceholderPlayerItem:(AVPlayerItem *)playerItem; // Deprecated -- (instancetype)initWithPlaceholderPlayerItemResourcePath:(NSString *)placeholderPath; // Deprecated -- (AVPictureInPictureControllerContentSource *)newContentSource API_AVAILABLE(ios(15.0)); -- (BOOL)isPictureInPictureSupported; -- (BOOL)isPictureInPictureActive; // Deprecated -- (BOOL)pictureInPictureActive; -- (BOOL)contentSourceNeedsRefresh; -- (CGSize)renderSizeForView:(UIView *)view; -- (BOOL)startPictureInPicture; // Deprecated -- (void)stopPictureInPicture; // Deprecated -- (void)addPIPControllerObserver:(id)observer; -- (void)activatePiPController; -- (void)deactivatePiPController; -- (void)pictureInPictureControllerStartPlayback; -- (void)pictureInPictureControllerStopPlayback; -- (void)pause; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLPlayerPool.h b/Tweaks/YouTubeHeader/MLPlayerPool.h deleted file mode 100644 index 9c5c122..0000000 --- a/Tweaks/YouTubeHeader/MLPlayerPool.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "GIMMe.h" -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" - -@interface MLPlayerPool : NSObject -@property (nonatomic, weak, readwrite) GIMMe *gimme; -- (void)createHamResourcesForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLPlayerPoolImpl.h b/Tweaks/YouTubeHeader/MLPlayerPoolImpl.h deleted file mode 100644 index 4a81310..0000000 --- a/Tweaks/YouTubeHeader/MLPlayerPoolImpl.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLPlayerPoolImpl : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLPlayerStickySettings.h b/Tweaks/YouTubeHeader/MLPlayerStickySettings.h deleted file mode 100644 index a764218..0000000 --- a/Tweaks/YouTubeHeader/MLPlayerStickySettings.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface MLPlayerStickySettings : NSObject -@property (assign) float rate; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLPlayerViewProtocol.h b/Tweaks/YouTubeHeader/MLPlayerViewProtocol.h deleted file mode 100644 index 3b63622..0000000 --- a/Tweaks/YouTubeHeader/MLPlayerViewProtocol.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" - -@protocol MLPlayerViewProtocol -- (void)makeActivePlayer; -- (void)setVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLQOEPingController.h b/Tweaks/YouTubeHeader/MLQOEPingController.h deleted file mode 100644 index f52b8a9..0000000 --- a/Tweaks/YouTubeHeader/MLQOEPingController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLQOEPingController : NSObject -@end diff --git a/Tweaks/YouTubeHeader/MLRemoteStream.h b/Tweaks/YouTubeHeader/MLRemoteStream.h deleted file mode 100644 index e5fae59..0000000 --- a/Tweaks/YouTubeHeader/MLRemoteStream.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIFormatStream.h" -#import "MLFormat.h" - -@interface MLRemoteStream : MLFormat -+ (instancetype)streamWithFormatStream:(YTIFormatStream *)formatStream; -@end diff --git a/Tweaks/YouTubeHeader/MLStreamingData.h b/Tweaks/YouTubeHeader/MLStreamingData.h deleted file mode 100644 index bff45a0..0000000 --- a/Tweaks/YouTubeHeader/MLStreamingData.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLRemoteStream.h" - -@interface MLStreamingData : NSObject -- (NSArray *)adaptiveStreams; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/MLVideo.h b/Tweaks/YouTubeHeader/MLVideo.h deleted file mode 100644 index 1bbab10..0000000 --- a/Tweaks/YouTubeHeader/MLVideo.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLStreamingData.h" -#import "YTIVideoDetails.h" - -@interface MLVideo : NSObject -- (MLStreamingData *)streamingData; -- (YTIVideoDetails *)videoDetails; -@end diff --git a/Tweaks/YouTubeHeader/MLVideoDecoderFactory.h b/Tweaks/YouTubeHeader/MLVideoDecoderFactory.h deleted file mode 100644 index a095cc1..0000000 --- a/Tweaks/YouTubeHeader/MLVideoDecoderFactory.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLVideoDecoderFactory : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/QTMIcon.h b/Tweaks/YouTubeHeader/QTMIcon.h deleted file mode 100644 index 7aa92c5..0000000 --- a/Tweaks/YouTubeHeader/QTMIcon.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface QTMIcon : NSObject -+ (UIImage *)imageWithName:(NSString *)name color:(UIColor *)color; -+ (UIImage *)tintImage:(UIImage *)image color:(UIColor *)color; -@end diff --git a/Tweaks/YouTubeHeader/README.md b/Tweaks/YouTubeHeader/README.md deleted file mode 100644 index 9937377..0000000 --- a/Tweaks/YouTubeHeader/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# YouTubeHeader - -Headers for iOS YouTube app. diff --git a/Tweaks/YouTubeHeader/UIView+AsyncDisplayKit.h b/Tweaks/YouTubeHeader/UIView+AsyncDisplayKit.h deleted file mode 100644 index 368f38c..0000000 --- a/Tweaks/YouTubeHeader/UIView+AsyncDisplayKit.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "ASDisplayNode.h" - -@interface UIView (AsyncDisplayKit) -- (void)addSubnode:(ASDisplayNode *)subnode; -@end diff --git a/Tweaks/YouTubeHeader/UIView+YouTube.h b/Tweaks/YouTubeHeader/UIView+YouTube.h deleted file mode 100644 index 235e899..0000000 --- a/Tweaks/YouTubeHeader/UIView+YouTube.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface UIView (YouTube) -- (BOOL)yt_isVisible; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTActionSheetAction.h b/Tweaks/YouTubeHeader/YTActionSheetAction.h deleted file mode 100644 index fcf8fe0..0000000 --- a/Tweaks/YouTubeHeader/YTActionSheetAction.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTActionSheetAction : NSObject -+ (instancetype)actionWithTitle:(NSString *)title style:(NSInteger)style handler:(void (^)(YTActionSheetAction *))handler; -+ (instancetype)actionWithTitle:(NSString *)title iconImage:(UIImage *)iconImage style:(NSInteger)style handler:(void (^)(YTActionSheetAction *))handler; -+ (instancetype)actionWithTitle:(NSString *)title subtitle:(NSString *)subtitle iconImage:(UIImage *)iconImage handler:(void (^)(YTActionSheetAction *))handler; -+ (instancetype)actionWithTitle:(NSString *)title subtitle:(NSString *)subtitle iconImage:(UIImage *)iconImage accessibilityIdentifier:(NSString *)accessibilityIdentifier handler:(void (^)(YTActionSheetAction *))handler; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTActionSheetController.h b/Tweaks/YouTubeHeader/YTActionSheetController.h deleted file mode 100644 index d64cf6a..0000000 --- a/Tweaks/YouTubeHeader/YTActionSheetController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTActionSheetController : NSObject -+ (instancetype)actionSheetController; -- (void)addCancelActionIfNeeded; -- (void)presentFromViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTAlertView.h b/Tweaks/YouTubeHeader/YTAlertView.h deleted file mode 100644 index 8af4386..0000000 --- a/Tweaks/YouTubeHeader/YTAlertView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "GOOAlertView.h" - -@interface YTAlertView : GOOAlertView -+ (instancetype)yt_dialog; -- (void)removeDefaultPadding; -@end diff --git a/Tweaks/YouTubeHeader/YTAppDelegate.h b/Tweaks/YouTubeHeader/YTAppDelegate.h deleted file mode 100644 index 981a36d..0000000 --- a/Tweaks/YouTubeHeader/YTAppDelegate.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTAppDelegate : UIResponder -@end diff --git a/Tweaks/YouTubeHeader/YTAppSettingsSectionItemActionController.h b/Tweaks/YouTubeHeader/YTAppSettingsSectionItemActionController.h deleted file mode 100644 index d9d59c2..0000000 --- a/Tweaks/YouTubeHeader/YTAppSettingsSectionItemActionController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTAppSettingsSectionItemActionController : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTAppSettingsStore.h b/Tweaks/YouTubeHeader/YTAppSettingsStore.h deleted file mode 100644 index f90bd93..0000000 --- a/Tweaks/YouTubeHeader/YTAppSettingsStore.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -@interface YTAppSettingsStore : NSObject -+ (NSUInteger)valueTypeForSetting:(int)setting; -- (void)setValue:(NSNumber *)value forSetting:(int)setting; -- (void)setBool:(BOOL)value forSetting:(int)setting; -- (NSNumber *)valueForSetting:(int)setting; -- (BOOL)boolForSetting:(int)setting; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTAsyncCollectionView.h b/Tweaks/YouTubeHeader/YTAsyncCollectionView.h deleted file mode 100644 index 381ccaf..0000000 --- a/Tweaks/YouTubeHeader/YTAsyncCollectionView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "ASCollectionView.h" - -@interface YTAsyncCollectionView : ASCollectionView -@end diff --git a/Tweaks/YouTubeHeader/YTAutonavEndscreenController.h b/Tweaks/YouTubeHeader/YTAutonavEndscreenController.h deleted file mode 100644 index d0a0f77..0000000 --- a/Tweaks/YouTubeHeader/YTAutonavEndscreenController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTAutonavEndscreenController : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTBackgroundabilityPolicy.h b/Tweaks/YouTubeHeader/YTBackgroundabilityPolicy.h deleted file mode 100644 index 1557312..0000000 --- a/Tweaks/YouTubeHeader/YTBackgroundabilityPolicy.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTBackgroundabilityPolicy : NSObject -- (void)addBackgroundabilityPolicyObserver:(id)observer; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTCellController.h b/Tweaks/YouTubeHeader/YTCellController.h deleted file mode 100644 index 889d924..0000000 --- a/Tweaks/YouTubeHeader/YTCellController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import "YTCollectionViewCellProtocol.h" - -@interface YTCellController : NSObject -@property (nonatomic, weak, readwrite) UICollectionViewCell *cell; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTColdConfig.h b/Tweaks/YouTubeHeader/YTColdConfig.h deleted file mode 100644 index 5f9a848..0000000 --- a/Tweaks/YouTubeHeader/YTColdConfig.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTColdConfig : NSObject -@end diff --git a/Tweaks/YouTubeHeader/YTCollectionViewCell.h b/Tweaks/YouTubeHeader/YTCollectionViewCell.h deleted file mode 100644 index 8bcd2db..0000000 --- a/Tweaks/YouTubeHeader/YTCollectionViewCell.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlideForActionsView.h" - -@interface YTCollectionViewCell : UICollectionViewCell -@property (nonatomic, strong, readwrite) YTSlideForActionsView *slideForActionsView; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTCollectionViewCellProtocol.h b/Tweaks/YouTubeHeader/YTCollectionViewCellProtocol.h deleted file mode 100644 index b16ffda..0000000 --- a/Tweaks/YouTubeHeader/YTCollectionViewCellProtocol.h +++ /dev/null @@ -1,2 +0,0 @@ -@protocol YTCollectionViewCellProtocol -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTColor.h b/Tweaks/YouTubeHeader/YTColor.h deleted file mode 100644 index 95b070f..0000000 --- a/Tweaks/YouTubeHeader/YTColor.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTColor : NSObject -+ (UIColor *)white1; -+ (UIColor *)black1; -+ (UIColor *)black2; -+ (UIColor *)black3; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTColorPalette.h b/Tweaks/YouTubeHeader/YTColorPalette.h deleted file mode 100644 index 6388c0d..0000000 --- a/Tweaks/YouTubeHeader/YTColorPalette.h +++ /dev/null @@ -1,67 +0,0 @@ -#import -#import - -// Deprecated, use YTCommonColorPalette -@interface YTColorPalette : NSObject -+ (instancetype)lightPalette; -+ (instancetype)darkPalette; -+ (instancetype)colorPaletteForPageStyle:(NSInteger)pageStyle; -- (NSInteger)pageStyle; -- (UIColor *)background1; -- (UIColor *)background2; -- (UIColor *)background3; -- (UIColor *)brandBackgroundSolid; -- (UIColor *)brandBackgroundPrimary; -- (UIColor *)brandBackgroundSecondary; -- (UIColor *)generalBackgroundA; -- (UIColor *)generalBackgroundB; -- (UIColor *)generalBackgroundC; -- (UIColor *)errorBackground; -- (UIColor *)textPrimary; -- (UIColor *)textSecondary; -- (UIColor *)textDisabled; -- (UIColor *)textPrimaryInverse; -- (UIColor *)callToAction; -- (UIColor *)iconActive; -- (UIColor *)iconActiveOther; -- (UIColor *)iconInactive; -- (UIColor *)iconDisabled; -- (UIColor *)badgeChipBackground; -- (UIColor *)buttonChipBackgroundHover; -- (UIColor *)touchResponse; -- (UIColor *)callToActionInverse; -- (UIColor *)brandIconActive; -- (UIColor *)brandIconInactive; -- (UIColor *)brandButtonBackground; -- (UIColor *)brandLinkText; -- (UIColor *)tenPercentLayer; -- (UIColor *)snackbarBackground; -- (UIColor *)themedBlue; -- (UIColor *)themedGreen; -- (UIColor *)staticBrandRed; -- (UIColor *)staticBrandWhite; -- (UIColor *)staticBrandBlack; -- (UIColor *)staticClearColor; -- (UIColor *)staticAdYellow; -- (UIColor *)staticGrey; -- (UIColor *)overlayBackgroundSolid; -- (UIColor *)overlayBackgroundHeavy; -- (UIColor *)overlayBackgroundMedium; -- (UIColor *)overlayBackgroundMediumLight; -- (UIColor *)overlayBackgroundLight; -- (UIColor *)overlayTextPrimary; -- (UIColor *)overlayTextSecondary; -- (UIColor *)overlayTextTertiary; -- (UIColor *)overlayIconActiveCallToAction; -- (UIColor *)overlayIconActiveOther; -- (UIColor *)overlayIconInactive; -- (UIColor *)overlayIconDisabled; -- (UIColor *)overlayFilledButtonActive; -- (UIColor *)overlayButtonSecondary; -- (UIColor *)overlayButtonPrimary; -- (UIColor *)overlayBackgroundBrand; -- (UIColor *)overlayBackgroundClear; -- (UIColor *)verifiedBadgeBackground; -- (UIColor *)themedOverlayBackground; -- (UIColor *)adIndicator; -@end diff --git a/Tweaks/YouTubeHeader/YTCommonColorPalette.h b/Tweaks/YouTubeHeader/YTCommonColorPalette.h deleted file mode 100644 index 16585a7..0000000 --- a/Tweaks/YouTubeHeader/YTCommonColorPalette.h +++ /dev/null @@ -1,74 +0,0 @@ -#import -#import - -// YouTube 17.19.2 and higher -@interface YTCommonColorPalette : NSObject -+ (instancetype)lightPalette; -+ (instancetype)darkPalette; -- (NSInteger)pageStyle; -- (UIColor *)background1; -- (UIColor *)background2; -- (UIColor *)background3; -- (UIColor *)staticBlue; -- (UIColor *)brandBackgroundSolid; -- (UIColor *)brandBackgroundPrimary; -- (UIColor *)brandBackgroundSecondary; -- (UIColor *)generalBackgroundA; -- (UIColor *)generalBackgroundB; -- (UIColor *)generalBackgroundC; -- (UIColor *)errorBackground; -- (UIColor *)textPrimary; -- (UIColor *)textSecondary; -- (UIColor *)textDisabled; -- (UIColor *)textPrimaryInverse; -- (UIColor *)callToAction; -- (UIColor *)iconActive; -- (UIColor *)iconActiveOther; -- (UIColor *)iconInactive; -- (UIColor *)iconDisabled; -- (UIColor *)badgeChipBackground; -- (UIColor *)buttonChipBackgroundHover; -- (UIColor *)touchResponse; -- (UIColor *)callToActionInverse; -- (UIColor *)brandIconActive; -- (UIColor *)brandIconInactive; -- (UIColor *)brandButtonBackground; -- (UIColor *)brandLinkText; -- (UIColor *)tenPercentLayer; -- (UIColor *)snackbarBackground; -- (UIColor *)themedBlue; -- (UIColor *)themedGreen; -- (UIColor *)staticBrandRed; -- (UIColor *)staticBrandWhite; -- (UIColor *)staticBrandBlack; -- (UIColor *)staticClearColor; -- (UIColor *)staticAdYellow; -- (UIColor *)staticGrey; -- (UIColor *)overlayBackgroundSolid; -- (UIColor *)overlayBackgroundHeavy; -- (UIColor *)overlayBackgroundMedium; -- (UIColor *)overlayBackgroundMediumLight; -- (UIColor *)overlayBackgroundLight; -- (UIColor *)overlayTextPrimary; -- (UIColor *)overlayTextSecondary; -- (UIColor *)overlayTextTertiary; -- (UIColor *)overlayIconActiveCallToAction; -- (UIColor *)overlayIconActiveOther; -- (UIColor *)overlayIconInactive; -- (UIColor *)overlayIconDisabled; -- (UIColor *)overlayFilledButtonActive; -- (UIColor *)overlayButtonSecondary; -- (UIColor *)overlayButtonPrimary; -- (UIColor *)overlayBackgroundBrand; -- (UIColor *)overlayBackgroundClear; -- (UIColor *)verifiedBadgeBackground; -- (UIColor *)themedOverlayBackground; -- (UIColor *)adIndicator; -- (UIColor *)errorIndicator; // 17.52.1+ -- (UIColor *)baseBackground; // 17.52.1+ -- (UIColor *)raisedBackground; // 17.52.1+ -- (UIColor *)menuBackground; // 17.52.1+ -- (UIColor *)invertedBackground; // 17.52.1+ -- (UIColor *)additiveBackground; // 17.52.1+ -- (UIColor *)outline; // 17.52.1+ -@end diff --git a/Tweaks/YouTubeHeader/YTCommonUtils.h b/Tweaks/YouTubeHeader/YTCommonUtils.h deleted file mode 100644 index 834ab41..0000000 --- a/Tweaks/YouTubeHeader/YTCommonUtils.h +++ /dev/null @@ -1,14 +0,0 @@ -#import -#import - -@interface YTCommonUtils : NSObject -+ (BOOL)isIPhoneWithNotch; -+ (BOOL)isIPad; -+ (BOOL)isSmallDevice; -+ (BOOL)isAppRunningInFullScreen; -+ (unsigned int)uniformRandomWithUpperBound:(unsigned int)upperBound; -+ (UIWindow *)mainWindow; // YTMainWindow -+ (NSBundle *)bundleForClass:(Class)cls; -+ (NSBundle *)resourceBundleForModuleName:(NSString *)module appBundle:(NSBundle *)appBundle; -+ (NSString *)hardwareModel; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTContentVideoPlayerOverlayView.h b/Tweaks/YouTubeHeader/YTContentVideoPlayerOverlayView.h deleted file mode 100644 index 0209c8a..0000000 --- a/Tweaks/YouTubeHeader/YTContentVideoPlayerOverlayView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTMainAppVideoPlayerOverlayView.h" - -@interface YTContentVideoPlayerOverlayView : YTMainAppVideoPlayerOverlayView -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTELMContext.h b/Tweaks/YouTubeHeader/YTELMContext.h deleted file mode 100644 index dd91b73..0000000 --- a/Tweaks/YouTubeHeader/YTELMContext.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTELMContext : NSObject -- (id)parentResponder; -@end diff --git a/Tweaks/YouTubeHeader/YTEditResources.h b/Tweaks/YouTubeHeader/YTEditResources.h deleted file mode 100644 index 6788177..0000000 --- a/Tweaks/YouTubeHeader/YTEditResources.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTEditResources : NSObject -+ (UIImage *)volumeControlsFeatureTabIconMuted:(BOOL)muted templateImage:(BOOL)templateImage; -@end diff --git a/Tweaks/YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h b/Tweaks/YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h deleted file mode 100644 index 652d6f9..0000000 --- a/Tweaks/YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTFullscreenEngagementActionBarButtonRenderer : NSObject -- (BOOL)isLikeButton; -- (BOOL)isDislikeButton; -@end diff --git a/Tweaks/YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h b/Tweaks/YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h deleted file mode 100644 index b2851b1..0000000 --- a/Tweaks/YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "Block.h" -#import "YTIFormattedStringLabel.h" - -@interface YTFullscreenEngagementActionBarButtonView : UIView -@property (nonatomic, assign, readwrite, getter=isToggled) BOOL toggled; -@property (nonatomic, strong, readwrite) YTIFormattedStringLabel *label; -@end diff --git a/Tweaks/YouTubeHeader/YTGlassContainerView.h b/Tweaks/YouTubeHeader/YTGlassContainerView.h deleted file mode 100644 index d148140..0000000 --- a/Tweaks/YouTubeHeader/YTGlassContainerView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTGlassContainerView : UIView -@end diff --git a/Tweaks/YouTubeHeader/YTGlobalConfig.h b/Tweaks/YouTubeHeader/YTGlobalConfig.h deleted file mode 100644 index 20d046d..0000000 --- a/Tweaks/YouTubeHeader/YTGlobalConfig.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTGlobalConfig : NSObject -@end diff --git a/Tweaks/YouTubeHeader/YTHotConfig.h b/Tweaks/YouTubeHeader/YTHotConfig.h deleted file mode 100644 index fa64645..0000000 --- a/Tweaks/YouTubeHeader/YTHotConfig.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTIHotConfigGroup.h" -#import "YTIHamplayerHotConfig.h" - -@interface YTHotConfig : NSObject -@property (atomic, strong, readwrite) YTIHotConfigGroup *hotConfigGroup; -- (YTIIosMediaHotConfig *)mediaHotConfig; -- (YTIHamplayerHotConfig *)hamplayerHotConfig; -- (BOOL)iosReleasePipControllerOnMain; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIAccessibilityData.h b/Tweaks/YouTubeHeader/YTIAccessibilityData.h deleted file mode 100644 index 372e071..0000000 --- a/Tweaks/YouTubeHeader/YTIAccessibilityData.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIAccessibilityData : NSObject -@property (nonatomic, copy, readwrite) NSString *label; -@end diff --git a/Tweaks/YouTubeHeader/YTIBrowseEndpoint.h b/Tweaks/YouTubeHeader/YTIBrowseEndpoint.h deleted file mode 100644 index 90b3c2e..0000000 --- a/Tweaks/YouTubeHeader/YTIBrowseEndpoint.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIBrowseEndpoint : NSObject -@property (nonatomic, copy, readwrite) NSString *browseId; -@end diff --git a/Tweaks/YouTubeHeader/YTIBrowseRequest.h b/Tweaks/YouTubeHeader/YTIBrowseRequest.h deleted file mode 100644 index 0d37fd0..0000000 --- a/Tweaks/YouTubeHeader/YTIBrowseRequest.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPBMessage.h" - -@interface YTIBrowseRequest : GPBMessage -+ (NSString *)browseIDForExploreTab; -+ (NSString *)browseIDForAccountTab; -+ (NSString *)browseIDForActivityTab; -+ (NSString *)browseIDForHomeTab; -+ (NSString *)browseIDForLibraryTab; -+ (NSString *)browseIDForTrendingTab; -+ (NSString *)browseIDForSubscriptionsTab; -+ (NSString *)browseIDForWhatToWatch; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIButtonRenderer.h b/Tweaks/YouTubeHeader/YTIButtonRenderer.h deleted file mode 100644 index 7ae8972..0000000 --- a/Tweaks/YouTubeHeader/YTIButtonRenderer.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "YTICommand.h" -#import "YTIFormattedString.h" -#import "YTIIcon.h" - -@interface YTIButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTICommand *command; -@property (nonatomic, strong, readwrite) YTIIcon *icon; -@property (nonatomic, strong, readwrite) YTICommand *navigationEndpoint; -@property (nonatomic, copy, readwrite) NSString *targetId; -@property (nonatomic, strong, readwrite) YTIFormattedString *text; -@property (nonatomic, copy, readwrite) NSString *tooltip; -@property (nonatomic, assign, readwrite) int size; -@property (nonatomic, assign, readwrite) int style; -@property (nonatomic, assign, readwrite) BOOL isDisabled; -@end diff --git a/Tweaks/YouTubeHeader/YTIButtonSupportedRenderers.h b/Tweaks/YouTubeHeader/YTIButtonSupportedRenderers.h deleted file mode 100644 index 234fe49..0000000 --- a/Tweaks/YouTubeHeader/YTIButtonSupportedRenderers.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIToggleButtonRenderer.h" -#import "YTIButtonRenderer.h" - -@interface YTIButtonSupportedRenderers : NSObject -@property (nonatomic, strong, readwrite) YTIToggleButtonRenderer *toggleButtonRenderer; -@property (retain, nonatomic) YTIButtonRenderer *buttonRenderer; -@end diff --git a/Tweaks/YouTubeHeader/YTIChapterRenderer.h b/Tweaks/YouTubeHeader/YTIChapterRenderer.h deleted file mode 100644 index 7125ad3..0000000 --- a/Tweaks/YouTubeHeader/YTIChapterRenderer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPBMessage.h" -#import "YTIFormattedString.h" - -@interface YTIChapterRenderer : GPBMessage -@property (nonatomic, readwrite, strong) YTIFormattedString *title; -@property (nonatomic, readwrite, assign) int timeRangeStartMillis; -@end diff --git a/Tweaks/YouTubeHeader/YTIColorInfo.h b/Tweaks/YouTubeHeader/YTIColorInfo.h deleted file mode 100644 index 74ffac0..0000000 --- a/Tweaks/YouTubeHeader/YTIColorInfo.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIColorInfo : NSObject -@property (nonatomic, assign, readwrite) int transferCharacteristics; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTICommand.h b/Tweaks/YouTubeHeader/YTICommand.h deleted file mode 100644 index 1dbf2c8..0000000 --- a/Tweaks/YouTubeHeader/YTICommand.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIReelWatchEndpoint.h" -#import "YTIBrowseEndpoint.h" - -@interface YTICommand : NSObject -@property (nonatomic, readwrite, strong) YTIReelWatchEndpoint *reelWatchEndpoint; -@property (nonatomic, readwrite, strong) YTIBrowseEndpoint *browseEndpoint; -@end diff --git a/Tweaks/YouTubeHeader/YTIElementRenderer.h b/Tweaks/YouTubeHeader/YTIElementRenderer.h deleted file mode 100644 index a02b85a..0000000 --- a/Tweaks/YouTubeHeader/YTIElementRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIElementRendererCompatibilityOptions.h" - -@interface YTIElementRenderer : GPBMessage -@property (nonatomic, strong, readwrite) YTIElementRendererCompatibilityOptions *compatibilityOptions; -@property (nonatomic, assign, readwrite) BOOL hasCompatibilityOptions; -@end diff --git a/Tweaks/YouTubeHeader/YTIElementRendererCompatibilityOptions.h b/Tweaks/YouTubeHeader/YTIElementRendererCompatibilityOptions.h deleted file mode 100644 index 7fad4d1..0000000 --- a/Tweaks/YouTubeHeader/YTIElementRendererCompatibilityOptions.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPBMessage.h" - -@interface YTIElementRendererCompatibilityOptions : GPBMessage -@property (nonatomic, assign, readwrite) BOOL hasAdLoggingData; -@end diff --git a/Tweaks/YouTubeHeader/YTIFormatStream.h b/Tweaks/YouTubeHeader/YTIFormatStream.h deleted file mode 100644 index f84ed37..0000000 --- a/Tweaks/YouTubeHeader/YTIFormatStream.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIColorInfo.h" - -@interface YTIFormatStream : NSObject -@property (nonatomic, strong, readwrite) YTIColorInfo *colorInfo; -@property (nonatomic, copy, readwrite) NSString *URL; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIFormattedString.h b/Tweaks/YouTubeHeader/YTIFormattedString.h deleted file mode 100644 index e950ca1..0000000 --- a/Tweaks/YouTubeHeader/YTIFormattedString.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTIFormattedStringSupportedAccessibilityDatas.h" - -@interface YTIFormattedString : NSObject -+ (instancetype)formattedStringWithString:(NSString *)string; -@property (nonatomic, strong, readwrite) NSMutableArray *runsArray; -@property (nonatomic, strong, readwrite) YTIFormattedStringSupportedAccessibilityDatas *accessibility; -- (NSString *)stringWithFormattingRemoved; -@end diff --git a/Tweaks/YouTubeHeader/YTIFormattedStringLabel.h b/Tweaks/YouTubeHeader/YTIFormattedStringLabel.h deleted file mode 100644 index 6865921..0000000 --- a/Tweaks/YouTubeHeader/YTIFormattedStringLabel.h +++ /dev/null @@ -1,7 +0,0 @@ -#import -#import "YTIFormattedString.h" - -@interface YTIFormattedStringLabel : UILabel -@property (nonatomic, copy, readwrite) NSAttributedString *attributedText; -- (void)setFormattedString:(YTIFormattedString *)string; -@end diff --git a/Tweaks/YouTubeHeader/YTIFormattedStringSupportedAccessibilityDatas.h b/Tweaks/YouTubeHeader/YTIFormattedStringSupportedAccessibilityDatas.h deleted file mode 100644 index e6c26d4..0000000 --- a/Tweaks/YouTubeHeader/YTIFormattedStringSupportedAccessibilityDatas.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIAccessibilityData.h" - -@interface YTIFormattedStringSupportedAccessibilityDatas : NSObject -@property (nonatomic, strong, readwrite) YTIAccessibilityData *accessibilityData; -@end diff --git a/Tweaks/YouTubeHeader/YTIGuideResponse.h b/Tweaks/YouTubeHeader/YTIGuideResponse.h deleted file mode 100644 index c24d970..0000000 --- a/Tweaks/YouTubeHeader/YTIGuideResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIGuideResponseSupportedRenderers.h" - -@interface YTIGuideResponse : NSObject -- (NSMutableArray *)itemsArray; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIGuideResponseSupportedRenderers.h b/Tweaks/YouTubeHeader/YTIGuideResponseSupportedRenderers.h deleted file mode 100644 index aa32640..0000000 --- a/Tweaks/YouTubeHeader/YTIGuideResponseSupportedRenderers.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIPivotBarRenderer.h" - -@interface YTIGuideResponseSupportedRenderers : NSObject -- (YTIPivotBarRenderer *)pivotBarRenderer; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIHamplayerABRConfig.h b/Tweaks/YouTubeHeader/YTIHamplayerABRConfig.h deleted file mode 100644 index 157ac68..0000000 --- a/Tweaks/YouTubeHeader/YTIHamplayerABRConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIHamplayerABRConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL preferSoftwareHdrOverHardwareSdr; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIHamplayerConfig.h b/Tweaks/YouTubeHeader/YTIHamplayerConfig.h deleted file mode 100644 index 0f44488..0000000 --- a/Tweaks/YouTubeHeader/YTIHamplayerConfig.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "YTIHamplayerStreamFilter.h" -#import "YTIHamplayerABRConfig.h" - -@interface YTIHamplayerConfig : NSObject -@property (nonatomic, assign, readwrite) int renderViewType; -@property (nonatomic, assign, readwrite) BOOL useSbdlRenderView; -@property (nonatomic, assign, readwrite) BOOL useResolutionForHfrHdFormatFilter; -@property (nonatomic, assign, readwrite) BOOL disableHfrHdFormatFilter; -@property (nonatomic, assign, readwrite) BOOL disableResolveOverlappingQualitiesByCodec; -@property (nonatomic, strong, readwrite) YTIHamplayerStreamFilter *streamFilter; -@property (nonatomic, strong, readwrite) YTIHamplayerABRConfig *videoAbrConfig; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIHamplayerHotConfig.h b/Tweaks/YouTubeHeader/YTIHamplayerHotConfig.h deleted file mode 100644 index 8a5ea2a..0000000 --- a/Tweaks/YouTubeHeader/YTIHamplayerHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIHamplayerHotConfig : NSObject -@property (nonatomic, assign, readwrite) int renderViewType; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h b/Tweaks/YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h deleted file mode 100644 index 742ac20..0000000 --- a/Tweaks/YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTIHamplayerSoftwareStreamFilter : NSObject -@property int maxArea; -@property int maxFps; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIHamplayerStreamFilter.h b/Tweaks/YouTubeHeader/YTIHamplayerStreamFilter.h deleted file mode 100644 index 5937c90..0000000 --- a/Tweaks/YouTubeHeader/YTIHamplayerStreamFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIHamplayerSoftwareStreamFilter.h" - -@interface YTIHamplayerStreamFilter : NSObject -@property (nonatomic, strong, readwrite) YTIHamplayerSoftwareStreamFilter *av1; -@property (nonatomic, strong, readwrite) YTIHamplayerSoftwareStreamFilter *vp9; -@property (nonatomic, assign, readwrite) BOOL enableVideoCodecSplicing; -@end diff --git a/Tweaks/YouTubeHeader/YTIHotConfigGroup.h b/Tweaks/YouTubeHeader/YTIHotConfigGroup.h deleted file mode 100644 index ff7c4a3..0000000 --- a/Tweaks/YouTubeHeader/YTIHotConfigGroup.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIMediaHotConfig.h" - -@interface YTIHotConfigGroup : NSObject -@property (nonatomic, strong, readwrite) YTIMediaHotConfig *mediaHotConfig; -@end diff --git a/Tweaks/YouTubeHeader/YTIIcon.h b/Tweaks/YouTubeHeader/YTIIcon.h deleted file mode 100644 index 42c0bff..0000000 --- a/Tweaks/YouTubeHeader/YTIIcon.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIIcon : NSObject -@property (nonatomic, assign, readwrite) int iconType; -@end diff --git a/Tweaks/YouTubeHeader/YTIIosMediaHotConfig.h b/Tweaks/YouTubeHeader/YTIIosMediaHotConfig.h deleted file mode 100644 index c94c99b..0000000 --- a/Tweaks/YouTubeHeader/YTIIosMediaHotConfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTIIosMediaHotConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL enablePictureInPicture; -@property (nonatomic, assign, readwrite) BOOL enablePipForNonBackgroundableContent; -@property (nonatomic, assign, readwrite) BOOL enablePipForNonPremiumUsers; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIIosOnesieHotConfig.h b/Tweaks/YouTubeHeader/YTIIosOnesieHotConfig.h deleted file mode 100644 index 65b1bf1..0000000 --- a/Tweaks/YouTubeHeader/YTIIosOnesieHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIIosOnesieHotConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL prepareVideoDecoder; -@end diff --git a/Tweaks/YouTubeHeader/YTIItemSectionRenderer.h b/Tweaks/YouTubeHeader/YTIItemSectionRenderer.h deleted file mode 100644 index 51428e5..0000000 --- a/Tweaks/YouTubeHeader/YTIItemSectionRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIItemSectionSupportedRenderers.h" - -@interface YTIItemSectionRenderer : GPBMessage -@property (nonatomic, strong, readwrite) NSMutableArray *contentsArray; -@end diff --git a/Tweaks/YouTubeHeader/YTIItemSectionSupportedRenderers.h b/Tweaks/YouTubeHeader/YTIItemSectionSupportedRenderers.h deleted file mode 100644 index e8d1d5a..0000000 --- a/Tweaks/YouTubeHeader/YTIItemSectionSupportedRenderers.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTIElementRenderer.h" - -@interface YTIItemSectionSupportedRenderers : GPBMessage -@property (nonatomic, strong, readwrite) YTIElementRenderer *elementRenderer; -@property (nonatomic, assign, readwrite) BOOL hasPromotedVideoRenderer; -@property (nonatomic, assign, readwrite) BOOL hasPromotedVideoInlineMutedRenderer; -@property (nonatomic, assign, readwrite) BOOL hasCompactPromotedVideoRenderer; -@end diff --git a/Tweaks/YouTubeHeader/YTILikeButtonRenderer.h b/Tweaks/YouTubeHeader/YTILikeButtonRenderer.h deleted file mode 100644 index 462abdc..0000000 --- a/Tweaks/YouTubeHeader/YTILikeButtonRenderer.h +++ /dev/null @@ -1,23 +0,0 @@ -#import "YTLikeStatus.h" -#import "YTILikeTarget.h" -#import "YTIFormattedString.h" - -@interface YTILikeButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTILikeTarget *target; -@property (nonatomic, strong, readwrite) YTIFormattedString *likeCountText; -@property (nonatomic, strong, readwrite) YTIFormattedString *likeCountWithLikeText; -@property (nonatomic, strong, readwrite) YTIFormattedString *likeCountWithUnlikeText; -@property (nonatomic, strong, readwrite) YTIFormattedString *dislikeCountText; -@property (nonatomic, strong, readwrite) YTIFormattedString *dislikeCountWithDislikeText; -@property (nonatomic, strong, readwrite) YTIFormattedString *dislikeCountWithUndislikeText; -@property (nonatomic, assign, readwrite) BOOL hasLikeCountText; -@property (nonatomic, assign, readwrite) BOOL hasLikeCountWithLikeText; -@property (nonatomic, assign, readwrite) BOOL hasLikeCountWithUnlikeText; -@property (nonatomic, assign, readwrite) BOOL hasDislikeCountText; -@property (nonatomic, assign, readwrite) BOOL hasDislikeCountWithDislikeText; -@property (nonatomic, assign, readwrite) BOOL hasDislikeCountWithUndislikeText; -@property (nonatomic, assign, readwrite) BOOL likesAllowed; -@property (nonatomic, assign, readwrite) YTLikeStatus likeStatus; -@property (nonatomic, assign, readwrite) int likeCount; -@property (nonatomic, assign, readwrite) int dislikeCount; -@end diff --git a/Tweaks/YouTubeHeader/YTILikeTarget.h b/Tweaks/YouTubeHeader/YTILikeTarget.h deleted file mode 100644 index 5c966fb..0000000 --- a/Tweaks/YouTubeHeader/YTILikeTarget.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTILikeTarget : NSObject -@property (nonatomic, copy, readwrite) NSString *videoId; -@end diff --git a/Tweaks/YouTubeHeader/YTIMediaCommonConfig.h b/Tweaks/YouTubeHeader/YTIMediaCommonConfig.h deleted file mode 100644 index 38697de..0000000 --- a/Tweaks/YouTubeHeader/YTIMediaCommonConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIMediaCommonConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL useServerDrivenAbr; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIMediaHotConfig.h b/Tweaks/YouTubeHeader/YTIMediaHotConfig.h deleted file mode 100644 index 4311fa5..0000000 --- a/Tweaks/YouTubeHeader/YTIMediaHotConfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIIosMediaHotConfig.h" -#import "YTIMediaQualitySettingsHotConfig.h" - -@interface YTIMediaHotConfig : NSObject -@property (nonatomic, strong, readwrite) YTIIosMediaHotConfig *iosMediaHotConfig; -@property (nonatomic, strong, readwrite) YTIMediaQualitySettingsHotConfig *mediaQualitySettingsHotConfig; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIMediaQualitySettingsHotConfig.h b/Tweaks/YouTubeHeader/YTIMediaQualitySettingsHotConfig.h deleted file mode 100644 index 9e14cc1..0000000 --- a/Tweaks/YouTubeHeader/YTIMediaQualitySettingsHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIMediaQualitySettingsHotConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL enablePersistentVideoQualitySettings; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIOfflinePromoRenderer.h b/Tweaks/YouTubeHeader/YTIOfflinePromoRenderer.h deleted file mode 100644 index 47b2f9b..0000000 --- a/Tweaks/YouTubeHeader/YTIOfflinePromoRenderer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTIOfflinePromoRenderer : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIOfflineabilityRenderer.h b/Tweaks/YouTubeHeader/YTIOfflineabilityRenderer.h deleted file mode 100644 index ddcd8ab..0000000 --- a/Tweaks/YouTubeHeader/YTIOfflineabilityRenderer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTIOfflineabilityRenderer : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIOfflineabilitySupportedRenderers.h b/Tweaks/YouTubeHeader/YTIOfflineabilitySupportedRenderers.h deleted file mode 100644 index 771f33a..0000000 --- a/Tweaks/YouTubeHeader/YTIOfflineabilitySupportedRenderers.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "YTIButtonRenderer.h" -#import "YTIOfflinePromoRenderer.h" -#import "YTIOfflineabilityRenderer.h" - -@interface YTIOfflineabilitySupportedRenderers : NSObject -@property (nonatomic, strong, readwrite) YTIOfflinePromoRenderer *offlinePromoRenderer; -@property (nonatomic, strong, readwrite) YTIOfflineabilityRenderer *offlineabilityRenderer; -@property (nonatomic, strong, readwrite) YTIButtonRenderer *buttonRenderer; -- (int)rendererOneOfCase; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIOnesieHotConfig.h b/Tweaks/YouTubeHeader/YTIOnesieHotConfig.h deleted file mode 100644 index 0901c3a..0000000 --- a/Tweaks/YouTubeHeader/YTIOnesieHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIIosOnesieHotConfig.h" - -@interface YTIOnesieHotConfig : NSObject -@property (nonatomic, strong, readwrite) YTIIosOnesieHotConfig *iosConfig; -@end diff --git a/Tweaks/YouTubeHeader/YTIPaygatedQualityDetails.h b/Tweaks/YouTubeHeader/YTIPaygatedQualityDetails.h deleted file mode 100644 index 9f2311b..0000000 --- a/Tweaks/YouTubeHeader/YTIPaygatedQualityDetails.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTICommand.h" - -@interface YTIPaygatedQualityDetails : GPBMessage -@property (nonatomic, strong, readwrite) YTICommand *endpoint; -@end diff --git a/Tweaks/YouTubeHeader/YTIPictureInPictureRendererRoot.h b/Tweaks/YouTubeHeader/YTIPictureInPictureRendererRoot.h deleted file mode 100644 index 7f8f33c..0000000 --- a/Tweaks/YouTubeHeader/YTIPictureInPictureRendererRoot.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIPictureInPictureRendererRoot : NSObject -+ (id)pictureInPictureRenderer; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIPivotBarIconOnlyItemRenderer.h b/Tweaks/YouTubeHeader/YTIPivotBarIconOnlyItemRenderer.h deleted file mode 100644 index 63f7b43..0000000 --- a/Tweaks/YouTubeHeader/YTIPivotBarIconOnlyItemRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPBMessage.h" - -@interface YTIPivotBarIconOnlyItemRenderer : GPBMessage -- (NSString *)pivotIdentifier; -@end diff --git a/Tweaks/YouTubeHeader/YTIPivotBarItemRenderer.h b/Tweaks/YouTubeHeader/YTIPivotBarItemRenderer.h deleted file mode 100644 index 2e71543..0000000 --- a/Tweaks/YouTubeHeader/YTIPivotBarItemRenderer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTICommand.h" - -@interface YTIPivotBarItemRenderer : NSObject -- (NSString *)pivotIdentifier; -- (YTICommand *)navigationEndpoint; -- (void)setNavigationEndpoint:(YTICommand *)navigationEndpoint; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIPivotBarRenderer.h b/Tweaks/YouTubeHeader/YTIPivotBarRenderer.h deleted file mode 100644 index a210d4f..0000000 --- a/Tweaks/YouTubeHeader/YTIPivotBarRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIPivotBarSupportedRenderers.h" - -@interface YTIPivotBarRenderer : NSObject -+ (YTIPivotBarSupportedRenderers *)pivotSupportedRenderersWithBrowseId:(NSString *)browseId title:(NSString *)title iconType:(int)iconType; -- (NSMutableArray *)itemsArray; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIPivotBarSupportedRenderers.h b/Tweaks/YouTubeHeader/YTIPivotBarSupportedRenderers.h deleted file mode 100644 index e089cfd..0000000 --- a/Tweaks/YouTubeHeader/YTIPivotBarSupportedRenderers.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIPivotBarItemRenderer.h" -#import "YTIPivotBarIconOnlyItemRenderer.h" - -@interface YTIPivotBarSupportedRenderers : NSObject -- (YTIPivotBarItemRenderer *)pivotBarItemRenderer; -- (YTIPivotBarIconOnlyItemRenderer *)pivotBarIconOnlyItemRenderer; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTIPlayerResponse.h b/Tweaks/YouTubeHeader/YTIPlayerResponse.h deleted file mode 100644 index f463a56..0000000 --- a/Tweaks/YouTubeHeader/YTIPlayerResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIVideoDetails.h" - -@interface YTIPlayerResponse : NSObject -@property (nonatomic, strong, readwrite) YTIVideoDetails *videoDetails; -@end diff --git a/Tweaks/YouTubeHeader/YTIReelWatchEndpoint.h b/Tweaks/YouTubeHeader/YTIReelWatchEndpoint.h deleted file mode 100644 index 1d09f3d..0000000 --- a/Tweaks/YouTubeHeader/YTIReelWatchEndpoint.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTIReelWatchEndpoint : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTISectionListRenderer.h b/Tweaks/YouTubeHeader/YTISectionListRenderer.h deleted file mode 100644 index 10c4576..0000000 --- a/Tweaks/YouTubeHeader/YTISectionListRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTISectionListSupportedRenderers.h" - -@interface YTISectionListRenderer : GPBMessage -@property (nonatomic, strong, readwrite) NSMutableArray *contentsArray; -@end diff --git a/Tweaks/YouTubeHeader/YTISectionListSupportedRenderers.h b/Tweaks/YouTubeHeader/YTISectionListSupportedRenderers.h deleted file mode 100644 index 4fb3d99..0000000 --- a/Tweaks/YouTubeHeader/YTISectionListSupportedRenderers.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIItemSectionRenderer.h" - -@interface YTISectionListSupportedRenderers : GPBMessage -@property (nonatomic, strong, readwrite) YTIItemSectionRenderer *itemSectionRenderer; -@end diff --git a/Tweaks/YouTubeHeader/YTIShowEngagementPanelEndpoint.h b/Tweaks/YouTubeHeader/YTIShowEngagementPanelEndpoint.h deleted file mode 100644 index 1d463e6..0000000 --- a/Tweaks/YouTubeHeader/YTIShowEngagementPanelEndpoint.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPBExtensionDescriptor.h" - -@interface YTIShowEngagementPanelEndpoint : NSObject -+ (GPBExtensionDescriptor *)showEngagementPanelEndpoint; -@end diff --git a/Tweaks/YouTubeHeader/YTISlimMetadataButtonRenderer.h b/Tweaks/YouTubeHeader/YTISlimMetadataButtonRenderer.h deleted file mode 100644 index ce79ab0..0000000 --- a/Tweaks/YouTubeHeader/YTISlimMetadataButtonRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIButtonSupportedRenderers.h" - -@interface YTISlimMetadataButtonRenderer : NSObject -@property (retain, nonatomic) YTIButtonSupportedRenderers *button; -@end diff --git a/Tweaks/YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h b/Tweaks/YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h deleted file mode 100644 index 0de4682..0000000 --- a/Tweaks/YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "YTISlimMetadataToggleButtonRenderer.h" -#import "YTISlimMetadataButtonRenderer.h" - -@interface YTISlimMetadataButtonSupportedRenderers : NSObject -@property (nonatomic, strong, readwrite) YTISlimMetadataToggleButtonRenderer *slimMetadataToggleButtonRenderer; -@property (retain, nonatomic) YTISlimMetadataButtonRenderer *slimMetadataButtonRenderer; -- (BOOL)slimButton_isLikeButton; -- (BOOL)slimButton_isDislikeButton; -- (BOOL)slimButton_isOfflineButton; -- (int)rendererOneOfCase; -@end diff --git a/Tweaks/YouTubeHeader/YTISlimMetadataToggleButtonRenderer.h b/Tweaks/YouTubeHeader/YTISlimMetadataToggleButtonRenderer.h deleted file mode 100644 index 827d073..0000000 --- a/Tweaks/YouTubeHeader/YTISlimMetadataToggleButtonRenderer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTILikeTarget.h" -#import "YTIButtonSupportedRenderers.h" - -@interface YTISlimMetadataToggleButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTILikeTarget *target; -@property (nonatomic, strong, readwrite) YTIButtonSupportedRenderers *button; -@end diff --git a/Tweaks/YouTubeHeader/YTIStringRun.h b/Tweaks/YouTubeHeader/YTIStringRun.h deleted file mode 100644 index 7cc010c..0000000 --- a/Tweaks/YouTubeHeader/YTIStringRun.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIStringRun : NSObject -@property (nonatomic, copy, readwrite) NSString *text; -@end diff --git a/Tweaks/YouTubeHeader/YTIToggleButtonRenderer.h b/Tweaks/YouTubeHeader/YTIToggleButtonRenderer.h deleted file mode 100644 index 63a3347..0000000 --- a/Tweaks/YouTubeHeader/YTIToggleButtonRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIFormattedString.h" - -@interface YTIToggleButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTIFormattedString *defaultText; -@property (nonatomic, strong, readwrite) YTIFormattedString *toggledText; -@end diff --git a/Tweaks/YouTubeHeader/YTIVideoDetails.h b/Tweaks/YouTubeHeader/YTIVideoDetails.h deleted file mode 100644 index 3c87590..0000000 --- a/Tweaks/YouTubeHeader/YTIVideoDetails.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTIVideoDetails : NSObject -@property (nonatomic, assign, readwrite) BOOL allowRatings; -@property (nonatomic, assign, readwrite) float averageRating; -@property (nonatomic, copy, readwrite) NSString *viewCount; -@property (nonatomic, copy, readwrite) NSString *channelId; -@end diff --git a/Tweaks/YouTubeHeader/YTIWatchNextResponse.h b/Tweaks/YouTubeHeader/YTIWatchNextResponse.h deleted file mode 100644 index 348ec06..0000000 --- a/Tweaks/YouTubeHeader/YTIWatchNextResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIWatchNextResponse : NSObject -@property (nonatomic, assign, readwrite) BOOL hasOnUiReady; -@end diff --git a/Tweaks/YouTubeHeader/YTInlinePlayerBarContainerView.h b/Tweaks/YouTubeHeader/YTInlinePlayerBarContainerView.h deleted file mode 100644 index 5eeccf2..0000000 --- a/Tweaks/YouTubeHeader/YTInlinePlayerBarContainerView.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "YTGlassContainerView.h" -#import "YTInlinePlayerBarView.h" -#import "YTSegmentableInlinePlayerBarView.h" -#import "YTLabel.h" -#import "YTQTMButton.h" - -@interface YTInlinePlayerBarContainerView : YTGlassContainerView -@property (nonatomic, strong, readwrite) YTInlinePlayerBarView *playerBar; // Replaced by segmentablePlayerBar in newer versions -@property (nonatomic, strong, readwrite) YTSegmentableInlinePlayerBarView *segmentablePlayerBar; -@property (nonatomic, strong, readwrite) UIView *multiFeedElementView; -@property (nonatomic, strong, readwrite) YTLabel *durationLabel; -@property (nonatomic, assign, readwrite) BOOL showOnlyFullscreenButton; -@property (nonatomic, assign, readwrite) int layout; -@property (nonatomic, weak, readwrite) id delegate; -- (YTQTMButton *)exitFullscreenButton; -- (YTQTMButton *)enterFullscreenButton; -- (void)setChapters:(NSArray *)chapters; -@end diff --git a/Tweaks/YouTubeHeader/YTInlinePlayerBarView.h b/Tweaks/YouTubeHeader/YTInlinePlayerBarView.h deleted file mode 100644 index 3c07d0b..0000000 --- a/Tweaks/YouTubeHeader/YTInlinePlayerBarView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTInlinePlayerBarView : UIView -@property (nonatomic, readonly, assign) CGFloat totalTime; -@property (nonatomic, readwrite, strong) YTPlayerViewController *playerViewController; -@end diff --git a/Tweaks/YouTubeHeader/YTInnerTubeCellController.h b/Tweaks/YouTubeHeader/YTInnerTubeCellController.h deleted file mode 100644 index ce2dc38..0000000 --- a/Tweaks/YouTubeHeader/YTInnerTubeCellController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTCellController.h" - -@interface YTInnerTubeCellController : YTCellController -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTLabel.h b/Tweaks/YouTubeHeader/YTLabel.h deleted file mode 100644 index bf2d917..0000000 --- a/Tweaks/YouTubeHeader/YTLabel.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTLabel : UILabel -@end diff --git a/Tweaks/YouTubeHeader/YTLightweightQTMButton.h b/Tweaks/YouTubeHeader/YTLightweightQTMButton.h deleted file mode 100644 index 5970b5d..0000000 --- a/Tweaks/YouTubeHeader/YTLightweightQTMButton.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTLightweightQTMButton : UIButton -@property (nonatomic, assign, readwrite, getter=isUppercaseTitle) BOOL uppercaseTitle; -@end diff --git a/Tweaks/YouTubeHeader/YTLikeStatus.h b/Tweaks/YouTubeHeader/YTLikeStatus.h deleted file mode 100644 index ffe5044..0000000 --- a/Tweaks/YouTubeHeader/YTLikeStatus.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _YT_LIKESTATUS -#define _YT_LIKESTATUS - -#import - -typedef NS_ENUM(int, YTLikeStatus) { - YTLikeStatusLike = 0, - YTLikeStatusDislike = 1, - YTLikeStatusNeutral = 2 -}; - -#endif diff --git a/Tweaks/YouTubeHeader/YTLocalPlaybackController.h b/Tweaks/YouTubeHeader/YTLocalPlaybackController.h deleted file mode 100644 index ab585b4..0000000 --- a/Tweaks/YouTubeHeader/YTLocalPlaybackController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "GIMMe.h" -#import "YTSingleVideoControllerDelegate.h" - -@interface YTLocalPlaybackController : NSObject -- (GIMMe *)gimme; // Deprecated -- (NSString *)currentVideoID; -- (int)playerVisibility; -- (void)setMuted:(BOOL)muted; -@end diff --git a/Tweaks/YouTubeHeader/YTMainAppControlsOverlayView.h b/Tweaks/YouTubeHeader/YTMainAppControlsOverlayView.h deleted file mode 100644 index a4d05cf..0000000 --- a/Tweaks/YouTubeHeader/YTMainAppControlsOverlayView.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTQTMButton.h" -#import "YTPlayerViewController.h" - -@interface YTMainAppControlsOverlayView : UIView -+ (CGFloat)topButtonAdditionalPadding; -@property (nonatomic, assign, readwrite, getter=isOverlayVisible) BOOL overlayVisible; -@property (nonatomic, strong, readwrite) YTPlayerViewController *playerViewController; -- (YTQTMButton *)buttonWithImage:(UIImage *)image accessibilityLabel:(NSString *)accessibilityLabel verticalContentPadding:(CGFloat)verticalContentPadding; -@end diff --git a/Tweaks/YouTubeHeader/YTMainAppPlayerOverlayView.h b/Tweaks/YouTubeHeader/YTMainAppPlayerOverlayView.h deleted file mode 100644 index 909f1c0..0000000 --- a/Tweaks/YouTubeHeader/YTMainAppPlayerOverlayView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTMainAppPlayerOverlayView : UIView -+ (CGFloat)topButtonAdditionalPadding; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTMainAppVideoPlayerOverlayView.h b/Tweaks/YouTubeHeader/YTMainAppVideoPlayerOverlayView.h deleted file mode 100644 index d833381..0000000 --- a/Tweaks/YouTubeHeader/YTMainAppVideoPlayerOverlayView.h +++ /dev/null @@ -1,20 +0,0 @@ -#import - -#ifdef LEGACY - -#import "YTMainAppPlayerOverlayView.h" - -@interface YTMainAppVideoPlayerOverlayView : YTMainAppPlayerOverlayView -@end - -#else - -#import "YTInlinePlayerBarContainerView.h" -#import "YTMainAppControlsOverlayView.h" - -@interface YTMainAppVideoPlayerOverlayView : UIView -@property (nonatomic, strong, readwrite) YTInlinePlayerBarContainerView *playerBar; -- (YTMainAppControlsOverlayView *)controlsOverlayView; -@end - -#endif \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h b/Tweaks/YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h deleted file mode 100644 index 7810af9..0000000 --- a/Tweaks/YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTMainAppVideoPlayerOverlayView.h" -#import "YTPlayerViewController.h" - -@interface YTMainAppVideoPlayerOverlayViewController : UIViewController -- (YTMainAppVideoPlayerOverlayView *)videoPlayerOverlayView; -- (YTPlayerViewController *)delegate; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTMultiSizeViewController.h b/Tweaks/YouTubeHeader/YTMultiSizeViewController.h deleted file mode 100644 index f741fe5..0000000 --- a/Tweaks/YouTubeHeader/YTMultiSizeViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTMultiSizeViewController : UIViewController -@end diff --git a/Tweaks/YouTubeHeader/YTNGWatchController.h b/Tweaks/YouTubeHeader/YTNGWatchController.h deleted file mode 100644 index bfee738..0000000 --- a/Tweaks/YouTubeHeader/YTNGWatchController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTNGWatchController : NSObject -@end diff --git a/Tweaks/YouTubeHeader/YTNGWatchLayerViewController.h b/Tweaks/YouTubeHeader/YTNGWatchLayerViewController.h deleted file mode 100644 index e4140e8..0000000 --- a/Tweaks/YouTubeHeader/YTNGWatchLayerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTNGWatchLayerViewController : UIViewController -- (YTPlayerViewController *)playerViewController; -@end diff --git a/Tweaks/YouTubeHeader/YTNGWatchMiniBarView.h b/Tweaks/YouTubeHeader/YTNGWatchMiniBarView.h deleted file mode 100644 index 2e02824..0000000 --- a/Tweaks/YouTubeHeader/YTNGWatchMiniBarView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTNGWatchMiniBarView : UIView -@property (nonatomic, assign, readwrite) NSInteger watchMiniPlayerLayout; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTOfflineButtonPressedResponderEvent.h b/Tweaks/YouTubeHeader/YTOfflineButtonPressedResponderEvent.h deleted file mode 100644 index dc520e2..0000000 --- a/Tweaks/YouTubeHeader/YTOfflineButtonPressedResponderEvent.h +++ /dev/null @@ -1,7 +0,0 @@ -#import -#import - -@interface YTOfflineButtonPressedResponderEvent : NSObject -+ (instancetype)eventWithOfflineVideoID:(NSString *)videoID fromView:(UIView *)view firstResponder:(id)firstResponder; -- (void)send; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPageStyleController.h b/Tweaks/YouTubeHeader/YTPageStyleController.h deleted file mode 100644 index 84c9eb3..0000000 --- a/Tweaks/YouTubeHeader/YTPageStyleController.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTCommonColorPalette.h" - -@interface YTPageStyleController : NSObject -+ (YTCommonColorPalette *)currentColorPalette; // For YouTube older than 17.19.2, import/change type to YTColorPalette -+ (NSInteger)pageStyle; -@property (nonatomic, assign, readwrite) NSInteger appThemeSetting; -@property (nonatomic, assign, readonly) NSInteger pageStyle; -@end diff --git a/Tweaks/YouTubeHeader/YTPivotBarItemView.h b/Tweaks/YouTubeHeader/YTPivotBarItemView.h deleted file mode 100644 index 848a6e6..0000000 --- a/Tweaks/YouTubeHeader/YTPivotBarItemView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTPivotBarItemView : UIView -@property (strong, nonatomic) UIButton *navigationButton; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlaybackController.h b/Tweaks/YouTubeHeader/YTPlaybackController.h deleted file mode 100644 index 2325329..0000000 --- a/Tweaks/YouTubeHeader/YTPlaybackController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSingleVideoController.h" - -@protocol YTPlaybackController -@property (strong, nonatomic) YTSingleVideoController *activeVideo; -@end diff --git a/Tweaks/YouTubeHeader/YTPlaybackControllerUIWrapper.h b/Tweaks/YouTubeHeader/YTPlaybackControllerUIWrapper.h deleted file mode 100644 index 372577b..0000000 --- a/Tweaks/YouTubeHeader/YTPlaybackControllerUIWrapper.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTSingleVideoController.h" - -@interface YTPlaybackControllerUIWrapper : NSObject -- (YTSingleVideoController *)activeVideo; -- (YTSingleVideoController *)contentVideo; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlaybackData.h b/Tweaks/YouTubeHeader/YTPlaybackData.h deleted file mode 100644 index e106b99..0000000 --- a/Tweaks/YouTubeHeader/YTPlaybackData.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "YTPlayerResponse.h" - -@interface YTPlaybackData : NSObject -- (MLVideo *)video; -- (YTPlayerResponse *)playerResponse; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlaybackStrippedWatchController.h b/Tweaks/YouTubeHeader/YTPlaybackStrippedWatchController.h deleted file mode 100644 index d423100..0000000 --- a/Tweaks/YouTubeHeader/YTPlaybackStrippedWatchController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTWatchMetadataPanelStateResponderProvider.h" -#import "YTWatchPlaybackController.h" - -@interface YTPlaybackStrippedWatchController : NSObject -@property (nonatomic, strong, readwrite) YTWatchPlaybackController *watchPlaybackController; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerBarSegmentMarkerView.h b/Tweaks/YouTubeHeader/YTPlayerBarSegmentMarkerView.h deleted file mode 100644 index cb81295..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerBarSegmentMarkerView.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTPlayerBarSegmentMarkerView : UIView -@property (nonatomic, readwrite, assign) CGFloat startTime; -@property (nonatomic, readwrite, assign) CGFloat endTime; -@property (nonatomic, readwrite, assign) CGFloat width; -@property (nonatomic, readwrite, assign) NSInteger type; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerBarSegmentedProgressView.h b/Tweaks/YouTubeHeader/YTPlayerBarSegmentedProgressView.h deleted file mode 100644 index fc782a8..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerBarSegmentedProgressView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import - -@interface YTPlayerBarSegmentedProgressView : UIView -@property (nonatomic, readwrite, assign) CGFloat totalTime; -@property (nonatomic, readwrite, assign) int playerViewLayout; -- (void)maybeCreateMarkerViews; -- (void)setChapters:(NSArray *)chapters; -- (void)createAndAddMarker:(CGFloat)arg1 type:(NSInteger)type width:(CGFloat)width; -- (void)createAndAddMarker:(CGFloat)arg1 type:(NSInteger)type clusterType:(NSInteger)clusterType width:(CGFloat)width; // Deprecated -- (NSMutableArray *)segmentViews; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerOverlay.h b/Tweaks/YouTubeHeader/YTPlayerOverlay.h deleted file mode 100644 index 7587fcf..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerOverlay.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTPlayerOverlay : NSObject -- (NSString *)overlayIdentifier; -- (NSInteger)overlayZIndex; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerOverlayProvider.h b/Tweaks/YouTubeHeader/YTPlayerOverlayProvider.h deleted file mode 100644 index c2f841d..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerOverlayProvider.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTPlayerOverlayProvider : NSObject -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerPIPController.h b/Tweaks/YouTubeHeader/YTPlayerPIPController.h deleted file mode 100644 index bb795a2..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerPIPController.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GIMMe.h" -#import "YTSingleVideoController.h" - -@interface YTPlayerPIPController : NSObject -@property (nonatomic, readonly, assign, getter=isPictureInPictureActive) BOOL pictureInPuctureActive; -@property (nonatomic, readonly, assign, getter=isPictureInPicturePossible) BOOL pictureInPucturePossible; -@property (retain, nonatomic) YTSingleVideoController *activeSingleVideo; -- (instancetype)initWithPlayerView:(id)playerView delegate:(id)delegate; // Deprecated, use initWithDelegate: -- (instancetype)initWithDelegate:(id)delegate; -- (GIMMe *)gimme; // Deprecated -- (BOOL)canInvokePictureInPicture; // Deprecated, use canEnablePictureInPicture -- (BOOL)canEnablePictureInPicture; -- (void)maybeInvokePictureInPicture; // Deprecated, use maybeEnablePictureInPicture -- (void)maybeEnablePictureInPicture; -- (void)play; -- (void)pause; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerResources.h b/Tweaks/YouTubeHeader/YTPlayerResources.h deleted file mode 100644 index 302c987..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerResources.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTPlayerResources : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlayerResponse.h b/Tweaks/YouTubeHeader/YTPlayerResponse.h deleted file mode 100644 index cb02869..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIPlayerResponse.h" - -@interface YTPlayerResponse : NSObject -- (YTIPlayerResponse *)playerData; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerStatus.h b/Tweaks/YouTubeHeader/YTPlayerStatus.h deleted file mode 100644 index 7503e06..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerStatus.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -@interface YTPlayerStatus : NSObject -- (BOOL)externalPlayback; -- (BOOL)backgroundPlayback; -- (BOOL)isInlinePlaybackActive; -- (BOOL)pictureInPicture; -- (int)visibility; -- (int)layout; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlayerView.h b/Tweaks/YouTubeHeader/YTPlayerView.h deleted file mode 100644 index 27cca92..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerView.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "MLAVPIPPlayerLayerView.h" -#import "YTPlaybackControllerUIWrapper.h" - -@interface YTPlayerView : UIView -@property (retain, nonatomic) MLAVPIPPlayerLayerView *pipRenderingView; // Removed in newer versions -@property (nonatomic, strong, readwrite) UIView *overlayView; // Usually YTMainAppVideoPlayerOverlayView -- (YTPlaybackControllerUIWrapper *)playerViewDelegate; -- (UIView *)renderingView; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlayerViewController.h b/Tweaks/YouTubeHeader/YTPlayerViewController.h deleted file mode 100644 index ea6bca7..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -#import -#import "GIMMe.h" -#import "YTPlaybackController.h" -#import "YTSingleVideoController.h" - -@interface YTPlayerViewController : UIViewController -@property (nonatomic, readonly, assign) BOOL isPlayingAd; -@property (nonatomic, strong, readwrite) NSString *channelID; -- (GIMMe *)gimme; // Deprecated -- (NSString *)currentVideoID; -- (YTSingleVideoController *)activeVideo; -- (CGFloat)currentVideoMediaTime; -- (CGFloat)currentVideoTotalMediaTime; -- (int)playerViewLayout; -- (BOOL)isMDXActive; -- (void)didPressToggleFullscreen; -- (void)setMuted:(BOOL)muted; -- (void)setPlayerViewLayout:(int)layout; -- (void)scrubToTime:(CGFloat)time; // Deprecated -- (void)seekToTime:(CGFloat)time; -@end diff --git a/Tweaks/YouTubeHeader/YTPlayerViewControllerConfig.h b/Tweaks/YouTubeHeader/YTPlayerViewControllerConfig.h deleted file mode 100644 index fba2fe6..0000000 --- a/Tweaks/YouTubeHeader/YTPlayerViewControllerConfig.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTPlayerViewControllerConfig : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCell.h b/Tweaks/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCell.h deleted file mode 100644 index 8e2f4e1..0000000 --- a/Tweaks/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCell.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTCollectionViewCell.h" - -@interface YTPlaylistPanelProminentThumbnailVideoCell : YTCollectionViewCell -- (void)setSwipeButtonTarget:(id)target action:(SEL)action; -- (void)setSwipeButtonActionsViewRightBlock:(void (^)(void))block; -@end diff --git a/Tweaks/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCellController.h b/Tweaks/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCellController.h deleted file mode 100644 index 438396b..0000000 --- a/Tweaks/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCellController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTPlaylistPanelProminentThumbnailVideoCellController : NSObject -- (void)didPressSwipeToRevealButton; -@end diff --git a/Tweaks/YouTubeHeader/YTQTMButton.h b/Tweaks/YouTubeHeader/YTQTMButton.h deleted file mode 100644 index 4ae3799..0000000 --- a/Tweaks/YouTubeHeader/YTQTMButton.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "YTLightweightQTMButton.h" - -@interface YTQTMButton : YTLightweightQTMButton -+ (instancetype)button; -+ (instancetype)closeButton; -+ (instancetype)iconButton; -+ (instancetype)textButton; -@property (nonatomic, assign, readwrite) CGFloat buttonImageTitlePadding; -@property (nonatomic, assign, readwrite) CGFloat minHitTargetSize; -@property (nonatomic, assign, readwrite) CGFloat verticalContentPadding; -@property (nonatomic, assign, readwrite) NSInteger buttonLayoutStyle; -@property (nonatomic, assign, readwrite) BOOL refreshRendererAfterPageStyling; -@property (nonatomic, assign, readwrite) BOOL sizeWithPaddingAndInsets; -@property (nonatomic, copy, readwrite) NSString *accessibilityIdentifier; -@property (nonatomic, copy, readwrite) NSString *accessibilityLabel; -- (void)setTitleTypeKind:(NSInteger)titleTypeKind typeVariant:(NSInteger)typeVariant; -@end diff --git a/Tweaks/YouTubeHeader/YTReelContentView.h b/Tweaks/YouTubeHeader/YTReelContentView.h deleted file mode 100644 index 0030a25..0000000 --- a/Tweaks/YouTubeHeader/YTReelContentView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTReelContentView : UIView -@property (nonatomic, assign, readwrite) BOOL alwaysShowShortsProgressBar; -@end diff --git a/Tweaks/YouTubeHeader/YTReelLikeModel.h b/Tweaks/YouTubeHeader/YTReelLikeModel.h deleted file mode 100644 index 6298ade..0000000 --- a/Tweaks/YouTubeHeader/YTReelLikeModel.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTILikeButtonRenderer.h" - -@interface YTReelLikeModel : NSObject -@property (nonatomic, copy, readwrite) NSString *videoID; -@property (nonatomic, strong, readwrite) YTILikeButtonRenderer *likeButtonRenderer; -@property (nonatomic, assign, readwrite) int status; -@property (nonatomic, assign, readwrite) int lastStatus; -@end diff --git a/Tweaks/YouTubeHeader/YTReelPlayerBottomButton.h b/Tweaks/YouTubeHeader/YTReelPlayerBottomButton.h deleted file mode 100644 index 47b480e..0000000 --- a/Tweaks/YouTubeHeader/YTReelPlayerBottomButton.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTQTMButton.h" - -@interface YTReelPlayerBottomButton : YTQTMButton -@property (nonatomic, assign, readwrite) BOOL applyRightSideLayoutImageSize; -@end diff --git a/Tweaks/YouTubeHeader/YTReelPlayerViewController.h b/Tweaks/YouTubeHeader/YTReelPlayerViewController.h deleted file mode 100644 index 9edfca1..0000000 --- a/Tweaks/YouTubeHeader/YTReelPlayerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTReelContentView.h" - -@interface YTReelPlayerViewController : UIViewController -- (YTReelContentView *)contentView; -@end diff --git a/Tweaks/YouTubeHeader/YTReelWatchLikesController.h b/Tweaks/YouTubeHeader/YTReelWatchLikesController.h deleted file mode 100644 index f4c2bd9..0000000 --- a/Tweaks/YouTubeHeader/YTReelWatchLikesController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTQTMButton.h" -#import "YTILikeButtonRenderer.h" - -@interface YTReelWatchLikesController : NSObject -@property (nonatomic, strong, readwrite) YTQTMButton *likeButton; -@property (nonatomic, strong, readwrite) YTQTMButton *dislikeButton; -- (id)likeModelForLikeButtonRenderer:(YTILikeButtonRenderer *)renderer; -- (void)updateLikeButtonWithModel:(id)model animated:(BOOL)animated; -@end diff --git a/Tweaks/YouTubeHeader/YTReelWatchPlaybackOverlayView.h b/Tweaks/YouTubeHeader/YTReelWatchPlaybackOverlayView.h deleted file mode 100644 index 4211bef..0000000 --- a/Tweaks/YouTubeHeader/YTReelWatchPlaybackOverlayView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTQTMButton.h" - -@interface YTReelWatchPlaybackOverlayView : UIView -@property (nonatomic, assign, readonly) YTQTMButton *overflowButton; -- (NSArray *)orderedRightSideButtons; -@end diff --git a/Tweaks/YouTubeHeader/YTRightNavigationButtons.h b/Tweaks/YouTubeHeader/YTRightNavigationButtons.h deleted file mode 100644 index 2f88021..0000000 --- a/Tweaks/YouTubeHeader/YTRightNavigationButtons.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTRightNavigationButtons : UIView -@property (nonatomic, readwrite, assign) CGFloat leadingPadding; -@property (nonatomic, readwrite, assign) CGFloat tailingPadding; // Legitimate typo -@end diff --git a/Tweaks/YouTubeHeader/YTSearchableSettingsViewController.h b/Tweaks/YouTubeHeader/YTSearchableSettingsViewController.h deleted file mode 100644 index 5fc7a15..0000000 --- a/Tweaks/YouTubeHeader/YTSearchableSettingsViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTSearchableSettingsViewController : UIViewController -- (void)storeCollectionViewSections:(NSArray *)sections; -@end diff --git a/Tweaks/YouTubeHeader/YTSectionListViewController.h b/Tweaks/YouTubeHeader/YTSectionListViewController.h deleted file mode 100644 index af177d1..0000000 --- a/Tweaks/YouTubeHeader/YTSectionListViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTSectionListViewController : UIViewController -@end diff --git a/Tweaks/YouTubeHeader/YTSegmentableInlinePlayerBarView.h b/Tweaks/YouTubeHeader/YTSegmentableInlinePlayerBarView.h deleted file mode 100644 index 3c8342d..0000000 --- a/Tweaks/YouTubeHeader/YTSegmentableInlinePlayerBarView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTSegmentableInlinePlayerBarView : UIView -@property (nonatomic, readonly, assign) CGFloat totalTime; -@property (nonatomic, readwrite, strong) YTPlayerViewController *playerViewController; -@end diff --git a/Tweaks/YouTubeHeader/YTSettingsCell.h b/Tweaks/YouTubeHeader/YTSettingsCell.h deleted file mode 100644 index 0b598b2..0000000 --- a/Tweaks/YouTubeHeader/YTSettingsCell.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTCollectionViewCell.h" - -@interface YTSettingsCell : YTCollectionViewCell -@property (nonatomic, assign, readwrite) BOOL enabled; -- (void)setSwitchOn:(BOOL)on animated:(BOOL)animated; -- (void)toggleSwitch; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSettingsPickerViewController.h b/Tweaks/YouTubeHeader/YTSettingsPickerViewController.h deleted file mode 100644 index 256db4a..0000000 --- a/Tweaks/YouTubeHeader/YTSettingsPickerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTStyledViewController.h" - -@interface YTSettingsPickerViewController : YTStyledViewController -- (instancetype)initWithNavTitle:(NSString *)navTitle pickerSectionTitle:(NSString *)pickerSectionTitle rows:(NSArray *)rows selectedItemIndex:(NSUInteger)selectedItemIndex parentResponder:(id)parentResponder; -@end diff --git a/Tweaks/YouTubeHeader/YTSettingsSectionController.h b/Tweaks/YouTubeHeader/YTSettingsSectionController.h deleted file mode 100644 index 4e23121..0000000 --- a/Tweaks/YouTubeHeader/YTSettingsSectionController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTSettingsSectionController : NSObject -@end diff --git a/Tweaks/YouTubeHeader/YTSettingsSectionItem.h b/Tweaks/YouTubeHeader/YTSettingsSectionItem.h deleted file mode 100644 index b3ab9d9..0000000 --- a/Tweaks/YouTubeHeader/YTSettingsSectionItem.h +++ /dev/null @@ -1,21 +0,0 @@ -#import "YTSettingsCell.h" - -@interface YTSettingsSectionItem : NSObject -@property (nonatomic, copy, readwrite) NSString *title; -@property (nonatomic, assign, readwrite) BOOL hasSwitch; -@property (nonatomic, assign, readwrite) BOOL switchVisible; -@property (nonatomic, assign, readwrite) BOOL on; -@property (nonatomic, assign, readwrite) BOOL enabled; -@property (nonatomic, assign, readwrite) int settingItemId; -@property (nonatomic, copy, readwrite) BOOL (^selectBlock)(YTSettingsCell *, NSUInteger); -@property (nonatomic, copy, readwrite) BOOL (^switchBlock)(YTSettingsCell *, BOOL); -+ (instancetype)itemWithTitle:(NSString *)title accessibilityIdentifier:(NSString *)accessibilityIdentifier detailTextBlock:(NSString *(^)(void))detailTextBlock selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)itemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(NSString *)accessibilityIdentifier detailTextBlock:(id)detailTextBlock selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock disabledSelectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))disabledSelectBlock; -+ (instancetype)switchItemWithTitle:(NSString *)title switchOn:(BOOL)switchOn switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock; -+ (instancetype)switchItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(NSString *)accessibilityIdentifier switchOn:(BOOL)switchOn switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock settingItemId:(int)settingItemId; -+ (instancetype)switchItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(NSString *)accessibilityIdentifier switchOn:(BOOL)switchOn switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock settingItemId:(int)settingItemId; -- (instancetype)initWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSettingsSectionItemManager.h b/Tweaks/YouTubeHeader/YTSettingsSectionItemManager.h deleted file mode 100644 index 6ea6259..0000000 --- a/Tweaks/YouTubeHeader/YTSettingsSectionItemManager.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "GIMMe.h" - -@interface YTSettingsSectionItemManager : NSObject -@property (nonatomic, readwrite, weak) GIMMe *gimme; -- (id)parentResponder; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSettingsViewController.h b/Tweaks/YouTubeHeader/YTSettingsViewController.h deleted file mode 100644 index 5959d3c..0000000 --- a/Tweaks/YouTubeHeader/YTSettingsViewController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTSettingsSectionItem.h" -#import "YTSettingsSectionController.h" - -@interface YTSettingsViewController : UIViewController -- (NSMutableDictionary *)settingsSectionControllers; -- (void)setSectionItems:(NSMutableArray *)sectionItems forCategory:(NSInteger)category title:(NSString *)title titleDescription:(NSString *)titleDescription headerHidden:(BOOL)headerHidden; -- (void)pushViewController:(UIViewController *)viewController; -- (void)reloadData; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSingleVideo.h b/Tweaks/YouTubeHeader/YTSingleVideo.h deleted file mode 100644 index 9d86038..0000000 --- a/Tweaks/YouTubeHeader/YTSingleVideo.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTPlaybackData.h" -#import "MLVideo.h" - -@interface YTSingleVideo : NSObject -- (MLVideo *)video; // Deprecated -- (NSString *)videoId; -- (YTPlaybackData *)playbackData; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSingleVideoController.h b/Tweaks/YouTubeHeader/YTSingleVideoController.h deleted file mode 100644 index e23f990..0000000 --- a/Tweaks/YouTubeHeader/YTSingleVideoController.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "MLFormat.h" -#import "YTSingleVideoControllerDelegate.h" -#import "YTSingleVideo.h" - -@interface YTSingleVideoController : NSObject -@property (nonatomic, weak, readwrite) NSObject *delegate; -- (YTSingleVideo *)singleVideo; -- (YTSingleVideo *)videoData; -- (NSArray *)selectableVideoFormats; -- (BOOL)isMuted; -- (void)playerRateDidChange:(float)rate; -- (void)setMuted:(BOOL)muted; -@end diff --git a/Tweaks/YouTubeHeader/YTSingleVideoControllerDelegate.h b/Tweaks/YouTubeHeader/YTSingleVideoControllerDelegate.h deleted file mode 100644 index 808da0b..0000000 --- a/Tweaks/YouTubeHeader/YTSingleVideoControllerDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@protocol YTSingleVideoControllerDelegate -- (void)singleVideoController:(id)controller requiresReloadWithContext:(id)context; -- (void)singleVideoController:(id)controller externalPlaybackActiveStateDidChange:(id)arg2; -@end diff --git a/Tweaks/YouTubeHeader/YTSingleVideoTime.h b/Tweaks/YouTubeHeader/YTSingleVideoTime.h deleted file mode 100644 index dc39331..0000000 --- a/Tweaks/YouTubeHeader/YTSingleVideoTime.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -@interface YTSingleVideoTime : NSObject -@property (nonatomic, readonly, assign) CGFloat absoluteTime; -@property (nonatomic, readonly, assign) CGFloat time; -@property (nonatomic, readonly, assign) CGFloat productionTime; -+ (instancetype)zero; -+ (instancetype)timeWithTime:(CGFloat)time; -+ (instancetype)timeWithTime:(CGFloat)time productionTime:(CGFloat)productionTime; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlideForActionsView.h b/Tweaks/YouTubeHeader/YTSlideForActionsView.h deleted file mode 100644 index 21718df..0000000 --- a/Tweaks/YouTubeHeader/YTSlideForActionsView.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTSlideForActionsView : UIView -@property (nonatomic, assign, readwrite) BOOL actionsEnabledRight; -@property (nonatomic, assign, readwrite) BOOL enableMinSnap; -@property (nonatomic, assign, readwrite) BOOL enableHapticFeedback; -@end diff --git a/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionView.h b/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionView.h deleted file mode 100644 index 40d02f3..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionView.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "YTIFormattedStringLabel.h" -#import "YTSlimVideoScrollableDetailsActionsView.h" - -@interface YTSlimVideoDetailsActionView : UIView -@property (nonatomic, strong, readwrite) YTIFormattedStringLabel *label; -@property (nonatomic, weak, readwrite) YTSlimVideoScrollableDetailsActionsView *visibilityDelegate; -@property (nonatomic) __weak id delegate; -@property (nonatomic, assign, readwrite, getter=isToggled) BOOL toggled; -- (instancetype)initWithSlimMetadataButtonSupportedRenderer:(id)renderer; -@end diff --git a/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionViewDelegate.h b/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionViewDelegate.h deleted file mode 100644 index 1639890..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionViewDelegate.h +++ /dev/null @@ -1,7 +0,0 @@ -#include "YTQTMButton.h" -#import "YTQTMButton.h" - -@protocol YTSlimVideoDetailsActionViewDelegate -- (void)didTapButton:(YTQTMButton *)button fromRect:(CGRect)rect inView:(UIView *)view; -- (void)handleLongPressOnButton:(YTQTMButton *)button fromRect:(CGRect)rect inView:(UIView *)view; -@end diff --git a/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionsView.h b/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionsView.h deleted file mode 100644 index e216a81..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoDetailsActionsView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlimVideoDetailsActionViewDelegate.h" - -@interface YTSlimVideoDetailsActionsView : UIScrollView -@property (nonatomic, weak, readwrite) NSObject *videoActionsDelegate; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlimVideoMetadataExpandingBehavior.h b/Tweaks/YouTubeHeader/YTSlimVideoMetadataExpandingBehavior.h deleted file mode 100644 index 0f85885..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoMetadataExpandingBehavior.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTSlimVideoScrollableActionBarCellControllerDelegate.h" - -@interface YTSlimVideoMetadataExpandingBehavior : NSObject -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCell.h b/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCell.h deleted file mode 100644 index 12c2f10..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCell.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTCollectionViewCellProtocol.h" -#import "YTSlimVideoScrollableDetailsActionsProtocol.h" - -@interface YTSlimVideoScrollableActionBarCell : UICollectionViewCell -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h b/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h deleted file mode 100644 index 71ff43d..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTSlimVideoScrollableActionBarCellControllerDelegate.h" -#import "YTInnerTubeCellController.h" - -@interface YTSlimVideoScrollableActionBarCellController : YTInnerTubeCellController -@property (nonatomic, weak, readwrite) NSObject *delegate; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCellControllerDelegate.h b/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCellControllerDelegate.h deleted file mode 100644 index 17cb153..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoScrollableActionBarCellControllerDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@protocol YTSlimVideoScrollableActionBarCellControllerDelegate -@required -- (NSString *)videoId; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlimVideoScrollableDetailsActionsProtocol.h b/Tweaks/YouTubeHeader/YTSlimVideoScrollableDetailsActionsProtocol.h deleted file mode 100644 index defbb58..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoScrollableDetailsActionsProtocol.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlimVideoDetailsActionView.h" - -@protocol YTSlimVideoScrollableDetailsActionsProtocol -- (YTSlimVideoDetailsActionView *)offlineActionView; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h b/Tweaks/YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h deleted file mode 100644 index 4f9c2fd..0000000 --- a/Tweaks/YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlimVideoDetailsActionViewDelegate.h" - -@interface YTSlimVideoScrollableDetailsActionsView : UIScrollView -@property (nonatomic, weak, readwrite) NSObject *videoActionsDelegate; -@end diff --git a/Tweaks/YouTubeHeader/YTStyledViewController.h b/Tweaks/YouTubeHeader/YTStyledViewController.h deleted file mode 100644 index 5760486..0000000 --- a/Tweaks/YouTubeHeader/YTStyledViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTMultiSizeViewController.h" - -@interface YTStyledViewController : YTMultiSizeViewController -@end diff --git a/Tweaks/YouTubeHeader/YTSystemNotifications.h b/Tweaks/YouTubeHeader/YTSystemNotifications.h deleted file mode 100644 index a9ff95b..0000000 --- a/Tweaks/YouTubeHeader/YTSystemNotifications.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTSystemNotifications : NSObject -- (void)addSystemNotificationsObserver:(id)observer; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTToastResponderEvent.h b/Tweaks/YouTubeHeader/YTToastResponderEvent.h deleted file mode 100644 index f46b4ae..0000000 --- a/Tweaks/YouTubeHeader/YTToastResponderEvent.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTToastResponderEvent : NSObject -+ (instancetype)eventWithMessage:(NSString *)message firstResponder:(id)firstResponder; -- (void)send; -@end diff --git a/Tweaks/YouTubeHeader/YTUIResources.h b/Tweaks/YouTubeHeader/YTUIResources.h deleted file mode 100644 index dd99366..0000000 --- a/Tweaks/YouTubeHeader/YTUIResources.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTUIResources : NSObject -+ (UIImage *)iconCheckTemplateImage; -+ (UIImage *)actionsheetDefaultImage; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTUIUtils.h b/Tweaks/YouTubeHeader/YTUIUtils.h deleted file mode 100644 index a7c115e..0000000 --- a/Tweaks/YouTubeHeader/YTUIUtils.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTUIUtils : NSObject -+ (BOOL)canOpenURL:(NSURL *)url; -+ (BOOL)openURL:(NSURL *)url; -+ (UIViewController *)topViewControllerForPresenting; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTVersionUtils.h b/Tweaks/YouTubeHeader/YTVersionUtils.h deleted file mode 100644 index c5b10b6..0000000 --- a/Tweaks/YouTubeHeader/YTVersionUtils.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTVersionUtils : NSObject -+ (NSString *)appVersion; -@end diff --git a/Tweaks/YouTubeHeader/YTVideoQualitySwitchOriginalController.h b/Tweaks/YouTubeHeader/YTVideoQualitySwitchOriginalController.h deleted file mode 100644 index 98d5b2c..0000000 --- a/Tweaks/YouTubeHeader/YTVideoQualitySwitchOriginalController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTVideoQualitySwitchOriginalController : NSObject -- (instancetype)initWithParentResponder:(id)responder; -@end \ No newline at end of file diff --git a/Tweaks/YouTubeHeader/YTWatchController.h b/Tweaks/YouTubeHeader/YTWatchController.h deleted file mode 100644 index 30b2b70..0000000 --- a/Tweaks/YouTubeHeader/YTWatchController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTWatchPlaybackController.h" - -@interface YTWatchController : NSObject -@property (nonatomic, strong, readwrite) YTWatchPlaybackController *watchPlaybackController; -- (void)showFullScreen; -- (void)showSmallScreen; -@end diff --git a/Tweaks/YouTubeHeader/YTWatchLayerViewController.h b/Tweaks/YouTubeHeader/YTWatchLayerViewController.h deleted file mode 100644 index d651b65..0000000 --- a/Tweaks/YouTubeHeader/YTWatchLayerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTWatchLayerViewController : UIViewController -- (YTPlayerViewController *)playerViewController; -@end diff --git a/Tweaks/YouTubeHeader/YTWatchMetadataPanelStateResponderProvider.h b/Tweaks/YouTubeHeader/YTWatchMetadataPanelStateResponderProvider.h deleted file mode 100644 index fc29ec7..0000000 --- a/Tweaks/YouTubeHeader/YTWatchMetadataPanelStateResponderProvider.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@protocol YTWatchMetadataPanelStateResponderProvider -@end diff --git a/Tweaks/YouTubeHeader/YTWatchMiniBarViewController.h b/Tweaks/YouTubeHeader/YTWatchMiniBarViewController.h deleted file mode 100644 index 07af781..0000000 --- a/Tweaks/YouTubeHeader/YTWatchMiniBarViewController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTWatchMiniBarViewController : UIViewController -@property (nonatomic, assign, readwrite, getter=isActivated) BOOL activated; -@property (nonatomic, assign, readwrite, getter=isVisible) BOOL visible; -@end diff --git a/Tweaks/YouTubeHeader/YTWatchNextResultsViewController.h b/Tweaks/YouTubeHeader/YTWatchNextResultsViewController.h deleted file mode 100644 index dcb4e1c..0000000 --- a/Tweaks/YouTubeHeader/YTWatchNextResultsViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTWatchNextResultsViewController : UIViewController -@end diff --git a/Tweaks/YouTubeHeader/YTWatchPlaybackController.h b/Tweaks/YouTubeHeader/YTWatchPlaybackController.h deleted file mode 100644 index 87cc89c..0000000 --- a/Tweaks/YouTubeHeader/YTWatchPlaybackController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTWatchPlaybackController : NSObject -@end diff --git a/Tweaks/YouTubeHeader/YTWatchViewController.h b/Tweaks/YouTubeHeader/YTWatchViewController.h deleted file mode 100644 index 62c1395..0000000 --- a/Tweaks/YouTubeHeader/YTWatchViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTWatchViewController : UIViewController -@property (nonatomic, weak, readwrite) YTPlayerViewController *playerViewController; -@end diff --git a/Tweaks/YouTubeHeader/_ASCollectionViewCell.h b/Tweaks/YouTubeHeader/_ASCollectionViewCell.h deleted file mode 100644 index 51ae67c..0000000 --- a/Tweaks/YouTubeHeader/_ASCollectionViewCell.h +++ /dev/null @@ -1,8 +0,0 @@ -#import -#import "ASCollectionElement.h" -#import "ASCellNode.h" - -@interface _ASCollectionViewCell : UICollectionViewCell -@property (nonatomic, strong, readwrite) ASCollectionElement *element; -- (ASCellNode *)node; -@end diff --git a/Tweaks/YouTubeHeader/_ASDisplayView.h b/Tweaks/YouTubeHeader/_ASDisplayView.h deleted file mode 100644 index cf50613..0000000 --- a/Tweaks/YouTubeHeader/_ASDisplayView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "ASDisplayNode.h" - -@interface _ASDisplayView : UIView -@property (nonatomic, copy, readwrite) NSString *accessibilityLabel; -@property (nonatomic) ASDisplayNode *keepalive_node; -@end diff --git a/Tweaks/iSponsorBlock b/Tweaks/iSponsorBlock new file mode 160000 index 0000000..96954d5 --- /dev/null +++ b/Tweaks/iSponsorBlock @@ -0,0 +1 @@ +Subproject commit 96954d578d56e6762f0b179a2b837598a542d40c diff --git a/Tweaks/iSponsorBlock/.github/ISSUE_TEMPLATE/bug_report.md b/Tweaks/iSponsorBlock/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 0e958b1..0000000 --- a/Tweaks/iSponsorBlock/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: Galactic-Dev - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Please complete the following information:** - - iOS Version: [e.g. 14.3] - - Device: [e.g. iPhone X] - - YouTube Version [e.g. 16.11.3] - - iSponsorBlock Version [e.g. 1.0-7] - -**Additional context** -Add any other context about the problem here. diff --git a/Tweaks/iSponsorBlock/.github/ISSUE_TEMPLATE/feature_request.md b/Tweaks/iSponsorBlock/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 11fc491..0000000 --- a/Tweaks/iSponsorBlock/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/Tweaks/iSponsorBlock/.gitignore b/Tweaks/iSponsorBlock/.gitignore deleted file mode 100644 index c857462..0000000 --- a/Tweaks/iSponsorBlock/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/theos-tweak -# Edit at https://www.toptal.com/developers/gitignore?templates=theos-tweak - -### THEOS-Tweak ### -._* -*.deb -.debmake -_ -obj -.theos -.DS_Store - -### XCode stuff -*.xcworkspace - -# End of https://www.toptal.com/developers/gitignore/api/theos-tweak diff --git a/Tweaks/iSponsorBlock/.gitmodules b/Tweaks/iSponsorBlock/.gitmodules deleted file mode 100644 index ef2ff86..0000000 --- a/Tweaks/iSponsorBlock/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "Headers/YouTubeHeader"] - path = Headers/YouTubeHeader - url = https://github.com/PoomSmart/YouTubeHeader diff --git a/Tweaks/iSponsorBlock/Headers/ColorFunctions.h b/Tweaks/iSponsorBlock/Headers/ColorFunctions.h deleted file mode 100644 index 1a3f7a9..0000000 --- a/Tweaks/iSponsorBlock/Headers/ColorFunctions.h +++ /dev/null @@ -1,37 +0,0 @@ -#import -#import -//https://stackoverflow.com/a/26341062 -static NSString *hexFromUIColor(UIColor *color) { - const CGFloat *components = CGColorGetComponents(color.CGColor); - - CGFloat r = components[0]; - CGFloat g = components[1]; - CGFloat b = components[2]; - - return [NSString stringWithFormat:@"#%02lX%02lX%02lX", - lroundf(r * 255), - lroundf(g * 255), - lroundf(b * 255)]; -} - -static CGFloat colorComponentFrom(NSString *string, NSUInteger start, NSUInteger length) { - NSString *substring = [string substringWithRange: NSMakeRange(start, length)]; - NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring]; - unsigned hexComponent; - [[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent]; - return hexComponent / 255.0; -} - -static UIColor *colorWithHexString(NSString *hexString) { - NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString]; - - CGFloat alpha, red, blue, green; - - // #RGB - alpha = 1.0f; - red = colorComponentFrom(colorString,0,2); - green = colorComponentFrom(colorString,2,2); - blue = colorComponentFrom(colorString,4,2); - - return [UIColor colorWithRed: red green: green blue: blue alpha: alpha]; -} diff --git a/Tweaks/iSponsorBlock/Headers/Localization.h b/Tweaks/iSponsorBlock/Headers/Localization.h deleted file mode 100644 index 068fe7d..0000000 --- a/Tweaks/iSponsorBlock/Headers/Localization.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -extern NSBundle *iSponsorBlockBundle(); - -static inline NSString *LOC(NSString *key) { - NSBundle *tweakBundle = iSponsorBlockBundle(); - return [tweakBundle localizedStringForKey:key value:nil table:nil]; -} \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/MBProgressHUD.h b/Tweaks/iSponsorBlock/Headers/MBProgressHUD.h deleted file mode 100644 index ca25ca1..0000000 --- a/Tweaks/iSponsorBlock/Headers/MBProgressHUD.h +++ /dev/null @@ -1,411 +0,0 @@ -// -// MBProgressHUD.h -// Version 1.2.0 -// Created by Matej Bukovinski on 2.4.09. -// - -// This code is distributed under the terms and conditions of the MIT license. - -// Copyright © 2009-2020 Matej Bukovinski -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -#import -#import -#import - -@class MBBackgroundView; -@protocol MBProgressHUDDelegate; - - -extern CGFloat const MBProgressMaxOffset; - -typedef NS_ENUM(NSInteger, MBProgressHUDMode) { - /// UIActivityIndicatorView. - MBProgressHUDModeIndeterminate, - /// A round, pie-chart like, progress view. - MBProgressHUDModeDeterminate, - /// Horizontal progress bar. - MBProgressHUDModeDeterminateHorizontalBar, - /// Ring-shaped progress view. - MBProgressHUDModeAnnularDeterminate, - /// Shows a custom view. - MBProgressHUDModeCustomView, - /// Shows only labels. - MBProgressHUDModeText -}; - -typedef NS_ENUM(NSInteger, MBProgressHUDAnimation) { - /// Opacity animation - MBProgressHUDAnimationFade, - /// Opacity + scale animation (zoom in when appearing zoom out when disappearing) - MBProgressHUDAnimationZoom, - /// Opacity + scale animation (zoom out style) - MBProgressHUDAnimationZoomOut, - /// Opacity + scale animation (zoom in style) - MBProgressHUDAnimationZoomIn -}; - -typedef NS_ENUM(NSInteger, MBProgressHUDBackgroundStyle) { - /// Solid color background - MBProgressHUDBackgroundStyleSolidColor, - /// UIVisualEffectView or UIToolbar.layer background view - MBProgressHUDBackgroundStyleBlur -}; - -typedef void (^MBProgressHUDCompletionBlock)(void); - - -NS_ASSUME_NONNULL_BEGIN - - -/** - * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. - * - * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. - * The MBProgressHUD window spans over the entire space given to it by the initWithFrame: constructor and catches all - * user input on this region, thereby preventing the user operations on components below the view. - * - * @note To still allow touches to pass through the HUD, you can set hud.userInteractionEnabled = NO. - * @attention MBProgressHUD is a UI class and should therefore only be accessed on the main thread. - */ -@interface MBProgressHUD : UIView - -/** - * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. - * - * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. - * - * @param view The view that the HUD will be added to - * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use - * animations while appearing. - * @return A reference to the created HUD. - * - * @see hideHUDForView:animated: - * @see animationType - */ -+ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; - -/// @name Showing and hiding - -/** - * Finds the top-most HUD subview that hasn't finished and hides it. The counterpart to this method is showHUDAddedTo:animated:. - * - * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. - * - * @param view The view that is going to be searched for a HUD subview. - * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use - * animations while disappearing. - * @return YES if a HUD was found and removed, NO otherwise. - * - * @see showHUDAddedTo:animated: - * @see animationType - */ -+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; - -/** - * Finds the top-most HUD subview that hasn't finished and returns it. - * - * @param view The view that is going to be searched. - * @return A reference to the last HUD subview discovered. - */ -+ (nullable MBProgressHUD *)HUDForView:(UIView *)view NS_SWIFT_NAME(forView(_:)); - -/** - * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with - * view.bounds as the parameter. - * - * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as - * the HUD's superview (i.e., the view that the HUD will be added to). - */ -- (instancetype)initWithView:(UIView *)view; - -/** - * Displays the HUD. - * - * @note You need to make sure that the main thread completes its run loop soon after this method call so that - * the user interface can be updated. Call this method when your task is already set up to be executed in a new thread - * (e.g., when using something like NSOperation or making an asynchronous call like NSURLRequest). - * - * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use - * animations while appearing. - * - * @see animationType - */ -- (void)showAnimated:(BOOL)animated; - -/** - * Hides the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to - * hide the HUD when your task completes. - * - * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use - * animations while disappearing. - * - * @see animationType - */ -- (void)hideAnimated:(BOOL)animated; - -/** - * Hides the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to - * hide the HUD when your task completes. - * - * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use - * animations while disappearing. - * @param delay Delay in seconds until the HUD is hidden. - * - * @see animationType - */ -- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; - -/** - * The HUD delegate object. Receives HUD state notifications. - */ -@property (weak, nonatomic) id delegate; - -/** - * Called after the HUD is hidden. - */ -@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock; - -/** - * Grace period is the time (in seconds) that the invoked method may be run without - * showing the HUD. If the task finishes before the grace time runs out, the HUD will - * not be shown at all. - * This may be used to prevent HUD display for very short tasks. - * Defaults to 0 (no grace time). - * @note The graceTime needs to be set before the hud is shown. You thus can't use `showHUDAddedTo:animated:`, - * but instead need to alloc / init the HUD, configure the grace time and than show it manually. - */ -@property (assign, nonatomic) NSTimeInterval graceTime; - -/** - * The minimum time (in seconds) that the HUD is shown. - * This avoids the problem of the HUD being shown and than instantly hidden. - * Defaults to 0 (no minimum show time). - */ -@property (assign, nonatomic) NSTimeInterval minShowTime; - -/** - * Removes the HUD from its parent view when hidden. - * Defaults to NO. - */ -@property (assign, nonatomic) BOOL removeFromSuperViewOnHide; - -/// @name Appearance - -/** - * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. - */ -@property (assign, nonatomic) MBProgressHUDMode mode; - -/** - * A color that gets forwarded to all labels and supported indicators. Also sets the tintColor - * for custom views on iOS 7+. Set to nil to manage color individually. - * Defaults to semi-translucent black on iOS 7 and later and white on earlier iOS versions. - */ -@property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; - -/** - * The animation type that should be used when the HUD is shown and hidden. - */ -@property (assign, nonatomic) MBProgressHUDAnimation animationType UI_APPEARANCE_SELECTOR; - -/** - * The bezel offset relative to the center of the view. You can use MBProgressMaxOffset - * and -MBProgressMaxOffset to move the HUD all the way to the screen edge in each direction. - * E.g., CGPointMake(0.f, MBProgressMaxOffset) would position the HUD centered on the bottom edge. - */ -@property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; - -/** - * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). - * This also represents the minimum bezel distance to the edge of the HUD view. - * Defaults to 20.f - */ -@property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; - -/** - * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). - */ -@property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; - -/** - * Force the HUD dimensions to be equal if possible. - */ -@property (assign, nonatomic, getter = isSquare) BOOL square UI_APPEARANCE_SELECTOR; - -/** - * When enabled, the bezel center gets slightly affected by the device accelerometer data. - * Defaults to NO. - * - * @note This can cause main thread checker assertions on certain devices. https://github.com/jdg/MBProgressHUD/issues/552 - */ -@property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled UI_APPEARANCE_SELECTOR; - -/// @name Progress - -/** - * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. - */ -@property (assign, nonatomic) float progress; - -/// @name ProgressObject - -/** - * The NSProgress object feeding the progress information to the progress indicator. - */ -@property (strong, nonatomic, nullable) NSProgress *progressObject; - -/// @name Views - -/** - * The view containing the labels and indicator (or customView). - */ -@property (strong, nonatomic, readonly) MBBackgroundView *bezelView; - -/** - * View covering the entire HUD area, placed behind bezelView. - */ -@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; - -/** - * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. - * The view should implement intrinsicContentSize for proper sizing. For best results use approximately 37 by 37 pixels. - */ -@property (strong, nonatomic, nullable) UIView *customView; - -/** - * A label that holds an optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit - * the entire text. - */ -@property (strong, nonatomic, readonly) UILabel *label; - -/** - * A label that holds an optional details message displayed below the labelText message. The details text can span multiple lines. - */ -@property (strong, nonatomic, readonly) UILabel *detailsLabel; - -/** - * A button that is placed below the labels. Visible only if a target / action is added and a title is assigned.. - */ -@property (strong, nonatomic, readonly) UIButton *button; -@property (strong, nonatomic, readonly) UIButton *cancelButton; - -@end - - -@protocol MBProgressHUDDelegate - -@optional - -/** - * Called after the HUD was fully hidden from the screen. - */ -- (void)hudWasHidden:(MBProgressHUD *)hud; - -@end - - -/** - * A progress view for showing definite progress by filling up a circle (pie chart). - */ -@interface MBRoundProgressView : UIView - -/** - * Progress (0.0 to 1.0) - */ -@property (nonatomic, assign) float progress; - -/** - * Indicator progress color. - * Defaults to white [UIColor whiteColor]. - */ -@property (nonatomic, strong) UIColor *progressTintColor; - -/** - * Indicator background (non-progress) color. - * Only applicable on iOS versions older than iOS 7. - * Defaults to translucent white (alpha 0.1). - */ -@property (nonatomic, strong) UIColor *backgroundTintColor; - -/* - * Display mode - NO = round or YES = annular. Defaults to round. - */ -@property (nonatomic, assign, getter = isAnnular) BOOL annular; - -@end - - -/** - * A flat bar progress view. - */ -@interface MBBarProgressView : UIView - -/** - * Progress (0.0 to 1.0) - */ -@property (nonatomic, assign) float progress; - -/** - * Bar border line color. - * Defaults to white [UIColor whiteColor]. - */ -@property (nonatomic, strong) UIColor *lineColor; - -/** - * Bar background color. - * Defaults to clear [UIColor clearColor]; - */ -@property (nonatomic, strong) UIColor *progressRemainingColor; - -/** - * Bar progress color. - * Defaults to white [UIColor whiteColor]. - */ -@property (nonatomic, strong) UIColor *progressColor; - -@end - - -@interface MBBackgroundView : UIView - -/** - * The background style. - * Defaults to MBProgressHUDBackgroundStyleBlur. - */ -@property (nonatomic) MBProgressHUDBackgroundStyle style; - -/** - * The blur effect style, when using MBProgressHUDBackgroundStyleBlur. - * Defaults to UIBlurEffectStyleLight. - */ -@property (nonatomic) UIBlurEffectStyle blurEffectStyle; - -/** - * The background color or the blur tint color. - * - * Defaults to nil on iOS 13 and later and - * `[UIColor colorWithWhite:0.8f alpha:0.6f]` - * on older systems. - */ -@property (nonatomic, strong, nullable) UIColor *color; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tweaks/iSponsorBlock/Headers/SponsorBlockRequest.h b/Tweaks/iSponsorBlock/Headers/SponsorBlockRequest.h deleted file mode 100644 index 08f1a25..0000000 --- a/Tweaks/iSponsorBlock/Headers/SponsorBlockRequest.h +++ /dev/null @@ -1,11 +0,0 @@ -#import -#import "iSponsorBlock.h" -#import - -@interface SponsorBlockRequest : NSObject -+(void)getSponsorTimes:(NSString *)videoID completionTarget:(id)target completionSelector:(SEL)sel apiInstance:(NSString *)apiInstance; -+(void)postSponsorTimes:(NSString *)videoID sponsorSegments:(NSArray *)segments userID:(NSString *)userID withViewController:(UIViewController *)viewController; -+(void)normalVoteForSegment:(SponsorSegment *)segment userID:(NSString *)userID type:(BOOL)type withViewController:(UIViewController *)viewController; -+(void)categoryVoteForSegment:(SponsorSegment *)segment userID:(NSString *)userID category:(NSString *)category withViewController:(UIViewController *)viewController; -+(void)viewedVideoSponsorTime:(SponsorSegment *)segment; -@end diff --git a/Tweaks/iSponsorBlock/Headers/SponsorBlockSettingsController.h b/Tweaks/iSponsorBlock/Headers/SponsorBlockSettingsController.h deleted file mode 100644 index be117ff..0000000 --- a/Tweaks/iSponsorBlock/Headers/SponsorBlockSettingsController.h +++ /dev/null @@ -1,52 +0,0 @@ -#import -#import -#import -#import "ColorFunctions.h" - -@protocol HBColorPickerDelegate -@optional -(void)colorPicker:(id)colorPicker didSelectColor:(UIColor *)color; -@end - -@interface UIView () -- (UIViewController *)_viewControllerForAncestor; -@end - -@interface UITableViewCell () -- (UITextField *)editableTextField; -- (id)_indexPath; -@end - -@interface UISegment : UIView -@end - -@interface HBColorPickerConfiguration -@property (nonatomic, assign) BOOL supportsAlpha; -@end - -@interface HBColorPickerViewController : UIViewController -@property (strong, nonatomic) NSObject *delegate; -@property (strong, nonatomic) HBColorPickerConfiguration *configuration; -@end - -@interface HBColorWell : UIControl -@property (nonatomic, assign) BOOL isDragInteractionEnabled; -@property (nonatomic, assign) BOOL isDropInteractionEnabled; -@property (strong, nonatomic) UIColor *color; -@end - -@interface SponsorBlockTableCell : UITableViewCell -@property (strong, nonatomic) NSString *category; -@property (strong, nonatomic) UIColor *color; -@property (strong, nonatomic) HBColorWell *colorWell; -@end - -@interface SponsorBlockSettingsController : UIViewController -@property (nonatomic, strong) NSString *tweakTitle; -@property (strong, nonatomic) UITableView *tableView; -@property (strong, nonatomic) NSArray *sectionTitles; -@property (strong, nonatomic) NSMutableDictionary *settings; -@property (strong, nonatomic) NSString *settingsPath; -- (void)enabledSwitchToggled:(UISwitch *)sender; -- (void)switchToggled:(UISwitch *)sender; -- (void)categorySegmentSelected:(UISegmentedControl *)segmentedControl; -@end diff --git a/Tweaks/iSponsorBlock/Headers/SponsorBlockViewController.h b/Tweaks/iSponsorBlock/Headers/SponsorBlockViewController.h deleted file mode 100644 index 2b411d3..0000000 --- a/Tweaks/iSponsorBlock/Headers/SponsorBlockViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -#import -#import "SponsorSegmentView.h" -#import "iSponsorBlock.h" - -@interface SponsorBlockViewController : UIViewController -@property (strong, nonatomic) YTPlayerViewController *playerViewController; -@property (strong, nonatomic) UIViewController *previousParentViewController; -@property (strong, nonatomic) YTMainAppControlsOverlayView *overlayView; -@property (strong, nonatomic) UIButton *startEndSegmentButton; -@property (strong, nonatomic) UILabel *segmentsInDatabaseLabel; -@property (strong, nonatomic) UILabel *userSegmentsLabel; -@property (strong, nonatomic) UIButton *submitSegmentsButton; -@property (strong, nonatomic) NSMutableArray *sponsorSegmentViews; -@property (strong, nonatomic) NSMutableArray *userSponsorSegmentViews; -@property (strong, nonatomic) UILabel *whitelistChannelLabel; -- (void)startEndSegmentButtonPressed:(UIButton *)sender; -- (NSMutableArray *)segmentViewsForSegments:(NSArray *)segments editable:(BOOL)editable; -- (void)setupViews; -@end diff --git a/Tweaks/iSponsorBlock/Headers/SponsorSegment.h b/Tweaks/iSponsorBlock/Headers/SponsorSegment.h deleted file mode 100644 index c39a1a3..0000000 --- a/Tweaks/iSponsorBlock/Headers/SponsorSegment.h +++ /dev/null @@ -1,10 +0,0 @@ -#import -#import - -@interface SponsorSegment : NSObject -@property (nonatomic, assign) CGFloat startTime; -@property (nonatomic, assign) CGFloat endTime; -@property (strong, nonatomic) NSString *category; -@property (strong, nonatomic) NSString *UUID; -- (instancetype)initWithStartTime:(CGFloat)startTime endTime:(CGFloat)endTime category:(NSString *)category UUID:(NSString *)UUID; -@end diff --git a/Tweaks/iSponsorBlock/Headers/SponsorSegmentView.h b/Tweaks/iSponsorBlock/Headers/SponsorSegmentView.h deleted file mode 100644 index 10ff7ae..0000000 --- a/Tweaks/iSponsorBlock/Headers/SponsorSegmentView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import -#import "SponsorSegment.h" -#import "SponsorBlockRequest.h" - -@interface SponsorSegmentView : UIView -@property (strong, nonatomic) SponsorSegment *sponsorSegment; -@property (nonatomic, assign) BOOL editable; -@property (strong, nonatomic) UILabel *segmentLabel; -@property (strong, nonatomic) UILabel *categoryLabel; -- (instancetype)initWithFrame:(CGRect)frame sponsorSegment:(SponsorSegment *)segment editable:(BOOL)editable; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/.gitattributes b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/.gitignore b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/.gitignore deleted file mode 100644 index 9bea433..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ - -.DS_Store diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASCollectionElement.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASCollectionElement.h deleted file mode 100644 index d1743f0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASCollectionElement.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface ASCollectionElement : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASCollectionView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASCollectionView.h deleted file mode 100644 index f7d41ea..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASCollectionView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface ASCollectionView : UICollectionView -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASControlNode.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASControlNode.h deleted file mode 100644 index 56c0a7e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASControlNode.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "ASDisplayNode.h" - -@interface ASControlNode : ASDisplayNode -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASDisplayNode.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASDisplayNode.h deleted file mode 100644 index c0d84b8..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASDisplayNode.h +++ /dev/null @@ -1,21 +0,0 @@ -#import -#import "ASLayoutElementStyleYoga.h" - -@interface ASDisplayNode : NSObject -@property (atomic, copy, readwrite) NSArray *yogaChildren; -@property (nonatomic, copy, readwrite) NSString *accessibilityIdentifier; -@property (atomic, weak, readonly) ASDisplayNode *yogaParent; -@property (atomic, strong, readwrite) id contents; -@property (atomic, assign, readwrite) CGFloat alpha; -@property (atomic, assign, readwrite) CGRect frame; -@property (atomic, assign, readwrite) CGRect bounds; -@property (atomic, assign, readonly) unsigned char interfaceState; -@property (atomic, assign, readwrite, getter=isHidden) BOOL hidden; -@property (atomic, assign, readwrite, getter=isLayerBacked) BOOL layerBacked; -@property (atomic, assign, readwrite) BOOL automaticallyManagesSubnodes; -- (id)controller; -- (ASLayoutElementStyleYoga *)style; -- (UIViewController *)closestViewController; -- (UIView *)view; -- (BOOL)isNodeLoaded; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASLayoutElementStyleYoga.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASLayoutElementStyleYoga.h deleted file mode 100644 index f498d5f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASLayoutElementStyleYoga.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface ASLayoutElementStyleYoga : NSObject -@property (nonatomic, assign, readwrite) CGFloat spacingBefore; -@property (nonatomic, assign, readwrite) CGFloat spacingAfter; -@property (nonatomic, assign, readwrite) CGFloat flexGrow; -@property (nonatomic, assign, readwrite) CGFloat flexShrink; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASNodeContext.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASNodeContext.h deleted file mode 100644 index 72bd1cc..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASNodeContext.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ASNodeContext : NSObject -- (instancetype)initWithOptions:(unsigned char)options; -- (unsigned char)options; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASNodeController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASNodeController.h deleted file mode 100644 index 54190b6..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASNodeController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface ASNodeController : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASTextNode.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASTextNode.h deleted file mode 100644 index 3af155f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ASTextNode.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "ASControlNode.h" - -@interface ASTextNode : ASControlNode -@property (atomic, copy, readwrite) NSAttributedString *attributedText; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMCellNode.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMCellNode.h deleted file mode 100644 index b1e7272..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMCellNode.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "ASCellNode.h" -#import "ELMElement.h" - -@interface ELMCellNode : ASCellNode -@property (atomic, strong, readwrite) ELMElement *element; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMContainerNode.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMContainerNode.h deleted file mode 100644 index 3da5283..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMContainerNode.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "ELMElement.h" -#import "ASDisplayNode.h" - -@interface ELMContainerNode : ASDisplayNode -@property (atomic, strong, readwrite) ELMElement *element; -- (void)addYogaChild:(id)child; -- (void)addSubnode:(id)subnode; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMElement.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMElement.h deleted file mode 100644 index 4829cd4..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMElement.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ELMElement : NSObject -- (id)newChildElementWithInstance:(const void *)instance; -- (const void *)instance; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMNodeController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMNodeController.h deleted file mode 100644 index 80c4b5c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMNodeController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "ASNodeController.h" - -@interface ELMNodeController : ASNodeController -- (const void *)materializationContext; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMNodeFactory.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMNodeFactory.h deleted file mode 100644 index f0359ec..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMNodeFactory.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ELMNodeFactory : NSObject -+ (instancetype)sharedInstance; -- (id)nodeWithElement:(id)element materializationContext:(const void *)context; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMTextNode.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMTextNode.h deleted file mode 100644 index 0226c9f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/ELMTextNode.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "ASTextNode.h" -#import "ELMElement.h" - -@interface ELMTextNode : ASTextNode -@property (atomic, strong, readwrite) ELMElement *element; -- (instancetype)initWithElement:(ELMElement *)element context:(id)context; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GIMBindingBuilder.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GIMBindingBuilder.h deleted file mode 100644 index f7629bf..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GIMBindingBuilder.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface GIMBindingBuilder : NSObject -- (instancetype)bindType:(Class)typeClass; -- (instancetype)initializedWith:(id (^)(id))block; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GIMMe.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GIMMe.h deleted file mode 100644 index c6d5aed..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GIMMe.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface GIMMe : NSObject -+ (instancetype)gimme; -- (instancetype)allocOf:(Class)cls; -- (id)nullableInstanceForType:(id)type; -- (id)instanceForType:(id)type; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GOOAlertView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GOOAlertView.h deleted file mode 100644 index 00ebf1f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GOOAlertView.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GOOModalView.h" - -@interface GOOAlertView : GOOModalView -@property (nonatomic, copy, readwrite) NSString *title; -@property (nonatomic, readonly, strong) UILabel *titleLabel; -@property (nonatomic, copy, readwrite) NSString *subtitle; -@property (nonatomic, readonly, strong) UILabel *subtitleLabel; -@property (nonatomic, readwrite, copy) UIImage *icon; -+ (instancetype)dialog; -+ (instancetype)infoDialog; -+ (instancetype)confirmationDialog; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelTitle:(NSString *)cancelTitle; -+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelAction:(void (^)(void))cancelAction cancelTitle:(NSString *)cancelTitle; -+ (instancetype)confirmationDialogWithSelector:(SEL)selector actionTitle:(NSString *)actionTitle; -+ (instancetype)confirmationDialogWithSelector:(SEL)selector actionTitle:(NSString *)actionTitle showsCancelButton:(BOOL)showsCancelButton; -- (void)addCancelButton:(SEL)selector; -- (void)addCancelButtonWithAction:(void (^)(void))action; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GOOModalView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GOOModalView.h deleted file mode 100644 index b1c929e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GOOModalView.h +++ /dev/null @@ -1,18 +0,0 @@ -#import - -@interface GOOModalView : UIView -@property (nonatomic, readwrite, weak) id target; -@property (nonatomic, readwrite, assign) BOOL shouldDismissOnBackgroundTap; -@property (nonatomic, readwrite, assign) BOOL shouldDismissOnApplicationBackground; -- (instancetype)initWithTarget:(id)target; -- (void)addTitle:(NSString *)title withAction:(void (^)(void))action; -- (void)addTitle:(NSString *)title withDestructiveAction:(void (^)(void))action; -- (void)addTitle:(NSString *)title withSelector:(SEL)selector; -- (void)addTitle:(NSString *)title withCancelSelector:(SEL)cancelSelector; -- (void)addTitle:(NSString *)title withDestructiveSelector:(SEL)cancelSelector; -- (void)addTitle:(NSString *)title iconImage:(UIImage *)iconImage withAction:(void (^)(void))action; -- (void)addTitle:(NSString *)title iconImage:(UIImage *)iconImage withSelector:(SEL)selector; -- (void)show; -- (void)cancel; -- (void)dismiss; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBExtensionDescriptor.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBExtensionDescriptor.h deleted file mode 100644 index c3d5e49..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBExtensionDescriptor.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface GPBExtensionDescriptor : NSObject -- (Class)msgClass; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBExtensionRegistry.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBExtensionRegistry.h deleted file mode 100644 index 87850c8..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBExtensionRegistry.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface GPBExtensionRegistry : NSObject -- (void)addExtension:(id)extension; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBMessage.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBMessage.h deleted file mode 100644 index 4bd822e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/GPBMessage.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface GPBMessage : NSObject -- (id)firstSubmessage; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMAsyncVTVideoDecoder.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMAsyncVTVideoDecoder.h deleted file mode 100644 index fb53cfd..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMAsyncVTVideoDecoder.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface HAMAsyncVTVideoDecoder : NSObject -- (instancetype)initWithDelegate:(id)delegate delegateQueue:(id)delegateQueue decodeQueue:(id)decodeQueue formatDescription:(id)formatDescription pixelBufferAttributes:(id)pixelBufferAttributes; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMMIMEType.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMMIMEType.h deleted file mode 100644 index 1af1157..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMMIMEType.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface HAMMIMEType : NSObject -- (unsigned int)audioCodec; -- (unsigned int)videoCodec; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMPixelBufferRenderingView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMPixelBufferRenderingView.h deleted file mode 100644 index 3c5b9c5..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMPixelBufferRenderingView.h +++ /dev/null @@ -1,2 +0,0 @@ -@protocol HAMPixelBufferRenderingView -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMSBDLSampleBufferRenderingView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMSBDLSampleBufferRenderingView.h deleted file mode 100644 index 6796c65..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/HAMSBDLSampleBufferRenderingView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface HAMSBDLSampleBufferRenderingView : UIView -@property (retain, nonatomic, readonly) AVSampleBufferDisplayLayer *displayLayer; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/LICENSE b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/LICENSE deleted file mode 100644 index 94533be..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 - 2022 PoomSmart - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicy.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicy.h deleted file mode 100644 index 959ff3e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicy.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface MLABRPolicy : NSObject -- (void)requestFormatReselection; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyFormatData.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyFormatData.h deleted file mode 100644 index ab122c1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyFormatData.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLFormat.h" - -@interface MLABRPolicyFormatData : NSObject -- (instancetype)initWithFormat:(MLFormat *)format; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyNew.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyNew.h deleted file mode 100644 index bc3cd18..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyNew.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLABRPolicy.h" - -// YouTube 17.30.3 and higher -@interface MLABRPolicyNew : MLABRPolicy -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyOld.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyOld.h deleted file mode 100644 index f036b2b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLABRPolicyOld.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLABRPolicy.h" - -// YouTube 17.30.3 and higher -@interface MLABRPolicyOld : MLABRPolicy -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVAssetPlayer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVAssetPlayer.h deleted file mode 100644 index 020d83c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVAssetPlayer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface MLAVAssetPlayer : NSObject -- (AVPlayerItem *)playerItem; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPIPPlayerLayerView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPIPPlayerLayerView.h deleted file mode 100644 index bea392e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPIPPlayerLayerView.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "MLAVPlayerLayerView.h" -#import "MLAVPlayer.h" -#import "MLAVPlayerViewDelegate.h" - -@interface MLAVPIPPlayerLayerView : MLAVPlayerLayerView -@property (nonatomic, readonly, strong) AVPlayerLayer *playerLayer; -@property (nonatomic, readwrite, weak) NSObject *delegate; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayer.h deleted file mode 100644 index 21e7270..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayer.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "MLAVAssetPlayer.h" -#import "MLInnerTubePlayerConfig.h" -#import "MLPlayerViewProtocol.h" -#import "MLPlayerStickySettings.h" - -@interface MLAVPlayer : NSObject -@property (nonatomic, readwrite, assign) BOOL active; -@property (nonatomic, readonly, assign) BOOL externalPlaybackActive; -@property (nonatomic, readwrite, assign) float rate; -@property (nonatomic, readonly, strong) MLVideo *video; -@property (nonatomic, readonly, strong) MLInnerTubePlayerConfig *config; -@property (nonatomic, readonly, strong) MLAVAssetPlayer *assetPlayer; -@property (nonatomic, readwrite, strong) UIView *renderingView; -- (instancetype)initWithVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings externalPlaybackActive:(BOOL)externalPlaybackActive; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayerLayerView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayerLayerView.h deleted file mode 100644 index cc2a684..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayerLayerView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLPlayerViewProtocol.h" -#import "HAMPixelBufferRenderingView.h" - -@interface MLAVPlayerLayerView : UIView -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayerViewDelegate.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayerViewDelegate.h deleted file mode 100644 index 85c6e00..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLAVPlayerViewDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@protocol MLAVPlayerViewDelegate -@required -- (void)playerViewErrorDidOccur:(id)arg1; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLDefaultPlayerViewFactory.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLDefaultPlayerViewFactory.h deleted file mode 100644 index 7c3523f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLDefaultPlayerViewFactory.h +++ /dev/null @@ -1,10 +0,0 @@ -#include "GIMMe.h" -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" -#import "MLAVPlayerLayerView.h" - -@interface MLDefaultPlayerViewFactory : NSObject -@property (nonatomic, weak, readwrite) GIMMe *gimme; -- (BOOL)canUsePlayerView:(UIView *)playerView forVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)config; -- (MLAVPlayerLayerView *)AVPlayerViewForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)config; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLFormat.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLFormat.h deleted file mode 100644 index 8cdf045..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLFormat.h +++ /dev/null @@ -1,17 +0,0 @@ -#import -#import "HAMMIMEType.h" -#import "YTIFormatStream.h" - -@interface MLFormat : NSObject -- (HAMMIMEType *)MIMEType; -- (YTIFormatStream *)formatStream; -- (NSURL *)URL; -- (int)width; -- (int)height; -- (int)singleDimensionResolution; -- (CGFloat)FPS; -- (BOOL)isAudio; -- (BOOL)isVideo; -- (BOOL)isText; -- (NSInteger)compareByQuality:(MLFormat *)format; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayer.h deleted file mode 100644 index 240626b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" -#import "MLPlayerStickySettings.h" - -@interface MLHAMPlayer : NSObject -- (instancetype)initWithVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig stickySettings:(MLPlayerStickySettings *)stickySettings playerViewProvider:(id)playerViewProvider; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayerItem.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayerItem.h deleted file mode 100644 index 125640d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayerItem.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "MLABRPolicy.h" -#import "MLFormat.h" -#import "MLInnerTubePlayerConfig.h" - -@interface MLHAMPlayerItem : NSObject -@property (nonatomic, readonly, strong) MLInnerTubePlayerConfig *config; -- (void)ABRPolicy:(MLABRPolicy *)policy selectableFormatsDidChange:(NSArray *)formats; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayerViewProtocol.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayerViewProtocol.h deleted file mode 100644 index 449dc58..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMPlayerViewProtocol.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" - -@protocol MLHAMPlayerViewProtocol -- (void)makeActivePlayer; -- (void)setVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMQueuePlayer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMQueuePlayer.h deleted file mode 100644 index 9d9b16a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMQueuePlayer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "MLHAMPlayer.h" - -@interface MLHAMQueuePlayer : MLHAMPlayer -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMSBDLSampleBufferRenderingView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMSBDLSampleBufferRenderingView.h deleted file mode 100644 index 374db3c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLHAMSBDLSampleBufferRenderingView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "HAMSBDLSampleBufferRenderingView.h" - -@interface MLHAMSBDLSampleBufferRenderingView : HAMSBDLSampleBufferRenderingView -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLInnerTubePlayerConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLInnerTubePlayerConfig.h deleted file mode 100644 index 669f452..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLInnerTubePlayerConfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIMediaCommonConfig.h" -#import "YTIHamplayerConfig.h" - -@interface MLInnerTubePlayerConfig : NSObject -@property (nonatomic, readonly, strong) YTIMediaCommonConfig *mediaCommonConfig; -@property (nonatomic, readonly, strong) YTIHamplayerConfig *hamplayerConfig; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLOnesieVideoData.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLOnesieVideoData.h deleted file mode 100644 index 2a595af..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLOnesieVideoData.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLOnesieVideoData : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPIPController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPIPController.h deleted file mode 100644 index 7e9182a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPIPController.h +++ /dev/null @@ -1,24 +0,0 @@ -#import -#import "MLAVPIPPlayerLayerView.h" -#import "MLHAMSBDLSampleBufferRenderingView.h" - -@interface MLPIPController : NSObject -@property (nonatomic, strong, readwrite) MLAVPIPPlayerLayerView *AVPlayerView; -@property (nonatomic, strong, readwrite) MLHAMSBDLSampleBufferRenderingView *HAMPlayerView; -- (instancetype)initWithPlaceholderPlayerItem:(AVPlayerItem *)playerItem; // Deprecated -- (instancetype)initWithPlaceholderPlayerItemResourcePath:(NSString *)placeholderPath; // Deprecated -- (AVPictureInPictureControllerContentSource *)newContentSource API_AVAILABLE(ios(15.0)); -- (BOOL)isPictureInPictureSupported; -- (BOOL)isPictureInPictureActive; // Deprecated -- (BOOL)pictureInPictureActive; -- (BOOL)contentSourceNeedsRefresh; -- (CGSize)renderSizeForView:(UIView *)view; -- (BOOL)startPictureInPicture; // Deprecated -- (void)stopPictureInPicture; // Deprecated -- (void)addPIPControllerObserver:(id)observer; -- (void)activatePiPController; -- (void)deactivatePiPController; -- (void)pictureInPictureControllerStartPlayback; -- (void)pictureInPictureControllerStopPlayback; -- (void)pause; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerPool.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerPool.h deleted file mode 100644 index 9c5c122..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerPool.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "GIMMe.h" -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" - -@interface MLPlayerPool : NSObject -@property (nonatomic, weak, readwrite) GIMMe *gimme; -- (void)createHamResourcesForVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerPoolImpl.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerPoolImpl.h deleted file mode 100644 index 4a81310..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerPoolImpl.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLPlayerPoolImpl : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerStickySettings.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerStickySettings.h deleted file mode 100644 index a764218..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerStickySettings.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface MLPlayerStickySettings : NSObject -@property (assign) float rate; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerViewProtocol.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerViewProtocol.h deleted file mode 100644 index 3b63622..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLPlayerViewProtocol.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "MLInnerTubePlayerConfig.h" - -@protocol MLPlayerViewProtocol -- (void)makeActivePlayer; -- (void)setVideo:(MLVideo *)video playerConfig:(MLInnerTubePlayerConfig *)playerConfig; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLQOEPingController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLQOEPingController.h deleted file mode 100644 index f52b8a9..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLQOEPingController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLQOEPingController : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLRemoteStream.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLRemoteStream.h deleted file mode 100644 index e5fae59..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLRemoteStream.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIFormatStream.h" -#import "MLFormat.h" - -@interface MLRemoteStream : MLFormat -+ (instancetype)streamWithFormatStream:(YTIFormatStream *)formatStream; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLStreamingData.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLStreamingData.h deleted file mode 100644 index bff45a0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLStreamingData.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "MLRemoteStream.h" - -@interface MLStreamingData : NSObject -- (NSArray *)adaptiveStreams; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLVideo.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLVideo.h deleted file mode 100644 index 1bbab10..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLVideo.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLStreamingData.h" -#import "YTIVideoDetails.h" - -@interface MLVideo : NSObject -- (MLStreamingData *)streamingData; -- (YTIVideoDetails *)videoDetails; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLVideoDecoderFactory.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLVideoDecoderFactory.h deleted file mode 100644 index a095cc1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/MLVideoDecoderFactory.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MLVideoDecoderFactory : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/QTMIcon.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/QTMIcon.h deleted file mode 100644 index 7aa92c5..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/QTMIcon.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface QTMIcon : NSObject -+ (UIImage *)imageWithName:(NSString *)name color:(UIColor *)color; -+ (UIImage *)tintImage:(UIImage *)image color:(UIColor *)color; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/README.md b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/README.md deleted file mode 100644 index 9937377..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# YouTubeHeader - -Headers for iOS YouTube app. diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/UIView+AsyncDisplayKit.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/UIView+AsyncDisplayKit.h deleted file mode 100644 index 368f38c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/UIView+AsyncDisplayKit.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "ASDisplayNode.h" - -@interface UIView (AsyncDisplayKit) -- (void)addSubnode:(ASDisplayNode *)subnode; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/UIView+YouTube.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/UIView+YouTube.h deleted file mode 100644 index 235e899..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/UIView+YouTube.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface UIView (YouTube) -- (BOOL)yt_isVisible; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTActionSheetAction.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTActionSheetAction.h deleted file mode 100644 index fcf8fe0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTActionSheetAction.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTActionSheetAction : NSObject -+ (instancetype)actionWithTitle:(NSString *)title style:(NSInteger)style handler:(void (^)(YTActionSheetAction *))handler; -+ (instancetype)actionWithTitle:(NSString *)title iconImage:(UIImage *)iconImage style:(NSInteger)style handler:(void (^)(YTActionSheetAction *))handler; -+ (instancetype)actionWithTitle:(NSString *)title subtitle:(NSString *)subtitle iconImage:(UIImage *)iconImage handler:(void (^)(YTActionSheetAction *))handler; -+ (instancetype)actionWithTitle:(NSString *)title subtitle:(NSString *)subtitle iconImage:(UIImage *)iconImage accessibilityIdentifier:(NSString *)accessibilityIdentifier handler:(void (^)(YTActionSheetAction *))handler; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTActionSheetController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTActionSheetController.h deleted file mode 100644 index d64cf6a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTActionSheetController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTActionSheetController : NSObject -+ (instancetype)actionSheetController; -- (void)addCancelActionIfNeeded; -- (void)presentFromViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAlertView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAlertView.h deleted file mode 100644 index 8af4386..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAlertView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "GOOAlertView.h" - -@interface YTAlertView : GOOAlertView -+ (instancetype)yt_dialog; -- (void)removeDefaultPadding; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppDelegate.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppDelegate.h deleted file mode 100644 index 981a36d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppDelegate.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTAppDelegate : UIResponder -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppSettingsSectionItemActionController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppSettingsSectionItemActionController.h deleted file mode 100644 index d9d59c2..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppSettingsSectionItemActionController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTAppSettingsSectionItemActionController : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppSettingsStore.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppSettingsStore.h deleted file mode 100644 index f90bd93..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAppSettingsStore.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -@interface YTAppSettingsStore : NSObject -+ (NSUInteger)valueTypeForSetting:(int)setting; -- (void)setValue:(NSNumber *)value forSetting:(int)setting; -- (void)setBool:(BOOL)value forSetting:(int)setting; -- (NSNumber *)valueForSetting:(int)setting; -- (BOOL)boolForSetting:(int)setting; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAsyncCollectionView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAsyncCollectionView.h deleted file mode 100644 index 381ccaf..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAsyncCollectionView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "ASCollectionView.h" - -@interface YTAsyncCollectionView : ASCollectionView -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAutonavEndscreenController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAutonavEndscreenController.h deleted file mode 100644 index d0a0f77..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTAutonavEndscreenController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTAutonavEndscreenController : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTBackgroundabilityPolicy.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTBackgroundabilityPolicy.h deleted file mode 100644 index 1557312..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTBackgroundabilityPolicy.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTBackgroundabilityPolicy : NSObject -- (void)addBackgroundabilityPolicyObserver:(id)observer; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCellController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCellController.h deleted file mode 100644 index 889d924..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCellController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import "YTCollectionViewCellProtocol.h" - -@interface YTCellController : NSObject -@property (nonatomic, weak, readwrite) UICollectionViewCell *cell; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColdConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColdConfig.h deleted file mode 100644 index 5f9a848..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColdConfig.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTColdConfig : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCollectionViewCell.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCollectionViewCell.h deleted file mode 100644 index 8bcd2db..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCollectionViewCell.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlideForActionsView.h" - -@interface YTCollectionViewCell : UICollectionViewCell -@property (nonatomic, strong, readwrite) YTSlideForActionsView *slideForActionsView; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCollectionViewCellProtocol.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCollectionViewCellProtocol.h deleted file mode 100644 index b16ffda..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCollectionViewCellProtocol.h +++ /dev/null @@ -1,2 +0,0 @@ -@protocol YTCollectionViewCellProtocol -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColor.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColor.h deleted file mode 100644 index 95b070f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColor.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTColor : NSObject -+ (UIColor *)white1; -+ (UIColor *)black1; -+ (UIColor *)black2; -+ (UIColor *)black3; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColorPalette.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColorPalette.h deleted file mode 100644 index 6388c0d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTColorPalette.h +++ /dev/null @@ -1,67 +0,0 @@ -#import -#import - -// Deprecated, use YTCommonColorPalette -@interface YTColorPalette : NSObject -+ (instancetype)lightPalette; -+ (instancetype)darkPalette; -+ (instancetype)colorPaletteForPageStyle:(NSInteger)pageStyle; -- (NSInteger)pageStyle; -- (UIColor *)background1; -- (UIColor *)background2; -- (UIColor *)background3; -- (UIColor *)brandBackgroundSolid; -- (UIColor *)brandBackgroundPrimary; -- (UIColor *)brandBackgroundSecondary; -- (UIColor *)generalBackgroundA; -- (UIColor *)generalBackgroundB; -- (UIColor *)generalBackgroundC; -- (UIColor *)errorBackground; -- (UIColor *)textPrimary; -- (UIColor *)textSecondary; -- (UIColor *)textDisabled; -- (UIColor *)textPrimaryInverse; -- (UIColor *)callToAction; -- (UIColor *)iconActive; -- (UIColor *)iconActiveOther; -- (UIColor *)iconInactive; -- (UIColor *)iconDisabled; -- (UIColor *)badgeChipBackground; -- (UIColor *)buttonChipBackgroundHover; -- (UIColor *)touchResponse; -- (UIColor *)callToActionInverse; -- (UIColor *)brandIconActive; -- (UIColor *)brandIconInactive; -- (UIColor *)brandButtonBackground; -- (UIColor *)brandLinkText; -- (UIColor *)tenPercentLayer; -- (UIColor *)snackbarBackground; -- (UIColor *)themedBlue; -- (UIColor *)themedGreen; -- (UIColor *)staticBrandRed; -- (UIColor *)staticBrandWhite; -- (UIColor *)staticBrandBlack; -- (UIColor *)staticClearColor; -- (UIColor *)staticAdYellow; -- (UIColor *)staticGrey; -- (UIColor *)overlayBackgroundSolid; -- (UIColor *)overlayBackgroundHeavy; -- (UIColor *)overlayBackgroundMedium; -- (UIColor *)overlayBackgroundMediumLight; -- (UIColor *)overlayBackgroundLight; -- (UIColor *)overlayTextPrimary; -- (UIColor *)overlayTextSecondary; -- (UIColor *)overlayTextTertiary; -- (UIColor *)overlayIconActiveCallToAction; -- (UIColor *)overlayIconActiveOther; -- (UIColor *)overlayIconInactive; -- (UIColor *)overlayIconDisabled; -- (UIColor *)overlayFilledButtonActive; -- (UIColor *)overlayButtonSecondary; -- (UIColor *)overlayButtonPrimary; -- (UIColor *)overlayBackgroundBrand; -- (UIColor *)overlayBackgroundClear; -- (UIColor *)verifiedBadgeBackground; -- (UIColor *)themedOverlayBackground; -- (UIColor *)adIndicator; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCommonColorPalette.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCommonColorPalette.h deleted file mode 100644 index 16585a7..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCommonColorPalette.h +++ /dev/null @@ -1,74 +0,0 @@ -#import -#import - -// YouTube 17.19.2 and higher -@interface YTCommonColorPalette : NSObject -+ (instancetype)lightPalette; -+ (instancetype)darkPalette; -- (NSInteger)pageStyle; -- (UIColor *)background1; -- (UIColor *)background2; -- (UIColor *)background3; -- (UIColor *)staticBlue; -- (UIColor *)brandBackgroundSolid; -- (UIColor *)brandBackgroundPrimary; -- (UIColor *)brandBackgroundSecondary; -- (UIColor *)generalBackgroundA; -- (UIColor *)generalBackgroundB; -- (UIColor *)generalBackgroundC; -- (UIColor *)errorBackground; -- (UIColor *)textPrimary; -- (UIColor *)textSecondary; -- (UIColor *)textDisabled; -- (UIColor *)textPrimaryInverse; -- (UIColor *)callToAction; -- (UIColor *)iconActive; -- (UIColor *)iconActiveOther; -- (UIColor *)iconInactive; -- (UIColor *)iconDisabled; -- (UIColor *)badgeChipBackground; -- (UIColor *)buttonChipBackgroundHover; -- (UIColor *)touchResponse; -- (UIColor *)callToActionInverse; -- (UIColor *)brandIconActive; -- (UIColor *)brandIconInactive; -- (UIColor *)brandButtonBackground; -- (UIColor *)brandLinkText; -- (UIColor *)tenPercentLayer; -- (UIColor *)snackbarBackground; -- (UIColor *)themedBlue; -- (UIColor *)themedGreen; -- (UIColor *)staticBrandRed; -- (UIColor *)staticBrandWhite; -- (UIColor *)staticBrandBlack; -- (UIColor *)staticClearColor; -- (UIColor *)staticAdYellow; -- (UIColor *)staticGrey; -- (UIColor *)overlayBackgroundSolid; -- (UIColor *)overlayBackgroundHeavy; -- (UIColor *)overlayBackgroundMedium; -- (UIColor *)overlayBackgroundMediumLight; -- (UIColor *)overlayBackgroundLight; -- (UIColor *)overlayTextPrimary; -- (UIColor *)overlayTextSecondary; -- (UIColor *)overlayTextTertiary; -- (UIColor *)overlayIconActiveCallToAction; -- (UIColor *)overlayIconActiveOther; -- (UIColor *)overlayIconInactive; -- (UIColor *)overlayIconDisabled; -- (UIColor *)overlayFilledButtonActive; -- (UIColor *)overlayButtonSecondary; -- (UIColor *)overlayButtonPrimary; -- (UIColor *)overlayBackgroundBrand; -- (UIColor *)overlayBackgroundClear; -- (UIColor *)verifiedBadgeBackground; -- (UIColor *)themedOverlayBackground; -- (UIColor *)adIndicator; -- (UIColor *)errorIndicator; // 17.52.1+ -- (UIColor *)baseBackground; // 17.52.1+ -- (UIColor *)raisedBackground; // 17.52.1+ -- (UIColor *)menuBackground; // 17.52.1+ -- (UIColor *)invertedBackground; // 17.52.1+ -- (UIColor *)additiveBackground; // 17.52.1+ -- (UIColor *)outline; // 17.52.1+ -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCommonUtils.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCommonUtils.h deleted file mode 100644 index 834ab41..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTCommonUtils.h +++ /dev/null @@ -1,14 +0,0 @@ -#import -#import - -@interface YTCommonUtils : NSObject -+ (BOOL)isIPhoneWithNotch; -+ (BOOL)isIPad; -+ (BOOL)isSmallDevice; -+ (BOOL)isAppRunningInFullScreen; -+ (unsigned int)uniformRandomWithUpperBound:(unsigned int)upperBound; -+ (UIWindow *)mainWindow; // YTMainWindow -+ (NSBundle *)bundleForClass:(Class)cls; -+ (NSBundle *)resourceBundleForModuleName:(NSString *)module appBundle:(NSBundle *)appBundle; -+ (NSString *)hardwareModel; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTContentVideoPlayerOverlayView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTContentVideoPlayerOverlayView.h deleted file mode 100644 index 0209c8a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTContentVideoPlayerOverlayView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTMainAppVideoPlayerOverlayView.h" - -@interface YTContentVideoPlayerOverlayView : YTMainAppVideoPlayerOverlayView -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTELMContext.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTELMContext.h deleted file mode 100644 index dd91b73..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTELMContext.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTELMContext : NSObject -- (id)parentResponder; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTEditResources.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTEditResources.h deleted file mode 100644 index 6788177..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTEditResources.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTEditResources : NSObject -+ (UIImage *)volumeControlsFeatureTabIconMuted:(BOOL)muted templateImage:(BOOL)templateImage; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h deleted file mode 100644 index 652d6f9..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTFullscreenEngagementActionBarButtonRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTFullscreenEngagementActionBarButtonRenderer : NSObject -- (BOOL)isLikeButton; -- (BOOL)isDislikeButton; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h deleted file mode 100644 index b2851b1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTFullscreenEngagementActionBarButtonView.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "Block.h" -#import "YTIFormattedStringLabel.h" - -@interface YTFullscreenEngagementActionBarButtonView : UIView -@property (nonatomic, assign, readwrite, getter=isToggled) BOOL toggled; -@property (nonatomic, strong, readwrite) YTIFormattedStringLabel *label; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTGlassContainerView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTGlassContainerView.h deleted file mode 100644 index d148140..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTGlassContainerView.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTGlassContainerView : UIView -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTGlobalConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTGlobalConfig.h deleted file mode 100644 index 20d046d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTGlobalConfig.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTGlobalConfig : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTHotConfig.h deleted file mode 100644 index fa64645..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTHotConfig.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTIHotConfigGroup.h" -#import "YTIHamplayerHotConfig.h" - -@interface YTHotConfig : NSObject -@property (atomic, strong, readwrite) YTIHotConfigGroup *hotConfigGroup; -- (YTIIosMediaHotConfig *)mediaHotConfig; -- (YTIHamplayerHotConfig *)hamplayerHotConfig; -- (BOOL)iosReleasePipControllerOnMain; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIAccessibilityData.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIAccessibilityData.h deleted file mode 100644 index 372e071..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIAccessibilityData.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIAccessibilityData : NSObject -@property (nonatomic, copy, readwrite) NSString *label; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIBrowseEndpoint.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIBrowseEndpoint.h deleted file mode 100644 index 90b3c2e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIBrowseEndpoint.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIBrowseEndpoint : NSObject -@property (nonatomic, copy, readwrite) NSString *browseId; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIBrowseRequest.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIBrowseRequest.h deleted file mode 100644 index 0d37fd0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIBrowseRequest.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPBMessage.h" - -@interface YTIBrowseRequest : GPBMessage -+ (NSString *)browseIDForExploreTab; -+ (NSString *)browseIDForAccountTab; -+ (NSString *)browseIDForActivityTab; -+ (NSString *)browseIDForHomeTab; -+ (NSString *)browseIDForLibraryTab; -+ (NSString *)browseIDForTrendingTab; -+ (NSString *)browseIDForSubscriptionsTab; -+ (NSString *)browseIDForWhatToWatch; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIButtonRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIButtonRenderer.h deleted file mode 100644 index 7ae8972..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIButtonRenderer.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "YTICommand.h" -#import "YTIFormattedString.h" -#import "YTIIcon.h" - -@interface YTIButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTICommand *command; -@property (nonatomic, strong, readwrite) YTIIcon *icon; -@property (nonatomic, strong, readwrite) YTICommand *navigationEndpoint; -@property (nonatomic, copy, readwrite) NSString *targetId; -@property (nonatomic, strong, readwrite) YTIFormattedString *text; -@property (nonatomic, copy, readwrite) NSString *tooltip; -@property (nonatomic, assign, readwrite) int size; -@property (nonatomic, assign, readwrite) int style; -@property (nonatomic, assign, readwrite) BOOL isDisabled; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIButtonSupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIButtonSupportedRenderers.h deleted file mode 100644 index 234fe49..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIButtonSupportedRenderers.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIToggleButtonRenderer.h" -#import "YTIButtonRenderer.h" - -@interface YTIButtonSupportedRenderers : NSObject -@property (nonatomic, strong, readwrite) YTIToggleButtonRenderer *toggleButtonRenderer; -@property (retain, nonatomic) YTIButtonRenderer *buttonRenderer; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIChapterRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIChapterRenderer.h deleted file mode 100644 index 7125ad3..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIChapterRenderer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPBMessage.h" -#import "YTIFormattedString.h" - -@interface YTIChapterRenderer : GPBMessage -@property (nonatomic, readwrite, strong) YTIFormattedString *title; -@property (nonatomic, readwrite, assign) int timeRangeStartMillis; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIColorInfo.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIColorInfo.h deleted file mode 100644 index 74ffac0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIColorInfo.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIColorInfo : NSObject -@property (nonatomic, assign, readwrite) int transferCharacteristics; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTICommand.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTICommand.h deleted file mode 100644 index 1dbf2c8..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTICommand.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIReelWatchEndpoint.h" -#import "YTIBrowseEndpoint.h" - -@interface YTICommand : NSObject -@property (nonatomic, readwrite, strong) YTIReelWatchEndpoint *reelWatchEndpoint; -@property (nonatomic, readwrite, strong) YTIBrowseEndpoint *browseEndpoint; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIElementRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIElementRenderer.h deleted file mode 100644 index a02b85a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIElementRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIElementRendererCompatibilityOptions.h" - -@interface YTIElementRenderer : GPBMessage -@property (nonatomic, strong, readwrite) YTIElementRendererCompatibilityOptions *compatibilityOptions; -@property (nonatomic, assign, readwrite) BOOL hasCompatibilityOptions; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIElementRendererCompatibilityOptions.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIElementRendererCompatibilityOptions.h deleted file mode 100644 index 7fad4d1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIElementRendererCompatibilityOptions.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPBMessage.h" - -@interface YTIElementRendererCompatibilityOptions : GPBMessage -@property (nonatomic, assign, readwrite) BOOL hasAdLoggingData; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormatStream.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormatStream.h deleted file mode 100644 index f84ed37..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormatStream.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIColorInfo.h" - -@interface YTIFormatStream : NSObject -@property (nonatomic, strong, readwrite) YTIColorInfo *colorInfo; -@property (nonatomic, copy, readwrite) NSString *URL; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedString.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedString.h deleted file mode 100644 index e950ca1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedString.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTIFormattedStringSupportedAccessibilityDatas.h" - -@interface YTIFormattedString : NSObject -+ (instancetype)formattedStringWithString:(NSString *)string; -@property (nonatomic, strong, readwrite) NSMutableArray *runsArray; -@property (nonatomic, strong, readwrite) YTIFormattedStringSupportedAccessibilityDatas *accessibility; -- (NSString *)stringWithFormattingRemoved; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedStringLabel.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedStringLabel.h deleted file mode 100644 index 6865921..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedStringLabel.h +++ /dev/null @@ -1,7 +0,0 @@ -#import -#import "YTIFormattedString.h" - -@interface YTIFormattedStringLabel : UILabel -@property (nonatomic, copy, readwrite) NSAttributedString *attributedText; -- (void)setFormattedString:(YTIFormattedString *)string; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedStringSupportedAccessibilityDatas.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedStringSupportedAccessibilityDatas.h deleted file mode 100644 index e6c26d4..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIFormattedStringSupportedAccessibilityDatas.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIAccessibilityData.h" - -@interface YTIFormattedStringSupportedAccessibilityDatas : NSObject -@property (nonatomic, strong, readwrite) YTIAccessibilityData *accessibilityData; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIGuideResponse.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIGuideResponse.h deleted file mode 100644 index c24d970..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIGuideResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIGuideResponseSupportedRenderers.h" - -@interface YTIGuideResponse : NSObject -- (NSMutableArray *)itemsArray; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIGuideResponseSupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIGuideResponseSupportedRenderers.h deleted file mode 100644 index aa32640..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIGuideResponseSupportedRenderers.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIPivotBarRenderer.h" - -@interface YTIGuideResponseSupportedRenderers : NSObject -- (YTIPivotBarRenderer *)pivotBarRenderer; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerABRConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerABRConfig.h deleted file mode 100644 index 157ac68..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerABRConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIHamplayerABRConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL preferSoftwareHdrOverHardwareSdr; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerConfig.h deleted file mode 100644 index 0f44488..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerConfig.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "YTIHamplayerStreamFilter.h" -#import "YTIHamplayerABRConfig.h" - -@interface YTIHamplayerConfig : NSObject -@property (nonatomic, assign, readwrite) int renderViewType; -@property (nonatomic, assign, readwrite) BOOL useSbdlRenderView; -@property (nonatomic, assign, readwrite) BOOL useResolutionForHfrHdFormatFilter; -@property (nonatomic, assign, readwrite) BOOL disableHfrHdFormatFilter; -@property (nonatomic, assign, readwrite) BOOL disableResolveOverlappingQualitiesByCodec; -@property (nonatomic, strong, readwrite) YTIHamplayerStreamFilter *streamFilter; -@property (nonatomic, strong, readwrite) YTIHamplayerABRConfig *videoAbrConfig; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerHotConfig.h deleted file mode 100644 index 8a5ea2a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIHamplayerHotConfig : NSObject -@property (nonatomic, assign, readwrite) int renderViewType; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h deleted file mode 100644 index 742ac20..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerSoftwareStreamFilter.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTIHamplayerSoftwareStreamFilter : NSObject -@property int maxArea; -@property int maxFps; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerStreamFilter.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerStreamFilter.h deleted file mode 100644 index 5937c90..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHamplayerStreamFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIHamplayerSoftwareStreamFilter.h" - -@interface YTIHamplayerStreamFilter : NSObject -@property (nonatomic, strong, readwrite) YTIHamplayerSoftwareStreamFilter *av1; -@property (nonatomic, strong, readwrite) YTIHamplayerSoftwareStreamFilter *vp9; -@property (nonatomic, assign, readwrite) BOOL enableVideoCodecSplicing; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHotConfigGroup.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHotConfigGroup.h deleted file mode 100644 index ff7c4a3..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIHotConfigGroup.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIMediaHotConfig.h" - -@interface YTIHotConfigGroup : NSObject -@property (nonatomic, strong, readwrite) YTIMediaHotConfig *mediaHotConfig; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIcon.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIcon.h deleted file mode 100644 index 42c0bff..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIcon.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIIcon : NSObject -@property (nonatomic, assign, readwrite) int iconType; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIosMediaHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIosMediaHotConfig.h deleted file mode 100644 index c94c99b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIosMediaHotConfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTIIosMediaHotConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL enablePictureInPicture; -@property (nonatomic, assign, readwrite) BOOL enablePipForNonBackgroundableContent; -@property (nonatomic, assign, readwrite) BOOL enablePipForNonPremiumUsers; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIosOnesieHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIosOnesieHotConfig.h deleted file mode 100644 index 65b1bf1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIIosOnesieHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIIosOnesieHotConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL prepareVideoDecoder; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIItemSectionRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIItemSectionRenderer.h deleted file mode 100644 index 51428e5..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIItemSectionRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIItemSectionSupportedRenderers.h" - -@interface YTIItemSectionRenderer : GPBMessage -@property (nonatomic, strong, readwrite) NSMutableArray *contentsArray; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIItemSectionSupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIItemSectionSupportedRenderers.h deleted file mode 100644 index e8d1d5a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIItemSectionSupportedRenderers.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTIElementRenderer.h" - -@interface YTIItemSectionSupportedRenderers : GPBMessage -@property (nonatomic, strong, readwrite) YTIElementRenderer *elementRenderer; -@property (nonatomic, assign, readwrite) BOOL hasPromotedVideoRenderer; -@property (nonatomic, assign, readwrite) BOOL hasPromotedVideoInlineMutedRenderer; -@property (nonatomic, assign, readwrite) BOOL hasCompactPromotedVideoRenderer; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTILikeButtonRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTILikeButtonRenderer.h deleted file mode 100644 index 462abdc..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTILikeButtonRenderer.h +++ /dev/null @@ -1,23 +0,0 @@ -#import "YTLikeStatus.h" -#import "YTILikeTarget.h" -#import "YTIFormattedString.h" - -@interface YTILikeButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTILikeTarget *target; -@property (nonatomic, strong, readwrite) YTIFormattedString *likeCountText; -@property (nonatomic, strong, readwrite) YTIFormattedString *likeCountWithLikeText; -@property (nonatomic, strong, readwrite) YTIFormattedString *likeCountWithUnlikeText; -@property (nonatomic, strong, readwrite) YTIFormattedString *dislikeCountText; -@property (nonatomic, strong, readwrite) YTIFormattedString *dislikeCountWithDislikeText; -@property (nonatomic, strong, readwrite) YTIFormattedString *dislikeCountWithUndislikeText; -@property (nonatomic, assign, readwrite) BOOL hasLikeCountText; -@property (nonatomic, assign, readwrite) BOOL hasLikeCountWithLikeText; -@property (nonatomic, assign, readwrite) BOOL hasLikeCountWithUnlikeText; -@property (nonatomic, assign, readwrite) BOOL hasDislikeCountText; -@property (nonatomic, assign, readwrite) BOOL hasDislikeCountWithDislikeText; -@property (nonatomic, assign, readwrite) BOOL hasDislikeCountWithUndislikeText; -@property (nonatomic, assign, readwrite) BOOL likesAllowed; -@property (nonatomic, assign, readwrite) YTLikeStatus likeStatus; -@property (nonatomic, assign, readwrite) int likeCount; -@property (nonatomic, assign, readwrite) int dislikeCount; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTILikeTarget.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTILikeTarget.h deleted file mode 100644 index 5c966fb..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTILikeTarget.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTILikeTarget : NSObject -@property (nonatomic, copy, readwrite) NSString *videoId; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaCommonConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaCommonConfig.h deleted file mode 100644 index 38697de..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaCommonConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIMediaCommonConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL useServerDrivenAbr; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaHotConfig.h deleted file mode 100644 index 4311fa5..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaHotConfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIIosMediaHotConfig.h" -#import "YTIMediaQualitySettingsHotConfig.h" - -@interface YTIMediaHotConfig : NSObject -@property (nonatomic, strong, readwrite) YTIIosMediaHotConfig *iosMediaHotConfig; -@property (nonatomic, strong, readwrite) YTIMediaQualitySettingsHotConfig *mediaQualitySettingsHotConfig; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaQualitySettingsHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaQualitySettingsHotConfig.h deleted file mode 100644 index 9e14cc1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIMediaQualitySettingsHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIMediaQualitySettingsHotConfig : NSObject -@property (nonatomic, assign, readwrite) BOOL enablePersistentVideoQualitySettings; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflinePromoRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflinePromoRenderer.h deleted file mode 100644 index 47b2f9b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflinePromoRenderer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTIOfflinePromoRenderer : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflineabilityRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflineabilityRenderer.h deleted file mode 100644 index ddcd8ab..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflineabilityRenderer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTIOfflineabilityRenderer : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflineabilitySupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflineabilitySupportedRenderers.h deleted file mode 100644 index 771f33a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOfflineabilitySupportedRenderers.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "YTIButtonRenderer.h" -#import "YTIOfflinePromoRenderer.h" -#import "YTIOfflineabilityRenderer.h" - -@interface YTIOfflineabilitySupportedRenderers : NSObject -@property (nonatomic, strong, readwrite) YTIOfflinePromoRenderer *offlinePromoRenderer; -@property (nonatomic, strong, readwrite) YTIOfflineabilityRenderer *offlineabilityRenderer; -@property (nonatomic, strong, readwrite) YTIButtonRenderer *buttonRenderer; -- (int)rendererOneOfCase; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOnesieHotConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOnesieHotConfig.h deleted file mode 100644 index 0901c3a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIOnesieHotConfig.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIIosOnesieHotConfig.h" - -@interface YTIOnesieHotConfig : NSObject -@property (nonatomic, strong, readwrite) YTIIosOnesieHotConfig *iosConfig; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPaygatedQualityDetails.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPaygatedQualityDetails.h deleted file mode 100644 index 9f2311b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPaygatedQualityDetails.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTICommand.h" - -@interface YTIPaygatedQualityDetails : GPBMessage -@property (nonatomic, strong, readwrite) YTICommand *endpoint; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPictureInPictureRendererRoot.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPictureInPictureRendererRoot.h deleted file mode 100644 index 7f8f33c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPictureInPictureRendererRoot.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIPictureInPictureRendererRoot : NSObject -+ (id)pictureInPictureRenderer; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarIconOnlyItemRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarIconOnlyItemRenderer.h deleted file mode 100644 index 63f7b43..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarIconOnlyItemRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPBMessage.h" - -@interface YTIPivotBarIconOnlyItemRenderer : GPBMessage -- (NSString *)pivotIdentifier; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarItemRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarItemRenderer.h deleted file mode 100644 index 2e71543..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarItemRenderer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTICommand.h" - -@interface YTIPivotBarItemRenderer : NSObject -- (NSString *)pivotIdentifier; -- (YTICommand *)navigationEndpoint; -- (void)setNavigationEndpoint:(YTICommand *)navigationEndpoint; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarRenderer.h deleted file mode 100644 index a210d4f..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIPivotBarSupportedRenderers.h" - -@interface YTIPivotBarRenderer : NSObject -+ (YTIPivotBarSupportedRenderers *)pivotSupportedRenderersWithBrowseId:(NSString *)browseId title:(NSString *)title iconType:(int)iconType; -- (NSMutableArray *)itemsArray; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarSupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarSupportedRenderers.h deleted file mode 100644 index e089cfd..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPivotBarSupportedRenderers.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTIPivotBarItemRenderer.h" -#import "YTIPivotBarIconOnlyItemRenderer.h" - -@interface YTIPivotBarSupportedRenderers : NSObject -- (YTIPivotBarItemRenderer *)pivotBarItemRenderer; -- (YTIPivotBarIconOnlyItemRenderer *)pivotBarIconOnlyItemRenderer; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPlayerResponse.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPlayerResponse.h deleted file mode 100644 index f463a56..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIPlayerResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIVideoDetails.h" - -@interface YTIPlayerResponse : NSObject -@property (nonatomic, strong, readwrite) YTIVideoDetails *videoDetails; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIReelWatchEndpoint.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIReelWatchEndpoint.h deleted file mode 100644 index 1d09f3d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIReelWatchEndpoint.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTIReelWatchEndpoint : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISectionListRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISectionListRenderer.h deleted file mode 100644 index 10c4576..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISectionListRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTISectionListSupportedRenderers.h" - -@interface YTISectionListRenderer : GPBMessage -@property (nonatomic, strong, readwrite) NSMutableArray *contentsArray; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISectionListSupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISectionListSupportedRenderers.h deleted file mode 100644 index 4fb3d99..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISectionListSupportedRenderers.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIItemSectionRenderer.h" - -@interface YTISectionListSupportedRenderers : GPBMessage -@property (nonatomic, strong, readwrite) YTIItemSectionRenderer *itemSectionRenderer; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIShowEngagementPanelEndpoint.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIShowEngagementPanelEndpoint.h deleted file mode 100644 index 1d463e6..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIShowEngagementPanelEndpoint.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPBExtensionDescriptor.h" - -@interface YTIShowEngagementPanelEndpoint : NSObject -+ (GPBExtensionDescriptor *)showEngagementPanelEndpoint; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataButtonRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataButtonRenderer.h deleted file mode 100644 index ce79ab0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataButtonRenderer.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIButtonSupportedRenderers.h" - -@interface YTISlimMetadataButtonRenderer : NSObject -@property (retain, nonatomic) YTIButtonSupportedRenderers *button; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h deleted file mode 100644 index 0de4682..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataButtonSupportedRenderers.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "YTISlimMetadataToggleButtonRenderer.h" -#import "YTISlimMetadataButtonRenderer.h" - -@interface YTISlimMetadataButtonSupportedRenderers : NSObject -@property (nonatomic, strong, readwrite) YTISlimMetadataToggleButtonRenderer *slimMetadataToggleButtonRenderer; -@property (retain, nonatomic) YTISlimMetadataButtonRenderer *slimMetadataButtonRenderer; -- (BOOL)slimButton_isLikeButton; -- (BOOL)slimButton_isDislikeButton; -- (BOOL)slimButton_isOfflineButton; -- (int)rendererOneOfCase; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataToggleButtonRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataToggleButtonRenderer.h deleted file mode 100644 index 827d073..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTISlimMetadataToggleButtonRenderer.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTILikeTarget.h" -#import "YTIButtonSupportedRenderers.h" - -@interface YTISlimMetadataToggleButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTILikeTarget *target; -@property (nonatomic, strong, readwrite) YTIButtonSupportedRenderers *button; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIStringRun.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIStringRun.h deleted file mode 100644 index 7cc010c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIStringRun.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIStringRun : NSObject -@property (nonatomic, copy, readwrite) NSString *text; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIToggleButtonRenderer.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIToggleButtonRenderer.h deleted file mode 100644 index 63a3347..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIToggleButtonRenderer.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTIFormattedString.h" - -@interface YTIToggleButtonRenderer : NSObject -@property (nonatomic, strong, readwrite) YTIFormattedString *defaultText; -@property (nonatomic, strong, readwrite) YTIFormattedString *toggledText; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIVideoDetails.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIVideoDetails.h deleted file mode 100644 index 3c87590..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIVideoDetails.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTIVideoDetails : NSObject -@property (nonatomic, assign, readwrite) BOOL allowRatings; -@property (nonatomic, assign, readwrite) float averageRating; -@property (nonatomic, copy, readwrite) NSString *viewCount; -@property (nonatomic, copy, readwrite) NSString *channelId; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIWatchNextResponse.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIWatchNextResponse.h deleted file mode 100644 index 348ec06..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTIWatchNextResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTIWatchNextResponse : NSObject -@property (nonatomic, assign, readwrite) BOOL hasOnUiReady; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInlinePlayerBarContainerView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInlinePlayerBarContainerView.h deleted file mode 100644 index 5eeccf2..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInlinePlayerBarContainerView.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "YTGlassContainerView.h" -#import "YTInlinePlayerBarView.h" -#import "YTSegmentableInlinePlayerBarView.h" -#import "YTLabel.h" -#import "YTQTMButton.h" - -@interface YTInlinePlayerBarContainerView : YTGlassContainerView -@property (nonatomic, strong, readwrite) YTInlinePlayerBarView *playerBar; // Replaced by segmentablePlayerBar in newer versions -@property (nonatomic, strong, readwrite) YTSegmentableInlinePlayerBarView *segmentablePlayerBar; -@property (nonatomic, strong, readwrite) UIView *multiFeedElementView; -@property (nonatomic, strong, readwrite) YTLabel *durationLabel; -@property (nonatomic, assign, readwrite) BOOL showOnlyFullscreenButton; -@property (nonatomic, assign, readwrite) int layout; -@property (nonatomic, weak, readwrite) id delegate; -- (YTQTMButton *)exitFullscreenButton; -- (YTQTMButton *)enterFullscreenButton; -- (void)setChapters:(NSArray *)chapters; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInlinePlayerBarView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInlinePlayerBarView.h deleted file mode 100644 index 3c07d0b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInlinePlayerBarView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTInlinePlayerBarView : UIView -@property (nonatomic, readonly, assign) CGFloat totalTime; -@property (nonatomic, readwrite, strong) YTPlayerViewController *playerViewController; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInnerTubeCellController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInnerTubeCellController.h deleted file mode 100644 index ce2dc38..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTInnerTubeCellController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTCellController.h" - -@interface YTInnerTubeCellController : YTCellController -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLabel.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLabel.h deleted file mode 100644 index bf2d917..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLabel.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTLabel : UILabel -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLightweightQTMButton.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLightweightQTMButton.h deleted file mode 100644 index 5970b5d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLightweightQTMButton.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTLightweightQTMButton : UIButton -@property (nonatomic, assign, readwrite, getter=isUppercaseTitle) BOOL uppercaseTitle; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLikeStatus.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLikeStatus.h deleted file mode 100644 index ffe5044..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLikeStatus.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _YT_LIKESTATUS -#define _YT_LIKESTATUS - -#import - -typedef NS_ENUM(int, YTLikeStatus) { - YTLikeStatusLike = 0, - YTLikeStatusDislike = 1, - YTLikeStatusNeutral = 2 -}; - -#endif diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLocalPlaybackController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLocalPlaybackController.h deleted file mode 100644 index ab585b4..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTLocalPlaybackController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "GIMMe.h" -#import "YTSingleVideoControllerDelegate.h" - -@interface YTLocalPlaybackController : NSObject -- (GIMMe *)gimme; // Deprecated -- (NSString *)currentVideoID; -- (int)playerVisibility; -- (void)setMuted:(BOOL)muted; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppControlsOverlayView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppControlsOverlayView.h deleted file mode 100644 index a4d05cf..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppControlsOverlayView.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTQTMButton.h" -#import "YTPlayerViewController.h" - -@interface YTMainAppControlsOverlayView : UIView -+ (CGFloat)topButtonAdditionalPadding; -@property (nonatomic, assign, readwrite, getter=isOverlayVisible) BOOL overlayVisible; -@property (nonatomic, strong, readwrite) YTPlayerViewController *playerViewController; -- (YTQTMButton *)buttonWithImage:(UIImage *)image accessibilityLabel:(NSString *)accessibilityLabel verticalContentPadding:(CGFloat)verticalContentPadding; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppPlayerOverlayView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppPlayerOverlayView.h deleted file mode 100644 index 909f1c0..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppPlayerOverlayView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTMainAppPlayerOverlayView : UIView -+ (CGFloat)topButtonAdditionalPadding; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppVideoPlayerOverlayView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppVideoPlayerOverlayView.h deleted file mode 100644 index d833381..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppVideoPlayerOverlayView.h +++ /dev/null @@ -1,20 +0,0 @@ -#import - -#ifdef LEGACY - -#import "YTMainAppPlayerOverlayView.h" - -@interface YTMainAppVideoPlayerOverlayView : YTMainAppPlayerOverlayView -@end - -#else - -#import "YTInlinePlayerBarContainerView.h" -#import "YTMainAppControlsOverlayView.h" - -@interface YTMainAppVideoPlayerOverlayView : UIView -@property (nonatomic, strong, readwrite) YTInlinePlayerBarContainerView *playerBar; -- (YTMainAppControlsOverlayView *)controlsOverlayView; -@end - -#endif \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h deleted file mode 100644 index 7810af9..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTMainAppVideoPlayerOverlayView.h" -#import "YTPlayerViewController.h" - -@interface YTMainAppVideoPlayerOverlayViewController : UIViewController -- (YTMainAppVideoPlayerOverlayView *)videoPlayerOverlayView; -- (YTPlayerViewController *)delegate; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMultiSizeViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMultiSizeViewController.h deleted file mode 100644 index f741fe5..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTMultiSizeViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTMultiSizeViewController : UIViewController -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchController.h deleted file mode 100644 index bfee738..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTNGWatchController : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchLayerViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchLayerViewController.h deleted file mode 100644 index e4140e8..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchLayerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTNGWatchLayerViewController : UIViewController -- (YTPlayerViewController *)playerViewController; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchMiniBarView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchMiniBarView.h deleted file mode 100644 index 2e02824..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTNGWatchMiniBarView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTNGWatchMiniBarView : UIView -@property (nonatomic, assign, readwrite) NSInteger watchMiniPlayerLayout; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTOfflineButtonPressedResponderEvent.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTOfflineButtonPressedResponderEvent.h deleted file mode 100644 index dc520e2..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTOfflineButtonPressedResponderEvent.h +++ /dev/null @@ -1,7 +0,0 @@ -#import -#import - -@interface YTOfflineButtonPressedResponderEvent : NSObject -+ (instancetype)eventWithOfflineVideoID:(NSString *)videoID fromView:(UIView *)view firstResponder:(id)firstResponder; -- (void)send; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPageStyleController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPageStyleController.h deleted file mode 100644 index 84c9eb3..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPageStyleController.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTCommonColorPalette.h" - -@interface YTPageStyleController : NSObject -+ (YTCommonColorPalette *)currentColorPalette; // For YouTube older than 17.19.2, import/change type to YTColorPalette -+ (NSInteger)pageStyle; -@property (nonatomic, assign, readwrite) NSInteger appThemeSetting; -@property (nonatomic, assign, readonly) NSInteger pageStyle; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPivotBarItemView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPivotBarItemView.h deleted file mode 100644 index 848a6e6..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPivotBarItemView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTPivotBarItemView : UIView -@property (strong, nonatomic) UIButton *navigationButton; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackController.h deleted file mode 100644 index 2325329..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSingleVideoController.h" - -@protocol YTPlaybackController -@property (strong, nonatomic) YTSingleVideoController *activeVideo; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackControllerUIWrapper.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackControllerUIWrapper.h deleted file mode 100644 index 372577b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackControllerUIWrapper.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTSingleVideoController.h" - -@interface YTPlaybackControllerUIWrapper : NSObject -- (YTSingleVideoController *)activeVideo; -- (YTSingleVideoController *)contentVideo; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackData.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackData.h deleted file mode 100644 index e106b99..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackData.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MLVideo.h" -#import "YTPlayerResponse.h" - -@interface YTPlaybackData : NSObject -- (MLVideo *)video; -- (YTPlayerResponse *)playerResponse; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackStrippedWatchController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackStrippedWatchController.h deleted file mode 100644 index d423100..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaybackStrippedWatchController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTWatchMetadataPanelStateResponderProvider.h" -#import "YTWatchPlaybackController.h" - -@interface YTPlaybackStrippedWatchController : NSObject -@property (nonatomic, strong, readwrite) YTWatchPlaybackController *watchPlaybackController; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerBarSegmentMarkerView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerBarSegmentMarkerView.h deleted file mode 100644 index cb81295..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerBarSegmentMarkerView.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface YTPlayerBarSegmentMarkerView : UIView -@property (nonatomic, readwrite, assign) CGFloat startTime; -@property (nonatomic, readwrite, assign) CGFloat endTime; -@property (nonatomic, readwrite, assign) CGFloat width; -@property (nonatomic, readwrite, assign) NSInteger type; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerBarSegmentedProgressView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerBarSegmentedProgressView.h deleted file mode 100644 index fc782a8..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerBarSegmentedProgressView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import - -@interface YTPlayerBarSegmentedProgressView : UIView -@property (nonatomic, readwrite, assign) CGFloat totalTime; -@property (nonatomic, readwrite, assign) int playerViewLayout; -- (void)maybeCreateMarkerViews; -- (void)setChapters:(NSArray *)chapters; -- (void)createAndAddMarker:(CGFloat)arg1 type:(NSInteger)type width:(CGFloat)width; -- (void)createAndAddMarker:(CGFloat)arg1 type:(NSInteger)type clusterType:(NSInteger)clusterType width:(CGFloat)width; // Deprecated -- (NSMutableArray *)segmentViews; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerOverlay.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerOverlay.h deleted file mode 100644 index 7587fcf..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerOverlay.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTPlayerOverlay : NSObject -- (NSString *)overlayIdentifier; -- (NSInteger)overlayZIndex; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerOverlayProvider.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerOverlayProvider.h deleted file mode 100644 index c2f841d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerOverlayProvider.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTPlayerOverlayProvider : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerPIPController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerPIPController.h deleted file mode 100644 index bb795a2..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerPIPController.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GIMMe.h" -#import "YTSingleVideoController.h" - -@interface YTPlayerPIPController : NSObject -@property (nonatomic, readonly, assign, getter=isPictureInPictureActive) BOOL pictureInPuctureActive; -@property (nonatomic, readonly, assign, getter=isPictureInPicturePossible) BOOL pictureInPucturePossible; -@property (retain, nonatomic) YTSingleVideoController *activeSingleVideo; -- (instancetype)initWithPlayerView:(id)playerView delegate:(id)delegate; // Deprecated, use initWithDelegate: -- (instancetype)initWithDelegate:(id)delegate; -- (GIMMe *)gimme; // Deprecated -- (BOOL)canInvokePictureInPicture; // Deprecated, use canEnablePictureInPicture -- (BOOL)canEnablePictureInPicture; -- (void)maybeInvokePictureInPicture; // Deprecated, use maybeEnablePictureInPicture -- (void)maybeEnablePictureInPicture; -- (void)play; -- (void)pause; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerResources.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerResources.h deleted file mode 100644 index 302c987..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerResources.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTPlayerResources : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerResponse.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerResponse.h deleted file mode 100644 index cb02869..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerResponse.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTIPlayerResponse.h" - -@interface YTPlayerResponse : NSObject -- (YTIPlayerResponse *)playerData; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerStatus.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerStatus.h deleted file mode 100644 index 7503e06..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerStatus.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -@interface YTPlayerStatus : NSObject -- (BOOL)externalPlayback; -- (BOOL)backgroundPlayback; -- (BOOL)isInlinePlaybackActive; -- (BOOL)pictureInPicture; -- (int)visibility; -- (int)layout; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerView.h deleted file mode 100644 index 27cca92..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerView.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "MLAVPIPPlayerLayerView.h" -#import "YTPlaybackControllerUIWrapper.h" - -@interface YTPlayerView : UIView -@property (retain, nonatomic) MLAVPIPPlayerLayerView *pipRenderingView; // Removed in newer versions -@property (nonatomic, strong, readwrite) UIView *overlayView; // Usually YTMainAppVideoPlayerOverlayView -- (YTPlaybackControllerUIWrapper *)playerViewDelegate; -- (UIView *)renderingView; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerViewController.h deleted file mode 100644 index ea6bca7..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -#import -#import "GIMMe.h" -#import "YTPlaybackController.h" -#import "YTSingleVideoController.h" - -@interface YTPlayerViewController : UIViewController -@property (nonatomic, readonly, assign) BOOL isPlayingAd; -@property (nonatomic, strong, readwrite) NSString *channelID; -- (GIMMe *)gimme; // Deprecated -- (NSString *)currentVideoID; -- (YTSingleVideoController *)activeVideo; -- (CGFloat)currentVideoMediaTime; -- (CGFloat)currentVideoTotalMediaTime; -- (int)playerViewLayout; -- (BOOL)isMDXActive; -- (void)didPressToggleFullscreen; -- (void)setMuted:(BOOL)muted; -- (void)setPlayerViewLayout:(int)layout; -- (void)scrubToTime:(CGFloat)time; // Deprecated -- (void)seekToTime:(CGFloat)time; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerViewControllerConfig.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerViewControllerConfig.h deleted file mode 100644 index fba2fe6..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlayerViewControllerConfig.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTPlayerViewControllerConfig : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCell.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCell.h deleted file mode 100644 index 8e2f4e1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCell.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTCollectionViewCell.h" - -@interface YTPlaylistPanelProminentThumbnailVideoCell : YTCollectionViewCell -- (void)setSwipeButtonTarget:(id)target action:(SEL)action; -- (void)setSwipeButtonActionsViewRightBlock:(void (^)(void))block; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCellController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCellController.h deleted file mode 100644 index 438396b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTPlaylistPanelProminentThumbnailVideoCellController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTPlaylistPanelProminentThumbnailVideoCellController : NSObject -- (void)didPressSwipeToRevealButton; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTQTMButton.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTQTMButton.h deleted file mode 100644 index 4ae3799..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTQTMButton.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "YTLightweightQTMButton.h" - -@interface YTQTMButton : YTLightweightQTMButton -+ (instancetype)button; -+ (instancetype)closeButton; -+ (instancetype)iconButton; -+ (instancetype)textButton; -@property (nonatomic, assign, readwrite) CGFloat buttonImageTitlePadding; -@property (nonatomic, assign, readwrite) CGFloat minHitTargetSize; -@property (nonatomic, assign, readwrite) CGFloat verticalContentPadding; -@property (nonatomic, assign, readwrite) NSInteger buttonLayoutStyle; -@property (nonatomic, assign, readwrite) BOOL refreshRendererAfterPageStyling; -@property (nonatomic, assign, readwrite) BOOL sizeWithPaddingAndInsets; -@property (nonatomic, copy, readwrite) NSString *accessibilityIdentifier; -@property (nonatomic, copy, readwrite) NSString *accessibilityLabel; -- (void)setTitleTypeKind:(NSInteger)titleTypeKind typeVariant:(NSInteger)typeVariant; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelContentView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelContentView.h deleted file mode 100644 index 0030a25..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelContentView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTReelContentView : UIView -@property (nonatomic, assign, readwrite) BOOL alwaysShowShortsProgressBar; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelLikeModel.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelLikeModel.h deleted file mode 100644 index 6298ade..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelLikeModel.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTILikeButtonRenderer.h" - -@interface YTReelLikeModel : NSObject -@property (nonatomic, copy, readwrite) NSString *videoID; -@property (nonatomic, strong, readwrite) YTILikeButtonRenderer *likeButtonRenderer; -@property (nonatomic, assign, readwrite) int status; -@property (nonatomic, assign, readwrite) int lastStatus; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelPlayerBottomButton.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelPlayerBottomButton.h deleted file mode 100644 index 47b480e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelPlayerBottomButton.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTQTMButton.h" - -@interface YTReelPlayerBottomButton : YTQTMButton -@property (nonatomic, assign, readwrite) BOOL applyRightSideLayoutImageSize; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelPlayerViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelPlayerViewController.h deleted file mode 100644 index 9edfca1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelPlayerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTReelContentView.h" - -@interface YTReelPlayerViewController : UIViewController -- (YTReelContentView *)contentView; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelWatchLikesController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelWatchLikesController.h deleted file mode 100644 index f4c2bd9..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelWatchLikesController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTQTMButton.h" -#import "YTILikeButtonRenderer.h" - -@interface YTReelWatchLikesController : NSObject -@property (nonatomic, strong, readwrite) YTQTMButton *likeButton; -@property (nonatomic, strong, readwrite) YTQTMButton *dislikeButton; -- (id)likeModelForLikeButtonRenderer:(YTILikeButtonRenderer *)renderer; -- (void)updateLikeButtonWithModel:(id)model animated:(BOOL)animated; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelWatchPlaybackOverlayView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelWatchPlaybackOverlayView.h deleted file mode 100644 index 4211bef..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTReelWatchPlaybackOverlayView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTQTMButton.h" - -@interface YTReelWatchPlaybackOverlayView : UIView -@property (nonatomic, assign, readonly) YTQTMButton *overflowButton; -- (NSArray *)orderedRightSideButtons; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTRightNavigationButtons.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTRightNavigationButtons.h deleted file mode 100644 index 2f88021..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTRightNavigationButtons.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTRightNavigationButtons : UIView -@property (nonatomic, readwrite, assign) CGFloat leadingPadding; -@property (nonatomic, readwrite, assign) CGFloat tailingPadding; // Legitimate typo -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSearchableSettingsViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSearchableSettingsViewController.h deleted file mode 100644 index 5fc7a15..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSearchableSettingsViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTSearchableSettingsViewController : UIViewController -- (void)storeCollectionViewSections:(NSArray *)sections; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSectionListViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSectionListViewController.h deleted file mode 100644 index af177d1..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSectionListViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTSectionListViewController : UIViewController -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSegmentableInlinePlayerBarView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSegmentableInlinePlayerBarView.h deleted file mode 100644 index 3c8342d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSegmentableInlinePlayerBarView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTSegmentableInlinePlayerBarView : UIView -@property (nonatomic, readonly, assign) CGFloat totalTime; -@property (nonatomic, readwrite, strong) YTPlayerViewController *playerViewController; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsCell.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsCell.h deleted file mode 100644 index 0b598b2..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsCell.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTCollectionViewCell.h" - -@interface YTSettingsCell : YTCollectionViewCell -@property (nonatomic, assign, readwrite) BOOL enabled; -- (void)setSwitchOn:(BOOL)on animated:(BOOL)animated; -- (void)toggleSwitch; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsPickerViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsPickerViewController.h deleted file mode 100644 index 256db4a..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsPickerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTStyledViewController.h" - -@interface YTSettingsPickerViewController : YTStyledViewController -- (instancetype)initWithNavTitle:(NSString *)navTitle pickerSectionTitle:(NSString *)pickerSectionTitle rows:(NSArray *)rows selectedItemIndex:(NSUInteger)selectedItemIndex parentResponder:(id)parentResponder; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionController.h deleted file mode 100644 index 4e23121..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTSettingsSectionController : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionItem.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionItem.h deleted file mode 100644 index b3ab9d9..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionItem.h +++ /dev/null @@ -1,21 +0,0 @@ -#import "YTSettingsCell.h" - -@interface YTSettingsSectionItem : NSObject -@property (nonatomic, copy, readwrite) NSString *title; -@property (nonatomic, assign, readwrite) BOOL hasSwitch; -@property (nonatomic, assign, readwrite) BOOL switchVisible; -@property (nonatomic, assign, readwrite) BOOL on; -@property (nonatomic, assign, readwrite) BOOL enabled; -@property (nonatomic, assign, readwrite) int settingItemId; -@property (nonatomic, copy, readwrite) BOOL (^selectBlock)(YTSettingsCell *, NSUInteger); -@property (nonatomic, copy, readwrite) BOOL (^switchBlock)(YTSettingsCell *, BOOL); -+ (instancetype)itemWithTitle:(NSString *)title accessibilityIdentifier:(NSString *)accessibilityIdentifier detailTextBlock:(NSString *(^)(void))detailTextBlock selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)itemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(NSString *)accessibilityIdentifier detailTextBlock:(id)detailTextBlock selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock; -+ (instancetype)checkmarkItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock disabledSelectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))disabledSelectBlock; -+ (instancetype)switchItemWithTitle:(NSString *)title switchOn:(BOOL)switchOn switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock; -+ (instancetype)switchItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(NSString *)accessibilityIdentifier switchOn:(BOOL)switchOn switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock settingItemId:(int)settingItemId; -+ (instancetype)switchItemWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription accessibilityIdentifier:(NSString *)accessibilityIdentifier switchOn:(BOOL)switchOn switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock settingItemId:(int)settingItemId; -- (instancetype)initWithTitle:(NSString *)title titleDescription:(NSString *)titleDescription; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionItemManager.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionItemManager.h deleted file mode 100644 index 6ea6259..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsSectionItemManager.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "GIMMe.h" - -@interface YTSettingsSectionItemManager : NSObject -@property (nonatomic, readwrite, weak) GIMMe *gimme; -- (id)parentResponder; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsViewController.h deleted file mode 100644 index 5959d3c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSettingsViewController.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "YTSettingsSectionItem.h" -#import "YTSettingsSectionController.h" - -@interface YTSettingsViewController : UIViewController -- (NSMutableDictionary *)settingsSectionControllers; -- (void)setSectionItems:(NSMutableArray *)sectionItems forCategory:(NSInteger)category title:(NSString *)title titleDescription:(NSString *)titleDescription headerHidden:(BOOL)headerHidden; -- (void)pushViewController:(UIViewController *)viewController; -- (void)reloadData; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideo.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideo.h deleted file mode 100644 index 9d86038..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideo.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "YTPlaybackData.h" -#import "MLVideo.h" - -@interface YTSingleVideo : NSObject -- (MLVideo *)video; // Deprecated -- (NSString *)videoId; -- (YTPlaybackData *)playbackData; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoController.h deleted file mode 100644 index e23f990..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoController.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "MLFormat.h" -#import "YTSingleVideoControllerDelegate.h" -#import "YTSingleVideo.h" - -@interface YTSingleVideoController : NSObject -@property (nonatomic, weak, readwrite) NSObject *delegate; -- (YTSingleVideo *)singleVideo; -- (YTSingleVideo *)videoData; -- (NSArray *)selectableVideoFormats; -- (BOOL)isMuted; -- (void)playerRateDidChange:(float)rate; -- (void)setMuted:(BOOL)muted; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoControllerDelegate.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoControllerDelegate.h deleted file mode 100644 index 808da0b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoControllerDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@protocol YTSingleVideoControllerDelegate -- (void)singleVideoController:(id)controller requiresReloadWithContext:(id)context; -- (void)singleVideoController:(id)controller externalPlaybackActiveStateDidChange:(id)arg2; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoTime.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoTime.h deleted file mode 100644 index dc39331..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSingleVideoTime.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -@interface YTSingleVideoTime : NSObject -@property (nonatomic, readonly, assign) CGFloat absoluteTime; -@property (nonatomic, readonly, assign) CGFloat time; -@property (nonatomic, readonly, assign) CGFloat productionTime; -+ (instancetype)zero; -+ (instancetype)timeWithTime:(CGFloat)time; -+ (instancetype)timeWithTime:(CGFloat)time productionTime:(CGFloat)productionTime; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlideForActionsView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlideForActionsView.h deleted file mode 100644 index 21718df..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlideForActionsView.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTSlideForActionsView : UIView -@property (nonatomic, assign, readwrite) BOOL actionsEnabledRight; -@property (nonatomic, assign, readwrite) BOOL enableMinSnap; -@property (nonatomic, assign, readwrite) BOOL enableHapticFeedback; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionView.h deleted file mode 100644 index 40d02f3..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionView.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "YTIFormattedStringLabel.h" -#import "YTSlimVideoScrollableDetailsActionsView.h" - -@interface YTSlimVideoDetailsActionView : UIView -@property (nonatomic, strong, readwrite) YTIFormattedStringLabel *label; -@property (nonatomic, weak, readwrite) YTSlimVideoScrollableDetailsActionsView *visibilityDelegate; -@property (nonatomic) __weak id delegate; -@property (nonatomic, assign, readwrite, getter=isToggled) BOOL toggled; -- (instancetype)initWithSlimMetadataButtonSupportedRenderer:(id)renderer; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionViewDelegate.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionViewDelegate.h deleted file mode 100644 index 1639890..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionViewDelegate.h +++ /dev/null @@ -1,7 +0,0 @@ -#include "YTQTMButton.h" -#import "YTQTMButton.h" - -@protocol YTSlimVideoDetailsActionViewDelegate -- (void)didTapButton:(YTQTMButton *)button fromRect:(CGRect)rect inView:(UIView *)view; -- (void)handleLongPressOnButton:(YTQTMButton *)button fromRect:(CGRect)rect inView:(UIView *)view; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionsView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionsView.h deleted file mode 100644 index e216a81..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoDetailsActionsView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlimVideoDetailsActionViewDelegate.h" - -@interface YTSlimVideoDetailsActionsView : UIScrollView -@property (nonatomic, weak, readwrite) NSObject *videoActionsDelegate; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoMetadataExpandingBehavior.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoMetadataExpandingBehavior.h deleted file mode 100644 index 0f85885..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoMetadataExpandingBehavior.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTSlimVideoScrollableActionBarCellControllerDelegate.h" - -@interface YTSlimVideoMetadataExpandingBehavior : NSObject -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCell.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCell.h deleted file mode 100644 index 12c2f10..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCell.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTCollectionViewCellProtocol.h" -#import "YTSlimVideoScrollableDetailsActionsProtocol.h" - -@interface YTSlimVideoScrollableActionBarCell : UICollectionViewCell -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h deleted file mode 100644 index 71ff43d..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCellController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "YTSlimVideoScrollableActionBarCellControllerDelegate.h" -#import "YTInnerTubeCellController.h" - -@interface YTSlimVideoScrollableActionBarCellController : YTInnerTubeCellController -@property (nonatomic, weak, readwrite) NSObject *delegate; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCellControllerDelegate.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCellControllerDelegate.h deleted file mode 100644 index 17cb153..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableActionBarCellControllerDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@protocol YTSlimVideoScrollableActionBarCellControllerDelegate -@required -- (NSString *)videoId; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableDetailsActionsProtocol.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableDetailsActionsProtocol.h deleted file mode 100644 index defbb58..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableDetailsActionsProtocol.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlimVideoDetailsActionView.h" - -@protocol YTSlimVideoScrollableDetailsActionsProtocol -- (YTSlimVideoDetailsActionView *)offlineActionView; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h deleted file mode 100644 index 4f9c2fd..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSlimVideoScrollableDetailsActionsView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTSlimVideoDetailsActionViewDelegate.h" - -@interface YTSlimVideoScrollableDetailsActionsView : UIScrollView -@property (nonatomic, weak, readwrite) NSObject *videoActionsDelegate; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTStyledViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTStyledViewController.h deleted file mode 100644 index 5760486..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTStyledViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import "YTMultiSizeViewController.h" - -@interface YTStyledViewController : YTMultiSizeViewController -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSystemNotifications.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSystemNotifications.h deleted file mode 100644 index a9ff95b..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTSystemNotifications.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTSystemNotifications : NSObject -- (void)addSystemNotificationsObserver:(id)observer; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTToastResponderEvent.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTToastResponderEvent.h deleted file mode 100644 index f46b4ae..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTToastResponderEvent.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTToastResponderEvent : NSObject -+ (instancetype)eventWithMessage:(NSString *)message firstResponder:(id)firstResponder; -- (void)send; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTUIResources.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTUIResources.h deleted file mode 100644 index dd99366..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTUIResources.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTUIResources : NSObject -+ (UIImage *)iconCheckTemplateImage; -+ (UIImage *)actionsheetDefaultImage; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTUIUtils.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTUIUtils.h deleted file mode 100644 index a7c115e..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTUIUtils.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -@interface YTUIUtils : NSObject -+ (BOOL)canOpenURL:(NSURL *)url; -+ (BOOL)openURL:(NSURL *)url; -+ (UIViewController *)topViewControllerForPresenting; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTVersionUtils.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTVersionUtils.h deleted file mode 100644 index c5b10b6..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTVersionUtils.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTVersionUtils : NSObject -+ (NSString *)appVersion; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTVideoQualitySwitchOriginalController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTVideoQualitySwitchOriginalController.h deleted file mode 100644 index 98d5b2c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTVideoQualitySwitchOriginalController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface YTVideoQualitySwitchOriginalController : NSObject -- (instancetype)initWithParentResponder:(id)responder; -@end \ No newline at end of file diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchController.h deleted file mode 100644 index 30b2b70..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "YTWatchPlaybackController.h" - -@interface YTWatchController : NSObject -@property (nonatomic, strong, readwrite) YTWatchPlaybackController *watchPlaybackController; -- (void)showFullScreen; -- (void)showSmallScreen; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchLayerViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchLayerViewController.h deleted file mode 100644 index d651b65..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchLayerViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTWatchLayerViewController : UIViewController -- (YTPlayerViewController *)playerViewController; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchMetadataPanelStateResponderProvider.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchMetadataPanelStateResponderProvider.h deleted file mode 100644 index fc29ec7..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchMetadataPanelStateResponderProvider.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@protocol YTWatchMetadataPanelStateResponderProvider -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchMiniBarViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchMiniBarViewController.h deleted file mode 100644 index 07af781..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchMiniBarViewController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface YTWatchMiniBarViewController : UIViewController -@property (nonatomic, assign, readwrite, getter=isActivated) BOOL activated; -@property (nonatomic, assign, readwrite, getter=isVisible) BOOL visible; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchNextResultsViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchNextResultsViewController.h deleted file mode 100644 index dcb4e1c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchNextResultsViewController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTWatchNextResultsViewController : UIViewController -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchPlaybackController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchPlaybackController.h deleted file mode 100644 index 87cc89c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchPlaybackController.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface YTWatchPlaybackController : NSObject -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchViewController.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchViewController.h deleted file mode 100644 index 62c1395..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/YTWatchViewController.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "YTPlayerViewController.h" - -@interface YTWatchViewController : UIViewController -@property (nonatomic, weak, readwrite) YTPlayerViewController *playerViewController; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/_ASCollectionViewCell.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/_ASCollectionViewCell.h deleted file mode 100644 index 51ae67c..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/_ASCollectionViewCell.h +++ /dev/null @@ -1,8 +0,0 @@ -#import -#import "ASCollectionElement.h" -#import "ASCellNode.h" - -@interface _ASCollectionViewCell : UICollectionViewCell -@property (nonatomic, strong, readwrite) ASCollectionElement *element; -- (ASCellNode *)node; -@end diff --git a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/_ASDisplayView.h b/Tweaks/iSponsorBlock/Headers/YouTubeHeader/_ASDisplayView.h deleted file mode 100644 index cf50613..0000000 --- a/Tweaks/iSponsorBlock/Headers/YouTubeHeader/_ASDisplayView.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "ASDisplayNode.h" - -@interface _ASDisplayView : UIView -@property (nonatomic, copy, readwrite) NSString *accessibilityLabel; -@property (nonatomic) ASDisplayNode *keepalive_node; -@end diff --git a/Tweaks/iSponsorBlock/Headers/iSponsorBlock.h b/Tweaks/iSponsorBlock/Headers/iSponsorBlock.h deleted file mode 100644 index e6a9f87..0000000 --- a/Tweaks/iSponsorBlock/Headers/iSponsorBlock.h +++ /dev/null @@ -1,138 +0,0 @@ -#import -#import -#import -#import "YouTubeHeader/YTInlinePlayerBarView.h" -#import "YouTubeHeader/YTMainAppControlsOverlayView.h" -#import "YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h" -#import "YouTubeHeader/YTRightNavigationButtons.h" -#import "YouTubeHeader/YTPageStyleController.h" -#import "YouTubeHeader/YTPlayerView.h" -#import "YouTubeHeader/YTPlayerViewController.h" -#import "YouTubeHeader/YTPlayerBarSegmentMarkerView.h" -#import "YouTubeHeader/YTPlayerBarSegmentedProgressView.h" -#import "YouTubeHeader/YTSegmentableInlinePlayerBarView.h" -#import "YouTubeHeader/YTSingleVideoTime.h" -#import "YouTubeHeader/YTNGWatchLayerViewController.h" -#import "YouTubeHeader/YTWatchLayerViewController.h" -#import "YouTubeHeader/YTIChapterRenderer.h" -#import "MBProgressHUD.h" -#import "SponsorSegment.h" -#include - -// prefs -BOOL kIsEnabled; -NSString *kUserID; -NSString *kAPIInstance; -NSDictionary *kCategorySettings; -CGFloat kMinimumDuration; -BOOL kShowSkipNotice; -BOOL kShowButtonsInPlayer; -BOOL kHideStartEndButtonInPlayer; -BOOL kShowModifiedTime; -BOOL kSkipAudioNotification; -BOOL kEnableSkipCountTracking; -CGFloat kSkipNoticeDuration; -NSMutableArray *kWhitelistedChannels; - -@interface YTPlayerViewController (iSB) -@property (strong, nonatomic) NSMutableArray *skipSegments; -@property (nonatomic, assign) NSInteger currentSponsorSegment; -@property (strong, nonatomic) MBProgressHUD *hud; -@property (nonatomic, assign) NSInteger unskippedSegment; -@property (strong, nonatomic) NSMutableArray *userSkipSegments; -@property (nonatomic, assign) BOOL hudDisplayed; -- (void)isb_scrubToTime:(CGFloat)time; -- (void)isb_fixVisualGlitch; -@end - -@interface YTMainAppControlsOverlayView (iSB) -- (void)sponsorBlockButtonPressed:(YTQTMButton *)sender; -- (void)sponsorStartedButtonPressed:(YTQTMButton *)sender; -- (void)sponsorEndedButtonPressed:(YTQTMButton *)sender; -- (void)presentSponsorBlockViewController; -@property (retain, nonatomic) YTQTMButton *sponsorBlockButton; -@property (retain, nonatomic) YTQTMButton *sponsorStartedEndedButton; -@property (nonatomic, assign) BOOL isDisplayingSponsorBlockViewController; -@end - -// Old class -@interface YTIChapterRendererWrapper : NSObject -- (instancetype)initWithStartTime:(CGFloat)arg1 endTime:(CGFloat)arg2 title:(NSString *)arg3; -+ (instancetype)chapterRendererWrapperWithRenderer:(YTIChapterRenderer *)arg1; -@property (nonatomic, assign) CGFloat endTime; -@end - -@interface YTPlayerBarSegmentedProgressView (iSB) -@property (strong, nonatomic) NSMutableArray *sponsorMarkerViews; -@property (nonatomic, retain) NSMutableArray *skipSegments; -- (void)removeSponsorMarkers; -@end - -@interface YTPlayerBarSegmentMarkerView (iSB) -@property (nonatomic, assign) BOOL isSponsorMarker; -@end - -@interface YTRightNavigationButtons (iSB) -@property (strong, nonatomic) YTQTMButton *sponsorBlockButton; -@end - -@interface YTInlinePlayerBarView (iSB) -@property (strong, nonatomic) NSMutableArray *sponsorMarkerViews; -@property (strong, nonatomic) NSMutableArray *skipSegments; -- (void)removeSponsorMarkers; -- (void)maybeCreateMarkerViewsISB; -@end - -@interface YTSegmentableInlinePlayerBarView (iSB) -@property (strong, nonatomic) NSMutableArray *sponsorMarkerViews; -@property (strong, nonatomic) NSMutableArray *skipSegments; -- (void)removeSponsorMarkers; -- (void)maybeCreateMarkerViewsISB; -@end - -// Cercube -@interface CADownloadObject : NSObject -@property(readonly, nonatomic) NSString *filePath; -@property(copy, nonatomic) NSString *fileName; // @dynamic fileName; -@property(copy, nonatomic) NSString *videoId; -@end - -@interface CADownloadObject_CADownloadObject_ : CADownloadObject -@end - -@interface AVPlayerItem (Private) -- (NSURL *)_URL; -@end - -@interface AVQueuePlayer (iSB) -@property (strong, nonatomic) NSMutableArray *skipSegments; -@property (nonatomic, assign) NSInteger currentSponsorSegment; -@property (strong, nonatomic) MBProgressHUD *hud; -@property (nonatomic, assign) NSInteger unskippedSegment; -@property (nonatomic, assign) BOOL isSeeking; -@property (nonatomic, assign) NSInteger currentPlayerItem; -@property (strong, nonatomic) id timeObserver; -@property (strong, nonatomic) AVPlayerViewController *playerViewController; -@property (strong, nonatomic) NSMutableArray *markerViews; -@property (nonatomic, assign) BOOL hudDisplayed; -- (void)sponsorBlockSetup; -- (void)updateMarkerViews; -@end - -@interface AVScrubber : UIView -@end - -@interface AVPlaybackControlsView : UIView -@property (strong, nonatomic) AVScrubber *scrubber; -@end - -@interface AVPlayerViewControllerContentView : UIView -@property (strong, nonatomic) AVPlaybackControlsView *playbackControlsView; -@end - -@interface AVPlayerViewController () -@property (strong, nonatomic) AVPlayerViewControllerContentView *contentView; -@end - -@interface AVContentOverlayView : UIView -@end diff --git a/Tweaks/iSponsorBlock/LICENSE b/Tweaks/iSponsorBlock/LICENSE deleted file mode 100644 index f288702..0000000 --- a/Tweaks/iSponsorBlock/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/Tweaks/iSponsorBlock/MBProgressHUD.m b/Tweaks/iSponsorBlock/MBProgressHUD.m deleted file mode 100644 index 2626981..0000000 --- a/Tweaks/iSponsorBlock/MBProgressHUD.m +++ /dev/null @@ -1,1201 +0,0 @@ -// -// MBProgressHUD.m -// Version 1.2.0 -// Created by Matej Bukovinski on 2.4.09. -// - -#import "Headers/MBProgressHUD.h" -#import - -#define MBMainThreadAssert() NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); - -CGFloat const MBProgressMaxOffset = 1000000.f; - -static const CGFloat MBDefaultPadding = 4.f; -static const CGFloat MBDefaultLabelFontSize = 16.f; -static const CGFloat MBDefaultDetailsLabelFontSize = 12.f; - - -@interface MBProgressHUD () - -@property (nonatomic, assign) BOOL useAnimation; -@property (nonatomic, assign, getter=hasFinished) BOOL finished; -@property (nonatomic, strong) UIView *indicator; -@property (nonatomic, strong) NSDate *showStarted; -@property (nonatomic, strong) NSArray *paddingConstraints; -@property (nonatomic, strong) NSArray *bezelConstraints; -@property (nonatomic, strong) UIView *topSpacer; -@property (nonatomic, strong) UIView *bottomSpacer; -@property (nonatomic, strong) UIMotionEffectGroup *bezelMotionEffects; -@property (nonatomic, weak) NSTimer *graceTimer; -@property (nonatomic, weak) NSTimer *minShowTimer; -@property (nonatomic, weak) NSTimer *hideDelayTimer; -@property (nonatomic, weak) CADisplayLink *progressObjectDisplayLink; - -@end - -@interface MBProgressHUDRoundedButton : UIButton -@end - - -@implementation MBProgressHUD - -#pragma mark - Class methods - -+ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { - MBProgressHUD *hud = [[self alloc] initWithView:view]; - hud.removeFromSuperViewOnHide = YES; - [view addSubview:hud]; - [hud showAnimated:animated]; - return hud; -} - -+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated { - MBProgressHUD *hud = [self HUDForView:view]; - if (hud != nil) { - hud.removeFromSuperViewOnHide = YES; - [hud hideAnimated:animated]; - return YES; - } - return NO; -} - -+ (MBProgressHUD *)HUDForView:(UIView *)view { - NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; - for (UIView *subview in subviewsEnum) { - if ([subview isKindOfClass:self]) { - MBProgressHUD *hud = (MBProgressHUD *)subview; - if (hud.hasFinished == NO) { - return hud; - } - } - } - return nil; -} - -#pragma mark - Lifecycle - -- (void)commonInit { - // Set default values for properties - _animationType = MBProgressHUDAnimationFade; - _mode = MBProgressHUDModeIndeterminate; - _margin = 20.0f; - _defaultMotionEffectsEnabled = NO; - - if (@available(iOS 13.0, tvOS 13, *)) { - _contentColor = [[UIColor labelColor] colorWithAlphaComponent:0.7f]; - } else { - _contentColor = [UIColor colorWithWhite:0.f alpha:0.7f]; - } - - // Transparent background - self.opaque = NO; - self.backgroundColor = [UIColor clearColor]; - // Make it invisible for now - self.alpha = 0.0f; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.layer.allowsGroupOpacity = NO; - - [self setupViews]; - [self updateIndicators]; - [self registerForNotifications]; -} - -- (instancetype)initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame])) { - [self commonInit]; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - if ((self = [super initWithCoder:aDecoder])) { - [self commonInit]; - } - return self; -} - -- (id)initWithView:(UIView *)view { - NSAssert(view, @"View must not be nil."); - return [self initWithFrame:view.bounds]; -} - -- (void)dealloc { - [self unregisterFromNotifications]; -} - -#pragma mark - Show & hide - -- (void)showAnimated:(BOOL)animated { - MBMainThreadAssert(); - [self.minShowTimer invalidate]; - self.useAnimation = animated; - self.finished = NO; - // If the grace time is set, postpone the HUD display - if (self.graceTime > 0.0) { - NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - self.graceTimer = timer; - } - // ... otherwise show the HUD immediately - else { - [self showUsingAnimation:self.useAnimation]; - } -} - -- (void)hideAnimated:(BOOL)animated { - MBMainThreadAssert(); - [self.graceTimer invalidate]; - self.useAnimation = animated; - self.finished = YES; - // If the minShow time is set, calculate how long the HUD was shown, - // and postpone the hiding operation if necessary - if (self.minShowTime > 0.0 && self.showStarted) { - NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted]; - if (interv < self.minShowTime) { - NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - self.minShowTimer = timer; - return; - } - } - // ... otherwise hide the HUD immediately - [self hideUsingAnimation:self.useAnimation]; -} - -- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay { - // Cancel any scheduled hideAnimated:afterDelay: calls - [self.hideDelayTimer invalidate]; - - NSTimer *timer = [NSTimer timerWithTimeInterval:delay target:self selector:@selector(handleHideTimer:) userInfo:@(animated) repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - self.hideDelayTimer = timer; -} - -#pragma mark - Timer callbacks - -- (void)handleGraceTimer:(NSTimer *)theTimer { - // Show the HUD only if the task is still running - if (!self.hasFinished) { - [self showUsingAnimation:self.useAnimation]; - } -} - -- (void)handleMinShowTimer:(NSTimer *)theTimer { - [self hideUsingAnimation:self.useAnimation]; -} - -- (void)handleHideTimer:(NSTimer *)timer { - [self hideAnimated:[timer.userInfo boolValue]]; -} - -#pragma mark - View Hierrarchy - -- (void)didMoveToSuperview { - [self updateForCurrentOrientationAnimated:NO]; -} - -#pragma mark - Internal show & hide operations - -- (void)showUsingAnimation:(BOOL)animated { - // Cancel any previous animations - [self.bezelView.layer removeAllAnimations]; - [self.backgroundView.layer removeAllAnimations]; - - // Cancel any scheduled hideAnimated:afterDelay: calls - [self.hideDelayTimer invalidate]; - - self.showStarted = [NSDate date]; - self.alpha = 1.f; - - // Needed in case we hide and re-show with the same NSProgress object attached. - [self setNSProgressDisplayLinkEnabled:YES]; - - // Set up motion effects only at this point to avoid needlessly - // creating the effect if it was disabled after initialization. - [self updateBezelMotionEffects]; - - if (animated) { - [self animateIn:YES withType:self.animationType completion:NULL]; - } else { - self.bezelView.alpha = 1.f; - self.backgroundView.alpha = 1.f; - } -} - -- (void)hideUsingAnimation:(BOOL)animated { - // Cancel any scheduled hideAnimated:afterDelay: calls. - // This needs to happen here instead of in done, - // to avoid races if another hideAnimated:afterDelay: - // call comes in while the HUD is animating out. - [self.hideDelayTimer invalidate]; - - if (animated && self.showStarted) { - self.showStarted = nil; - [self animateIn:NO withType:self.animationType completion:^(BOOL finished) { - [self done]; - }]; - } else { - self.showStarted = nil; - self.bezelView.alpha = 0.f; - self.backgroundView.alpha = 1.f; - [self done]; - } -} - -- (void)animateIn:(BOOL)animatingIn withType:(MBProgressHUDAnimation)type completion:(void(^)(BOOL finished))completion { - // Automatically determine the correct zoom animation type - if (type == MBProgressHUDAnimationZoom) { - type = animatingIn ? MBProgressHUDAnimationZoomIn : MBProgressHUDAnimationZoomOut; - } - - CGAffineTransform small = CGAffineTransformMakeScale(0.5f, 0.5f); - CGAffineTransform large = CGAffineTransformMakeScale(1.5f, 1.5f); - - // Set starting state - UIView *bezelView = self.bezelView; - if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomIn) { - bezelView.transform = small; - } else if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomOut) { - bezelView.transform = large; - } - - // Perform animations - dispatch_block_t animations = ^{ - if (animatingIn) { - bezelView.transform = CGAffineTransformIdentity; - } else if (!animatingIn && type == MBProgressHUDAnimationZoomIn) { - bezelView.transform = large; - } else if (!animatingIn && type == MBProgressHUDAnimationZoomOut) { - bezelView.transform = small; - } - CGFloat alpha = animatingIn ? 1.f : 0.f; - bezelView.alpha = alpha; - self.backgroundView.alpha = alpha; - }; - [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; -} - -- (void)done { - [self setNSProgressDisplayLinkEnabled:NO]; - - if (self.hasFinished) { - self.alpha = 0.0f; - if (self.removeFromSuperViewOnHide) { - [self removeFromSuperview]; - } - } - MBProgressHUDCompletionBlock completionBlock = self.completionBlock; - if (completionBlock) { - completionBlock(); - } - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(hudWasHidden:)]) { - [delegate performSelector:@selector(hudWasHidden:) withObject:self]; - } -} - -#pragma mark - UI - -- (void)setupViews { - UIColor *defaultColor = self.contentColor; - - MBBackgroundView *backgroundView = [[MBBackgroundView alloc] initWithFrame:self.bounds]; - backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; - backgroundView.backgroundColor = [UIColor clearColor]; - backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - backgroundView.alpha = 0.f; - [self addSubview:backgroundView]; - _backgroundView = backgroundView; - - MBBackgroundView *bezelView = [MBBackgroundView new]; - bezelView.translatesAutoresizingMaskIntoConstraints = NO; - bezelView.layer.cornerRadius = 5.f; - bezelView.alpha = 0.f; - [self addSubview:bezelView]; - _bezelView = bezelView; - - UILabel *label = [UILabel new]; - label.adjustsFontSizeToFitWidth = NO; - label.textAlignment = NSTextAlignmentCenter; - label.textColor = defaultColor; - label.font = [UIFont boldSystemFontOfSize:MBDefaultLabelFontSize]; - label.opaque = NO; - label.backgroundColor = [UIColor clearColor]; - _label = label; - - UILabel *detailsLabel = [UILabel new]; - detailsLabel.adjustsFontSizeToFitWidth = NO; - detailsLabel.textAlignment = NSTextAlignmentCenter; - detailsLabel.textColor = defaultColor; - detailsLabel.numberOfLines = 0; - detailsLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; - detailsLabel.opaque = NO; - detailsLabel.backgroundColor = [UIColor clearColor]; - _detailsLabel = detailsLabel; - - UIButton *button = [MBProgressHUDRoundedButton buttonWithType:UIButtonTypeCustom]; - button.titleLabel.textAlignment = NSTextAlignmentCenter; - button.titleLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; - [button setTitleColor:defaultColor forState:UIControlStateNormal]; - _button = button; - - for (UIView *view in @[label, detailsLabel, button]) { - view.translatesAutoresizingMaskIntoConstraints = NO; - [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; - [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; - [bezelView addSubview:view]; - } - - UIView *topSpacer = [UIView new]; - topSpacer.translatesAutoresizingMaskIntoConstraints = NO; - topSpacer.hidden = YES; - [bezelView addSubview:topSpacer]; - _topSpacer = topSpacer; - - UIView *bottomSpacer = [UIView new]; - bottomSpacer.translatesAutoresizingMaskIntoConstraints = NO; - bottomSpacer.hidden = YES; - [bezelView addSubview:bottomSpacer]; - _bottomSpacer = bottomSpacer; -} - -- (void)updateIndicators { - UIView *indicator = self.indicator; - BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; - BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]]; - - MBProgressHUDMode mode = self.mode; - if (mode == MBProgressHUDModeIndeterminate) { - if (!isActivityIndicator) { - // Update to indeterminate indicator - UIActivityIndicatorView *activityIndicator; - [indicator removeFromSuperview]; -#if !TARGET_OS_MACCATALYST - if (@available(iOS 13.0, tvOS 13.0, *)) { -#endif - activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge]; - activityIndicator.color = [UIColor whiteColor]; -#if !TARGET_OS_MACCATALYST - } else { - activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - } -#endif - [activityIndicator startAnimating]; - indicator = activityIndicator; - [self.bezelView addSubview:indicator]; - } - } - else if (mode == MBProgressHUDModeDeterminateHorizontalBar) { - // Update to bar determinate indicator - [indicator removeFromSuperview]; - indicator = [[MBBarProgressView alloc] init]; - [self.bezelView addSubview:indicator]; - } - else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) { - if (!isRoundIndicator) { - // Update to determinante indicator - [indicator removeFromSuperview]; - indicator = [[MBRoundProgressView alloc] init]; - [self.bezelView addSubview:indicator]; - } - if (mode == MBProgressHUDModeAnnularDeterminate) { - [(MBRoundProgressView *)indicator setAnnular:YES]; - } - } - else if (mode == MBProgressHUDModeCustomView && self.customView != indicator) { - // Update custom view indicator - [indicator removeFromSuperview]; - indicator = self.customView; - [self.bezelView addSubview:indicator]; - } - else if (mode == MBProgressHUDModeText) { - [indicator removeFromSuperview]; - indicator = nil; - } - indicator.translatesAutoresizingMaskIntoConstraints = NO; - self.indicator = indicator; - - if ([indicator respondsToSelector:@selector(setProgress:)]) { - [(id)indicator setValue:@(self.progress) forKey:@"progress"]; - } - - [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; - [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; - - [self updateViewsForColor:self.contentColor]; - [self setNeedsUpdateConstraints]; -} - -- (void)updateViewsForColor:(UIColor *)color { - if (!color) return; - - self.label.textColor = color; - self.detailsLabel.textColor = color; - [self.button setTitleColor:color forState:UIControlStateNormal]; - - // UIAppearance settings are prioritized. If they are preset the set color is ignored. - - UIView *indicator = self.indicator; - if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { - UIActivityIndicatorView *appearance = nil; -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 - appearance = [UIActivityIndicatorView appearanceWhenContainedIn:[MBProgressHUD class], nil]; -#else - // For iOS 9+ - appearance = [UIActivityIndicatorView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; -#endif - - if (appearance.color == nil) { - ((UIActivityIndicatorView *)indicator).color = color; - } - } else if ([indicator isKindOfClass:[MBRoundProgressView class]]) { - MBRoundProgressView *appearance = nil; -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 - appearance = [MBRoundProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; -#else - appearance = [MBRoundProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; -#endif - if (appearance.progressTintColor == nil) { - ((MBRoundProgressView *)indicator).progressTintColor = color; - } - if (appearance.backgroundTintColor == nil) { - ((MBRoundProgressView *)indicator).backgroundTintColor = [color colorWithAlphaComponent:0.1]; - } - } else if ([indicator isKindOfClass:[MBBarProgressView class]]) { - MBBarProgressView *appearance = nil; -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 - appearance = [MBBarProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; -#else - appearance = [MBBarProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; -#endif - if (appearance.progressColor == nil) { - ((MBBarProgressView *)indicator).progressColor = color; - } - if (appearance.lineColor == nil) { - ((MBBarProgressView *)indicator).lineColor = color; - } - } else { - [indicator setTintColor:color]; - } -} - -- (void)updateBezelMotionEffects { - MBBackgroundView *bezelView = self.bezelView; - UIMotionEffectGroup *bezelMotionEffects = self.bezelMotionEffects; - - if (self.defaultMotionEffectsEnabled && !bezelMotionEffects) { - CGFloat effectOffset = 10.f; - UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - effectX.maximumRelativeValue = @(effectOffset); - effectX.minimumRelativeValue = @(-effectOffset); - - UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - effectY.maximumRelativeValue = @(effectOffset); - effectY.minimumRelativeValue = @(-effectOffset); - - UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init]; - group.motionEffects = @[effectX, effectY]; - - self.bezelMotionEffects = group; - [bezelView addMotionEffect:group]; - } else if (bezelMotionEffects) { - self.bezelMotionEffects = nil; - [bezelView removeMotionEffect:bezelMotionEffects]; - } -} - -#pragma mark - Layout - -- (void)updateConstraints { - UIView *bezel = self.bezelView; - UIView *topSpacer = self.topSpacer; - UIView *bottomSpacer = self.bottomSpacer; - CGFloat margin = self.margin; - NSMutableArray *bezelConstraints = [NSMutableArray array]; - NSDictionary *metrics = @{@"margin": @(margin)}; - - NSMutableArray *subviews = [NSMutableArray arrayWithObjects:self.topSpacer, self.label, self.detailsLabel, self.button, self.bottomSpacer, nil]; - if (self.indicator) [subviews insertObject:self.indicator atIndex:1]; - - // Remove existing constraints - [self removeConstraints:self.constraints]; - [topSpacer removeConstraints:topSpacer.constraints]; - [bottomSpacer removeConstraints:bottomSpacer.constraints]; - if (self.bezelConstraints) { - [bezel removeConstraints:self.bezelConstraints]; - self.bezelConstraints = nil; - } - - // Center bezel in container (self), applying the offset if set - CGPoint offset = self.offset; - NSMutableArray *centeringConstraints = [NSMutableArray array]; - [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:offset.x]]; - [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:offset.y]]; - [self applyPriority:998.f toConstraints:centeringConstraints]; - [self addConstraints:centeringConstraints]; - - // Ensure minimum side margin is kept - NSMutableArray *sideConstraints = [NSMutableArray array]; - [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; - [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; - [self applyPriority:999.f toConstraints:sideConstraints]; - [self addConstraints:sideConstraints]; - - // Minimum bezel size, if set - CGSize minimumSize = self.minSize; - if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) { - NSMutableArray *minSizeConstraints = [NSMutableArray array]; - [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]]; - [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]]; - [self applyPriority:997.f toConstraints:minSizeConstraints]; - [bezelConstraints addObjectsFromArray:minSizeConstraints]; - } - - // Square aspect ratio, if set - if (self.square) { - NSLayoutConstraint *square = [NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeWidth multiplier:1.f constant:0]; - square.priority = 997.f; - [bezelConstraints addObject:square]; - } - - // Top and bottom spacing - [topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; - [bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; - // Top and bottom spaces should be equal - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]]; - - // Layout subviews in bezel - NSMutableArray *paddingConstraints = [NSMutableArray new]; - [subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { - // Center in bezel - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]]; - // Ensure the minimum edge margin is kept - [bezelConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]]; - // Element spacing - if (idx == 0) { - // First, ensure spacing to bezel edge - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]]; - } else if (idx == subviews.count - 1) { - // Last, ensure spacing to bezel edge - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]]; - } - if (idx > 0) { - // Has previous - NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]; - [bezelConstraints addObject:padding]; - [paddingConstraints addObject:padding]; - } - }]; - - [bezel addConstraints:bezelConstraints]; - self.bezelConstraints = bezelConstraints; - - self.paddingConstraints = [paddingConstraints copy]; - [self updatePaddingConstraints]; - - [super updateConstraints]; -} - -- (void)layoutSubviews { - // There is no need to update constraints if they are going to - // be recreated in [super layoutSubviews] due to needsUpdateConstraints being set. - // This also avoids an issue on iOS 8, where updatePaddingConstraints - // would trigger a zombie object access. - if (!self.needsUpdateConstraints) { - [self updatePaddingConstraints]; - } - [super layoutSubviews]; -} - -- (void)updatePaddingConstraints { - // Set padding dynamically, depending on whether the view is visible or not - __block BOOL hasVisibleAncestors = NO; - [self.paddingConstraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *padding, NSUInteger idx, BOOL *stop) { - UIView *firstView = (UIView *)padding.firstItem; - UIView *secondView = (UIView *)padding.secondItem; - BOOL firstVisible = !firstView.hidden && !CGSizeEqualToSize(firstView.intrinsicContentSize, CGSizeZero); - BOOL secondVisible = !secondView.hidden && !CGSizeEqualToSize(secondView.intrinsicContentSize, CGSizeZero); - // Set if both views are visible or if there's a visible view on top that doesn't have padding - // added relative to the current view yet - padding.constant = (firstVisible && (secondVisible || hasVisibleAncestors)) ? MBDefaultPadding : 0.f; - hasVisibleAncestors |= secondVisible; - }]; -} - -- (void)applyPriority:(UILayoutPriority)priority toConstraints:(NSArray *)constraints { - for (NSLayoutConstraint *constraint in constraints) { - constraint.priority = priority; - } -} - -#pragma mark - Properties - -- (void)setMode:(MBProgressHUDMode)mode { - if (mode != _mode) { - _mode = mode; - [self updateIndicators]; - } -} - -- (void)setCustomView:(UIView *)customView { - if (customView != _customView) { - _customView = customView; - if (self.mode == MBProgressHUDModeCustomView) { - [self updateIndicators]; - } - } -} - -- (void)setOffset:(CGPoint)offset { - if (!CGPointEqualToPoint(offset, _offset)) { - _offset = offset; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setMargin:(CGFloat)margin { - if (margin != _margin) { - _margin = margin; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setMinSize:(CGSize)minSize { - if (!CGSizeEqualToSize(minSize, _minSize)) { - _minSize = minSize; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setSquare:(BOOL)square { - if (square != _square) { - _square = square; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setProgressObjectDisplayLink:(CADisplayLink *)progressObjectDisplayLink { - if (progressObjectDisplayLink != _progressObjectDisplayLink) { - [_progressObjectDisplayLink invalidate]; - - _progressObjectDisplayLink = progressObjectDisplayLink; - - [_progressObjectDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; - } -} - -- (void)setProgressObject:(NSProgress *)progressObject { - if (progressObject != _progressObject) { - _progressObject = progressObject; - [self setNSProgressDisplayLinkEnabled:YES]; - } -} - -- (void)setProgress:(float)progress { - if (progress != _progress) { - _progress = progress; - UIView *indicator = self.indicator; - if ([indicator respondsToSelector:@selector(setProgress:)]) { - [(id)indicator setValue:@(self.progress) forKey:@"progress"]; - } - } -} - -- (void)setContentColor:(UIColor *)contentColor { - if (contentColor != _contentColor && ![contentColor isEqual:_contentColor]) { - _contentColor = contentColor; - [self updateViewsForColor:contentColor]; - } -} - -- (void)setDefaultMotionEffectsEnabled:(BOOL)defaultMotionEffectsEnabled { - if (defaultMotionEffectsEnabled != _defaultMotionEffectsEnabled) { - _defaultMotionEffectsEnabled = defaultMotionEffectsEnabled; - [self updateBezelMotionEffects]; - } -} - -#pragma mark - NSProgress - -- (void)setNSProgressDisplayLinkEnabled:(BOOL)enabled { - // We're using CADisplayLink, because NSProgress can change very quickly and observing it may starve the main thread, - // so we're refreshing the progress only every frame draw - if (enabled && self.progressObject) { - // Only create if not already active. - if (!self.progressObjectDisplayLink) { - self.progressObjectDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgressFromProgressObject)]; - } - } else { - self.progressObjectDisplayLink = nil; - } -} - -- (void)updateProgressFromProgressObject { - self.progress = self.progressObject.fractionCompleted; -} - -#pragma mark - Notifications - -- (void)registerForNotifications { -#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - - [nc addObserver:self selector:@selector(statusBarOrientationDidChange:) - name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; -#endif -} - -- (void)unregisterFromNotifications { -#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; -#endif -} - -#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST -- (void)statusBarOrientationDidChange:(NSNotification *)notification { - UIView *superview = self.superview; - if (!superview) { - return; - } else { - [self updateForCurrentOrientationAnimated:YES]; - } -} -#endif - -- (void)updateForCurrentOrientationAnimated:(BOOL)animated { - // Stay in sync with the superview in any case - if (self.superview) { - self.frame = self.superview.bounds; - } - - // Not needed on iOS 8+, compile out when the deployment target allows, - // to avoid sharedApplication problems on extension targets -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 - // Only needed pre iOS 8 when added to a window - BOOL iOS8OrLater = kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0; - if (iOS8OrLater || ![self.superview isKindOfClass:[UIWindow class]]) return; - - // Make extension friendly. Will not get called on extensions (iOS 8+) due to the above check. - // This just ensures we don't get a warning about extension-unsafe API. - Class UIApplicationClass = NSClassFromString(@"UIApplication"); - if (!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) return; - - UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; - UIInterfaceOrientation orientation = application.statusBarOrientation; - CGFloat radians = 0; - - if (UIInterfaceOrientationIsLandscape(orientation)) { - radians = orientation == UIInterfaceOrientationLandscapeLeft ? -(CGFloat)M_PI_2 : (CGFloat)M_PI_2; - // Window coordinates differ! - self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); - } else { - radians = orientation == UIInterfaceOrientationPortraitUpsideDown ? (CGFloat)M_PI : 0.f; - } - - if (animated) { - [UIView animateWithDuration:0.3 animations:^{ - self.transform = CGAffineTransformMakeRotation(radians); - }]; - } else { - self.transform = CGAffineTransformMakeRotation(radians); - } -#endif -} - -- (id)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - id hitView = [super hitTest:point withEvent:event]; - if (hitView != self && ![hitView isKindOfClass:[MBBackgroundView class]]) { - return hitView; - } - return nil; -} - -@end - - -@implementation MBRoundProgressView - -#pragma mark - Lifecycle - -- (id)init { - return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; -} - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.backgroundColor = [UIColor clearColor]; - self.opaque = NO; - _progress = 0.f; - _annular = NO; - _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; - _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; - } - return self; -} - -#pragma mark - Layout - -- (CGSize)intrinsicContentSize { - return CGSizeMake(37.f, 37.f); -} - -#pragma mark - Properties - -- (void)setProgress:(float)progress { - if (progress != _progress) { - _progress = progress; - [self setNeedsDisplay]; - } -} - -- (void)setProgressTintColor:(UIColor *)progressTintColor { - NSAssert(progressTintColor, @"The color should not be nil."); - if (progressTintColor != _progressTintColor && ![progressTintColor isEqual:_progressTintColor]) { - _progressTintColor = progressTintColor; - [self setNeedsDisplay]; - } -} - -- (void)setBackgroundTintColor:(UIColor *)backgroundTintColor { - NSAssert(backgroundTintColor, @"The color should not be nil."); - if (backgroundTintColor != _backgroundTintColor && ![backgroundTintColor isEqual:_backgroundTintColor]) { - _backgroundTintColor = backgroundTintColor; - [self setNeedsDisplay]; - } -} - -#pragma mark - Drawing - -- (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); - - if (_annular) { - // Draw background - CGFloat lineWidth = 2.f; - UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; - processBackgroundPath.lineWidth = lineWidth; - processBackgroundPath.lineCapStyle = kCGLineCapButt; - CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); - CGFloat radius = (self.bounds.size.width - lineWidth)/2; - CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees - CGFloat endAngle = (2 * (float)M_PI) + startAngle; - [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - [_backgroundTintColor set]; - [processBackgroundPath stroke]; - // Draw progress - UIBezierPath *processPath = [UIBezierPath bezierPath]; - processPath.lineCapStyle = kCGLineCapSquare; - processPath.lineWidth = lineWidth; - endAngle = (self.progress * 2 * (float)M_PI) + startAngle; - [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - [_progressTintColor set]; - [processPath stroke]; - } else { - // Draw background - CGFloat lineWidth = 2.f; - CGRect allRect = self.bounds; - CGRect circleRect = CGRectInset(allRect, lineWidth/2.f, lineWidth/2.f); - CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); - [_progressTintColor setStroke]; - [_backgroundTintColor setFill]; - CGContextSetLineWidth(context, lineWidth); - CGContextStrokeEllipseInRect(context, circleRect); - // 90 degrees - CGFloat startAngle = - ((float)M_PI / 2.f); - // Draw progress - UIBezierPath *processPath = [UIBezierPath bezierPath]; - processPath.lineCapStyle = kCGLineCapButt; - processPath.lineWidth = lineWidth * 2.f; - CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - (processPath.lineWidth / 2.f); - CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; - [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - // Ensure that we don't get color overlapping when _progressTintColor alpha < 1.f. - CGContextSetBlendMode(context, kCGBlendModeCopy); - [_progressTintColor set]; - [processPath stroke]; - } -} - -@end - - -@implementation MBBarProgressView - -#pragma mark - Lifecycle - -- (id)init { - return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; -} - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _progress = 0.f; - _lineColor = [UIColor whiteColor]; - _progressColor = [UIColor whiteColor]; - _progressRemainingColor = [UIColor clearColor]; - self.backgroundColor = [UIColor clearColor]; - self.opaque = NO; - } - return self; -} - -#pragma mark - Layout - -- (CGSize)intrinsicContentSize { - return CGSizeMake(120.f, 10.f); -} - -#pragma mark - Properties - -- (void)setProgress:(float)progress { - if (progress != _progress) { - _progress = progress; - [self setNeedsDisplay]; - } -} - -- (void)setProgressColor:(UIColor *)progressColor { - NSAssert(progressColor, @"The color should not be nil."); - if (progressColor != _progressColor && ![progressColor isEqual:_progressColor]) { - _progressColor = progressColor; - [self setNeedsDisplay]; - } -} - -- (void)setProgressRemainingColor:(UIColor *)progressRemainingColor { - NSAssert(progressRemainingColor, @"The color should not be nil."); - if (progressRemainingColor != _progressRemainingColor && ![progressRemainingColor isEqual:_progressRemainingColor]) { - _progressRemainingColor = progressRemainingColor; - [self setNeedsDisplay]; - } -} - -#pragma mark - Drawing - -- (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSetLineWidth(context, 2); - CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); - CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); - - // Draw background and Border - CGFloat radius = (rect.size.height / 2) - 2; - CGContextMoveToPoint(context, 2, rect.size.height/2); - CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); - CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); - CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); - CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); - CGContextDrawPath(context, kCGPathFillStroke); - - CGContextSetFillColorWithColor(context, [_progressColor CGColor]); - radius = radius - 2; - CGFloat amount = self.progress * rect.size.width; - - // Progress in the middle area - if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, amount, 4); - CGContextAddLineToPoint(context, amount, radius + 4); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, amount, rect.size.height - 4); - CGContextAddLineToPoint(context, amount, radius + 4); - - CGContextFillPath(context); - } - - // Progress in the right arc - else if (amount > radius + 4) { - CGFloat x = amount - (rect.size.width - radius - 4); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); - CGFloat angle = -acos(x/radius); - if (isnan(angle)) angle = 0; - CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); - CGContextAddLineToPoint(context, amount, rect.size.height/2); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); - angle = acos(x/radius); - if (isnan(angle)) angle = 0; - CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); - CGContextAddLineToPoint(context, amount, rect.size.height/2); - - CGContextFillPath(context); - } - - // Progress is in the left arc - else if (amount < radius + 4 && amount > 0) { - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); - - CGContextFillPath(context); - } -} - -@end - - -@interface MBBackgroundView () - -@property UIVisualEffectView *effectView; - -@end - - -@implementation MBBackgroundView - -#pragma mark - Lifecycle - -- (instancetype)initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame])) { - _style = MBProgressHUDBackgroundStyleBlur; - if (@available(iOS 13.0, *)) { - #if TARGET_OS_TV - _blurEffectStyle = UIBlurEffectStyleRegular; - #else - _blurEffectStyle = UIBlurEffectStyleSystemThickMaterial; - #endif - // Leaving the color unassigned yields best results. - } else { - _blurEffectStyle = UIBlurEffectStyleLight; - _color = [UIColor colorWithWhite:0.8f alpha:0.6f]; - } - - self.clipsToBounds = YES; - - [self updateForBackgroundStyle]; - } - return self; -} - -#pragma mark - Layout - -- (CGSize)intrinsicContentSize { - // Smallest size possible. Content pushes against this. - return CGSizeZero; -} - -#pragma mark - Appearance - -- (void)setStyle:(MBProgressHUDBackgroundStyle)style { - if (_style != style) { - _style = style; - [self updateForBackgroundStyle]; - } -} - -- (void)setColor:(UIColor *)color { - NSAssert(color, @"The color should not be nil."); - if (color != _color && ![color isEqual:_color]) { - _color = color; - [self updateViewsForColor:color]; - } -} - -- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle { - if (_blurEffectStyle == blurEffectStyle) { - return; - } - - _blurEffectStyle = blurEffectStyle; - - [self updateForBackgroundStyle]; -} - -/////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - Views - -- (void)updateForBackgroundStyle { - [self.effectView removeFromSuperview]; - self.effectView = nil; - - MBProgressHUDBackgroundStyle style = self.style; - if (style == MBProgressHUDBackgroundStyleBlur) { - UIBlurEffect *effect = [UIBlurEffect effectWithStyle:self.blurEffectStyle]; - UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; - [self insertSubview:effectView atIndex:0]; - effectView.frame = self.bounds; - effectView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - self.backgroundColor = self.color; - self.layer.allowsGroupOpacity = NO; - self.effectView = effectView; - } else { - self.backgroundColor = self.color; - } -} - -- (void)updateViewsForColor:(UIColor *)color { - if (self.style == MBProgressHUDBackgroundStyleBlur) { - self.backgroundColor = self.color; - } else { - self.backgroundColor = self.color; - } -} - -@end - - -@implementation MBProgressHUDRoundedButton - -#pragma mark - Lifecycle - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - CALayer *layer = self.layer; - layer.borderWidth = 1.f; - } - return self; -} - -#pragma mark - Layout - -- (void)layoutSubviews { - [super layoutSubviews]; - // Fully rounded corners - CGFloat height = CGRectGetHeight(self.bounds); - self.layer.cornerRadius = ceil(height / 2.f); -} - -- (CGSize)intrinsicContentSize { - // Only show if we have associated control events and a title - if ((self.allControlEvents == 0) || ([self titleForState:UIControlStateNormal].length == 0)) - return CGSizeZero; - CGSize size = [super intrinsicContentSize]; - // Add some side padding - size.width += 20.f; - return size; -} - -#pragma mark - Color - -- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state { - [super setTitleColor:color forState:state]; - // Update related colors - [self setHighlighted:self.highlighted]; - self.layer.borderColor = color.CGColor; -} - -- (void)setHighlighted:(BOOL)highlighted { - [super setHighlighted:highlighted]; - UIColor *baseColor = [self titleColorForState:UIControlStateSelected]; - self.backgroundColor = highlighted ? [baseColor colorWithAlphaComponent:0.1f] : [UIColor clearColor]; -} - -@end diff --git a/Tweaks/iSponsorBlock/Makefile b/Tweaks/iSponsorBlock/Makefile deleted file mode 100644 index f258700..0000000 --- a/Tweaks/iSponsorBlock/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -ifeq ($(ROOTLESS),1) -THEOS_PACKAGE_SCHEME=rootless -endif - -export ARCHS = arm64 -TARGET := iphone:clang:latest:13.0 -INSTALL_TARGET_PROCESSES = YouTube - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = iSponsorBlock - -iSponsorBlock_FILES = iSponsorBlock.xm $(wildcard *.m) -iSponsorBlock_LIBRARIES = colorpicker -iSponsorBlock_CFLAGS = -fobjc-arc -Wno-deprecated-declarations - -include $(THEOS_MAKE_PATH)/tweak.mk diff --git a/Tweaks/iSponsorBlock/README.md b/Tweaks/iSponsorBlock/README.md deleted file mode 100644 index bece52b..0000000 --- a/Tweaks/iSponsorBlock/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# iSponsorBlock -A jailbreak tweak that implements the SponsorBlock API to skip sponsorships in youtube vidoes. - -More info about SponsorBlock and the API used can be found [here](https://sponsor.ajay.app). - -This tweak has been tested on the latest YouTube version (18.20.3) and supports, at least, down to version 17.30.1. - -# Installation - -Add the following repository: https://repo.icrazeios.com - -# Customization -To access this tweaks settings open the YouTube app, and there should be a button in the top right, like in this image: https://imgur.com/lLpfXue. diff --git a/Tweaks/iSponsorBlock/SponsorBlockRequest.m b/Tweaks/iSponsorBlock/SponsorBlockRequest.m deleted file mode 100644 index 221e2b6..0000000 --- a/Tweaks/iSponsorBlock/SponsorBlockRequest.m +++ /dev/null @@ -1,156 +0,0 @@ -#import "Headers/SponsorBlockRequest.h" -#import "Headers/Localization.h" - -@implementation SponsorBlockRequest -+ (void)getSponsorTimes:(NSString *)videoID completionTarget:(id)target completionSelector:(SEL)sel apiInstance:(NSString *)apiInstance { - __block NSMutableArray *skipSegments = [NSMutableArray array]; - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - NSString *categories = @"[%22sponsor%22,%20%22intro%22,%20%22outro%22,%20%22interaction%22,%20%22selfpromo%22,%20%22music_offtopic%22]"; - //NSString *categories = @"[%22sponsor%22,%20%22intro%22,%20%22outro%22,%20%22interaction%22,%20%22selfpromo%22,%20%22music_offtopic%22,%20%22preview%22,%20%22filler%22]"; - - [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/skipSegments?videoID=%@&categories=%@", apiInstance, videoID, categories]]]; - request.HTTPMethod = @"GET"; - NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if (data != nil && error == nil) { - NSArray *jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; - NSMutableArray *segments = [NSMutableArray array]; - for (NSDictionary *dict in jsonData) { - SponsorSegment *segment = [[SponsorSegment alloc] initWithStartTime:[[dict objectForKey:@"segment"][0] floatValue] endTime:[[dict objectForKey:@"segment"][1] floatValue] category:(NSString *)[dict objectForKey:@"category"] UUID:(NSString *)[dict objectForKey:@"UUID"]]; - [segments addObject:segment]; - } - skipSegments = [segments sortedArrayUsingComparator:^NSComparisonResult(SponsorSegment *a, SponsorSegment *b) { - NSNumber *first = @(a.startTime); - NSNumber *second = @(b.startTime); - return [first compare:second]; - }].mutableCopy; - NSMutableArray *seekBarSegments = skipSegments.mutableCopy; - for (SponsorSegment *segment in skipSegments.copy) { - NSInteger setting = [[kCategorySettings objectForKey:segment.category] intValue]; - switch (setting) { - case 0: - [skipSegments removeObject:segment]; - [seekBarSegments removeObject:segment]; - break; - case 2: - [skipSegments removeObject:segment]; - break; - //only leaves the object in seekBarSegments so it appears in the seek bar but doesn't get skipped - default: - break; - } - if (segment.endTime - segment.startTime < kMinimumDuration) { - [skipSegments removeObject:segment]; - [seekBarSegments removeObject:segment]; - } - - } - [target performSelectorOnMainThread:sel withObject:skipSegments waitUntilDone:NO]; - - if ([target isKindOfClass:objc_getClass("YTPlayerViewController")]) { - YTPlayerViewController *playerViewController = (YTPlayerViewController *)target; - YTPlayerView *playerView = (YTPlayerView *)playerViewController.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if ([overlayView isKindOfClass:objc_getClass("YTMainAppVideoPlayerOverlayView")]) { - if (overlayView.playerBar.playerBar) { - [overlayView.playerBar.playerBar performSelectorOnMainThread:@selector(setSkipSegments:) withObject:seekBarSegments waitUntilDone:NO]; - } - else { - [overlayView.playerBar.segmentablePlayerBar performSelectorOnMainThread:@selector(setSkipSegments:) withObject:seekBarSegments waitUntilDone:NO]; - } - } - } - } - }]; - [dataTask resume]; -} -+ (void)postSponsorTimes:(NSString *)videoID sponsorSegments:(NSArray *)segments userID:(NSString *)userID withViewController:(UIViewController *)viewController { - for (SponsorSegment *segment in segments) { - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://sponsor.ajay.app/api/skipSegments?videoID=%@&startTime=%f&endTime=%f&category=%@&userID=%@", videoID, segment.startTime, segment.endTime, segment.category, userID]]]; - request.HTTPMethod = @"POST"; - NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - NSHTTPURLResponse *URLResponse = (NSHTTPURLResponse *)response; - if (URLResponse.statusCode != 200) { - dispatch_async(dispatch_get_main_queue(), ^{ - UIAlertController *alert = [UIAlertController alertControllerWithTitle:LOC(@"Error") message:[NSString stringWithFormat:@"%@: %ld %@", LOC(@"ErrorCode"), URLResponse.statusCode, [NSHTTPURLResponse localizedStringForStatusCode:URLResponse.statusCode]] preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:LOC(@"OK") style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) {}]; - [alert addAction:defaultAction]; - [viewController presentViewController:alert animated:YES completion:nil]; - }); - return; - } - else { - dispatch_async(dispatch_get_main_queue(), ^{ - UIAlertController *alert = [UIAlertController alertControllerWithTitle:LOC(@"Success") message:LOC(@"SuccessfullySubmittedSegments") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:LOC(@"OK") style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) {}]; - [alert addAction:defaultAction]; - [viewController presentViewController:alert animated:YES completion:nil]; - }); - } - }]; - [dataTask resume]; - } -} -+ (void)normalVoteForSegment:(SponsorSegment *)segment userID:(NSString *)userID type:(BOOL)type withViewController:(UIViewController *)viewController { - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://sponsor.ajay.app/api/voteOnSponsorTime?UUID=%@&userID=%@&type=%d", segment.UUID, userID, type]]]; - request.HTTPMethod = @"POST"; - NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - NSHTTPURLResponse *URLResponse = (NSHTTPURLResponse *)response; - NSString *title; - CGFloat delay; - if (URLResponse.statusCode != 200) { - title = [NSString stringWithFormat:@"%@: (%ld %@)", LOC(@"ErrorVoting"), URLResponse.statusCode, [NSHTTPURLResponse localizedStringForStatusCode:URLResponse.statusCode]]; - delay = 3.0f; - } - else { - title = LOC(@"SuccessfullyVoted"); - delay = 1.0f; - } - dispatch_async(dispatch_get_main_queue(), ^{ - MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:viewController.view animated:YES]; - hud.mode = MBProgressHUDModeText; - hud.label.text = title; - hud.offset = CGPointMake(0.f, 50); - [hud hideAnimated:YES afterDelay:delay]; - }); - }]; - [dataTask resume]; -} -+ (void)categoryVoteForSegment:(SponsorSegment *)segment userID:(NSString *)userID category:(NSString *)category withViewController:(UIViewController *)viewController { - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://sponsor.ajay.app/api/voteOnSponsorTime?UUID=%@&userID=%@&category=%@", segment.UUID, userID, category]]]; - request.HTTPMethod = @"POST"; - NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - NSHTTPURLResponse *URLResponse = (NSHTTPURLResponse *)response; - NSString *title; - CGFloat delay; - if (URLResponse.statusCode != 200) { - title = [NSString stringWithFormat:@"%@: (%ld %@)", LOC(@"ErrorVoting"), URLResponse.statusCode, [NSHTTPURLResponse localizedStringForStatusCode:URLResponse.statusCode]]; - delay = 3.0f; - } - else { - title = LOC(@"SuccessfullyVoted"); - delay = 1.0f; - } - dispatch_async(dispatch_get_main_queue(), ^{ - MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:viewController.view animated:YES]; - hud.mode = MBProgressHUDModeText; - hud.label.text = title; - hud.offset = CGPointMake(0.f, 50); - [hud hideAnimated:YES afterDelay:delay]; - }); - }]; - [dataTask resume]; -} -+ (void)viewedVideoSponsorTime:(SponsorSegment *)segment { - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; - [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://sponsor.ajay.app/api/viewedVideoSponsorTime?UUID=%@", segment.UUID]]]; - request.HTTPMethod = @"POST"; - NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - }]; - [dataTask resume]; -} -@end diff --git a/Tweaks/iSponsorBlock/SponsorBlockSettingsController.m b/Tweaks/iSponsorBlock/SponsorBlockSettingsController.m deleted file mode 100644 index ed06eca..0000000 --- a/Tweaks/iSponsorBlock/SponsorBlockSettingsController.m +++ /dev/null @@ -1,367 +0,0 @@ -#import "Headers/SponsorBlockSettingsController.h" -#import "Headers/Localization.h" - -@implementation SponsorBlockTableCell -- (void)colorPicker:(id)colorPicker didSelectColor:(UIColor *)color { - self.colorWell.color = color; - NSString *hexString = hexFromUIColor(color); - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *settingsPath = [documentsDirectory stringByAppendingPathComponent:@"iSponsorBlock.plist"]; - NSMutableDictionary *settings = [NSMutableDictionary dictionary]; - [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:settingsPath]]; - NSDictionary *categorySettings = [settings objectForKey:@"categorySettings"]; - - [categorySettings setValue:hexString forKey:[NSString stringWithFormat:@"%@Color", self.category]]; - [settings setValue:categorySettings forKey:@"categorySettings"]; - [settings writeToURL:[NSURL fileURLWithPath:settingsPath isDirectory:NO] error:nil]; - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.galacticdev.isponsorblockprefs.changed"), NULL, NULL, YES); -} - -- (void)presentColorPicker:(UITableViewCell *)sender { - HBColorPickerViewController *viewController = [[objc_getClass("HBColorPickerViewController") alloc] init]; - viewController.delegate = self; - viewController.popoverPresentationController.sourceView = self; - - HBColorPickerConfiguration *configuration = [[objc_getClass("HBColorPickerConfiguration") alloc] initWithColor:self.colorWell.color]; - configuration.supportsAlpha = NO; - viewController.configuration = configuration; - - UIViewController *rootViewController = self._viewControllerForAncestor; - [rootViewController presentViewController:viewController animated:YES completion:nil]; - - //fixes the bottom of the color picker from getting cut off - viewController.view.frame = CGRectMake(0,-50, viewController.view.frame.size.width, viewController.view.frame.size.height); -} -@end - -@implementation SponsorBlockSettingsController -- (void)viewDidLoad { - [super viewDidLoad]; - - UIBarButtonItem *dismissButton; - - dismissButton = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"xmark"] - style:UIBarButtonItemStylePlain - target:self - action:@selector(dismissButtonTapped:)]; - - dismissButton.tintColor = [UIColor blackColor]; - self.navigationItem.leftBarButtonItem = dismissButton; - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - self.settingsPath = [documentsDirectory stringByAppendingPathComponent:@"iSponsorBlock.plist"]; - self.settings = [NSMutableDictionary dictionary]; - [self.settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:self.settingsPath]]; - - self.view.backgroundColor = UIColor.systemBackgroundColor; - - //detects if device is an se gen 1 or not, crude fix for text getting cut off - if ([UIScreen mainScreen].bounds.size.width > 320) { - self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleInsetGrouped]; - } - else { - self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped]; - } - - [self.view addSubview:self.tableView]; - self.tableView.translatesAutoresizingMaskIntoConstraints = NO; - [self.tableView.heightAnchor constraintEqualToAnchor:self.view.heightAnchor].active = YES; - [self.tableView.widthAnchor constraintEqualToAnchor:self.view.widthAnchor].active = YES; - self.tableView.delegate = self; - self.tableView.dataSource = self; - - NSBundle *tweakBundle = iSponsorBlockBundle(); - UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[tweakBundle pathForResource:@"LogoSponsorBlocker128px" ofType:@"png"]]]; - UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,0,0)]; - label.text = @"iSponsorBlock"; - label.font = [UIFont boldSystemFontOfSize:48]; - self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0,0,0,200)]; - [self.tableView.tableHeaderView addSubview:imageView]; - [self.tableView.tableHeaderView addSubview:label]; - - self.tweakTitle = label.text; - - imageView.translatesAutoresizingMaskIntoConstraints = NO; - label.translatesAutoresizingMaskIntoConstraints = NO; - [imageView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES; - [imageView.topAnchor constraintEqualToAnchor:self.tableView.tableHeaderView.topAnchor constant:5].active = YES; - [label.centerXAnchor constraintEqualToAnchor:imageView.centerXAnchor].active = YES; - [label.topAnchor constraintEqualToAnchor:imageView.bottomAnchor constant:5].active = YES; - - //for dismissing num pad when tapping anywhere on the string - UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)]; - tap.cancelsTouchesInView = NO; - [self.view addGestureRecognizer:tap]; - - self.sectionTitles = @[LOC(@"Sponsor"), LOC(@"Intermission/IntroAnimation"), LOC(@"Endcards/Credits"), LOC(@"InteractionReminder"), LOC(@"Unpaid/SelfPromotion"), LOC(@"Non-MusicSection"), LOC(@"SponsorBlockUserID"), LOC(@"SponsorBlockAPIInstance")]; -} - -//Add iSponsorBlock text to Navbar label if header text out of screen -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - CGRect labelCellRect = [self.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; - CGRect visibleRect = CGRectMake(self.tableView.contentOffset.x, - self.tableView.contentOffset.y + self.navigationController.navigationBar.frame.size.height, - self.tableView.bounds.size.width, - self.tableView.bounds.size.height - self.navigationController.navigationBar.frame.size.height); - - if (!CGRectContainsRect(visibleRect, labelCellRect)) { - self.title = self.tweakTitle; - [UIView animateWithDuration:0.3 animations:^{ - self.navigationItem.titleView.alpha = 1.0; - }]; - } else { - self.title = nil; - [UIView animateWithDuration:0.3 animations:^{ - self.navigationItem.titleView.alpha = 0.0; - }]; - } -} - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 18; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (section == 0) return 1; - else if (section <= 6 || section == 17) return 2; - return 1; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SponsorBlockCell"]; - if (!cell) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SponsorBlocKCell"]; - } - - if (indexPath.section == 0) { - cell.textLabel.text = LOC(@"Enabled"); - UISwitch *enabledSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,51,31)]; - cell.accessoryView = enabledSwitch; - [enabledSwitch addTarget:self action:@selector(enabledSwitchToggled:) forControlEvents:UIControlEventValueChanged]; - if ([self.settings valueForKey:@"enabled"]) { - [enabledSwitch setOn:[[self.settings valueForKey:@"enabled"] boolValue] animated:NO]; - } - else { - [enabledSwitch setOn:YES animated:NO]; - [self enabledSwitchToggled:enabledSwitch]; - } - return cell; - } - - if (indexPath.section <= 6) { - SponsorBlockTableCell *tableCell = [[SponsorBlockTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SponsorBlockCell2"]; - NSDictionary *categorySettings = [self.settings objectForKey:@"categorySettings"]; - UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[LOC(@"Disable"), LOC(@"AutoSkip"), LOC(@"ShowInSeekBar"), LOC(@"ManualSkip")]]; - - //make it so "Show in Seek Bar" text won't be cut off on certain devices - NSMutableArray *segments = [segmentedControl valueForKey:@"_segments"]; - UISegment *segment = segments[2]; - UILabel *label = [segment valueForKey:@"_info"]; - label.adjustsFontSizeToFitWidth = YES; - - switch (indexPath.section) { - case 1: - segmentedControl.selectedSegmentIndex = [[categorySettings objectForKey:@"sponsor"] intValue]; - tableCell.category = @"sponsor"; - break; - case 2: - segmentedControl.selectedSegmentIndex = [[categorySettings objectForKey:@"intro"] intValue]; - tableCell.category = @"intro"; - break; - case 3: - segmentedControl.selectedSegmentIndex = [[categorySettings objectForKey:@"outro"] intValue]; - tableCell.category = @"outro"; - break; - case 4: - segmentedControl.selectedSegmentIndex = [[categorySettings objectForKey:@"interaction"] intValue]; - tableCell.category = @"interaction"; - break; - case 5: - segmentedControl.selectedSegmentIndex = [[categorySettings objectForKey:@"selfpromo"] intValue]; - tableCell.category = @"selfpromo"; - break; - case 6: - segmentedControl.selectedSegmentIndex = [[categorySettings objectForKey:@"music_offtopic"] intValue]; - tableCell.category = @"music_offtopic"; - break; - - default: - break; - } - if (indexPath.row == 0) { - [segmentedControl addTarget:self action:@selector(categorySegmentSelected:) forControlEvents:UIControlEventValueChanged]; - segmentedControl.apportionsSegmentWidthsByContent = YES; - [tableCell.contentView addSubview:segmentedControl]; - segmentedControl.translatesAutoresizingMaskIntoConstraints = NO; - [segmentedControl.centerYAnchor constraintEqualToAnchor:tableCell.contentView.centerYAnchor].active = YES; - [segmentedControl.widthAnchor constraintEqualToAnchor:tableCell.contentView.widthAnchor].active = YES; - } - else { - tableCell.textLabel.text = LOC(@"SetColorToShowInSeekBar"); - tableCell.textLabel.adjustsFontSizeToFitWidth = YES; - HBColorWell *colorWell = [[objc_getClass("HBColorWell") alloc] initWithFrame:CGRectMake(0,0,32,32)]; - [colorWell addTarget:tableCell action:@selector(presentColorPicker:) forControlEvents:UIControlEventTouchUpInside]; - [colorWell addTarget:tableCell action:@selector(colorWellValueChanged:) forControlEvents:UIControlEventValueChanged]; - UIColor *color = colorWithHexString([categorySettings objectForKey:[NSString stringWithFormat:@"%@Color", tableCell.category]]); - colorWell.color = color; - tableCell.accessoryView = colorWell; - tableCell.colorWell = colorWell; - } - return tableCell; - } - if (indexPath.section == 7) { - UITableViewCell *textCell = [[UITableViewCell alloc] initWithStyle:1000 reuseIdentifier:@"SponsorBlockTextCell"]; - textCell.textLabel.text = LOC(@"UserID"); - textCell.textLabel.adjustsFontSizeToFitWidth = YES; - [textCell editableTextField].text = [self.settings valueForKey:@"userID"]; - [textCell editableTextField].delegate = self; - return textCell; - } - if (indexPath.section == 8) { - UITableViewCell *textCell = [[UITableViewCell alloc] initWithStyle:1000 reuseIdentifier:@"SponsorBlockTextCell"]; - textCell.textLabel.text = LOC(@"API_URL"); - textCell.textLabel.adjustsFontSizeToFitWidth = YES; - [textCell editableTextField].text = [self.settings valueForKey:@"apiInstance"]; - [textCell editableTextField].delegate = self; - return textCell; - } - if (indexPath.section == 9) { - UITableViewCell *textCell = [[UITableViewCell alloc] initWithStyle:1000 reuseIdentifier:@"SponsorBlockTextCell"]; - textCell.textLabel.text = LOC(@"MinimumSegmentDuration"); - textCell.textLabel.adjustsFontSizeToFitWidth = YES; - [textCell editableTextField].text = [NSString stringWithFormat:@"%.1f", [[self.settings valueForKey:@"minimumDuration"] floatValue]]; - [textCell editableTextField].keyboardType = UIKeyboardTypeDecimalPad; - [textCell editableTextField].delegate = self; - return textCell; - } - if (indexPath.section == 10) { - UITableViewCell *textCell = [[UITableViewCell alloc] initWithStyle:1000 reuseIdentifier:@"SponsorBlockTextCell"]; - textCell.textLabel.text = LOC(@"HowLongNoticeWillAppear"); - textCell.textLabel.adjustsFontSizeToFitWidth = YES; - [textCell editableTextField].text = [NSString stringWithFormat:@"%.1f", [[self.settings valueForKey:@"skipNoticeDuration"] floatValue]]; - [textCell editableTextField].keyboardType = UIKeyboardTypeDecimalPad; - [textCell editableTextField].delegate = self; - return textCell; - } - if (indexPath.section >= 11 && indexPath.section < 17) { - NSArray *titles = @[LOC(@"ShowSkipNotice"), LOC(@"ShowButtonsInPlayer"), LOC(@"HideStartEndButtonInPlayer"), LOC(@"ShowModifiedTime"), LOC(@"AudioNotificationOnSkip"), LOC(@"EnableSkipCountTracking")]; - NSArray *titlesNames = @[@"showSkipNotice", @"showButtonsInPlayer", @"hideStartEndButtonInPlayer", @"showModifiedTime", @"skipAudioNotification", @"enableSkipCountTracking"]; - UITableViewCell *tableCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SponsorBlockCell3"]; - - tableCell.textLabel.text = titles[indexPath.section-11]; - tableCell.textLabel.adjustsFontSizeToFitWidth = YES; - - UISwitch *toggleSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,51,31)]; - tableCell.accessoryView = toggleSwitch; - [toggleSwitch addTarget:self action:@selector(switchToggled:) forControlEvents:UIControlEventValueChanged]; - if ([self.settings valueForKey:titlesNames[indexPath.section-11]]) { - [toggleSwitch setOn:[[self.settings valueForKey:titlesNames[indexPath.section-11]] boolValue] animated:NO]; - } else { - [toggleSwitch setOn:YES animated:NO]; - [self switchToggled:toggleSwitch]; - } - return tableCell; - } - if (indexPath.section == 17) { - UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SponsorBlockDonationCell"]; - cell.textLabel.text = indexPath.row == 0 ? LOC(@"DonateOnVenmo") : LOC(@"DonateOnPayPal"); - cell.imageView.image = [UIImage systemImageNamed:@"dollarsign.circle.fill"]; - return cell; - } - return nil; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (section == 0) return nil; - if (section <= 8) return self.sectionTitles[section-1]; - return nil; -} - -- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { - if (section == 0) return LOC(@"RestartFooter"); - if (section == 7) return LOC(@"UserIDFooter"); - if (section == 8) return LOC(@"APIFooter"); - if (section == 15) return LOC(@"AudioFooter"); - return nil; -} - -//To allow highlights only for certain sections -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == 17) { - return YES; - } else { - return NO; - } -} - -- (void)dismissButtonTapped:(id)sender { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == 17) { - if (indexPath.row == 0) { - if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"venmo://"]]) { - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"venmo://venmo.com/code?user_id=3178620965093376215"] options:@{} completionHandler:nil]; - } else { - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://venmo.com/code?user_id=3178620965093376215"] options:@{} completionHandler:nil]; - } - - } else { - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://paypal.me/DBrett684"] options:@{} completionHandler:nil]; - } - } - [tableView deselectRowAtIndexPath:indexPath animated:YES]; //To prevent highlight sticking after pressing on buttons -} - -- (void)enabledSwitchToggled:(UISwitch *)sender { - [self.settings setValue:@(sender.on) forKey:@"enabled"]; - [self writeSettings]; -} - -- (void)switchToggled:(UISwitch *)sender { - UITableViewCell *cell = (UITableViewCell *)sender.superview; - NSArray *titlesNames = @[@"showSkipNotice", @"showButtonsInPlayer", @"hideStartEndButtonInPlayer", @"showModifiedTime", @"skipAudioNotification", @"enableSkipCountTracking"]; - NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; - [self.settings setValue:@(sender.on) forKey:titlesNames[indexPath.section-11]]; - [self writeSettings]; -} - -- (void)categorySegmentSelected:(UISegmentedControl *)segmentedControl { - NSMutableDictionary *categorySettings = [self.settings valueForKey:@"categorySettings"]; - [categorySettings setValue:@(segmentedControl.selectedSegmentIndex) forKey:[(SponsorBlockTableCell *)segmentedControl.superview.superview category]]; - - [self.settings setValue:categorySettings forKey:@"categorySettings"]; - [self writeSettings]; -} - -- (void)textFieldDidEndEditing:(UITextField *)textField { - UITableViewCell *cell = (UITableViewCell *)textField.superview.superview; - NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; - f.numberStyle = NSNumberFormatterDecimalStyle; - - NSString *minimumDurationTitle = LOC(@"MinimumSegmentDuration"); - NSString *skipNoticeDurationTitle = LOC(@"HowLongNoticeWillAppear"); - NSString *userIDTitle = LOC(@"UserID"); - NSString *apiURLTitle = LOC(@"API_URL"); - - if ([cell.textLabel.text isEqualToString:minimumDurationTitle]) { - [self.settings setValue:[f numberFromString:textField.text] forKey:@"minimumDuration"]; - } else if ([cell.textLabel.text isEqualToString:skipNoticeDurationTitle]) { - [self.settings setValue:[f numberFromString:textField.text] forKey:@"skipNoticeDuration"]; - } else if ([cell.textLabel.text isEqualToString:userIDTitle]) { - [self.settings setValue:textField.text forKey:@"userID"]; - } else if ([cell.textLabel.text isEqualToString:apiURLTitle]) { - [self.settings setValue:textField.text forKey:@"apiInstance"]; - } - [self writeSettings]; -} - -- (void)writeSettings { - [self.settings writeToURL:[NSURL fileURLWithPath:self.settingsPath isDirectory:NO] error:nil]; - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.galacticdev.isponsorblockprefs.changed"), NULL, NULL, YES); -} -@end diff --git a/Tweaks/iSponsorBlock/SponsorBlockViewController.m b/Tweaks/iSponsorBlock/SponsorBlockViewController.m deleted file mode 100644 index 1b856f0..0000000 --- a/Tweaks/iSponsorBlock/SponsorBlockViewController.m +++ /dev/null @@ -1,427 +0,0 @@ -#import "Headers/SponsorBlockViewController.h" -#import "Headers/Localization.h" - -@implementation SponsorBlockViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - self.view.backgroundColor = [UIColor systemBackgroundColor]; - [self addChildViewController:self.playerViewController]; - [self.view addSubview:self.playerViewController.view]; - [self setupViews]; -} - -- (void)setupViews { - [self.segmentsInDatabaseLabel removeFromSuperview]; - [self.userSegmentsLabel removeFromSuperview]; - [self.submitSegmentsButton removeFromSuperview]; - [self.whitelistChannelLabel removeFromSuperview]; - - self.sponsorSegmentViews = [NSMutableArray array]; - self.userSponsorSegmentViews = [NSMutableArray array]; - - if (!self.startEndSegmentButton) { - self.startEndSegmentButton = [UIButton buttonWithType:UIButtonTypeCustom]; - self.startEndSegmentButton.backgroundColor = UIColor.systemBlueColor; - [self.startEndSegmentButton addTarget:self action:@selector(startEndSegmentButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - - if (self.playerViewController.userSkipSegments.lastObject.endTime != -1) [self.startEndSegmentButton setTitle:LOC(@"SegmentStartsNow") forState:UIControlStateNormal]; - else [self.startEndSegmentButton setTitle:LOC(@"SegmentEndsNow") forState:UIControlStateNormal]; - self.startEndSegmentButton.titleLabel.adjustsFontSizeToFitWidth = YES; - - [self.playerViewController.view addSubview:self.startEndSegmentButton]; - - self.startEndSegmentButton.layer.cornerRadius = 12; - self.startEndSegmentButton.frame = CGRectMake(0,0,512,50); - self.startEndSegmentButton.translatesAutoresizingMaskIntoConstraints = NO; - - [self.startEndSegmentButton.topAnchor constraintEqualToAnchor:self.playerViewController.view.bottomAnchor constant:10].active = YES; - [self.startEndSegmentButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES; - [self.startEndSegmentButton.widthAnchor constraintEqualToConstant:self.view.frame.size.width/2].active = YES; - [self.startEndSegmentButton.heightAnchor constraintEqualToConstant:50].active = YES; - self.startEndSegmentButton.clipsToBounds = YES; - } - - self.whitelistChannelLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - self.whitelistChannelLabel.text = LOC(@"WhitelistChannel"); - [self.playerViewController.view addSubview:self.whitelistChannelLabel]; - self.whitelistChannelLabel.translatesAutoresizingMaskIntoConstraints = NO; - [self.whitelistChannelLabel.topAnchor constraintEqualToAnchor:self.startEndSegmentButton.bottomAnchor constant:10].active = YES; - [self.whitelistChannelLabel.centerXAnchor constraintEqualToAnchor:self.startEndSegmentButton.centerXAnchor].active = YES; - [self.whitelistChannelLabel.widthAnchor constraintEqualToConstant:185].active = YES; - [self.whitelistChannelLabel.heightAnchor constraintEqualToConstant:31].active = YES; - self.whitelistChannelLabel.userInteractionEnabled = YES; - - UISwitch *whitelistSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,51,31)]; - [whitelistSwitch addTarget:self action:@selector(whitelistSwitchToggled:) forControlEvents:UIControlEventValueChanged]; - [self.whitelistChannelLabel addSubview:whitelistSwitch]; - whitelistSwitch.translatesAutoresizingMaskIntoConstraints = NO; - [whitelistSwitch.leadingAnchor constraintEqualToAnchor:self.whitelistChannelLabel.trailingAnchor constant:-51].active = YES; - [whitelistSwitch.centerYAnchor constraintEqualToAnchor:self.whitelistChannelLabel.centerYAnchor].active = YES; - - if ([kWhitelistedChannels containsObject:self.playerViewController.channelID]) { - [whitelistSwitch setOn:YES animated:NO]; - } - else { - [whitelistSwitch setOn:NO animated:NO]; - } - - // I'm using the playerBar skipSegments instead of the playerViewController ones because of the show in seek bar option - YTPlayerView *playerView = (YTPlayerView *)self.playerViewController.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if ([overlayView.playerBar.playerBar skipSegments].count > 0 || overlayView.playerBar.segmentablePlayerBar.skipSegments.count > 0) { - self.segmentsInDatabaseLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - self.segmentsInDatabaseLabel.userInteractionEnabled = YES; - - self.segmentsInDatabaseLabel.text = LOC(@"SegmentsInDatabase"); - self.segmentsInDatabaseLabel.numberOfLines = 1; - self.segmentsInDatabaseLabel.adjustsFontSizeToFitWidth = YES; - self.segmentsInDatabaseLabel.textAlignment = NSTextAlignmentCenter; - - [playerView addSubview:self.segmentsInDatabaseLabel]; - self.segmentsInDatabaseLabel.translatesAutoresizingMaskIntoConstraints = NO; - - [self.segmentsInDatabaseLabel.topAnchor constraintEqualToAnchor:self.whitelistChannelLabel.bottomAnchor constant:-15].active = YES; - [self.segmentsInDatabaseLabel.centerXAnchor constraintEqualToAnchor:playerView.centerXAnchor].active = YES; - [self.segmentsInDatabaseLabel.widthAnchor constraintEqualToAnchor:playerView.widthAnchor].active = YES; - [self.segmentsInDatabaseLabel.heightAnchor constraintEqualToConstant:75.0f].active = YES; - - NSArray *segmentViewsForSegments; - if (overlayView.playerBar.playerBar) { - segmentViewsForSegments = overlayView.playerBar.playerBar.skipSegments; - } - else { - segmentViewsForSegments = overlayView.playerBar.segmentablePlayerBar.skipSegments; - } - self.sponsorSegmentViews = [self segmentViewsForSegments:segmentViewsForSegments editable:NO]; - - for (int i = 0; i < self.sponsorSegmentViews.count; i++) { - [self.segmentsInDatabaseLabel addSubview:self.sponsorSegmentViews[i]]; - [self.sponsorSegmentViews[i] addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]]; - - self.sponsorSegmentViews[i].translatesAutoresizingMaskIntoConstraints = NO; - [self.sponsorSegmentViews[i].widthAnchor constraintEqualToConstant:playerView.frame.size.width/self.sponsorSegmentViews.count-10].active = YES; - [self.sponsorSegmentViews[i].heightAnchor constraintEqualToConstant:30].active = YES; - [self.sponsorSegmentViews[i].topAnchor constraintEqualToAnchor:self.segmentsInDatabaseLabel.bottomAnchor constant:-25].active = YES; - - if (self.sponsorSegmentViews.count == 1) { - [self.sponsorSegmentViews[i].centerXAnchor constraintEqualToAnchor:self.segmentsInDatabaseLabel.centerXAnchor].active = YES; - break; - } - - if (i > 0) { - [self.sponsorSegmentViews[i].leftAnchor constraintEqualToAnchor:self.sponsorSegmentViews[i-1].rightAnchor constant:5].active = YES; - } - else { - [self.sponsorSegmentViews[i].leftAnchor constraintEqualToAnchor:self.segmentsInDatabaseLabel.leftAnchor constant:5*(self.sponsorSegmentViews.count / 2)].active = YES; - } - } - - } - - if (self.playerViewController.userSkipSegments.count > 0) { - self.userSegmentsLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - self.userSegmentsLabel.userInteractionEnabled = YES; - - self.userSegmentsLabel.text = LOC(@"YourSegments"); - - self.userSponsorSegmentViews = [self segmentViewsForSegments:self.playerViewController.userSkipSegments editable:YES]; - for (int i = 0; i < self.userSponsorSegmentViews.count; i++) { - [self.userSegmentsLabel addSubview:self.userSponsorSegmentViews[i]]; - [self.userSponsorSegmentViews[i] addInteraction:[[UIContextMenuInteraction alloc] initWithDelegate:self]]; - - self.userSponsorSegmentViews[i].translatesAutoresizingMaskIntoConstraints = NO; - [self.userSponsorSegmentViews[i].widthAnchor constraintEqualToConstant:playerView.frame.size.width/self.userSponsorSegmentViews.count-10].active = YES; - [self.userSponsorSegmentViews[i].heightAnchor constraintEqualToConstant:30].active = YES; - [self.userSponsorSegmentViews[i].topAnchor constraintEqualToAnchor:self.userSegmentsLabel.bottomAnchor constant:-25].active = YES; - - if (self.userSponsorSegmentViews.count == 1) { - [self.userSponsorSegmentViews[i].centerXAnchor constraintEqualToAnchor:self.userSegmentsLabel.centerXAnchor].active = YES; - break; - } - - if (i > 0) { - [self.userSponsorSegmentViews[i].leftAnchor constraintEqualToAnchor:self.userSponsorSegmentViews[i-1].rightAnchor constant:5].active = YES; - } - else { - [self.userSponsorSegmentViews[i].leftAnchor constraintEqualToAnchor:self.userSegmentsLabel.leftAnchor constant:5*(self.userSponsorSegmentViews.count / 2)].active = YES; - } - } - self.userSegmentsLabel.numberOfLines = 2; - self.userSegmentsLabel.adjustsFontSizeToFitWidth = YES; - self.userSegmentsLabel.textAlignment = NSTextAlignmentCenter; - - [playerView addSubview:self.userSegmentsLabel]; - self.userSegmentsLabel.translatesAutoresizingMaskIntoConstraints = NO; - - if ([overlayView.playerBar.playerBar skipSegments].count > 0 || overlayView.playerBar.segmentablePlayerBar.skipSegments.count > 0) [self.userSegmentsLabel.topAnchor constraintEqualToAnchor:self.segmentsInDatabaseLabel.bottomAnchor constant:-10].active = YES; - else [self.userSegmentsLabel.topAnchor constraintEqualToAnchor:self.whitelistChannelLabel.bottomAnchor constant:-10].active = YES; - - [self.userSegmentsLabel.centerXAnchor constraintEqualToAnchor:playerView.centerXAnchor].active = YES; - [self.userSegmentsLabel.widthAnchor constraintEqualToAnchor:playerView.widthAnchor].active = YES; - [self.userSegmentsLabel.heightAnchor constraintEqualToConstant:75.0f].active = YES; - - self.submitSegmentsButton = [UIButton buttonWithType:UIButtonTypeCustom]; - self.submitSegmentsButton.backgroundColor = UIColor.systemBlueColor; - - [self.submitSegmentsButton addTarget:self action:@selector(submitSegmentsButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - [self.submitSegmentsButton setTitle:LOC(@"SubmitSegments") forState:UIControlStateNormal]; - - [playerView addSubview:self.submitSegmentsButton]; - self.submitSegmentsButton.layer.cornerRadius = 12; - self.submitSegmentsButton.frame = CGRectMake(0,0,512,50); - - self.submitSegmentsButton.translatesAutoresizingMaskIntoConstraints = NO; - [self.submitSegmentsButton.topAnchor constraintEqualToAnchor:self.userSegmentsLabel.bottomAnchor constant:15].active = YES; - [self.submitSegmentsButton.centerXAnchor constraintEqualToAnchor:playerView.centerXAnchor].active = YES; - [self.submitSegmentsButton.widthAnchor constraintEqualToConstant:self.view.frame.size.width/2].active = YES; - [self.submitSegmentsButton.heightAnchor constraintEqualToConstant:50].active = YES; - self.submitSegmentsButton.clipsToBounds = YES; - } -} - -- (void)whitelistSwitchToggled:(UISwitch *)sender { - if (sender.isOn) { - [kWhitelistedChannels addObject:self.playerViewController.channelID]; - } - else { - [kWhitelistedChannels removeObject:self.playerViewController.channelID]; - } - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *settingsPath = [documentsDirectory stringByAppendingPathComponent:@"iSponsorBlock.plist"]; - NSMutableDictionary *settings = [NSMutableDictionary dictionary]; - [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:settingsPath]]; - - [settings setValue:kWhitelistedChannels forKey:@"whitelistedChannels"]; - [settings writeToURL:[NSURL fileURLWithPath:settingsPath isDirectory:NO] error:nil]; - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.galacticdev.isponsorblockprefs.changed"), NULL, NULL, YES); -} - -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; - [self.startEndSegmentButton removeFromSuperview]; - [self.segmentsInDatabaseLabel removeFromSuperview]; - [self.userSegmentsLabel removeFromSuperview]; - [self.submitSegmentsButton removeFromSuperview]; - [self.whitelistChannelLabel removeFromSuperview]; - - [self.previousParentViewController addChildViewController:self.playerViewController]; - [self.previousParentViewController.view addSubview:self.playerViewController.view]; - - self.overlayView.isDisplayingSponsorBlockViewController = NO; - self.overlayView.sponsorBlockButton.hidden = NO; - self.overlayView.sponsorStartedEndedButton.hidden = NO; - [self.overlayView setOverlayVisible:YES]; -} - -- (void)startEndSegmentButtonPressed:(UIButton *)sender { - NSString *segmentStartsNowTitle = LOC(@"SegmentStartsNow"); - NSString *segmentEndsNowTitle = LOC(@"SegmentEndsNow"); - NSString *errorTitle = LOC(@"Error"); - NSString *okTitle = LOC(@"OK"); - NSInteger minutes = lroundf(self.playerViewController.userSkipSegments.lastObject.startTime)/60; - NSInteger seconds = lroundf(self.playerViewController.userSkipSegments.lastObject.startTime)%60; - NSString *errorMessage = [NSString stringWithFormat:@"%@ %ld:%02ld", LOC(@"EndTimeLessThanStartTime"), minutes, seconds]; - - if ([sender.titleLabel.text isEqualToString:segmentStartsNowTitle]) { - [self.playerViewController.userSkipSegments addObject:[[SponsorSegment alloc] initWithStartTime:self.playerViewController.currentVideoMediaTime endTime:-1 category:nil UUID:nil]]; - [sender setTitle:segmentEndsNowTitle forState:UIControlStateNormal]; - } else { - self.playerViewController.userSkipSegments.lastObject.endTime = self.playerViewController.currentVideoMediaTime; - if (self.playerViewController.userSkipSegments.lastObject.endTime != self.playerViewController.currentVideoMediaTime) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:errorTitle message:errorMessage preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:okTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}]; - [alert addAction:defaultAction]; - [self presentViewController:alert animated:YES completion:nil]; - return; - } - [sender setTitle:segmentStartsNowTitle forState:UIControlStateNormal]; - } - [self setupViews]; -} - -- (void)submitSegmentsButtonPressed:(UIButton *)sender { - for (SponsorSegment *segment in self.playerViewController.userSkipSegments) { - if (segment.endTime == -1 || !segment.category) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:LOC(@"Error") message:LOC(@"UnfinishedSegments") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:LOC(@"OK") style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) {}]; - [alert addAction:defaultAction]; - [self presentViewController:alert animated:YES completion:nil]; - return; - } - } - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *settingsPath = [documentsDirectory stringByAppendingPathComponent:@"iSponsorBlock.plist"]; - NSMutableDictionary *settings = [NSMutableDictionary dictionary]; - [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:settingsPath]]; - - [SponsorBlockRequest postSponsorTimes:self.playerViewController.currentVideoID sponsorSegments:self.playerViewController.userSkipSegments userID:kUserID withViewController:self.previousParentViewController]; - [self.previousParentViewController dismissViewControllerAnimated:YES completion:nil]; -} - -- (NSMutableArray *)segmentViewsForSegments:(NSArray *)segments editable:(BOOL)editable { - for (SponsorSegment *segment in segments) { - if (!editable) { - [self.sponsorSegmentViews addObject:[[SponsorSegmentView alloc] initWithFrame:CGRectMake(0,0,50,30) sponsorSegment:segment editable:editable]]; - } - else { - [self.userSponsorSegmentViews addObject:[[SponsorSegmentView alloc] initWithFrame:CGRectMake(0,0,50,30) sponsorSegment:segment editable:editable]]; - } - } - if (!editable) return self.sponsorSegmentViews; - return self.userSponsorSegmentViews; -} - - -- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction - configurationForMenuAtLocation:(CGPoint)location { - SponsorSegmentView *sponsorSegmentView = interaction.view; - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *path = [documentsDirectory stringByAppendingPathComponent:@"iSponsorBlock.plist"]; - NSMutableDictionary *settings = [NSMutableDictionary dictionary]; - [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:path]]; - - UIContextMenuConfiguration *config = [UIContextMenuConfiguration configurationWithIdentifier:nil - previewProvider:nil - actionProvider:^UIMenu* _Nullable(NSArray* _Nonnull suggestedActions) { - NSMutableArray *categoryActions = [NSMutableArray array]; - [categoryActions addObject:[UIAction actionWithTitle:LOC(@"Sponsor") image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - if (sponsorSegmentView.editable) { - sponsorSegmentView.sponsorSegment.category = @"sponsor"; - [self setupViews]; - return; - } - [SponsorBlockRequest categoryVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] category:@"sponsor" withViewController:self]; - }]]; - - [categoryActions addObject:[UIAction actionWithTitle:LOC(@"Intermission/IntroAnimation") image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - if (sponsorSegmentView.editable) { - sponsorSegmentView.sponsorSegment.category = @"intro"; - [self setupViews]; - return; - } - [SponsorBlockRequest categoryVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] category:@"intro" withViewController:self]; - }]]; - - [categoryActions addObject:[UIAction actionWithTitle:LOC(@"Outro") image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - if (sponsorSegmentView.editable) { - sponsorSegmentView.sponsorSegment.category = @"outro"; - [self setupViews]; - return; - } - [SponsorBlockRequest categoryVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] category:@"outro" withViewController:self]; - }]]; - - [categoryActions addObject:[UIAction actionWithTitle:LOC(@"InteractionReminder_Subcribe/Like") image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - if (sponsorSegmentView.editable) { - sponsorSegmentView.sponsorSegment.category = @"interaction"; - [self setupViews]; - return; - } - [SponsorBlockRequest categoryVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] category:@"interaction" withViewController:self]; - }]]; - - [categoryActions addObject:[UIAction actionWithTitle:LOC(@"Unpaid/SelfPromotion") image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - if (sponsorSegmentView.editable) { - sponsorSegmentView.sponsorSegment.category = @"selfpromo"; - [self setupViews]; - return; - } - [SponsorBlockRequest categoryVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] category:@"selfpromo" withViewController:self]; - }]]; - - [categoryActions addObject:[UIAction actionWithTitle:LOC(@"Non-MusicSection") image:nil identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - if (sponsorSegmentView.editable) { - sponsorSegmentView.sponsorSegment.category = @"music_offtopic"; - [self setupViews]; - return; - } - [SponsorBlockRequest categoryVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] category:@"music_offtopic" withViewController:self]; - }]]; - NSMutableArray* actions = [NSMutableArray array]; - if (sponsorSegmentView.editable) { - [actions addObject:[UIAction actionWithTitle:LOC(@"EditStartTime") image:[UIImage systemImageNamed:@"arrow.left.to.line"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:LOC(@"Edit") message:LOC(@"EditStartTime_Desc") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:LOC(@"OK") style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; - f.numberStyle = NSNumberFormatterDecimalStyle; - - NSArray *strings = [alert.textFields[0].text componentsSeparatedByString:@":"]; - if (strings.count != 2) return; - NSString *minutesString = strings[0]; - NSString *secondsString = strings[1]; - - CGFloat minutes = [[f numberFromString:minutesString] floatValue]; - CGFloat seconds = [[f numberFromString:secondsString] floatValue]; - sponsorSegmentView.sponsorSegment.startTime = (minutes*60)+seconds; - [self setupViews]; - }]; - UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - - }]; - [alert addAction:defaultAction]; - [alert addAction:cancelAction]; - [alert addTextFieldWithConfigurationHandler:nil]; - [self presentViewController:alert animated:YES completion:nil]; - }]]; - - [actions addObject:[UIAction actionWithTitle:LOC(@"EditEndTime") image:[UIImage systemImageNamed:@"arrow.right.to.line"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:LOC(@"Edit") message:LOC(@"EditEndTime_Desc") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:LOC(@"OK") style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; - f.numberStyle = NSNumberFormatterDecimalStyle; - - NSArray *strings = [alert.textFields[0].text componentsSeparatedByString:@":"]; - if (strings.count != 2) return; - NSString *minutesString = strings[0]; - NSString *secondsString = strings[1]; - - CGFloat minutes = [[f numberFromString:minutesString] floatValue]; - CGFloat seconds = [[f numberFromString:secondsString] floatValue]; - sponsorSegmentView.sponsorSegment.endTime = (minutes*60)+seconds; - [self setupViews]; - }]; - UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - - }]; - [alert addAction:defaultAction]; - [alert addAction:cancelAction]; - [alert addTextFieldWithConfigurationHandler:nil]; - [self presentViewController:alert animated:YES completion:nil]; - }]]; - - UIMenu *categoriesMenu = [UIMenu menuWithTitle:LOC(@"EditCategory") image:[UIImage systemImageNamed:@"square.grid.2x2"] identifier:nil options:0 children:categoryActions]; - [actions addObject:categoriesMenu]; - [actions addObject:[UIAction actionWithTitle:LOC(@"Delete") image:[UIImage systemImageNamed:@"trash"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - [self.playerViewController.userSkipSegments removeObject:sponsorSegmentView.sponsorSegment]; - [self setupViews]; - }]]; - - UIMenu* menu = [UIMenu menuWithTitle:LOC(@"EditSegment") children:actions]; - return menu; - } - else { - [actions addObject:[UIAction actionWithTitle:LOC(@"Upvote") image:[UIImage systemImageNamed:@"hand.thumbsup.fill"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - [SponsorBlockRequest normalVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] type:YES withViewController:self]; - }]]; - - [actions addObject:[UIAction actionWithTitle:LOC(@"Downvote") image:[UIImage systemImageNamed:@"hand.thumbsdown.fill"] identifier:nil handler:^(__kindof UIAction* _Nonnull action) { - [SponsorBlockRequest normalVoteForSegment:sponsorSegmentView.sponsorSegment userID:[settings objectForKey:@"userID"] type:NO withViewController:self]; - }]]; - - UIMenu *categoriesMenu = [UIMenu menuWithTitle:LOC(@"VoteToChangeCategory") image:[UIImage systemImageNamed:@"square.grid.2x2"] identifier:nil options:0 children:categoryActions]; - UIMenu* menu = [UIMenu menuWithTitle:LOC(@"VoteOnSegment") children:[actions arrayByAddingObject:categoriesMenu]]; - return menu; - } - }]; - return config; -} -@end diff --git a/Tweaks/iSponsorBlock/SponsorSegment.m b/Tweaks/iSponsorBlock/SponsorSegment.m deleted file mode 100644 index 00be768..0000000 --- a/Tweaks/iSponsorBlock/SponsorSegment.m +++ /dev/null @@ -1,21 +0,0 @@ -#import "Headers/SponsorSegment.h" - -@implementation SponsorSegment -- (instancetype)initWithStartTime:(CGFloat)startTime endTime:(CGFloat)endTime category:(NSString *)category UUID:(NSString *)UUID { - self = [super init]; - if (self) { - self.startTime = startTime; - self.endTime = endTime; - self.category = category; - self.UUID = UUID; - } - return self; -} -- (void)setEndTime:(CGFloat)endTime { - if (endTime < self.startTime) { - _endTime = -1; - return; - } - _endTime = endTime; -} -@end diff --git a/Tweaks/iSponsorBlock/SponsorSegmentView.m b/Tweaks/iSponsorBlock/SponsorSegmentView.m deleted file mode 100644 index e658eeb..0000000 --- a/Tweaks/iSponsorBlock/SponsorSegmentView.m +++ /dev/null @@ -1,86 +0,0 @@ -#import "Headers/SponsorSegmentView.h" -#import "Headers/Localization.h" - -@implementation SponsorSegmentView -- (instancetype)initWithFrame:(CGRect)frame sponsorSegment:(SponsorSegment *)segment editable:(BOOL)editable { - self = [super initWithFrame:frame]; - if (self) { - self.sponsorSegment = segment; - self.editable = editable; - - NSString *category; - if ([segment.category isEqualToString:@"sponsor"]) { - category = LOC(@"Sponsor"); - } - else if ([segment.category isEqualToString:@"intro"]) { - category = LOC(@"Intermission"); - } - else if ([segment.category isEqualToString:@"outro"]) { - category = LOC(@"Outro"); - } - else if ([segment.category isEqualToString:@"interaction"]) { - category = LOC(@"Interaction"); - } - else if ([segment.category isEqualToString:@"selfpromo"]) { - category = LOC(@"SelfPromo"); - } - else if ([segment.category isEqualToString:@"music_offtopic"]) { - category = LOC(@"Non-Music"); - } - self.categoryLabel = [[UILabel alloc] initWithFrame:self.frame]; - self.segmentLabel = [[UILabel alloc] initWithFrame:self.frame]; - self.categoryLabel.text = category; - - NSInteger startSeconds = lroundf(segment.startTime); - NSInteger startHours = startSeconds / 3600; - NSInteger startMinutes = (startSeconds - (startHours * 3600)) / 60; - startSeconds = startSeconds %60; - NSString *startTime; - if (startHours >= 1) { - startTime = [NSString stringWithFormat:@"%ld:%02ld:%02ld", startHours, startMinutes, startSeconds]; - } - else { - startTime = [NSString stringWithFormat:@"%ld:%02ld", startMinutes, startSeconds]; - } - - NSInteger endSeconds = lroundf(segment.endTime); - NSInteger endHours = endSeconds / 3600; - NSInteger endMinutes = (endSeconds - (endHours * 3600)) / 60; - endSeconds = endSeconds %60; - NSString *endTime; - if (endHours >= 1) { - endTime = [NSString stringWithFormat:@"%ld:%02ld:%02ld", endHours, endMinutes, endSeconds]; - } - else { - endTime = [NSString stringWithFormat:@"%ld:%02ld", endMinutes, endSeconds]; - } - - self.segmentLabel.text = [NSString stringWithFormat:@"%@ %@ %@ %@", LOC(@"From"), startTime, LOC(@"to"), endTime]; - - [self addSubview:self.categoryLabel]; - self.categoryLabel.adjustsFontSizeToFitWidth = YES; - self.categoryLabel.font = [UIFont systemFontOfSize:12]; - self.categoryLabel.textAlignment = NSTextAlignmentCenter; - self.categoryLabel.translatesAutoresizingMaskIntoConstraints = NO; - - [self addSubview:self.segmentLabel]; - self.segmentLabel.adjustsFontSizeToFitWidth = YES; - self.segmentLabel.font = [UIFont systemFontOfSize:12]; - self.segmentLabel.textAlignment = NSTextAlignmentCenter; - self.segmentLabel.translatesAutoresizingMaskIntoConstraints = NO; - - [self.segmentLabel.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES; - [self.segmentLabel.heightAnchor constraintEqualToConstant:self.frame.size.height/2].active = YES; - - [self.categoryLabel.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES; - [self.categoryLabel.heightAnchor constraintEqualToConstant:self.frame.size.height/2].active = YES; - [self.categoryLabel.topAnchor constraintEqualToAnchor:self.segmentLabel.bottomAnchor].active = YES; - - self.backgroundColor = UIColor.systemGray4Color; - self.layer.cornerRadius = 10; - self.segmentLabel.layer.cornerRadius = 10; - self.categoryLabel.layer.cornerRadius = 10; - } - return self; -} -@end diff --git a/Tweaks/iSponsorBlock/control b/Tweaks/iSponsorBlock/control deleted file mode 100644 index aa1e74c..0000000 --- a/Tweaks/iSponsorBlock/control +++ /dev/null @@ -1,11 +0,0 @@ -Package: com.galacticdev.isponsorblock -Name: iSponsorBlock -Version: 1.2 -Architecture: iphoneos-arm -Description: SponsorBlock port for iOS -Maintainer: Galactic Dev -Author: Galactic Dev -Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000), ws.hbang.alderis (>= 1.1) -Icon: https://raw.githubusercontent.com/ajayyy/SponsorBlock/master/public/icons/LogoSponsorBlocker64px.png -Depiction: https://galacticdev.me/iSponsorBlock diff --git a/Tweaks/iSponsorBlock/iSponsorBlock.plist b/Tweaks/iSponsorBlock/iSponsorBlock.plist deleted file mode 100644 index fb2904e..0000000 --- a/Tweaks/iSponsorBlock/iSponsorBlock.plist +++ /dev/null @@ -1 +0,0 @@ -{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; } diff --git a/Tweaks/iSponsorBlock/iSponsorBlock.xm b/Tweaks/iSponsorBlock/iSponsorBlock.xm deleted file mode 100644 index d283bf9..0000000 --- a/Tweaks/iSponsorBlock/iSponsorBlock.xm +++ /dev/null @@ -1,1047 +0,0 @@ -#import "Headers/iSponsorBlock.h" -#import -#import -#import "Headers/ColorFunctions.h" -#import "Headers/SponsorBlockSettingsController.h" -#import "Headers/SponsorBlockRequest.h" -#import "Headers/SponsorBlockViewController.h" - -#define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] - -extern "C" NSBundle *iSponsorBlockBundle() { - static NSBundle *bundle = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"iSponsorBlock" ofType:@"bundle"]; - if (tweakBundlePath) - bundle = [NSBundle bundleWithPath:tweakBundlePath]; - else - bundle = [NSBundle bundleWithPath:ROOT_PATH_NS("/Library/Application Support/iSponsorBlock.bundle")]; - }); - return bundle; -} - -NSBundle *tweakBundle = iSponsorBlockBundle(); - -// Sound effect for skip segments -static void playSponsorAudio() { - NSString *audioFilePath = [tweakBundle pathForResource:@"SponsorAudio" ofType:@"m4a"]; - NSURL *audioFileURL = [NSURL fileURLWithPath:audioFilePath]; - SystemSoundID soundID; - AudioServicesCreateSystemSoundID((__bridge CFURLRef)audioFileURL, &soundID); - AudioServicesPlaySystemSound(soundID); -} - -// Check and translate segment title for HUD -NSDictionary *categoryLocalization = @{ - @"sponsor": LOC(@"sponsor"), - @"intro": LOC(@"intro"), - @"outro": LOC(@"outro"), - @"interaction": LOC(@"interaction"), - @"selfpromo": LOC(@"selfpromo"), - @"music_offtopic": LOC(@"music_offtopic") -}; - -%group Main -NSString *modifiedTimeString; - -%hook YTPlayerViewController -%property (strong, nonatomic) NSMutableArray *skipSegments; -%property (nonatomic, assign) NSInteger currentSponsorSegment; -%property (strong, nonatomic) MBProgressHUD *hud; -%property (nonatomic, assign) NSInteger unskippedSegment; -%property (strong, nonatomic) NSMutableArray *userSkipSegments; -%property (strong, nonatomic) NSString *channelID; -%property (nonatomic, assign) BOOL hudDisplayed; - -// used to keep support for older versions, as seekToTime is new -%new -- (void)isb_scrubToTime:(CGFloat)time { - // YT v17.30.1 switched scrubToTime to seekToTime - [self respondsToSelector:@selector(scrubToTime:)] ? [self scrubToTime:time] : [self seekToTime:time]; -} - -- (void)singleVideo:(id)arg1 currentVideoTimeDidChange:(YTSingleVideoTime *)arg2 { - %orig; - YTPlayerView *playerView = (YTPlayerView *)self.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if (!self.channelID) self.channelID = @""; - if (self.skipSegments.count > 0 && [overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)] && ![kWhitelistedChannels containsObject:self.channelID]) { - if (kShowModifiedTime) { - UILabel *durationLabel = overlayView.playerBar.durationLabel; - if (![durationLabel.text containsString:modifiedTimeString]) durationLabel.text = [NSString stringWithFormat:@"%@ (%@)", durationLabel.text, modifiedTimeString]; - [durationLabel sizeToFit]; - } - - SponsorSegment *sponsorSegment = [[SponsorSegment alloc] initWithStartTime:-1 endTime:-1 category:nil UUID:nil]; - if (self.currentSponsorSegment <= self.skipSegments.count-1) { - sponsorSegment = self.skipSegments[self.currentSponsorSegment]; - } else if (self.unskippedSegment != self.currentSponsorSegment-1) { - sponsorSegment = self.skipSegments[self.currentSponsorSegment-1]; - } - - if ((lroundf(arg2.time) == ceil(sponsorSegment.startTime) && arg2.time >= sponsorSegment.startTime) || (lroundf(arg2.time) >= ceil(sponsorSegment.startTime) && arg2.time < sponsorSegment.endTime)) { - - if ([[kCategorySettings objectForKey:sponsorSegment.category] intValue] == 3) { - if (self.hud.superview != self.view && self.hudDisplayed == NO) { - self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; - self.hudDisplayed = YES; // Set yes to make sure that HUD is not persistent (Issue #62) - self.hud.mode = MBProgressHUDModeCustomView; - NSString *localizedSegment = categoryLocalization[sponsorSegment.category] ?: sponsorSegment.category; - NSString *localizedManualSkip = LOC(@"ManuallySkipReminder"); - NSString *formattedManualSkip = [NSString stringWithFormat:localizedManualSkip, localizedSegment, lroundf(sponsorSegment.startTime)/60, lroundf(sponsorSegment.startTime)%60, lroundf(sponsorSegment.endTime)/60, lroundf(sponsorSegment.endTime)%60]; - self.hud.label.text = formattedManualSkip; - self.hud.label.numberOfLines = 0; - [self.hud.button setTitle:LOC(@"Skip") forState:UIControlStateNormal]; - [self.hud.button addTarget:self action:@selector(manuallySkipSegment:) forControlEvents:UIControlEventTouchUpInside]; - // Add custom button to hide HUD - UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeSystem]; - UIImage *cancelImage = [[UIImage systemImageNamed:@"x.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - [cancelButton setImage:cancelImage forState:UIControlStateNormal]; - [cancelButton setTintColor:[[UIColor blackColor] colorWithAlphaComponent:0.7]]; - [cancelButton addTarget:self action:@selector(cancelHUD:) forControlEvents:UIControlEventTouchUpInside]; - - UIView *buttonSuperview = self.hud.button.superview; - [buttonSuperview addSubview:cancelButton]; - - CGFloat buttonSpacing = 10.0; - cancelButton.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [cancelButton.topAnchor constraintEqualToAnchor:self.hud.button.topAnchor], - [cancelButton.leadingAnchor constraintEqualToAnchor:self.hud.button.trailingAnchor constant:buttonSpacing], - [cancelButton.heightAnchor constraintEqualToAnchor:self.hud.button.heightAnchor] - ]]; - self.hud.offset = CGPointMake(self.view.frame.size.width, -MBProgressMaxOffset); - - // Use a delay equal to the length of the sponsored segment to avoid HUD call - double delayInSeconds = sponsorSegment.endTime - sponsorSegment.startTime; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [MBProgressHUD hideHUDForView:self.view animated:YES]; // Hide HUD if user is not interacting with buttons - self.hudDisplayed = NO; // Reset flag to make it work for the next segment - }); - } - } - //edge case where segment end time is longer than the video - else if (sponsorSegment.endTime > self.currentVideoTotalMediaTime) { - [self isb_scrubToTime:self.currentVideoTotalMediaTime]; - if (kEnableSkipCountTracking) [SponsorBlockRequest viewedVideoSponsorTime:sponsorSegment]; - } - else { - [self isb_scrubToTime:sponsorSegment.endTime]; - if (kEnableSkipCountTracking) [SponsorBlockRequest viewedVideoSponsorTime:sponsorSegment]; - } - if ([[kCategorySettings objectForKey:sponsorSegment.category] intValue] == 1) { - if (self.hud.superview != self.view && kShowSkipNotice) { - [MBProgressHUD hideHUDForView:self.view animated:YES]; - self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; - self.hud.mode = MBProgressHUDModeCustomView; - // Translate and add segment name to the skipped HUD (issue #70) - NSString *localizedSegment = categoryLocalization[sponsorSegment.category] ?: sponsorSegment.category; - self.hud.label.text = [NSString stringWithFormat:LOC(@"SkippedSegment"), localizedSegment]; - self.hud.label.numberOfLines = 0; - [self.hud.button setTitle:LOC(@"Unskip") forState:UIControlStateNormal]; - [self.hud.button addTarget:self action:@selector(unskipSegment:) forControlEvents:UIControlEventTouchUpInside]; - self.hud.offset = CGPointMake(self.view.frame.size.width, -MBProgressMaxOffset); - [self.hud hideAnimated:YES afterDelay:kSkipNoticeDuration]; - - // Play sound effect if option enabled - if (kSkipAudioNotification) { - playSponsorAudio(); - } - } - } - - if (self.currentSponsorSegment <= self.skipSegments.count-1 && [[kCategorySettings objectForKey:sponsorSegment.category] intValue] != 3) self.currentSponsorSegment ++; - } - else if (lroundf(arg2.time) > sponsorSegment.startTime && self.currentSponsorSegment != self.skipSegments.count && self.currentSponsorSegment != self.skipSegments.count-1) { - self.currentSponsorSegment ++; - } - else if (self.currentSponsorSegment == 0 && self.unskippedSegment != -1) { - self.currentSponsorSegment ++; - } - else if (self.currentSponsorSegment > 0 && lroundf(arg2.time) < self.skipSegments[self.currentSponsorSegment-1].startTime-0.01) { - if ([self isMDXActive]) { - - } - else if (self.unskippedSegment != self.currentSponsorSegment-1) { - self.currentSponsorSegment--; - } - else if (arg2.time < self.skipSegments[self.currentSponsorSegment-1].startTime-0.01) { - self.unskippedSegment = -1; - } - } - } - if ([overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - YTSegmentableInlinePlayerBarView *playerBarView = overlayView.playerBar.segmentablePlayerBar; - - [playerBarView maybeCreateMarkerViewsISB]; - - for (UIView *markerView in playerBarView.subviews) { - if (![playerBarView.sponsorMarkerViews containsObject:markerView] && playerBarView.skipSegments.count == 0) { - [playerBarView maybeCreateMarkerViewsISB]; - return; - } - } - } -} -- (void)playbackController:(id)arg1 didActivateVideo:(id)arg2 withPlaybackData:(id)arg3 { - %orig; - if (self.isPlayingAd) return; - YTPlayerView *playerView = (YTPlayerView *)self.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if ([overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - [MBProgressHUD hideHUDForView:playerView animated:YES]; //fix manual skip popup not disappearing when changing videos - self.hudDisplayed = NO; // Reset flag when changing videos - - self.skipSegments = [NSMutableArray array]; - self.userSkipSegments = [NSMutableArray array]; - [SponsorBlockRequest getSponsorTimes:self.currentVideoID completionTarget:self completionSelector:@selector(setSkipSegments:) apiInstance:kAPIInstance]; - self.currentSponsorSegment = 0; - self.unskippedSegment = -1; - overlayView.controlsOverlayView.playerViewController = self; - overlayView.controlsOverlayView.isDisplayingSponsorBlockViewController = NO; - - YTSingleVideoController *activeVideo = self.activeVideo; - if ([activeVideo isKindOfClass:%c(YTSingleVideoController)]) { - if ([self.activeVideo.singleVideo respondsToSelector:@selector(video)]) self.channelID = self.activeVideo.singleVideo.video.videoDetails.channelId; - else self.channelID = self.activeVideo.singleVideo.playbackData.video.videoDetails.channelId; - } - } -} -- (void)setSkipSegments:(NSMutableArray *)arg1 { - %orig; - NSInteger totalSavedTime = 0; - for (SponsorSegment *segment in arg1) totalSavedTime += lroundf(segment.endTime) - lroundf(segment.startTime); - if (arg1.count > 0) { - NSInteger seconds = lroundf(self.currentVideoTotalMediaTime - totalSavedTime); - NSInteger hours = seconds / 3600; - NSInteger minutes = (seconds - (hours * 3600)) / 60; - seconds = seconds % 60; - - if (hours >= 1) modifiedTimeString = [NSString stringWithFormat:@"%ld:%02ld:%02ld",hours, minutes, seconds]; - else modifiedTimeString = [NSString stringWithFormat:@"%ld:%02ld", minutes, seconds]; - } - - else { - modifiedTimeString = nil; - } -} - -%new -- (void)isb_fixVisualGlitch { - if (!self.isPlayingAd) { - YTPlayerView *playerView = (YTPlayerView *)self.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if ([overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - YTSegmentableInlinePlayerBarView *playerBarView = overlayView.playerBar.segmentablePlayerBar; - [playerBarView maybeCreateMarkerViewsISB]; - } - } -} - -- (void)scrubToTime:(CGFloat)arg1 { - %orig; - [self isb_fixVisualGlitch]; -} - -- (void)seekToTime:(CGFloat)arg1 { - %orig; - [self isb_fixVisualGlitch]; -} - -%new -- (void)unskipSegment:(UIButton *)sender { - if (self.currentSponsorSegment > 0) { - [self isb_scrubToTime:self.skipSegments[self.currentSponsorSegment-1].startTime]; - self.unskippedSegment = self.currentSponsorSegment-1; - } else { - [self isb_scrubToTime:self.skipSegments[self.currentSponsorSegment].startTime]; - self.unskippedSegment = self.currentSponsorSegment; - } - [MBProgressHUD hideHUDForView:self.view animated:YES]; -} - -%new -- (void)manuallySkipSegment:(UIButton *)sender { - SponsorSegment *sponsorSegment = [[SponsorSegment alloc] initWithStartTime:-1 endTime:-1 category:nil UUID:nil]; - if (self.currentSponsorSegment <= self.skipSegments.count-1) { - sponsorSegment = self.skipSegments[self.currentSponsorSegment]; - } else if (self.unskippedSegment != self.currentSponsorSegment-1) { - sponsorSegment = self.skipSegments[self.currentSponsorSegment-1]; - } - - if (sponsorSegment.endTime > self.currentVideoTotalMediaTime) { - [self isb_scrubToTime:self.currentVideoTotalMediaTime]; - if (kEnableSkipCountTracking) [SponsorBlockRequest viewedVideoSponsorTime:sponsorSegment]; - } - else { - [self isb_scrubToTime:sponsorSegment.endTime]; - if (kEnableSkipCountTracking) [SponsorBlockRequest viewedVideoSponsorTime:sponsorSegment]; - } - [MBProgressHUD hideHUDForView:self.view animated:YES]; - // Prevent app crashing if segment was already skipped once - if (self.currentSponsorSegment < 0) { - self.currentSponsorSegment++; - } - - // Reset flag immediately if segment was skipped - if (self.hudDisplayed != NO) { - self.hudDisplayed = NO; - } - - // Play sound effect if option enabled - if (kSkipAudioNotification) { - playSponsorAudio(); - } -} - -%new -- (void)cancelHUD:(UIButton *)sender { - [MBProgressHUD hideHUDForView:self.view animated:YES]; -} - -- (void)setPlayerViewLayout:(NSInteger)arg1 { - %orig; - YTPlayerView *playerView = (YTPlayerView *)self.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if ([overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - YTSegmentableInlinePlayerBarView *playerBarView = overlayView.playerBar.segmentablePlayerBar; - [playerBarView maybeCreateMarkerViewsISB]; - } -} - -- (void)updateViewportSizeProvider { - %orig; - YTPlayerView *playerView = (YTPlayerView *)self.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if ([overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - YTSegmentableInlinePlayerBarView *playerBarView = overlayView.playerBar.segmentablePlayerBar; - [playerBarView maybeCreateMarkerViewsISB]; - } -} -%end - -%hook YTMainAppVideoPlayerOverlayViewController - -- (void)updateTopRightButtonAvailability { - %orig; - YTMainAppVideoPlayerOverlayView *v = [self videoPlayerOverlayView]; - YTMainAppControlsOverlayView *c = [v valueForKey:@"_controlsOverlayView"]; - c.sponsorBlockButton.hidden = !kShowButtonsInPlayer; - c.sponsorStartedEndedButton.hidden = !kShowButtonsInPlayer || kHideStartEndButtonInPlayer; - [c setNeedsLayout]; -} - -%end - -%hook YTMainAppControlsOverlayView -%property (retain, nonatomic) YTQTMButton *sponsorBlockButton; -%property (retain, nonatomic) YTQTMButton *sponsorStartedEndedButton; -%property (retain, nonatomic) YTPlayerViewController *playerViewController; -%property (nonatomic, assign) BOOL isDisplayingSponsorBlockViewController; - -- (id)initWithDelegate:(id)delegate { - self = %orig; - if (kShowButtonsInPlayer) { - CGFloat padding = [[self class] topButtonAdditionalPadding]; - self.sponsorBlockButton = [self buttonWithImage:[UIImage imageWithContentsOfFile:[tweakBundle pathForResource:@"PlayerInfoIconSponsorBlocker256px-20@2x" ofType:@"png"]] accessibilityLabel:@"iSponsorBlock" verticalContentPadding:padding]; - [self.sponsorBlockButton addTarget:self action:@selector(sponsorBlockButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - self.sponsorBlockButton.hidden = YES; - self.sponsorBlockButton.alpha = 0; - - if (!kHideStartEndButtonInPlayer) { - BOOL isStart = self.playerViewController.userSkipSegments.lastObject.endTime != -1; - NSString *startedEndedImagePath = isStart ? [tweakBundle pathForResource:@"sponsorblockstart-20@2x" ofType:@"png"] : [tweakBundle pathForResource:@"sponsorblockend-20@2x" ofType:@"png"]; - self.sponsorStartedEndedButton = [self buttonWithImage:[UIImage imageWithContentsOfFile:startedEndedImagePath] accessibilityLabel:isStart ? @"iSponsorBlock start" : @"iSponsorBlock end" verticalContentPadding:padding]; - [self.sponsorStartedEndedButton addTarget:self action:@selector(sponsorStartedEndedButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - self.sponsorStartedEndedButton.hidden = YES; - self.sponsorStartedEndedButton.alpha = 0; - } - - @try { - UIView *containerView = [self valueForKey:@"_topControlsAccessibilityContainerView"]; - [containerView addSubview:self.sponsorBlockButton]; - if (!kHideStartEndButtonInPlayer) { - [containerView addSubview:self.sponsorStartedEndedButton]; - } - } @catch (id ex) { - [self addSubview:self.sponsorBlockButton]; - if (!kHideStartEndButtonInPlayer) { - [self addSubview:self.sponsorStartedEndedButton]; - } - } - } - return self; -} - -- (NSMutableArray *)topControls { - NSMutableArray *topControls = %orig; - if (kShowButtonsInPlayer) { - [topControls insertObject:self.sponsorBlockButton atIndex:0]; - if (!kHideStartEndButtonInPlayer) { - [topControls insertObject:self.sponsorStartedEndedButton atIndex:0]; - } - } - return topControls; -} - -- (void)setTopOverlayVisible:(BOOL)visible isAutonavCanceledState:(BOOL)canceledState { - if (self.isDisplayingSponsorBlockViewController) { - %orig(NO, canceledState); - self.sponsorBlockButton.imageView.hidden = YES; - self.sponsorStartedEndedButton.imageView.hidden = YES; - return; - } - - self.sponsorBlockButton.alpha = canceledState || !visible ? 0:1; - self.sponsorStartedEndedButton.alpha = canceledState || !visible ? 0:1; - %orig; -} - -%new -- (void)sponsorBlockButtonPressed:(YTQTMButton *)sender { - self.isDisplayingSponsorBlockViewController = YES; - self.sponsorBlockButton.hidden = YES; - self.sponsorStartedEndedButton.hidden = YES; - if ([self.playerViewController playerViewLayout] == 3) [self.playerViewController didPressToggleFullscreen]; - [self presentSponsorBlockViewController]; -} -%new -- (void)sponsorStartedEndedButtonPressed:(YTQTMButton *)sender { - if (self.playerViewController.userSkipSegments.lastObject.endTime != -1) { - [self.playerViewController.userSkipSegments addObject:[[SponsorSegment alloc] initWithStartTime:self.playerViewController.currentVideoMediaTime endTime:-1 category:nil UUID:nil]]; - [self.sponsorStartedEndedButton setImage:[UIImage imageWithContentsOfFile:[tweakBundle pathForResource:@"sponsorblockend-20@2x" ofType:@"png"]] forState:UIControlStateNormal]; - } - else { - self.playerViewController.userSkipSegments.lastObject.endTime = self.playerViewController.currentVideoMediaTime; - if (self.playerViewController.userSkipSegments.lastObject.endTime != self.playerViewController.currentVideoMediaTime) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"End Time That You Set Was Less Than the Start Time, Please Select a Time After %ld:%02ld",lroundf(self.playerViewController.userSkipSegments.lastObject.startTime)/60, lroundf(self.playerViewController.userSkipSegments.lastObject.startTime)%60] preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) {}]; - [alert addAction:defaultAction]; - [[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:alert animated:YES completion:nil]; - return; - } - [self.sponsorStartedEndedButton setImage:[UIImage imageWithContentsOfFile:[tweakBundle pathForResource:@"sponsorblockstart-20@2x" ofType:@"png"]] forState:UIControlStateNormal]; - } -} -%new -- (void)presentSponsorBlockViewController { - SponsorBlockViewController *addSponsorViewController = [[SponsorBlockViewController alloc] init]; - addSponsorViewController.playerViewController = self.playerViewController; - addSponsorViewController.previousParentViewController = self.playerViewController.parentViewController; - addSponsorViewController.overlayView = self; - addSponsorViewController.preferredContentSize = CGSizeMake(CGRectGetWidth(self.playerViewController.view.frame), 0.9 * CGRectGetHeight(UIScreen.mainScreen.bounds)); - [[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:addSponsorViewController animated:YES completion:nil]; - self.isDisplayingSponsorBlockViewController = YES; - [self setOverlayVisible:NO]; - -} -%end - -%hook YTInlinePlayerBarView -%property (strong, nonatomic) NSMutableArray *sponsorMarkerViews; -%property (strong, nonatomic) NSMutableArray *skipSegments; -%property (strong, nonatomic) YTPlayerViewController *playerViewController; -%new -- (void)maybeCreateMarkerViewsISB { - [self removeSponsorMarkers]; - self.skipSegments = self.skipSegments; -} -- (void)setSkipSegments:(NSMutableArray *)arg1 { - %orig; - [self removeSponsorMarkers]; - if ([kWhitelistedChannels containsObject:self.playerViewController.channelID]) { - return; - } - self.sponsorMarkerViews = [NSMutableArray array]; - for (SponsorSegment *segment in arg1) { - CGFloat startTime = segment.startTime; - CGFloat endTime = segment.endTime; - CGFloat beginX = (startTime * self.frame.size.width) / self.totalTime; - CGFloat endX = (endTime * self.frame.size.width) / self.totalTime; - CGFloat markerWidth = MAX(endX - beginX, 0); - - UIColor *color; - if ([segment.category isEqualToString:@"sponsor"]) color = colorWithHexString([kCategorySettings objectForKey:@"sponsorColor"]); - else if ([segment.category isEqualToString:@"intro"]) color = colorWithHexString([kCategorySettings objectForKey:@"introColor"]); - else if ([segment.category isEqualToString:@"outro"]) color = colorWithHexString([kCategorySettings objectForKey:@"outroColor"]); - else if ([segment.category isEqualToString:@"interaction"]) color = colorWithHexString([kCategorySettings objectForKey:@"interactionColor"]); - else if ([segment.category isEqualToString:@"selfpromo"]) color = colorWithHexString([kCategorySettings objectForKey:@"selfpromoColor"]); - else if ([segment.category isEqualToString:@"music_offtopic"]) color = colorWithHexString([kCategorySettings objectForKey:@"music_offtopicColor"]); - UIView *newMarkerView = [[UIView alloc] initWithFrame:CGRectZero]; - newMarkerView.backgroundColor = color; - [self addSubview:newMarkerView]; - newMarkerView.translatesAutoresizingMaskIntoConstraints = NO; - if (isnan(markerWidth) || !isfinite(beginX)) { - return; - } - [newMarkerView.widthAnchor constraintEqualToConstant:markerWidth].active = YES; - [newMarkerView.heightAnchor constraintEqualToConstant:2].active = YES; - [newMarkerView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:beginX].active = YES; - [newMarkerView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES; - - [self.sponsorMarkerViews addObject:newMarkerView]; - } -} - -%new -- (void)removeSponsorMarkers { - for (UIView *markerView in self.sponsorMarkerViews) { - [markerView removeFromSuperview]; - } - self.sponsorMarkerViews = [NSMutableArray array]; -} -%end - -%hook YTSegmentableInlinePlayerBarView -%property (strong, nonatomic) NSMutableArray *sponsorMarkerViews; -%property (strong, nonatomic) NSMutableArray *skipSegments; -%property (strong, nonatomic) YTPlayerViewController *playerViewController; -%new -- (void)maybeCreateMarkerViewsISB { - [self removeSponsorMarkers]; - self.skipSegments = self.skipSegments; -} -- (void)setSkipSegments:(NSMutableArray *)arg1 { - %orig; - [self removeSponsorMarkers]; - if ([kWhitelistedChannels containsObject:self.playerViewController.channelID]) { - return; - } - self.sponsorMarkerViews = [NSMutableArray array]; - UIView *scrubber = [self valueForKey:@"_scrubberCircle"]; - UIView *referenceView = [[self valueForKey:@"_segmentViews"] firstObject]; - if (referenceView == nil) return; - CGFloat originY = referenceView.frame.origin.y; - for (SponsorSegment *segment in arg1) { - CGFloat startTime = segment.startTime; - CGFloat endTime = segment.endTime; - CGFloat beginX = (startTime * self.frame.size.width) / self.totalTime; - CGFloat endX = (endTime * self.frame.size.width) / self.totalTime; - CGFloat markerWidth = MAX(endX - beginX, 0); - - UIColor *color; - if ([segment.category isEqualToString:@"sponsor"]) color = colorWithHexString([kCategorySettings objectForKey:@"sponsorColor"]); - else if ([segment.category isEqualToString:@"intro"]) color = colorWithHexString([kCategorySettings objectForKey:@"introColor"]); - else if ([segment.category isEqualToString:@"outro"]) color = colorWithHexString([kCategorySettings objectForKey:@"outroColor"]); - else if ([segment.category isEqualToString:@"interaction"]) color = colorWithHexString([kCategorySettings objectForKey:@"interactionColor"]); - else if ([segment.category isEqualToString:@"selfpromo"]) color = colorWithHexString([kCategorySettings objectForKey:@"selfpromoColor"]); - else if ([segment.category isEqualToString:@"music_offtopic"]) color = colorWithHexString([kCategorySettings objectForKey:@"music_offtopicColor"]); - - if (isnan(markerWidth) || !isfinite(beginX)) { - return; - } - - UIView *newMarkerView = [[UIView alloc] initWithFrame:CGRectMake(beginX, originY, markerWidth, 2)]; - newMarkerView.userInteractionEnabled = NO; - newMarkerView.backgroundColor = color; - [self insertSubview:newMarkerView belowSubview:scrubber]; - [self.sponsorMarkerViews addObject:newMarkerView]; - } -} - -%new -- (void)removeSponsorMarkers { - for (UIView *markerView in self.sponsorMarkerViews) { - [markerView removeFromSuperview]; - } - self.sponsorMarkerViews = [NSMutableArray array]; -} -%end - - -%hook YTInlinePlayerBarContainerView -- (instancetype)initWithScrubbedTimeLabelsDisplayBelowStoryboard:(BOOL)arg1 enableSegmentedProgressView:(BOOL)arg2 { - return %orig(arg1, YES); -} -//does the same thing as the method above on youtube v. 16.0x -- (instancetype)initWithEnableSegmentedProgressView:(BOOL)arg1 { - return %orig(YES); -} -- (BOOL)alwaysEnableSegmentedProgressView { - return YES; -} - -- (void)setPeekableViewVisible:(BOOL)arg1 { - %orig; - if (kShowModifiedTime && modifiedTimeString && ![self.durationLabel.text containsString:modifiedTimeString]) { - NSString *text = [NSString stringWithFormat:@"%@ (%@)", self.durationLabel.text, modifiedTimeString]; - self.durationLabel.text = text; - [self.durationLabel sizeToFit]; - } -} - -//thanks @iCraze >> -%new -- (id)playerBar { - return [self segmentablePlayerBar]; -} -%end - -%hook YTNGWatchLayerViewController - -- (void)didCompleteFullscreenDismissAnimation { - %orig; - YTPlayerView *playerView = (YTPlayerView *)self.playerViewController.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if (!self.playerViewController.isPlayingAd && overlayView.controlsOverlayView.isDisplayingSponsorBlockViewController && [overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - [overlayView.controlsOverlayView presentSponsorBlockViewController]; - } -} -%end - -//For newer versions of YT the class name changed -%hook YTWatchLayerViewController - -- (void)didCompleteFullscreenDismissAnimation { - %orig; - YTPlayerView *playerView = (YTPlayerView *)self.playerViewController.view; - YTMainAppVideoPlayerOverlayView *overlayView = (YTMainAppVideoPlayerOverlayView *)playerView.overlayView; - if (!self.playerViewController.isPlayingAd && overlayView.controlsOverlayView.isDisplayingSponsorBlockViewController && [overlayView isKindOfClass:%c(YTMainAppVideoPlayerOverlayView)]) { - [overlayView.controlsOverlayView presentSponsorBlockViewController]; - } -} -%end - - -%hook YTPlayerView -//https://stackoverflow.com/questions/11770743/capturing-touches-on-a-subview-outside-the-frame-of-its-superview-using-hittest -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - if (self.clipsToBounds || self.hidden || self.alpha == 0) { - return nil; - } - - for (UIView *subview in self.subviews.reverseObjectEnumerator) { - CGPoint subPoint = [subview convertPoint:point fromView:self]; - UIView *result = [subview hitTest:subPoint withEvent:event]; - if (result) return result; - } - return nil; -} -%end -%end - -%group Cercube -//ew global variables -NSArray *skipSegments; -AVQueuePlayer *queuePlayer; - -%hook CADownloadObject -+ (id)modelWithMetadata:(id)arg1 format:(id)arg2 context:(id)arg3 type:(id)arg4 audioOnly:(_Bool)arg5 directory:(id)arg6 { - CADownloadObject *downloadObject = %orig; - [SponsorBlockRequest getSponsorTimes:downloadObject.videoId completionTarget:downloadObject completionSelector:@selector(setSkipSegments:) apiInstance:kAPIInstance]; - return downloadObject; -} - -%new -- (void)setSkipSegments:(NSMutableArray *)skipSegments { - NSString *path = [self.filePath.stringByDeletingLastPathComponent stringByAppendingPathComponent:[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"plist"]]; - [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil]; - NSMutableArray *segments = [NSMutableArray array]; - for (SponsorSegment *segment in skipSegments) { - [segments addObject:@{ - @"startTime" : @(segment.startTime), - @"endTime" : @(segment.endTime), - @"category" : segment.category, - @"UUID" : segment.UUID - }]; - } - NSDictionary *dict = @{ - @"skipSegments" : segments - }; - [dict writeToURL:[NSURL fileURLWithPath:path isDirectory:NO] error:nil]; -} -%end -%hook AVPlayerViewController -- (void)viewDidLoad { - %orig; - [(AVQueuePlayer *)self.player setPlayerViewController:self]; -} -%end - -%hook AVScrubber -//this is bad but i don't feel like finding a better way -- (void)layoutSubviews { - %orig; - [queuePlayer updateMarkerViews]; -} -%end - -%hook AVQueuePlayer -%property (strong, nonatomic) NSMutableArray *skipSegments; -%property (nonatomic, assign) NSInteger currentSponsorSegment; -%property (strong, nonatomic) MBProgressHUD *hud; -%property (nonatomic, assign) NSInteger unskippedSegment; -%property (nonatomic, assign) BOOL isSeeking; -%property (nonatomic, assign) NSInteger currentPlayerItem; -%property (strong, nonatomic) id timeObserver; -%property (strong, nonatomic) AVPlayerViewController *playerViewController; -%property (strong, nonatomic) NSMutableArray *markerViews; -%property (nonatomic, assign) BOOL hudDisplayed; -- (instancetype)initWithItems:(NSArray *)items { - self.currentPlayerItem = 0; - queuePlayer = self; - return %orig; -} -- (void)seekToTime:(CMTime)time { - %orig; - self.isSeeking = YES; - [NSTimer scheduledTimerWithTimeInterval:1.0f repeats:NO block:^(NSTimer *timer) { - self.isSeeking = NO; - }]; -} -- (void)_itemIsReadyToPlay:(id)arg1 { - %orig; - self.isSeeking = NO; - [self sponsorBlockSetup]; -} -- (void)_advanceCurrentItemAccordingToFigPlaybackItem:(id)arg1 { - %orig; - if (self.currentPlayerItem + 1 < [self items].count) self.currentPlayerItem ++; -} -- (void)_removeItem:(id)arg1 { - %orig; - [self removeTimeObserver:self.timeObserver]; - self.timeObserver = nil; - if (self.currentPlayerItem != 0) self.currentPlayerItem --; - [self sponsorBlockSetup]; -} -%new -- (void)updateMarkerViews { - if (self.skipSegments.count > 0) { - CGFloat totalTime = [@([self items][self.currentPlayerItem].duration.value) floatValue] / [self items][self.currentPlayerItem].duration.timescale; - for (UIView *markerView in self.markerViews) { - AVScrubber *scrubber = self.playerViewController.contentView.playbackControlsView.scrubber; - CGFloat startTime = self.skipSegments[[self.markerViews indexOfObject:markerView]].startTime; - CGFloat endTime = self.skipSegments[[self.markerViews indexOfObject:markerView]].endTime; - CGFloat beginX = (startTime * scrubber.frame.size.width) / totalTime; - CGFloat endX = (endTime * scrubber.frame.size.width) / totalTime; - CGFloat markerWidth = endX - beginX; - markerView.frame = CGRectMake(beginX, scrubber.frame.size.height/2-2, markerWidth, 5); - } - } -} -%new -- (void)sponsorBlockSetup { - if ([self items].count <= 0) return; - NSString *path = [[[[self items][self.currentPlayerItem] _URL].path stringByDeletingPathExtension] stringByAppendingPathExtension:@"plist"]; - NSDictionary *segmentsDict = [NSDictionary dictionaryWithContentsOfFile:path]; - NSDictionary *segments = [segmentsDict objectForKey:@"skipSegments"]; - self.skipSegments = [NSMutableArray array]; - CGFloat totalTime = [@([self items][self.currentPlayerItem].duration.value) floatValue] / [self items][self.currentPlayerItem].duration.timescale; - for (UIView *markerView in self.markerViews) { - [markerView removeFromSuperview]; - } - self.markerViews = [NSMutableArray array]; - for (NSDictionary *dict in segments) { - SponsorSegment *segment = [[SponsorSegment alloc] initWithStartTime:[[dict objectForKey:@"startTime"] floatValue] endTime:[[dict objectForKey:@"endTime"] floatValue] category:[dict objectForKey:@"category"] UUID:[dict objectForKey:@"UUID"]]; - [self.skipSegments addObject:segment]; - AVScrubber *scrubber = self.playerViewController.contentView.playbackControlsView.scrubber; - CGFloat startTime = segment.startTime; - CGFloat endTime = segment.endTime; - CGFloat beginX = (startTime * scrubber.frame.size.width) / totalTime; - CGFloat endX = (endTime * scrubber.frame.size.width) / totalTime; - CGFloat markerWidth = endX - beginX; - UIView *markerView = [[UIView alloc] initWithFrame:CGRectMake(beginX, 2, markerWidth, 5)]; - - if ([segment.category isEqualToString:@"sponsor"]) markerView.backgroundColor = colorWithHexString([kCategorySettings objectForKey:@"sponsorColor"]); - else if ([segment.category isEqualToString:@"intro"]) markerView.backgroundColor = colorWithHexString([kCategorySettings objectForKey:@"introColor"]); - else if ([segment.category isEqualToString:@"outro"]) markerView.backgroundColor = colorWithHexString([kCategorySettings objectForKey:@"outroColor"]); - else if ([segment.category isEqualToString:@"interaction"]) markerView.backgroundColor = colorWithHexString([kCategorySettings objectForKey:@"interactionColor"]); - else if ([segment.category isEqualToString:@"selfpromo"]) markerView.backgroundColor = colorWithHexString([kCategorySettings objectForKey:@"selfpromoColor"]); - else if ([segment.category isEqualToString:@"music_offtopic"]) markerView.backgroundColor = colorWithHexString([kCategorySettings objectForKey:@"music_offtopicColor"]); - [scrubber addSubview:markerView]; - [self.markerViews addObject:markerView]; - } - skipSegments = self.skipSegments; - self.currentSponsorSegment = 0; - self.unskippedSegment = -1; - CMTime timeInterval = CMTimeMake(1,10); - __weak AVQueuePlayer *weakSelf = self; - [self removeTimeObserver:self.timeObserver]; - self.timeObserver = nil; - - self.timeObserver = [self addPeriodicTimeObserverForInterval:timeInterval queue:nil usingBlock:^(CMTime time) { - CGFloat timeFloat = [@(time.value) floatValue] / time.timescale; - if (weakSelf.skipSegments.count > 0) { - SponsorSegment *sponsorSegment = [[SponsorSegment alloc] initWithStartTime:-1 endTime:-1 category:nil UUID:nil]; - if (weakSelf.currentSponsorSegment <= weakSelf.skipSegments.count-1) { - sponsorSegment = weakSelf.skipSegments[weakSelf.currentSponsorSegment]; - } - else if (weakSelf.unskippedSegment != weakSelf.currentSponsorSegment-1) { - sponsorSegment = weakSelf.skipSegments[weakSelf.currentSponsorSegment-1]; - } - - if ((lroundf(timeFloat) == ceil(sponsorSegment.startTime) && timeFloat >= sponsorSegment.startTime) || (lroundf(timeFloat) >= ceil(sponsorSegment.startTime) && timeFloat < sponsorSegment.endTime)) { - if ([[kCategorySettings objectForKey:sponsorSegment.category] intValue] == 3) { - if (weakSelf.hud.superview != weakSelf.playerViewController.view && weakSelf.hudDisplayed == NO) { - weakSelf.hud = [MBProgressHUD showHUDAddedTo:weakSelf.playerViewController.view animated:YES]; - weakSelf.hudDisplayed = YES; // Set yes to make sure that HUD is not persistent (Issue #62) - weakSelf.hud.mode = MBProgressHUDModeCustomView; - NSString *localizedSegment = categoryLocalization[sponsorSegment.category] ?: sponsorSegment.category; - NSString *localizedManualSkip = LOC(@"ManuallySkipReminder"); - NSString *formattedManualSkip = [NSString stringWithFormat:localizedManualSkip, localizedSegment, lroundf(sponsorSegment.startTime)/60, lroundf(sponsorSegment.startTime)%60, lroundf(sponsorSegment.endTime)/60, lroundf(sponsorSegment.endTime)%60]; - weakSelf.hud.label.text = formattedManualSkip; - weakSelf.hud.label.numberOfLines = 0; - [weakSelf.hud.button setTitle:LOC(@"Skip") forState:UIControlStateNormal]; - [weakSelf.hud.button addTarget:weakSelf action:@selector(manuallySkipSegment:) forControlEvents:UIControlEventTouchUpInside]; - // Add custom button to hide HUD - UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeSystem]; - UIImage *cancelImage = [[UIImage systemImageNamed:@"x.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - [cancelButton setImage:cancelImage forState:UIControlStateNormal]; - [cancelButton setTintColor:[[UIColor blackColor] colorWithAlphaComponent:0.7]]; - [cancelButton addTarget:weakSelf action:@selector(cancelHUD:) forControlEvents:UIControlEventTouchUpInside]; - - UIView *buttonSuperview = weakSelf.hud.button.superview; - [buttonSuperview addSubview:cancelButton]; - - CGFloat buttonSpacing = 10.0; - cancelButton.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [cancelButton.topAnchor constraintEqualToAnchor:weakSelf.hud.button.topAnchor], - [cancelButton.leadingAnchor constraintEqualToAnchor:weakSelf.hud.button.trailingAnchor constant:buttonSpacing], - [cancelButton.heightAnchor constraintEqualToAnchor:weakSelf.hud.button.heightAnchor] - ]]; - weakSelf.hud.offset = CGPointMake(weakSelf.playerViewController.view.frame.size.width, -MBProgressMaxOffset); - double delayInSeconds = sponsorSegment.endTime - sponsorSegment.startTime; - - // Use a delay equal to the length of the sponsored segment to avoid HUD call - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [MBProgressHUD hideHUDForView:weakSelf.playerViewController.view animated:YES]; // Hide HUD if user is not interacting with buttons - weakSelf.hudDisplayed = NO; // Reset flag to make it work for the next segment - }); - } - } - - else if (sponsorSegment.endTime > totalTime) { - [weakSelf seekToTime:CMTimeMake(totalTime,1) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; - } - else { - [weakSelf seekToTime:CMTimeMake(sponsorSegment.endTime,1)]; - } - - if ([[kCategorySettings objectForKey:sponsorSegment.category] intValue] == 1) { - if (weakSelf.hud.superview != weakSelf.playerViewController.view && kShowSkipNotice) { - [MBProgressHUD hideHUDForView:weakSelf.playerViewController.view animated:YES]; - weakSelf.hud = [MBProgressHUD showHUDAddedTo:weakSelf.playerViewController.view animated:YES]; - weakSelf.hud.mode = MBProgressHUDModeCustomView; - // Translate and add segment name to the skipped HUD (issue #70) - NSString *localizedSegment = categoryLocalization[sponsorSegment.category] ?: sponsorSegment.category; - weakSelf.hud.label.text = [NSString stringWithFormat:LOC(@"SkippedSegment"), localizedSegment]; - weakSelf.hud.label.numberOfLines = 0; - [weakSelf.hud.button setTitle:LOC(@"Unskip") forState:UIControlStateNormal]; - [weakSelf.hud.button addTarget:weakSelf action:@selector(unskipSegment:) forControlEvents:UIControlEventTouchUpInside]; - weakSelf.hud.offset = CGPointMake(weakSelf.playerViewController.view.frame.size.width, -MBProgressMaxOffset); - [weakSelf.hud hideAnimated:YES afterDelay:kSkipNoticeDuration]; - - // Play sound effect if option enabled - if (kSkipAudioNotification) { - playSponsorAudio(); - } - } - } - - if (weakSelf.currentSponsorSegment <= weakSelf.skipSegments.count-1) weakSelf.currentSponsorSegment ++; - } - else if (lroundf(timeFloat) > sponsorSegment.startTime && weakSelf.currentSponsorSegment < weakSelf.skipSegments.count-1) { - weakSelf.currentSponsorSegment ++; - } - else if (weakSelf.currentSponsorSegment == 0 && weakSelf.unskippedSegment != -1) { - weakSelf.currentSponsorSegment ++; - } - else if (weakSelf.currentSponsorSegment > 0 && lroundf(timeFloat) < weakSelf.skipSegments[weakSelf.currentSponsorSegment-1].startTime-0.01) { - if (weakSelf.unskippedSegment != weakSelf.currentSponsorSegment-1) { - weakSelf.currentSponsorSegment--; - } - else if (timeFloat < weakSelf.skipSegments[weakSelf.currentSponsorSegment-1].startTime-0.01) { - weakSelf.unskippedSegment = -1; - } - } - } - }]; -} -%new -- (void)unskipSegment:(UIButton *)sender { - if (self.currentSponsorSegment > 0) { - [self seekToTime:CMTimeMake(self.skipSegments[self.currentSponsorSegment-1].startTime,1)]; - self.unskippedSegment = self.currentSponsorSegment-1; - } else { - [self seekToTime:CMTimeMake(self.skipSegments[self.currentSponsorSegment].startTime,1)]; - self.unskippedSegment = self.currentSponsorSegment; - } - [MBProgressHUD hideHUDForView:self.playerViewController.view animated:YES]; -} -%end -%end - -%group JustSettings -NSInteger pageStyle = 0; -%hook YTRightNavigationButtons -%property (retain, nonatomic) YTQTMButton *sponsorBlockButton; -- (NSMutableArray *)buttons { - NSMutableArray *retVal = %orig.mutableCopy; - [self.sponsorBlockButton removeFromSuperview]; - [self addSubview:self.sponsorBlockButton]; - if (!self.sponsorBlockButton || pageStyle != [%c(YTPageStyleController) pageStyle]) { - self.sponsorBlockButton = [%c(YTQTMButton) iconButton]; - self.sponsorBlockButton.frame = CGRectMake(0, 0, 40, 40); - - if ([%c(YTPageStyleController) pageStyle]) { //dark mode - [self.sponsorBlockButton setImage:[UIImage imageWithContentsOfFile:[tweakBundle pathForResource:@"sponsorblocksettings-20@2x" ofType:@"png"]] forState:UIControlStateNormal]; - } - else { //light mode - UIImage *image = [UIImage imageWithContentsOfFile:[tweakBundle pathForResource:@"sponsorblocksettings-20@2x" ofType:@"png"]]; - image = [image imageWithTintColor:UIColor.blackColor renderingMode:UIImageRenderingModeAlwaysTemplate]; - [self.sponsorBlockButton setImage:image forState:UIControlStateNormal]; - [self.sponsorBlockButton setTintColor:UIColor.blackColor]; - } - pageStyle = [%c(YTPageStyleController) pageStyle]; - - [self.sponsorBlockButton addTarget:self action:@selector(sponsorBlockButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - [retVal insertObject:self.sponsorBlockButton atIndex:0]; - } - return retVal; -} -- (NSMutableArray *)visibleButtons { - NSMutableArray *retVal = %orig.mutableCopy; - - //fixes button overlapping yt logo on smaller devices - [self setLeadingPadding:-10]; - if (self.sponsorBlockButton) { - [self.sponsorBlockButton removeFromSuperview]; - [self addSubview:self.sponsorBlockButton]; - [retVal insertObject:self.sponsorBlockButton atIndex:0]; - } - return retVal; -} -%new -- (void)sponsorBlockButtonPressed:(UIButton *)sender { - SponsorBlockSettingsController *settingsController = [[SponsorBlockSettingsController alloc] init]; - UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:settingsController]; - [[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:navigationController animated:YES completion:nil]; -} -%end -%end - -static void loadPrefs() { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *path = [documentsDirectory stringByAppendingPathComponent:@"iSponsorBlock.plist"]; - NSMutableDictionary *settings = [NSMutableDictionary dictionary]; - [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:path]]; - kIsEnabled = [settings objectForKey:@"enabled"] ? [[settings objectForKey:@"enabled"] boolValue] : YES; - - kUserID = [settings objectForKey:@"userID"] ? [settings objectForKey:@"userID"] : [[NSUUID UUID] UUIDString]; - // reset to uuid if user set to an empty string - if ([kUserID isEqualToString:@""]) kUserID = [[NSUUID UUID] UUIDString]; - - kAPIInstance = [settings objectForKey:@"apiInstance"] ? [settings objectForKey:@"apiInstance"] : @"https://sponsor.ajay.app/api"; - // reset to official if user set to an empty string - if ([kAPIInstance isEqualToString:@""]) kAPIInstance = @"https://sponsor.ajay.app/api"; - - kCategorySettings = [settings objectForKey:@"categorySettings"] ? [settings objectForKey:@"categorySettings"] : @{ - @"sponsor" : @1, - @"sponsorColor" : hexFromUIColor(UIColor.greenColor), - @"intro" : @0, - @"introColor" : hexFromUIColor(UIColor.systemTealColor), - @"outro" : @0, - @"outroColor" : hexFromUIColor(UIColor.blueColor), - @"interaction" : @0, - @"interactionColor" : hexFromUIColor(UIColor.systemPinkColor), - @"selfpromo" : @0, - @"selfpromoColor" : hexFromUIColor(UIColor.yellowColor), - @"music_offtopic" : @0, - @"music_offtopicColor" : hexFromUIColor(UIColor.orangeColor) - }; - kMinimumDuration = [settings objectForKey:@"minimumDuration"] ? [[settings objectForKey:@"minimumDuration"] floatValue] : 0.0f; - kShowSkipNotice = [settings objectForKey:@"showSkipNotice"] ? [[settings objectForKey:@"showSkipNotice"] boolValue] : YES; - kShowButtonsInPlayer = [settings objectForKey:@"showButtonsInPlayer"] ? [[settings objectForKey:@"showButtonsInPlayer"] boolValue] : YES; - kHideStartEndButtonInPlayer = [settings objectForKey:@"hideStartEndButtonInPlayer"] ? [[settings objectForKey:@"hideStartEndButtonInPlayer"] boolValue] : NO; - kShowModifiedTime = [settings objectForKey:@"showModifiedTime"] ? [[settings objectForKey:@"showModifiedTime"] boolValue] : YES; - kSkipAudioNotification = [settings objectForKey:@"skipAudioNotification"] ? [[settings objectForKey:@"skipAudioNotification"] boolValue] : NO; - kEnableSkipCountTracking = [settings objectForKey:@"enableSkipCountTracking"] ? [[settings objectForKey:@"enableSkipCountTracking"] boolValue] : YES; - kSkipNoticeDuration = [settings objectForKey:@"skipNoticeDuration"] ? [[settings objectForKey:@"skipNoticeDuration"] floatValue] : 3.0f; - kWhitelistedChannels = [settings objectForKey:@"whitelistedChannels"] ? [(NSArray *)[settings objectForKey:@"whitelistedChannels"] mutableCopy] : [NSMutableArray array]; - - NSDictionary *newSettings = @{ - @"enabled" : @(kIsEnabled), - @"userID" : kUserID, - @"apiInstance" : kAPIInstance, - @"categorySettings" : kCategorySettings, - @"minimumDuration" : @(kMinimumDuration), - @"showSkipNotice" : @(kShowSkipNotice), - @"showButtonsInPlayer" : @(kShowButtonsInPlayer), - @"hideStartEndButtonInPlayer" : @(kHideStartEndButtonInPlayer), - @"showModifiedTime" : @(kShowModifiedTime), - @"skipAudioNotification" : @(kSkipAudioNotification), - @"enableSkipCountTracking" : @(kEnableSkipCountTracking), - @"skipNoticeDuration" : @(kSkipNoticeDuration), - @"whitelistedChannels" : kWhitelistedChannels - }; - if (![newSettings isEqualToDictionary:settings]) { - [newSettings writeToURL:[NSURL fileURLWithPath:path isDirectory:NO] error:nil]; - } - -} - -%group LateLoad - -%hook YTAppDelegate - -- (BOOL)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2 { - BOOL orig = %orig; - loadPrefs(); - if (kIsEnabled) { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - if (dlopen(ROOT_PATH("/Library/MobileSubstrate/DynamicLibraries/Cercube.dylib"), RTLD_LAZY)) { - %init(Cercube) - NSString *downloadsDirectory = [documentsDirectory stringByAppendingPathComponent:@"Carida_Files"]; - NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:downloadsDirectory error:nil]; - for (NSString *path in files) { - if ([path.pathExtension isEqualToString:@"plist"]) { - NSString *mp4Path = [downloadsDirectory stringByAppendingPathComponent:[[path stringByDeletingPathExtension] stringByAppendingPathExtension:@"mp4"]]; - BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:mp4Path]; - if (!fileExists) { - [[NSFileManager defaultManager] removeItemAtPath:[downloadsDirectory stringByAppendingPathComponent:path] error:nil]; - } - } - } - } - %init(Main); - } - return orig; -} - -%end - -%end - -static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { - loadPrefs(); -} - -%ctor { - CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.galacticdev.isponsorblockprefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); - %init(LateLoad); - %init(JustSettings); -} - -%dtor { - if (dlopen(ROOT_PATH("/Library/MobileSubstrate/DynamicLibraries/Cercube.dylib"), RTLD_LAZY)) { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *downloadsDirectory = [documentsDirectory stringByAppendingPathComponent:@"Carida_Files"]; - NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:downloadsDirectory error:nil]; - for (NSString *path in files) { - if ([path.pathExtension isEqualToString:@"plist"]) { - NSString *mp4Path = [downloadsDirectory stringByAppendingPathComponent:[[path stringByDeletingPathExtension] stringByAppendingPathExtension:@"mp4"]]; - BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:mp4Path]; - if (!fileExists) { - [[NSFileManager defaultManager] removeItemAtPath:[downloadsDirectory stringByAppendingPathComponent:path] error:nil]; - } - } - } - } -} diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/Info.plist b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/Info.plist deleted file mode 100644 index 7755de5..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/Info.plist and /dev/null differ diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/LogoSponsorBlocker128px.png b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/LogoSponsorBlocker128px.png deleted file mode 100644 index 34ad275..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/LogoSponsorBlocker128px.png and /dev/null differ diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/PlayerInfoIconSponsorBlocker256px-20@2x.png b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/PlayerInfoIconSponsorBlocker256px-20@2x.png deleted file mode 100644 index 7f2cf8e..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/PlayerInfoIconSponsorBlocker256px-20@2x.png and /dev/null differ diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/SponsorAudio.m4a b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/SponsorAudio.m4a deleted file mode 100644 index 5a59874..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/SponsorAudio.m4a and /dev/null differ diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/en.lproj/Localizable.strings b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/en.lproj/Localizable.strings deleted file mode 100644 index 2d97f1a..0000000 --- a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/en.lproj/Localizable.strings +++ /dev/null @@ -1,86 +0,0 @@ -/* iSponsorBlock Settings */ -"Enabled" = "Enabled"; -"RestartFooter" = "Restart YouTube for changes to take effect"; - -"Sponsor" = "Sponsor"; -"Intermission/IntroAnimation" = "Intermission/Intro Animation"; -"Intermission" = "Intermission"; -"Endcards/Credits" = "Endcards/Credits"; -"Outro" = "Outro"; -"InteractionReminder" = "Interaction Reminder (Subscribe)"; -"InteractionReminder_Subcribe/Like" = "Interaction Reminder (Subcribe/Like)"; -"Interaction" = "Interaction"; -"Unpaid/SelfPromotion" = "Unpaid/Self Promotion"; -"SelfPromo" = "Self Promo"; -"Non-MusicSection" = "Music: Non-Music Section"; -"Non-Music" = "Non-Music"; -"SponsorBlockUserID" = "SponsorBlock User ID"; -"SponsorBlockAPIInstance" = "SponsorBlock API Instance"; - -"Disable" = "Disable"; -"AutoSkip" = "Auto Skip"; -"ShowInSeekBar" = "Show in Seek Bar"; -"ManualSkip" = "Manual Skip"; -"SetColorToShowInSeekBar" = "Set Color To Show in Seek Bar"; - -"UserID" = "User ID:"; -"UserIDFooter" = "If you want to use a custom SponsorBlock user ID, you can enter it here. If you don't know what this is, leave it as default."; -"API_URL" = "API URL:"; -"APIFooter" = "If you want to use a custom SponsorBlock API instance, you can enter it here. If you don't know what this is, leave it as default. Example:https://sponsor.ajay.app/api"; -"MinimumSegmentDuration" = "Set Minimum Segment Duration:"; -"HowLongNoticeWillAppear" = "Set How Long Skip Notice Will Appear:"; -"ShowSkipNotice" = "Show Skip Notice"; -"ShowButtonsInPlayer" = "Show iSponsorBlock Buttons in Video Player"; -"HideStartEndButtonInPlayer" = "Hide Start/End Button in Video Player"; -"ShowModifiedTime" = "Show Modified Time in Seek Bar"; -"AudioNotificationOnSkip" = "Audio Notification on Skip"; -"AudioFooter" = "Unavailable in silent mode"; -"EnableSkipCountTracking" = "Enable Skip Count Tracking"; -"DonateOnVenmo" = "Donate on Venmo"; -"DonateOnPayPal" = "Donate on PayPal"; - -/* Segments stuff */ -"SegmentStartsNow" = "Segment Starts Now"; -"SegmentEndsNow" = "Segment Ends Now"; -"WhitelistChannel" = "Whitelist Channel"; -"SegmentsInDatabase" = "There are already segments in the database:"; -"YourSegments" = "Your Segments:"; -"SubmitSegments" = "Submit Segments"; -"SuccessfullySubmittedSegments" = "Successfully Submitted Segments"; -"EndTimeLessThanStartTime" = "End Time That You Set Was Less Than the Start Time, Please Select a Time After"; //Example: ..., Please Select a Time After 10:15 -"UnfinishedSegments" = "You Have Unfinished Segments\n Please Add a Category and/or End Time to Your Segments"; -"EditStartTime" = "Edit Start Time"; -"EditStartTime_Desc" = "Edit Start Time: (ex. type 1:15)"; -"EditEndTime" = "Edit End Time"; -"EditEndTime_Desc" = "Edit End Time: (ex. type 1:15)"; -"From" = "From"; // Time. Example: From 1:15 to 3:00. If you dont need it, just leave empty -"to" = "to"; // Time. Example: From 1:15 to 3:00 -"EditCategory" = "Edit Category"; -"EditSegment" = "Edit Segment"; -"Edit" = "Edit"; -"Error" = "Error"; -"ErrorCode" = "Error Code"; -"Success" = "Success"; -"OK" = "OK"; -"Cancel" = "Cancel"; -"Delete" = "Delete"; -"Upvote" = "Upvote"; -"Downvote" = "Downvote"; -"VoteToChangeCategory" = "Vote to Change Category"; -"VoteOnSegment" = "Vote on Segment"; -"SuccessfullyVoted" = "Successfully Voted"; -"ErrorVoting" = "Error Voting"; - -/* Pop-ups*/ -"ManuallySkipReminder" = "Manually Skip %@ segment\nfrom %ld:%02ld to %ld:%02ld?"; -"Skip" = "Skip"; -"SkippedSegment" = "Skipped %@ Segment"; -"Unskip" = "Unskip"; - -/* Segments in pop-ups*/ -"sponsor" = "sponsor"; -"intro" = "intro"; -"outro" = "outro"; -"interaction" = "interaction"; -"selfpromo" = "self promo"; -"music_offtopic" = "non-music"; diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/ru.lproj/Localizable.strings b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/ru.lproj/Localizable.strings deleted file mode 100644 index 41b73ed..0000000 --- a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/ru.lproj/Localizable.strings +++ /dev/null @@ -1,86 +0,0 @@ -/* iSponsorBlock Settings */ -"Enabled" = "Активировать iSponsorBlock"; -"RestartFooter" = "Для применения настроек перезапустите YouTube"; - -"Sponsor" = "Спонсорская реклама"; -"Intermission/IntroAnimation" = "Вступление/Интервалы"; -"Intermission" = "Вступление"; -"Endcards/Credits" = "Конечные заставки/Титры"; -"Outro" = "Концовка"; -"InteractionReminder" = "Взаимодействие (Подписаться)"; -"InteractionReminder_Subcribe/Like" = "Взаимодействие (Лайк/Подписка)"; -"Interaction" = "Взаимодействие"; -"Unpaid/SelfPromotion" = "Самореклама"; -"SelfPromo" = "Самореклама"; -"Non-MusicSection" = "Музыка: Сегмент без музыки"; -"Non-Music" = "Сегмент без музыки"; -"SponsorBlockUserID" = "Идентификатор SponsorBlock"; -"SponsorBlockAPIInstance" = "Используемый API"; - -"Disable" = "Выкл"; -"AutoSkip" = "Перематывать"; -"ShowInSeekBar" = "Игнорировать"; -"ManualSkip" = "Вручную"; -"SetColorToShowInSeekBar" = "Цвет сегмента, отображаемый в плеере"; - -"UserID" = "Ваш ID:"; -"UserIDFooter" = "Если вы хотите использовать другой идентификатор пользователя SponsorBlock, то можете ввести его в окне выше. Если же вы не знаете, что это такое, то оставьте как есть."; -"API_URL" = "Ссылка на API:"; -"APIFooter" = "Если вы хотите использовать альтернативый API, то можете ввести его в окне выше. Если же вы не знаете, что это такое, то оставьте адрес по умолчанию. Адрес по умолчанию: https://sponsor.ajay.app/api"; -"MinimumSegmentDuration" = "Минимальная длина рекламы:"; -"HowLongNoticeWillAppear" = "Длительность уведомлений:"; -"ShowSkipNotice" = "Отображать уведомления о перемотке"; -"ShowButtonsInPlayer" = "Отображать кнопки твика в плеере"; -"HideStartEndButtonInPlayer" = "Скрыть кнопку создания меток"; -"ShowModifiedTime" = "Отображать сокращенное время в плеере"; -"AudioNotificationOnSkip" = "Аудиоуведомление о перемотке"; -"AudioFooter" = "Недоступно в беззвучном режиме"; -"EnableSkipCountTracking" = "Включить подсчет пропущенной рекламы"; -"DonateOnVenmo" = "Задонатить в Venmo"; -"DonateOnPayPal" = "Задонатить в PayPal"; - -/* Segments stuff */ -"SegmentStartsNow" = "Начало сегмента"; -"SegmentEndsNow" = "Конец сегмента"; -"WhitelistChannel" = "В белый список"; -"SegmentsInDatabase" = "Сегменты в базе данных:"; -"YourSegments" = "Ваши сегменты:"; -"SubmitSegments" = "Отправить"; -"SuccessfullySubmittedSegments" = "Успешно отправлено"; -"EndTimeLessThanStartTime" = "Выбранное вами время конца сегмента находится раньше начала сегмента. Выберите время после"; //Example: ..., Please Select a Time After 10:15 -"UnfinishedSegments" = "Имеются неполноценные сегменты.\nУбедитесь, что вы выбрали категорию и/или время окончания сегмента"; -"EditStartTime" = "Изменить начало сегмента"; -"EditStartTime_Desc" = "Время начала: (Например: 1:15)"; -"EditEndTime" = "Изменить окончание сегмента"; -"EditEndTime_Desc" = "Время окончания: (Например: 1:15)"; -"From" = "С"; // Time. Example: From 1:15 to 3:00. If you dont need it, just leave empty -"to" = "по"; // Time. Example: From 1:15 to 3:00 -"EditCategory" = "Изменить категорию"; -"EditSegment" = "Изменить сегмент"; -"Edit" = "Изменить"; -"Error" = "Ошибка"; -"ErrorCode" = "Код ошибки"; -"Success" = "Готово"; -"OK" = "OK"; -"Cancel" = "Отмена"; -"Delete" = "Удалить"; -"Upvote" = "Проголосовать за"; -"Downvote" = "Проголосовать против"; -"VoteToChangeCategory" = "Проголосовать за смену категории"; -"VoteOnSegment" = "Проголосовать за сегмент"; -"SuccessfullyVoted" = "Голос отправлен"; -"ErrorVoting" = "Ошибка голосования"; - -/* Pop-ups*/ -"ManuallySkipReminder" = "Перемотать %@ с %ld:%02ld до %ld:%02ld?"; -"Skip" = "Да"; -"SkippedSegment" = "Перемотан\n%@"; -"Unskip" = "Отмена"; - -/* Segments in pop-ups*/ -"sponsor" = "спонсорский\nсегмент"; -"intro" = "сегмент со\nвступлением"; -"outro" = "сегмент\nс титрами"; -"interaction" = "сегмент со\nвзаимодействием"; -"selfpromo" = "сегмент с\nсаморекламой"; -"music_offtopic" = "сегмент\nбез музыки"; diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblockend-20@2x.png b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblockend-20@2x.png deleted file mode 100644 index 25075b7..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblockend-20@2x.png and /dev/null differ diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblocksettings-20@2x.png b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblocksettings-20@2x.png deleted file mode 100644 index 0783502..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblocksettings-20@2x.png and /dev/null differ diff --git a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblockstart-20@2x.png b/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblockstart-20@2x.png deleted file mode 100644 index 2a49f5c..0000000 Binary files a/Tweaks/iSponsorBlock/layout/Library/Application Support/iSponsorBlock.bundle/sponsorblockstart-20@2x.png and /dev/null differ