updated submodules
6
.gitmodules
vendored
@@ -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
|
||||
|
1
Extensions
Submodule
2
Extensions/.gitattributes
vendored
@@ -1,2 +0,0 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
1
Extensions/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
.DS_Store
|
@@ -1,333 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Info.plist</key>
|
||||
<data>
|
||||
5KaPBsMVTGZfcc05Od8nGW6/EyQ=
|
||||
</data>
|
||||
<key>_locales/en/messages.json</key>
|
||||
<data>
|
||||
8cPkszxzYFSjhRWsf34A0AiHaPM=
|
||||
</data>
|
||||
<key>background.js</key>
|
||||
<data>
|
||||
tClFxbnUm0L65Qj+Qu8Fk9asL2o=
|
||||
</data>
|
||||
<key>content.js</key>
|
||||
<data>
|
||||
a6o4B4PMlrIOBXlniU2NS4D9SJE=
|
||||
</data>
|
||||
<key>embedded.mobileprovision</key>
|
||||
<data>
|
||||
dVGLS8Qpu/eCI1J5VCu9IfYq3Z4=
|
||||
</data>
|
||||
<key>images/cat_1.0.gif</key>
|
||||
<data>
|
||||
DtSTnvB7wRt647kM1b38KLfDfXA=
|
||||
</data>
|
||||
<key>images/icon-128.png</key>
|
||||
<data>
|
||||
rYa1lv1LgkO3fkP9h6gRSjlQgqk=
|
||||
</data>
|
||||
<key>images/icon-256.png</key>
|
||||
<data>
|
||||
05xbekvTg28KsH9RRIKQRL8tqQs=
|
||||
</data>
|
||||
<key>images/icon-48.png</key>
|
||||
<data>
|
||||
BWUZe8raKzOzA2cDWIYFoBPxxw8=
|
||||
</data>
|
||||
<key>images/icon-512.png</key>
|
||||
<data>
|
||||
shzpVHJMsAu4q820Fb+YzByiFhc=
|
||||
</data>
|
||||
<key>images/icon-64.png</key>
|
||||
<data>
|
||||
HZC4YIb4ZLg4lpjNAKFqSaka6r0=
|
||||
</data>
|
||||
<key>images/icon-96.png</key>
|
||||
<data>
|
||||
IPAOd1HfCtCI7ybhVhwA5TU/BZ8=
|
||||
</data>
|
||||
<key>images/toolbar-icon-16.png</key>
|
||||
<data>
|
||||
Bkb2Cy8VYIcWl7wFZ2HcWZcCoyA=
|
||||
</data>
|
||||
<key>images/toolbar-icon-19.png</key>
|
||||
<data>
|
||||
XLkdODJ73CVbwn/1LCAsfB6scPg=
|
||||
</data>
|
||||
<key>images/toolbar-icon-32.png</key>
|
||||
<data>
|
||||
0cQgf/z3urGdzsmtmc2Wnim1+lg=
|
||||
</data>
|
||||
<key>images/toolbar-icon-38.png</key>
|
||||
<data>
|
||||
eas7Tl3/r2JMZf6nK84ZjoBJrZo=
|
||||
</data>
|
||||
<key>images/toolbar-icon-48.png</key>
|
||||
<data>
|
||||
fxyz1xgkIR877Cf/7uYNUqXrxoM=
|
||||
</data>
|
||||
<key>images/toolbar-icon-72.png</key>
|
||||
<data>
|
||||
pHL3CJwjPY30T9sFvvcA2qlraBw=
|
||||
</data>
|
||||
<key>manifest.json</key>
|
||||
<data>
|
||||
b37QyqMYHlvlfOjbvJLOKeAM5Y4=
|
||||
</data>
|
||||
<key>popup.css</key>
|
||||
<data>
|
||||
mXR2qQxu+ceMOItNpc4aImux5wY=
|
||||
</data>
|
||||
<key>popup.html</key>
|
||||
<data>
|
||||
zTk6QImmvcZjMYLQY8ek+cqSEWg=
|
||||
</data>
|
||||
<key>popup.js</key>
|
||||
<data>
|
||||
grmSQBg1aRbGzHHjd3TWHS/HbOY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>_locales/en/messages.json</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
4pOaVgBrOGGIoI81XdEOZidIyW9peYtz85HIYX7d1QE=
|
||||
</data>
|
||||
</dict>
|
||||
<key>background.js</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
2S7ONYvdkGsryEavyrR7nMCTwsjNGqMV2BSWIxWLSYg=
|
||||
</data>
|
||||
</dict>
|
||||
<key>content.js</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
9CYz6yZ8bRI2JRzRwnn4DOGuPuy2GSsOudXSZU6s1po=
|
||||
</data>
|
||||
</dict>
|
||||
<key>embedded.mobileprovision</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
4TQyzTTz0VYUTM0IXf2PMSufVEkzd4WlPWbwKMyfKfQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/cat_1.0.gif</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
65Ql3FhfivRMoMifbuY5KK8I/1rZx/Zmmwsx1La4OyI=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/icon-128.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
TV8I8bcVP9rAnVA4AJRAWtkJveIenMpYsd/7+rsMLzo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/icon-256.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
kksdsW0Y1svz0bT0i3UzQGBmBDxJGr2eTCZmaqTS+XM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/icon-48.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
mBNPpZ78p0eH4WsNdF/EXw/sFHq5f8PqERARlLulYbY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/icon-512.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
waQn18oFc3GbhXXm2HEn6xFQk3HKehp9crGljWAMsGQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/icon-64.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
CJwxajQk49Cd0RfR22yEPO6pjDbg+Aa4Ocxi+812CiM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/icon-96.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
zuzRjCepizxOWXh9ftCPth38GUxy1Ea/4zS3dw19OXo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/toolbar-icon-16.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
xmXH4YHb+Pq/YuC1e8JLIun93LuM3+/8MvB3r8oTKls=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/toolbar-icon-19.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
qSX/1Ux4BOUIhixJK5NkvyTomLwp0yISfsQ97uF8/5g=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/toolbar-icon-32.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
pGDg4NcSdD5EQaZgaiwxNosbSEXmZnpRc79RfitKc1c=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/toolbar-icon-38.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
BUU3dwrCSvNOiFkBQWdPkrwASjUvxSxbizW+Izt3LBA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/toolbar-icon-48.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
JLZV5da+fZkfw0m2KfMqHSixWBCJvZoUNlt3la7gm54=
|
||||
</data>
|
||||
</dict>
|
||||
<key>images/toolbar-icon-72.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
TwM7A1Bkuv4C3SWorFNwG+w38mWo3TaMtglLdDXxcFw=
|
||||
</data>
|
||||
</dict>
|
||||
<key>manifest.json</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
+nWdvS9ap7YzpjqKSWsGUHP5K2irkTGozQX/tI4WrYc=
|
||||
</data>
|
||||
</dict>
|
||||
<key>popup.css</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
LIfF3an8mzKIMD8PDhKILnrZBhxxSTzoZQKyRiyWuB0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>popup.html</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
9Ro1fCC5Meq0eSNrYab7V3uc4tNvmwRqMsCb1757M6Q=
|
||||
</data>
|
||||
</dict>
|
||||
<key>popup.js</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
ruLXAORE+vDoLKPGBSkl7hnXv8V+ZexCoX3KvJyHxBk=
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@@ -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."
|
||||
}
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
console.log("Received request: ", request);
|
||||
|
||||
if (request.greeting === "hello")
|
||||
sendResponse({ farewell: "goodbye" });
|
||||
});
|
@@ -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();
|
||||
|
||||
|
Before Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 454 B |
Before Width: | Height: | Size: 569 B |
Before Width: | Height: | Size: 919 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.1 KiB |
@@ -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": [ ]
|
||||
}
|
@@ -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. */
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
<script type="module" src="popup.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
body {
|
||||
background-image:url('images/cat_1.0.gif');
|
||||
background-size:100%;
|
||||
background-repeat: repeat-y;
|
||||
background-attachment: fixed;
|
||||
height:100%;
|
||||
width:100%;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<strong>Extension made by @CokePokes</strong>
|
||||
</body>
|
||||
</html>
|
@@ -1 +0,0 @@
|
||||
console.log("Hello World!", browser);
|
@@ -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!
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,157 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Base.lproj/MainInterface.storyboardc/Info.plist</key>
|
||||
<data>
|
||||
Bgt43YuQd48Y7NBkKAH/I1Nd+7Q=
|
||||
</data>
|
||||
<key>Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib</key>
|
||||
<data>
|
||||
t/rVTMy59WLCl0e0ydlT2JlJKIs=
|
||||
</data>
|
||||
<key>Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib</key>
|
||||
<data>
|
||||
56s4vIzFNrq5HEvB3Mr6qnqVRFg=
|
||||
</data>
|
||||
<key>Info.plist</key>
|
||||
<data>
|
||||
7+n2S5sS/Ngeoe21gJMc6iC6+ac=
|
||||
</data>
|
||||
<key>embedded.mobileprovision</key>
|
||||
<data>
|
||||
dVGLS8Qpu/eCI1J5VCu9IfYq3Z4=
|
||||
</data>
|
||||
<key>icon.png</key>
|
||||
<data>
|
||||
/pip+c1EETgjhxNcOhgiyQxxzyU=
|
||||
</data>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>Base.lproj/MainInterface.storyboardc/Info.plist</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
Qnp5pVqL/lRCSEISDYZs1VBLxfcEnfpOzHg6WgcgLgk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Base.lproj/MainInterface.storyboardc/UIViewController-j1y-V4-xli.nib</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
VpQww1vK2BoM0RIaiw/B/8JZ3kp5Pks5bM8Sjtjju9w=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Base.lproj/MainInterface.storyboardc/j1y-V4-xli-view-wbc-yd-nQP.nib</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
C87FO0vFlvhG8vp7+3v+EcR9kbOeu9v+mDLy/iU+6e8=
|
||||
</data>
|
||||
</dict>
|
||||
<key>embedded.mobileprovision</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
4TQyzTTz0VYUTM0IXf2PMSufVEkzd4WlPWbwKMyfKfQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>icon.png</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
mfufJ0CJyFLUpRnLC8q8awHkGqmWeQtRDgF5EBXKUQs=
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@@ -1,7 +0,0 @@
|
||||
var GetURL = function() {};
|
||||
GetURL.prototype = {
|
||||
run: function(arguments) {
|
||||
arguments.completionFunction({"URL": document.URL});
|
||||
}
|
||||
};
|
||||
var ExtensionPreprocessingJS = new GetURL;
|
1
Tweaks/Alderis
Submodule
16
Tweaks/Alderis/.gitignore
vendored
@@ -1,16 +0,0 @@
|
||||
# Crap
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.xcuserstate
|
||||
|
||||
# Carthage
|
||||
Carthage/
|
||||
|
||||
# Theos
|
||||
.theos
|
||||
packages/
|
@@ -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
|
@@ -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: '(?<!iOS\s)(?<!macOS\s)(?<!\.)\b[\d_]+\.0\b'
|
||||
match_kinds:
|
||||
- number
|
||||
- attribute.builtin
|
||||
message: "Don't add a .0 to the end of floating point literals"
|
||||
color_init:
|
||||
name: "Color Initializer"
|
||||
regex: 'UIColor\(red: (.+), green: \1, blue: \1, alpha: .+\)'
|
||||
message: "Use UIColor(white:alpha:)"
|
||||
force_try: warning
|
||||
force_cast: warning
|
||||
function_body_length: 200
|
||||
line_length: 200
|
||||
file_length: 450
|
||||
cyclomatic_complexity: 12
|
||||
function_parameter_count: 7
|
@@ -1,30 +0,0 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Alderis"
|
||||
spec.version = "1.2.0"
|
||||
spec.summary = "A fresh new color picker, with a gentle, fun, and dead simple user interface."
|
||||
spec.description = <<-DESC
|
||||
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.
|
||||
DESC
|
||||
spec.homepage = "https://github.com/hbang/Alderis"
|
||||
spec.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"
|
||||
spec.license = "Apache License, Version 2.0"
|
||||
spec.author = "HASHBANG Productions"
|
||||
spec.social_media_url = "https://twitter.com/hashbang"
|
||||
|
||||
spec.swift_versions = "5.0"
|
||||
spec.platform = :ios, "12.0"
|
||||
|
||||
spec.source = { :git => "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
|
@@ -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 = "<group>"; };
|
||||
4E1C74162826C1F100227EC3 /* ColorPickerAccessibilityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerAccessibilityViewController.swift; sourceTree = "<group>"; };
|
||||
4E1C741828276D5600227EC3 /* TextViewLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewLabel.swift; sourceTree = "<group>"; };
|
||||
4E1C741A2827829E00227EC3 /* AccessibilityComplianceLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityComplianceLabel.swift; sourceTree = "<group>"; };
|
||||
4E1C741C2827882600227EC3 /* AccessibilityContrastSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityContrastSelector.swift; sourceTree = "<group>"; };
|
||||
4E1C741E2827B3C800227EC3 /* UIFloat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFloat.swift; sourceTree = "<group>"; };
|
||||
4E1C74202827B8F800227EC3 /* NSBeep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSBeep.swift; sourceTree = "<group>"; };
|
||||
4E2E6C05282BD5990089E4FB /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = "<group>"; };
|
||||
569C25512427F57000022C60 /* ColorPickerTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerTabViewController.swift; sourceTree = "<group>"; };
|
||||
569C25572428346900022C60 /* ColorPickerMapSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerMapSlider.swift; sourceTree = "<group>"; };
|
||||
56C74666242F722A003ED00A /* ColorPickerSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerSlider.swift; sourceTree = "<group>"; };
|
||||
56C74668242F75E3003ED00A /* ColorPickerNumericSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerNumericSlider.swift; sourceTree = "<group>"; };
|
||||
94A2368B252B5951002B5D0B /* UIColorAdditions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColorAdditions.swift; sourceTree = "<group>"; };
|
||||
CF73D32B241E4720000B1B10 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
|
||||
CF73D32D241E49EE000B1B10 /* ColorWell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorWell.swift; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
CF73D339241F9C23000B1B10 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
CF73D350241F9FB3000B1B10 /* ColorPickerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerDelegate.swift; sourceTree = "<group>"; };
|
||||
CF7750B62520D3B50069CC57 /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = "<group>"; };
|
||||
CF7750BD252203630069CC57 /* DialogButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogButton.swift; sourceTree = "<group>"; };
|
||||
CF7750CE252433680069CC57 /* ColorPickerConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPickerConfiguration.swift; sourceTree = "<group>"; };
|
||||
CF7750D52524615D0069CC57 /* SeparatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeparatorView.swift; sourceTree = "<group>"; };
|
||||
CF775121252852110069CC57 /* AlderisSDKCompatibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AlderisSDKCompatibility.h; sourceTree = "<group>"; };
|
||||
CF79DA30251723C500F17BCB /* BottomSheetTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetTransition.swift; sourceTree = "<group>"; };
|
||||
CFAFFC9024277CEE005AD4C1 /* Assets-ios12.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Assets-ios12.xcassets"; sourceTree = "<group>"; };
|
||||
CFE70273241A4C5500083903 /* ColorPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerViewController.swift; sourceTree = "<group>"; };
|
||||
CFE7027B241A62ED00083903 /* ColorPickerInnerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerInnerViewController.swift; sourceTree = "<group>"; };
|
||||
CFE7027E241B984600083903 /* ColorPickerSwatchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerSwatchViewController.swift; sourceTree = "<group>"; };
|
||||
CFE70280241CBDE700083903 /* ColorPickerMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerMapViewController.swift; sourceTree = "<group>"; };
|
||||
CFE70282241CC88D00083903 /* ColorPickerSlidersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerSlidersViewController.swift; sourceTree = "<group>"; };
|
||||
CFE70288241D0E7300083903 /* ColorPickerWheelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerWheelView.swift; sourceTree = "<group>"; };
|
||||
/* 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 = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 1;
|
||||
};
|
||||
CF39D43F222BC07C001EF57F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CF73D336241F9C23000B1B10 /* Alderis.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 = "<group>";
|
||||
};
|
||||
/* 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 */;
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Alderis Demo.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1330"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "CF73D335241F9C23000B1B10"
|
||||
BuildableName = "Alderis.framework"
|
||||
BlueprintName = "Alderis"
|
||||
ReferencedContainer = "container:Alderis.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "CF73D335241F9C23000B1B10"
|
||||
BuildableName = "Alderis.framework"
|
||||
BlueprintName = "Alderis"
|
||||
ReferencedContainer = "container:Alderis.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@@ -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
|
||||
}
|
||||
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
||||
}
|
@@ -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"
|
@@ -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
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 310 B |
Before Width: | Height: | Size: 661 B |
Before Width: | Height: | Size: 942 B |
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 606 B |
Before Width: | Height: | Size: 909 B |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 169 B |
Before Width: | Height: | Size: 287 B |
Before Width: | Height: | Size: 377 B |
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 184 B |
Before Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 427 B |
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 164 B |
Before Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 383 B |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 229 B |
Before Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 574 B |
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 507 B |
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 189 B |
Before Width: | Height: | Size: 309 B |
Before Width: | Height: | Size: 412 B |
@@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 211 B |
Before Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 419 B |
@@ -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)
|
||||
}
|
||||
|
||||
}
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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<Color, CGFloat>
|
||||
let limit: CGFloat
|
||||
let title: String
|
||||
private let sliderTintColorForColor: (Color) -> [Color]
|
||||
|
||||
init(
|
||||
keyPath: WritableKeyPath<Color, CGFloat>,
|
||||
limit: CGFloat,
|
||||
title: String,
|
||||
sliderTintColorForColor: @escaping (Color) -> [Color]
|
||||
) {
|
||||
self.keyPath = keyPath
|
||||
self.limit = limit
|
||||
self.title = title
|
||||
self.sliderTintColorForColor = sliderTintColorForColor
|
||||
}
|
||||
|
||||
init(
|
||||
keyPath: WritableKeyPath<Color, CGFloat>,
|
||||
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)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
||||
}
|
@@ -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
|
||||
|
||||
}
|
@@ -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)
|
||||
|
||||
}
|
@@ -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..<tabsView.numberOfSegments {
|
||||
tabsView.setWidth(40, forSegmentAt: i)
|
||||
}
|
||||
}
|
||||
|
||||
let pageViewContainer = UIView()
|
||||
pageViewContainer.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])
|
||||
pageViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
pageViewController.willMove(toParent: self)
|
||||
addChild(pageViewController)
|
||||
pageViewContainer.addSubview(pageViewController.view)
|
||||
|
||||
let mainStackView = UIStackView(arrangedSubviews: [titleView, tabsContainerView, pageViewContainer])
|
||||
mainStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
mainStackView.axis = .vertical
|
||||
mainStackView.alignment = .fill
|
||||
mainStackView.distribution = .fill
|
||||
view.addSubview(mainStackView)
|
||||
|
||||
heightConstraint = pageViewContainer.heightAnchor.constraint(equalToConstant: 0)
|
||||
|
||||
let barHeight: CGFloat = UIFloat(48)
|
||||
let topHeight = (titleView.isHidden ? 0 : barHeight) + (tabsContainerView.isHidden ? 0 : barHeight)
|
||||
let titleLabelTopOffset: CGFloat = tabsContainerView.isHidden ? 0 : 3
|
||||
NSLayoutConstraint.activate([
|
||||
backgroundView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
backgroundView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||
backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
|
||||
mainStackView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
mainStackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||
mainStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
mainStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
|
||||
titleView.heightAnchor.constraint(equalToConstant: barHeight),
|
||||
tabsContainerView.heightAnchor.constraint(equalToConstant: barHeight),
|
||||
|
||||
titleLabel.topAnchor.constraint(equalTo: titleView.topAnchor, constant: titleLabelTopOffset),
|
||||
titleLabel.bottomAnchor.constraint(equalTo: titleView.bottomAnchor),
|
||||
titleLabel.leadingAnchor.constraint(equalTo: titleView.leadingAnchor, constant: 4),
|
||||
titleLabel.trailingAnchor.constraint(equalTo: titleView.trailingAnchor, constant: -4),
|
||||
|
||||
tabsBackgroundView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
tabsBackgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
tabsBackgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
tabsBackgroundView.heightAnchor.constraint(equalToConstant: topHeight),
|
||||
|
||||
tabsCheckerboardView.topAnchor.constraint(equalTo: tabsBackgroundView.topAnchor),
|
||||
tabsCheckerboardView.bottomAnchor.constraint(equalTo: tabsBackgroundView.bottomAnchor),
|
||||
tabsCheckerboardView.leadingAnchor.constraint(equalTo: tabsBackgroundView.leadingAnchor),
|
||||
tabsCheckerboardView.trailingAnchor.constraint(equalTo: tabsBackgroundView.trailingAnchor),
|
||||
|
||||
topSeparatorView.leadingAnchor.constraint(equalTo: tabsBackgroundView.leadingAnchor),
|
||||
topSeparatorView.trailingAnchor.constraint(equalTo: tabsBackgroundView.trailingAnchor),
|
||||
topSeparatorView.bottomAnchor.constraint(equalTo: tabsBackgroundView.bottomAnchor),
|
||||
|
||||
pageViewController.view.topAnchor.constraint(equalTo: pageViewContainer.topAnchor),
|
||||
pageViewController.view.bottomAnchor.constraint(equalTo: pageViewContainer.bottomAnchor),
|
||||
pageViewController.view.leadingAnchor.constraint(equalTo: pageViewContainer.leadingAnchor),
|
||||
pageViewController.view.trailingAnchor.constraint(equalTo: pageViewContainer.trailingAnchor),
|
||||
|
||||
heightConstraint
|
||||
])
|
||||
|
||||
if !isCatalystMac {
|
||||
let buttonsCheckerboardView = UIView()
|
||||
buttonsCheckerboardView.translatesAutoresizingMaskIntoConstraints = false
|
||||
buttonsCheckerboardView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert
|
||||
buttonsCheckerboardView.backgroundColor = Assets.checkerboardPatternColor
|
||||
view.insertSubview(buttonsCheckerboardView, aboveSubview: tabsBackgroundView)
|
||||
|
||||
let buttonsBackgroundView = UIView()
|
||||
buttonsBackgroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||
buttonsBackgroundView.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert
|
||||
view.insertSubview(buttonsBackgroundView, aboveSubview: buttonsCheckerboardView)
|
||||
self.buttonsBackgroundView = buttonsBackgroundView
|
||||
|
||||
let bottomSeparatorView = SeparatorView(direction: .horizontal)
|
||||
bottomSeparatorView.translatesAutoresizingMaskIntoConstraints = false
|
||||
buttonsBackgroundView.addSubview(bottomSeparatorView)
|
||||
|
||||
let cancelButton = DialogButton()
|
||||
cancelButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
cancelButton.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert
|
||||
cancelButton.titleLabel!.font = .systemFont(ofSize: 17, weight: .regular)
|
||||
cancelButton.setTitle(Assets.uikitLocalize("Cancel"), for: .normal)
|
||||
cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
|
||||
self.cancelButton = cancelButton
|
||||
|
||||
let saveButton = DialogButton()
|
||||
saveButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
saveButton.accessibilityIgnoresInvertColors = configuration.overrideSmartInvert
|
||||
saveButton.titleLabel!.font = .systemFont(ofSize: 17, weight: .semibold)
|
||||
saveButton.setTitle(Assets.uikitLocalize("Done"), for: .normal)
|
||||
saveButton.addTarget(self, action: #selector(saveTapped), for: .touchUpInside)
|
||||
self.saveButton = saveButton
|
||||
|
||||
let buttonSeparatorView = SeparatorView(direction: .vertical)
|
||||
buttonSeparatorView.translatesAutoresizingMaskIntoConstraints = false
|
||||
buttonsBackgroundView.addSubview(buttonSeparatorView)
|
||||
|
||||
let buttonsView = UIStackView(arrangedSubviews: [cancelButton, saveButton])
|
||||
buttonsView.translatesAutoresizingMaskIntoConstraints = false
|
||||
buttonsView.axis = .horizontal
|
||||
buttonsView.alignment = .fill
|
||||
mainStackView.addSubview(buttonsView)
|
||||
mainStackView.addArrangedSubview(buttonsView)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
buttonsView.heightAnchor.constraint(equalToConstant: barHeight),
|
||||
|
||||
buttonsBackgroundView.topAnchor.constraint(equalTo: buttonsView.topAnchor),
|
||||
buttonsBackgroundView.bottomAnchor.constraint(equalTo: buttonsView.bottomAnchor),
|
||||
buttonsBackgroundView.leadingAnchor.constraint(equalTo: buttonsView.leadingAnchor),
|
||||
buttonsBackgroundView.trailingAnchor.constraint(equalTo: buttonsView.trailingAnchor),
|
||||
|
||||
buttonSeparatorView.heightAnchor.constraint(equalToConstant: barHeight / 2),
|
||||
buttonSeparatorView.centerXAnchor.constraint(equalTo: buttonsBackgroundView.centerXAnchor),
|
||||
buttonSeparatorView.centerYAnchor.constraint(equalTo: buttonsBackgroundView.centerYAnchor),
|
||||
|
||||
buttonsCheckerboardView.topAnchor.constraint(equalTo: buttonsBackgroundView.topAnchor),
|
||||
buttonsCheckerboardView.bottomAnchor.constraint(equalTo: buttonsBackgroundView.bottomAnchor),
|
||||
buttonsCheckerboardView.leadingAnchor.constraint(equalTo: buttonsBackgroundView.leadingAnchor),
|
||||
buttonsCheckerboardView.trailingAnchor.constraint(equalTo: buttonsBackgroundView.trailingAnchor),
|
||||
|
||||
bottomSeparatorView.leadingAnchor.constraint(equalTo: buttonsBackgroundView.leadingAnchor),
|
||||
bottomSeparatorView.trailingAnchor.constraint(equalTo: buttonsBackgroundView.trailingAnchor),
|
||||
bottomSeparatorView.topAnchor.constraint(equalTo: buttonsBackgroundView.topAnchor),
|
||||
|
||||
cancelButton.widthAnchor.constraint(equalTo: saveButton.widthAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
colorDidChange()
|
||||
tab = configuration.initialTab
|
||||
tabsView?.selectedSegmentIndex = currentTab
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
updateHeightConstraint()
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
updateHeightConstraint()
|
||||
}
|
||||
|
||||
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
|
||||
super.preferredContentSizeDidChange(forChildContentContainer: container)
|
||||
updateHeightConstraint()
|
||||
}
|
||||
|
||||
private func updateHeightConstraint() {
|
||||
heightConstraint.constant = (view.frame.size.width / 12) * 10
|
||||
preferredContentSize = view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
|
||||
}
|
||||
|
||||
@objc private func segmentControlChanged(_ sender: UISegmentedControl) {
|
||||
UIView.animate(withDuration: 0.2) {
|
||||
self.currentTab = self.tabsView.selectedSegmentIndex
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func oldTabButtonTapped(_ sender: UIButton) {
|
||||
UIView.animate(withDuration: 0.2) {
|
||||
self.currentTab = sender.tag
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func cancelTapped() {
|
||||
if !compatibilityMode {
|
||||
delegate?.colorPicker?(colorPicker, didSelect: configuration.color)
|
||||
}
|
||||
delegate?.colorPickerDidCancel?(colorPicker)
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
@objc func saveTapped() {
|
||||
if compatibilityMode {
|
||||
delegate?.colorPicker?(colorPicker, didSelect: color.uiColor)
|
||||
} else {
|
||||
delegate?.colorPicker?(colorPicker, didAccept: color.uiColor)
|
||||
}
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
private func colorDidChange(withSource source: ColorPickerTabViewControllerBase? = nil) {
|
||||
let uiColor = color.uiColor
|
||||
if !compatibilityMode {
|
||||
delegate?.colorPicker?(colorPicker, didSelect: uiColor)
|
||||
}
|
||||
|
||||
let foregroundColor: UIColor = color.isDark ? .white : .black
|
||||
|
||||
view.tintColor = uiColor
|
||||
tabsBackgroundView.backgroundColor = uiColor
|
||||
buttonsBackgroundView?.backgroundColor = uiColor
|
||||
titleLabel.textColor = foregroundColor
|
||||
cancelButton?.setTitleColor(foregroundColor, for: .normal)
|
||||
saveButton?.setTitleColor(foregroundColor, for: .normal)
|
||||
cancelButton?.highlightBackgroundColor = foregroundColor.withAlphaComponent(0.25)
|
||||
saveButton?.highlightBackgroundColor = foregroundColor.withAlphaComponent(0.25)
|
||||
tabsView.setTitleTextAttributes([ .foregroundColor: foregroundColor ], for: .normal)
|
||||
|
||||
if #available(iOS 13, *) {
|
||||
} else {
|
||||
tabsView.tintColor = foregroundColor
|
||||
}
|
||||
|
||||
// Even though `shouldBroadcast: false` avoids recursion if we call setColor on the callee tab,
|
||||
// doing so on ColorPickerSlidersViewController would reset `hexOptions`, leading to a buggy
|
||||
// typing experience in `hexTextField`
|
||||
for tab in tabs where tab != source {
|
||||
tab.setColor(color, shouldBroadcast: false)
|
||||
}
|
||||
|
||||
backgroundView.backgroundColor = uiColor.withAlphaComponent(color.alpha * 0.2)
|
||||
}
|
||||
|
||||
private func tabDidChange(oldValue: Int) {
|
||||
let stuff = {
|
||||
let direction: UIPageViewController.NavigationDirection = self.currentTab < oldValue ? .reverse : .forward
|
||||
self.pageViewController.setViewControllers([self.tabs[self.currentTab]], direction: direction, animated: !isCatalystMac)
|
||||
self.colorDidChange()
|
||||
|
||||
UIView.animate(withDuration: 0.2) {
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
if isCatalystMac {
|
||||
UIView.performWithoutAnimation(stuff)
|
||||
} else {
|
||||
stuff()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ColorPickerInnerViewController: ColorPickerTabDelegate {
|
||||
|
||||
func colorPickerTab(_ tab: ColorPickerTabViewControllerBase, didSelect color: Color) {
|
||||
setColor(color, withSource: tab)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ColorPickerInnerViewController: 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.setColor(Color(uiColor: color), withSource: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ColorPickerInnerViewController: UIPopoverPresentationControllerDelegate {
|
||||
|
||||
/// :nodoc:
|
||||
public func presentationControllerWillDismiss(_ presentationController: UIPresentationController) {
|
||||
saveTapped()
|
||||
}
|
||||
|
||||
}
|
@@ -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")
|
||||
}
|
||||
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
||||
}
|
@@ -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))
|
||||
}
|
||||
}
|