diff --git a/README.md b/.github/README.md
similarity index 96%
rename from README.md
rename to .github/README.md
index 33968fe..15483c4 100644
--- a/README.md
+++ b/.github/README.md
@@ -1,6 +1,6 @@
-
+
@@ -28,7 +28,7 @@
- [ ] [Persian](https://github.com/victor-savinov/user-agent/tree/master/_locales/fa/messages.json) `/fa/`
- [ ] [Finnish](https://github.com/victor-savinov/user-agent/tree/master/_locales/fi/messages.json) `/fi/`
- [ ] [Filipino](https://github.com/victor-savinov/user-agent/tree/master/_locales/fil/messages.json) `/fil/`
-- [ ] [French](https://github.com/victor-savinov/user-agent/tree/master/_locales/fr/messages.json) `/fr/`
+- [x] [French](https://github.com/victor-savinov/user-agent/tree/master/_locales/fr/messages.json) `/fr/`
- [ ] [Gujarati](https://github.com/victor-savinov/user-agent/tree/master/_locales/gu/messages.json) `/gu/`
- [ ] [Hebrew](https://github.com/victor-savinov/user-agent/tree/master/_locales/he/messages.json) `/he/`
- [ ] [Hindi](https://github.com/victor-savinov/user-agent/tree/master/_locales/hi/messages.json) `/hi/`
@@ -63,4 +63,4 @@
- [ ] [Ukrainian](https://github.com/victor-savinov/user-agent/tree/master/_locales/uk/messages.json) `/uk/`
- [ ] [Vietnamese](https://github.com/victor-savinov/user-agent/tree/master/_locales/vi/messages.json) `/vi/`
- [ ] [Chinese (China)](https://github.com/victor-savinov/user-agent/tree/master/_locales/zh_CN/messages.json) `/zh_CN/`
-- [ ] [Chinese (Taiwan)](https://github.com/victor-savinov/user-agent/tree/master/_locales/zh_TW/messages.json) `/zh_TW/`
+- [ ] [Chinese (Taiwan)](https://github.com/victor-savinov/user-agent/tree/master/_locales/zh_TW/messages.json) `/zh_TW/`
\ No newline at end of file
diff --git a/_locales/am/messages.json b/_locales/am/messages.json
index d03d442..c39c031 100644
--- a/_locales/am/messages.json
+++ b/_locales/am/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ar/messages.json b/_locales/ar/messages.json
index d03d442..c39c031 100644
--- a/_locales/ar/messages.json
+++ b/_locales/ar/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/bg/messages.json b/_locales/bg/messages.json
index d03d442..c39c031 100644
--- a/_locales/bg/messages.json
+++ b/_locales/bg/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/bn/messages.json b/_locales/bn/messages.json
index d03d442..c39c031 100644
--- a/_locales/bn/messages.json
+++ b/_locales/bn/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ca/messages.json b/_locales/ca/messages.json
index d03d442..c39c031 100644
--- a/_locales/ca/messages.json
+++ b/_locales/ca/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/cs/messages.json b/_locales/cs/messages.json
index d03d442..c39c031 100644
--- a/_locales/cs/messages.json
+++ b/_locales/cs/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/da/messages.json b/_locales/da/messages.json
index d03d442..c39c031 100644
--- a/_locales/da/messages.json
+++ b/_locales/da/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/de/messages.json b/_locales/de/messages.json
index fc973ca..46c2dbb 100644
--- a/_locales/de/messages.json
+++ b/_locales/de/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/el/messages.json b/_locales/el/messages.json
index d03d442..c39c031 100644
--- a/_locales/el/messages.json
+++ b/_locales/el/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index d03d442..c39c031 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/es/messages.json b/_locales/es/messages.json
index d03d442..c39c031 100644
--- a/_locales/es/messages.json
+++ b/_locales/es/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/et/messages.json b/_locales/et/messages.json
index d03d442..c39c031 100644
--- a/_locales/et/messages.json
+++ b/_locales/et/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/fa/messages.json b/_locales/fa/messages.json
index d03d442..c39c031 100644
--- a/_locales/fa/messages.json
+++ b/_locales/fa/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/fi/messages.json b/_locales/fi/messages.json
index d03d442..c39c031 100644
--- a/_locales/fi/messages.json
+++ b/_locales/fi/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/fil/messages.json b/_locales/fil/messages.json
index d03d442..c39c031 100644
--- a/_locales/fil/messages.json
+++ b/_locales/fil/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json
index e5ef77d..a4e9bc1 100644
--- a/_locales/fr/messages.json
+++ b/_locales/fr/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "À propos"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Apparence"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Navigateur web"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Voiture"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Appareil"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Cacher \"Nous partager...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Langue"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Écran"
},
@@ -95,4 +110,4 @@
"watch": {
"message": "Montre"
}
-}
+}
\ No newline at end of file
diff --git a/_locales/gu/messages.json b/_locales/gu/messages.json
index d03d442..c39c031 100644
--- a/_locales/gu/messages.json
+++ b/_locales/gu/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/he/messages.json b/_locales/he/messages.json
index d03d442..c39c031 100644
--- a/_locales/he/messages.json
+++ b/_locales/he/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json
index d03d442..c39c031 100644
--- a/_locales/hi/messages.json
+++ b/_locales/hi/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/hin/messages.json b/_locales/hin/messages.json
new file mode 100644
index 0000000..c39c031
--- /dev/null
+++ b/_locales/hin/messages.json
@@ -0,0 +1,113 @@
+{
+ "about": {
+ "message": "About"
+ },
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
+ "appearance": {
+ "message": "Appearance"
+ },
+ "audioFormats": {
+ "message": "Audio formats"
+ },
+ "browser": {
+ "message": "Browser"
+ },
+ "cancel": {
+ "message": "Cancel"
+ },
+ "car": {
+ "message": "Car"
+ },
+ "computer": {
+ "message": "Computer"
+ },
+ "cores": {
+ "message": "Cores"
+ },
+ "custom": {
+ "message": "Custom"
+ },
+ "device": {
+ "message": "Device"
+ },
+ "export": {
+ "message": "Export"
+ },
+ "extension": {
+ "message": "Extension"
+ },
+ "flash": {
+ "message": "Flash"
+ },
+ "gameConsole": {
+ "message": "Game console"
+ },
+ "gpu": {
+ "message": "GPU"
+ },
+ "hardware": {
+ "message": "Hardware"
+ },
+ "hideStarUs": {
+ "message": "Hide \"Star us...\""
+ },
+ "import": {
+ "message": "Import"
+ },
+ "language": {
+ "message": "Language"
+ },
+ "languages": {
+ "message": "Languages"
+ },
+ "name": {
+ "message": "Name"
+ },
+ "os": {
+ "message": "OS"
+ },
+ "permissions": {
+ "message": "Permissions"
+ },
+ "phone": {
+ "message": "Phone"
+ },
+ "platform": {
+ "message": "Platform"
+ },
+ "ram": {
+ "message": "RAM"
+ },
+ "reset": {
+ "message": "Reset"
+ },
+ "screen": {
+ "message": "Screen"
+ },
+ "settings": {
+ "message": "Settings"
+ },
+ "software": {
+ "message": "Software"
+ },
+ "tablet": {
+ "message": "Tablet"
+ },
+ "tv": {
+ "message": "TV"
+ },
+ "type": {
+ "message": "Type"
+ },
+ "version": {
+ "message": "Version"
+ },
+ "videoFormats": {
+ "message": "Video formats"
+ },
+ "watch": {
+ "message": "Watch"
+ }
+}
\ No newline at end of file
diff --git a/_locales/hr/messages.json b/_locales/hr/messages.json
index d03d442..c39c031 100644
--- a/_locales/hr/messages.json
+++ b/_locales/hr/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/hu/messages.json b/_locales/hu/messages.json
index d03d442..c39c031 100644
--- a/_locales/hu/messages.json
+++ b/_locales/hu/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/id/messages.json b/_locales/id/messages.json
index d03d442..c39c031 100644
--- a/_locales/id/messages.json
+++ b/_locales/id/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/it/messages.json b/_locales/it/messages.json
index d03d442..c39c031 100644
--- a/_locales/it/messages.json
+++ b/_locales/it/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json
index d03d442..c39c031 100644
--- a/_locales/ja/messages.json
+++ b/_locales/ja/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/kn/messages.json b/_locales/kn/messages.json
index d03d442..c39c031 100644
--- a/_locales/kn/messages.json
+++ b/_locales/kn/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json
index d03d442..c39c031 100644
--- a/_locales/ko/messages.json
+++ b/_locales/ko/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/lt/messages.json b/_locales/lt/messages.json
index d03d442..c39c031 100644
--- a/_locales/lt/messages.json
+++ b/_locales/lt/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/lv/messages.json b/_locales/lv/messages.json
index d03d442..c39c031 100644
--- a/_locales/lv/messages.json
+++ b/_locales/lv/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ml/messages.json b/_locales/ml/messages.json
index d03d442..c39c031 100644
--- a/_locales/ml/messages.json
+++ b/_locales/ml/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/mr/messages.json b/_locales/mr/messages.json
index d03d442..c39c031 100644
--- a/_locales/mr/messages.json
+++ b/_locales/mr/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ms/messages.json b/_locales/ms/messages.json
index d03d442..c39c031 100644
--- a/_locales/ms/messages.json
+++ b/_locales/ms/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/nb_NO/messages.json b/_locales/nb_NO/messages.json
new file mode 100644
index 0000000..c39c031
--- /dev/null
+++ b/_locales/nb_NO/messages.json
@@ -0,0 +1,113 @@
+{
+ "about": {
+ "message": "About"
+ },
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
+ "appearance": {
+ "message": "Appearance"
+ },
+ "audioFormats": {
+ "message": "Audio formats"
+ },
+ "browser": {
+ "message": "Browser"
+ },
+ "cancel": {
+ "message": "Cancel"
+ },
+ "car": {
+ "message": "Car"
+ },
+ "computer": {
+ "message": "Computer"
+ },
+ "cores": {
+ "message": "Cores"
+ },
+ "custom": {
+ "message": "Custom"
+ },
+ "device": {
+ "message": "Device"
+ },
+ "export": {
+ "message": "Export"
+ },
+ "extension": {
+ "message": "Extension"
+ },
+ "flash": {
+ "message": "Flash"
+ },
+ "gameConsole": {
+ "message": "Game console"
+ },
+ "gpu": {
+ "message": "GPU"
+ },
+ "hardware": {
+ "message": "Hardware"
+ },
+ "hideStarUs": {
+ "message": "Hide \"Star us...\""
+ },
+ "import": {
+ "message": "Import"
+ },
+ "language": {
+ "message": "Language"
+ },
+ "languages": {
+ "message": "Languages"
+ },
+ "name": {
+ "message": "Name"
+ },
+ "os": {
+ "message": "OS"
+ },
+ "permissions": {
+ "message": "Permissions"
+ },
+ "phone": {
+ "message": "Phone"
+ },
+ "platform": {
+ "message": "Platform"
+ },
+ "ram": {
+ "message": "RAM"
+ },
+ "reset": {
+ "message": "Reset"
+ },
+ "screen": {
+ "message": "Screen"
+ },
+ "settings": {
+ "message": "Settings"
+ },
+ "software": {
+ "message": "Software"
+ },
+ "tablet": {
+ "message": "Tablet"
+ },
+ "tv": {
+ "message": "TV"
+ },
+ "type": {
+ "message": "Type"
+ },
+ "version": {
+ "message": "Version"
+ },
+ "videoFormats": {
+ "message": "Video formats"
+ },
+ "watch": {
+ "message": "Watch"
+ }
+}
\ No newline at end of file
diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json
index d03d442..c39c031 100644
--- a/_locales/nl/messages.json
+++ b/_locales/nl/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/no/messages.json b/_locales/no/messages.json
index d03d442..c39c031 100644
--- a/_locales/no/messages.json
+++ b/_locales/no/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json
index d03d442..c39c031 100644
--- a/_locales/pl/messages.json
+++ b/_locales/pl/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json
index d03d442..c39c031 100644
--- a/_locales/pt_BR/messages.json
+++ b/_locales/pt_BR/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/pt_PT/messages.json b/_locales/pt_PT/messages.json
index d03d442..c39c031 100644
--- a/_locales/pt_PT/messages.json
+++ b/_locales/pt_PT/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ro/messages.json b/_locales/ro/messages.json
index d03d442..c39c031 100644
--- a/_locales/ro/messages.json
+++ b/_locales/ro/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json
index f9d0a8d..f86d114 100644
--- a/_locales/ru/messages.json
+++ b/_locales/ru/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "О системе"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "Все ваши настройки будут удалены и не могут быть восстановлены"
+ },
"appearance": {
"message": "Внешний вид"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Браузер"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Автомобиль"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Устройство"
},
+ "export": {
+ "message": "Экспортировать"
+ },
"extension": {
"message": "Расширение"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Скрыть \"Star us...\""
},
+ "import": {
+ "message": "Импортировать"
+ },
"language": {
"message": "Язык"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Сбросить"
+ },
"screen": {
"message": "Экран"
},
diff --git a/_locales/sk/messages.json b/_locales/sk/messages.json
index d03d442..c39c031 100644
--- a/_locales/sk/messages.json
+++ b/_locales/sk/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/sl/messages.json b/_locales/sl/messages.json
index d03d442..c39c031 100644
--- a/_locales/sl/messages.json
+++ b/_locales/sl/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/sr/messages.json b/_locales/sr/messages.json
index d03d442..c39c031 100644
--- a/_locales/sr/messages.json
+++ b/_locales/sr/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json
index d03d442..c39c031 100644
--- a/_locales/sv/messages.json
+++ b/_locales/sv/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/sw/messages.json b/_locales/sw/messages.json
index d03d442..c39c031 100644
--- a/_locales/sw/messages.json
+++ b/_locales/sw/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/ta/messages.json b/_locales/ta/messages.json
index d03d442..c39c031 100644
--- a/_locales/ta/messages.json
+++ b/_locales/ta/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/te/messages.json b/_locales/te/messages.json
index d03d442..c39c031 100644
--- a/_locales/te/messages.json
+++ b/_locales/te/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/th/messages.json b/_locales/th/messages.json
index d03d442..c39c031 100644
--- a/_locales/th/messages.json
+++ b/_locales/th/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json
index d03d442..c39c031 100644
--- a/_locales/tr/messages.json
+++ b/_locales/tr/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json
index d03d442..c39c031 100644
--- a/_locales/uk/messages.json
+++ b/_locales/uk/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/vi/messages.json b/_locales/vi/messages.json
index d03d442..c39c031 100644
--- a/_locales/vi/messages.json
+++ b/_locales/vi/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json
index d03d442..c39c031 100644
--- a/_locales/zh_CN/messages.json
+++ b/_locales/zh_CN/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json
index d03d442..c39c031 100644
--- a/_locales/zh_TW/messages.json
+++ b/_locales/zh_TW/messages.json
@@ -2,6 +2,9 @@
"about": {
"message": "About"
},
+ "allYourSettingsWillBeErasedAndCanTBeRecovered": {
+ "message": "All your settings will be erased and can't be recovered"
+ },
"appearance": {
"message": "Appearance"
},
@@ -11,6 +14,9 @@
"browser": {
"message": "Browser"
},
+ "cancel": {
+ "message": "Cancel"
+ },
"car": {
"message": "Car"
},
@@ -26,6 +32,9 @@
"device": {
"message": "Device"
},
+ "export": {
+ "message": "Export"
+ },
"extension": {
"message": "Extension"
},
@@ -44,6 +53,9 @@
"hideStarUs": {
"message": "Hide \"Star us...\""
},
+ "import": {
+ "message": "Import"
+ },
"language": {
"message": "Language"
},
@@ -68,6 +80,9 @@
"ram": {
"message": "RAM"
},
+ "reset": {
+ "message": "Reset"
+ },
"screen": {
"message": "Screen"
},
diff --git a/assets/data/user-agent.json b/assets/data/user-agent.json
new file mode 100644
index 0000000..ab37a08
--- /dev/null
+++ b/assets/data/user-agent.json
@@ -0,0 +1,123 @@
+{
+ "car": {
+ "Tesla": "Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/88.0.4324.150 Chrome/88.0.4324.150 Safari/537.36 Tesla/2021.4.18.2-6c676ce09ea5"
+ },
+ "computer": {
+ "Windows": {
+ "Windows 10": {
+ "Chrome": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Windows NT 10.0; rv:95.0) Gecko/20171102 Firefox/95.0",
+ "Opera": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 OPR/79.0.4143.61",
+ "Edge": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31/PmaOHqHf-37",
+ "Vivaldi": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.83 Safari/537.36 Vivaldi/4.2.2406.48",
+ "Whale": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.232 Whale/2.10.124.26 Safari/537.36"
+ },
+ "Windows 8.1": {
+ "Chrome": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.8948.8989 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0/10csO9CgK-99",
+ "Opera": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.50 (Edition Yx 02)",
+ "Edge": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31",
+ "Vivaldi": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.122 Safari/537.36 Vivaldi/2.3.1440.60",
+ "Whale": "Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.229 Whale/2.10.123.42 Safari/537.36"
+ },
+ "Windows 8": {
+ "Chrome": "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.48 CitizenFX/1.0.0.4590 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0/10csO9CgK-99",
+ "Opera": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.66",
+ "Edge": "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31",
+ "Vivaldi": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.143 Safari/537.36 Vivaldi/1.95.1077.45",
+ "Whale": "Mozilla/5.0 (Windows NT 6.2; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Whale/2.8.108.15 Safari/537.36"
+ },
+ "Windows 7": {
+ "Chrome": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.48 CitizenFX/1.0.0.4590 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0/CZyfq6zd2FAGsZdS0An",
+ "Opera": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.66 (Edition Campaign 70)",
+ "Edge": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31",
+ "Vivaldi": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.183 Safari/537.36 Vivaldi/6969562071AB",
+ "Whale": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.232 Whale/2.10.124.26 Safari/537.36",
+ "Internet Explorer": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.2)"
+ },
+ "Windows Vista": {
+ "Chrome": "Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9.1b2pre) Gecko/20081026 Minefield/3.1b2pre",
+ "Opera": "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 OPR/78.0.4093.231",
+ "Edge": "Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299",
+ "Vivaldi": "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 Vivaldi/1.0.435.46",
+ "Internet Explorer": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; BOIE9;FRFR)"
+ },
+ "Windows XP": {
+ "Chrome": "Mozilla/5.0 (Windows XP) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a",
+ "Opera": "Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.99",
+ "Internet Explorer": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
+ },
+ "Windows 2000": {
+ "Firefox": "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8) Gecko/20051111 Firefox/1.5",
+ "Opera": "Opera/9.80 (Windows NT 5.0; U; MRA 5.9 (build 4930); ru) Presto/2.10.229 Version/11.62",
+ "Internet Explorer": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
+ },
+ "Windows 98": {
+ "Firefox": "Mozilla/5.0 (Windows; U; Win98; bg; rv:1.8.1.10) Gecko/20100526 Firefox/3.7a5pre",
+ "Opera": "Opera/8.20.(Windows 98; ro-RO) Presto/2.9.186 Version/11.00",
+ "Internet Explorer": "Mozilla/4.0 (compatible; MSIE 4.01; MSN 2.5; Windows 98)"
+ }
+ },
+ "macOS": {
+ "Safari": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.7 Safari/605.1.15",
+ "Chrome": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4653.2 Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4; rv:87.0) Gecko/20100101 Firefox/87.0",
+ "Opera": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.50",
+ "Edge": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31",
+ "Vivaldi": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.88 Safari/537.36 Vivaldi/2.4.1488.36",
+ "Whale": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Whale/2.8.108.15 Safari/537.36"
+ },
+ "Linux": {
+ "Chrome": "Mozilla/5.0 (Linux; 7.0; P2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36",
+ "Firefox": "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.8) Gecko/20051111 Firefox/54.0",
+ "Vivaldi": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Vivaldi/4.1.2369.21"
+ }
+ },
+ "gameConsole": {
+ "PlayStation": {
+ "PlayStation 4": "Mozilla/5.0 (PlayStation 4 5.05) AppleWebKit/601.2 (KHTML, like Gecko)",
+ "PlayStation 3": "Mozilla/5.0 (PLAYSTATION 3 4.81) AppleWebKit/531.22.8 (KHTML, like Gecko)",
+ "PlayStation Vita": "Mozilla/5.0 (PlayStation Vita 3.50) AppleWebKit/537.73 (KHTML, like Gecko) Silk/3.2",
+ "PlayStation Portable": "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)"
+ },
+ "Xbox": {
+ "Xbox One": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299",
+ "Xbox 360": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)"
+ },
+ "Nintendo": {
+ "Nintendo Switch": "Mozilla/5.0 (Nintendo Switch; WebApplet) AppleWebKit/606.4 (KHTML, like Gecko) NF/6.0.1.18.3 NintendoBrowser/5.1.0.21481",
+ "Nintendo Wii U": "Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.4.2.13 NintendoBrowser/4.3.2.11274.US",
+ "Nintendo Wii": "Opera/9.30 (Nintendo Wii; U; ; 3642; en)",
+ "Nintendo 3DS": "Mozilla/5.0 (New Nintendo 3DS like iPhone) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.0.5.22 Mobile NintendoBrowser/1.10.10166.US"
+ }
+ },
+ "phone": {
+ "Android": {
+ "Chrome": "Mozilla/5.0 (Linux; Android 10; W-V680-OPE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Mobile Safari/537.36",
+ "Firefox": "Mozilla/5.0 (Android 10.0; Mobile; rv:90.0) Gecko/90.0 Firefox/90.0",
+ "Opera": "Mozilla/5.0 (Linux; Android 11; CPH1979) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36 OPR/64.3.3282.60839",
+ "Edge": "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Mobile Safari/537.36 EdgA/93.0.961.62"
+ },
+ "iOS": {
+ "Safari": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.2 Mobile/15E148 Safari/604.1",
+ "Chrome": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/93.0.4577.78 Mobile/15E148 Safari/604.1",
+ "Firefox": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/37.0 Mobile/15E148 Safari/605.1.15"
+ },
+ "Symbian": {
+ "Opera": "Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1204232254; U; en-GB) Presto/2.10.254 Version/12.00",
+ "Nokia Browser": "Nokia7610/2.0 (5.0509.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0",
+ "Ovi 2.0": "Mozilla/5.0 (Series40; Nokia200/11.64; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.0.2.68.14"
+ }
+ },
+ "tv": {
+ "Google TV": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/90.0.4430.212 Large Screen Safari/534.24 GoogleTV/092754youtube.com/tv#",
+ "Samsung TV": "Mozilla/5.0 (SMART-TV; Linux; Tizen 2.4.0) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.1 TV Safari/538.1"
+ },
+ "watch": {
+ "watchOS": "atc/1.0 watchOS/7.5 model/Watch3,3 hwp/t8004 build/18T567 (6; dt:155)"
+ }
+}
\ No newline at end of file
diff --git a/assets/fonts/Poppins-Bold.ttf b/assets/fonts/Poppins-Bold.ttf
deleted file mode 100644
index b94d47f..0000000
Binary files a/assets/fonts/Poppins-Bold.ttf and /dev/null differ
diff --git a/assets/fonts/Poppins-Regular.ttf b/assets/fonts/Poppins-Regular.ttf
deleted file mode 100644
index be06e7f..0000000
Binary files a/assets/fonts/Poppins-Regular.ttf and /dev/null differ
diff --git a/assets/fonts/Poppins-SemiBold.ttf b/assets/fonts/Poppins-SemiBold.ttf
deleted file mode 100644
index dabf7c2..0000000
Binary files a/assets/fonts/Poppins-SemiBold.ttf and /dev/null differ
diff --git a/assets/fonts/Roboto-Bold.ttf b/assets/fonts/Roboto-Bold.ttf
new file mode 100644
index 0000000..3742457
Binary files /dev/null and b/assets/fonts/Roboto-Bold.ttf differ
diff --git a/assets/fonts/Roboto-Medium.ttf b/assets/fonts/Roboto-Medium.ttf
new file mode 100644
index 0000000..e89b0b7
Binary files /dev/null and b/assets/fonts/Roboto-Medium.ttf differ
diff --git a/assets/fonts/Roboto-Regular.ttf b/assets/fonts/Roboto-Regular.ttf
new file mode 100644
index 0000000..3d6861b
Binary files /dev/null and b/assets/fonts/Roboto-Regular.ttf differ
diff --git a/assets/satus/satus.css b/assets/satus/satus.css
new file mode 100644
index 0000000..dd1e3a1
--- /dev/null
+++ b/assets/satus/satus.css
@@ -0,0 +1,1858 @@
+/*--------------------------------------------------------------
+# SCROLLBAR
+--------------------------------------------------------------*/
+
+:where([class^='satus'])::-webkit-scrollbar {
+ width: 4px;
+}
+
+:where([class^='satus'])::-webkit-scrollbar:hover {
+ width: 8px;
+}
+
+:where([class^='satus'])::-webkit-scrollbar-thumb {
+ background: rgba(var(--satus-light), .2);
+}
+
+:where([class^='satus'])::-webkit-scrollbar-thumb:hover {
+ background: rgba(var(--satus-light), .3);
+}
+/*--------------------------------------------------------------
+# ANIMATIONS
+--------------------------------------------------------------*/
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeInLeft {
+ from {
+ opacity: 0;
+ transform: translateX(-100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0);
+ }
+}
+
+@keyframes fadeInRight {
+ from {
+ opacity: 0;
+ transform: translateX(100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0);
+ }
+}
+
+@keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes fadeOutLeft {
+ from {
+ opacity: 1;
+ transform: translateX(0);
+ }
+ to {
+ opacity: 0;
+ transform: translateX(-50%);
+ }
+}
+
+@keyframes fadeOutRight {
+ from {
+ opacity: 1;
+ transform: translateX(0);
+ }
+ to {
+ opacity: 0;
+ transform: translateX(50%);
+ }
+}
+
+@keyframes zoomIn {
+ from {
+ transform: scale(.8);
+ opacity: 0;
+ }
+ to {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@keyframes zoomOut {
+ from {
+ transform: scale(1);
+ opacity: 1;
+ }
+ to {
+ transform: scale(.8);
+ opacity: 0;
+ }
+}
+/*--------------------------------------------------------------
+>>> THEMES
+--------------------------------------------------------------*/
+
+.satus-base {
+ --satus-light: 0, 20, 82;
+ --satus-primary: #ff4158;
+
+ --satus-alert-hue-error: 0;
+ --satus-alert-hue-success: 200;
+
+ --satus-base-background: #f3f4f6;
+ --satus-base-foreground: #565e76;
+
+ --satus-checkbox-background: #f3f4f6;
+ --satus-checkbox-border: #dcdfe5;
+ --satus-checkbox-foreground: rgb(255, 255, 255, .96);
+
+ --satus-divider: rgba(var(--satus-light),.1);
+
+ --satus-header-background: #fff;
+ --satus-header-foreground: inherit;
+ --satus-header-shadow: 0 1px 0 #dcdee5;
+
+ --satus-layers-background: var(--satus-base-background);
+ --satus-layers-foreground: inerit;
+
+ --satus-section-background: #fff;
+ --satus-section-border: #dcdee5;
+
+ --satus-sidebar-background: #fff;
+ --satus-sidebar-foreground: inherit;
+ --satus-sidebar-shadow: #dcdee5;
+
+ --satus-modal-foreground: inherit;
+ --satus-modal-background: #fff;
+ --satus-modal-shadow: 0 1px 4px #7d86a1;
+
+ --satus-tabs-background: var(--satus-section-background);
+
+ --satus-text-field-background: #edf0f2;
+ --satus-text-field-border: #dcdee5;
+ --satus-text-field-color: #7d8ba1;
+ --satus-text-field-selection: rgb(149, 166, 178, .35);
+ --satus-text-field-cursor: #fa0;
+
+ --satus-switch-track: #e1e4ea;
+ --satus-switch-track--checked: var(--satus-primary);
+ --satus-switch-thumb: #fff;
+}
+/*--------------------------------------------------------------
+>>> NORMALIZE
+--------------------------------------------------------------*/
+
+:where([class^='satus']) {
+ box-sizing: border-box;
+}
+
+:where([class^='satus'])[hidden]:not([hidden='false']) {
+ display: none;
+}
+
+:where([class^='satus'])[transparent] {
+ opacity: 0;
+}
+/*--------------------------------------------------------------
+>>> MODAL
+----------------------------------------------------------------
+# Container
+# Scrim
+# Surface
+# Variants
+ # Vertical menu
+--------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------
+# CONTAINER
+--------------------------------------------------------------*/
+
+.satus-modal {
+ position: fixed;
+ z-index: 9;
+ top: 0;
+ left: 0;
+ display: flex;
+ width: 100vw;
+ height: 100vh;
+ justify-content: center;
+ align-items: center;
+}
+
+
+/*--------------------------------------------------------------
+# SCRIM
+--------------------------------------------------------------*/
+
+.satus-modal__scrim {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ animation: fadeIn 150ms linear forwards;
+ opacity: 0;
+ background: rgba(0, 0, 0, .16);
+ backdrop-filter: blur(8px);
+}
+
+.satus-modal--closing .satus-modal__scrim {
+ animation: fadeOut 70ms linear forwards;
+}
+
+
+/*--------------------------------------------------------------
+# SURFACE
+--------------------------------------------------------------*/
+
+.satus-modal__surface {
+ display: flex;
+ overflow-y: auto;
+ flex-direction: column;
+ box-sizing: border-box;
+ width: 95%;
+ min-width: 240px;
+ max-width: 560px;
+ max-height: 80%;
+ margin: 8px;
+ padding: 12px 16px;
+ transform: scale(.8);
+ animation: zoomIn 150ms linear forwards;
+ animation-delay: 20ms;
+ opacity: 0;
+ color: var(--satus-modal-foreground);
+ border-radius: 3px;
+ background-color: var(--satus-modal-background);
+ box-shadow: var(--satus-modal-shadow);
+}
+
+.satus-modal--closing .satus-modal__surface {
+ animation: zoomOut 70ms linear forwards;
+}
+
+.satus-section--actions {
+ justify-content: flex-end;
+}
+.satus-section--actions > *:not(:first-child) {
+ margin-left: 8px;
+}
+
+
+/*--------------------------------------------------------------
+# VARIANTS
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# VERTICAL MENU
+--------------------------------------------------------------*/
+
+.satus-modal--vertical-menu .satus-modal__surface {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ left: auto;
+ min-width: 180px;
+ max-width: 180px;
+ margin: 0;
+ padding: 8px 0;
+ transform-origin: right top;
+}
+
+.satus-modal--vertical-menu .satus-modal__surface>[class^='satus']:where(:not(.satus-divider)) {
+ height: 36px;
+ padding: 0 16px;
+ border-radius: 0;
+}
+
+.satus-modal--vertical-menu .satus-modal__surface>.satus-span {
+ font-size: 13px;
+ font-weight: 500;
+ margin: 6px 0;
+ padding: 0 12px;
+}
+
+.satus-modal--vertical-menu .satus-modal__surface>.satus-tabs {
+ margin: 0 12px;
+ border-radius: 3px;
+ height: 26px;
+ padding: 0;
+}
+
+.satus-modal--vertical-menu .satus-select svg,
+.satus-modal--vertical-menu .satus-button svg {
+ margin: 0 14px 0 0;
+ opacity: .64;
+ flex: 0 0 18px;
+}
+
+.satus-modal--vertical-menu .satus-button .satus-span {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+/*--------------------------------------------------------------
+>>> GRID
+--------------------------------------------------------------*/
+
+.satus-grid {
+ display: flex;
+ align-items: stretch;
+ height: 100%;
+ padding: 8px;
+}
+/*--------------------------------------------------------------
+>>> TEXT FIELD
+----------------------------------------------------------------
+# Parts
+ # Container
+ # Input
+ #
+# Syntax highlighting
+ # Regular expression
+--------------------------------------------------------------*/
+
+.satus-text-field {
+ display: flex;
+
+ min-width: 240px;
+ height: 36px;
+
+ color: var(--satus-text-field-foreground, inherit);
+ border-radius: 4px;
+ background: var(--satus-text-field-background);
+
+ align-items: center;
+ justify-content: space-between;
+}
+
+.satus-text-field__container {
+ position: relative;
+
+ overflow: hidden;
+
+ height: 100%;
+
+ flex: 1;
+}
+
+.satus-text-field__textarea {
+ font: inherit;
+
+ position: absolute;
+ z-index: 9;
+ top: 0;
+ left: 0;
+
+ overflow: auto;
+
+ width: 100%;
+ min-width: 0;
+ max-width: none;
+ height: 100%;
+ min-height: 0;
+ max-height: none;
+ margin: 0;
+ padding: 0 12px;
+
+ white-space: pre;
+
+ opacity: 0;
+ color: inherit;
+ border: none;
+ border-radius: 4px;
+ outline: none;
+
+ appearance: none;
+ overflow-wrap: normal;
+}
+
+.satus-text-field__display {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ display: flex;
+
+ width: 100%;
+ height: 100%;
+}
+
+.satus-text-field__line-numbers {
+ padding: 0 12px 0 0;
+
+ opacity: .5;
+}
+
+.satus-text-field__line-numbers>span {
+ font-size: inherit;
+
+ display: block;
+
+ width: 100%;
+
+ text-align: right;
+}
+
+.satus-text-field__pre {
+ font: inherit;
+
+ display: flex;
+
+ margin: 0;
+}
+
+.satus-text-field__hidden-value {
+ font: inherit;
+
+ position: absolute;
+
+ overflow: auto;
+
+ white-space: pre;
+ pointer-events: none;
+
+ opacity: 0;
+
+ overflow-wrap: normal;
+}
+
+.satus-text-field__selection {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ display: none;
+
+ width: 0;
+ height: 22px;
+ margin: 6px 12px;
+
+ border: 1px solid var(--satus-text-field-selection);
+ border-radius: 3px;
+ background: var(--satus-text-field-selection);
+}
+
+.satus-text-field__cursor {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ display: none;
+
+ width: 2px;
+ height: 22px;
+ margin: -3px 0 0;
+
+ animation: blink 1s step-end 8;
+
+ background: var(--satus-text-field-cursor);
+}
+
+.satus-text-field__textarea:focus+.satus-text-field__display>.satus-text-field__cursor,
+.satus-text-field__textarea:focus+.satus-text-field__display>.satus-text-field__selection:not([disabled]) {
+ display: block;
+}
+
+@keyframes blink {
+
+ from,
+ to {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0;
+ }
+}
+
+
+/*--------------------------------------------------------------
+# SYNTAX HIGHLIGHTING
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# REGULAR EXPRESSION
+--------------------------------------------------------------*/
+
+.satus-text-field__pre>.group {
+ color: #47ff47;
+ background-color: rgb(71, 255, 71, .16);
+}
+
+.satus-text-field__pre>.character-class {
+ color: #ffc247;
+ background-color: rgb(255, 170, 0, .16);
+}
+
+.satus-text-field__pre>.quantifier {
+ color: #47c2ff;
+ background-color: rgb(71, 194, 255, .16);
+}
+
+.satus-text-field__pre>.anchor {
+ color: #47c2ff;
+ background-color: rgb(71, 194, 255, .16);
+}
+
+.satus-text-field__pre>.metasequence {
+ color: #47ff47;
+ background-color: rgb(71, 255, 71, .16);
+}
+
+.satus-text-field__pre>.text {
+ color: #c4c4d4;
+ background-color: rgb(196, 196, 212, .16);
+}
+/*--------------------------------------------------------------
+>>> CHART
+--------------------------------------------------------------*/
+
+.satus-chart {
+ font-size: 90%;
+
+ position: relative;
+
+ height: 128px;
+ margin: 4px 12px;
+
+ color: rgba(var(--satus-light), .32);
+ border: 1px dashed rgba(var(--satus-light), .2);
+ border-top: unset;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+
+.satus-chart__labels {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ display: flex;
+
+ width: 100%;
+ height: 100%;
+
+ justify-content: space-between;
+ align-items: stretch;
+}
+
+.satus-chart__section {
+ padding: 4px;
+
+ flex: 1;
+}
+
+.satus-chart__section:not(:last-child) {
+ border-right: 1px dashed rgba(var(--satus-light), .2);
+}
+
+
+.satus-chart__bars {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ display: flex;
+
+ width: 100%;
+ height: 100%;
+
+ justify-content: space-between;
+ align-items: stretch;
+}
+
+.satus-chart__bar {
+ display: flex;
+ flex-direction: column;
+
+ margin: 0 1px;
+
+ flex: 1;
+ align-items: center;
+ justify-content: flex-end;
+}
+
+.satus-chart__piece {
+ width: 100%;
+}
+
+.satus-chart__piece:first-child {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+/*--------------------------------------------------------------
+>>> SELECT
+--------------------------------------------------------------*/
+
+.satus-select {
+ position: relative;
+
+ display: flex;
+
+ cursor: pointer;
+
+ align-items: center;
+ justify-content: space-between;
+}
+
+.satus-select:hover {
+ background-color: var(--satus-hover);
+}
+
+.satus-select__content {
+ display: flex;
+
+ flex: 2;
+ overflow: hidden;
+
+ align-items: center;
+}
+
+.satus-select svg {
+ width: 20px;
+ height: 18px;
+ margin: 0 14px 0 0;
+
+ opacity: .64;
+}
+
+.satus-select__content .satus-span {
+ overflow: hidden;
+
+ text-overflow: ellipsis;
+}
+
+.satus-select__value {
+ display: block;
+ overflow: hidden;
+
+ flex: 1;
+ margin-left: 8px;
+
+ text-align: right;
+ text-overflow: ellipsis;
+
+ opacity: .64;
+}
+
+.satus-select select {
+ font: inherit;
+
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: inherit;
+
+ cursor: inherit;
+
+ opacity: 0;
+ border: none;
+ outline: none;
+
+ appearance: none;
+}
+
+.satus-select:hover {
+ cursor: pointer;
+
+ background-color: rgba(var(--satus-light), .06);
+}
+
+.satus-select:focus {
+ background-color: rgba(var(--satus-light), .08);
+}
+
+.satus-select select::-webkit-scrollbar {
+ width: 4px;
+}
+
+.satus-select select::-webkit-scrollbar:hover {
+ width: 8px;
+}
+
+.satus-select select::-webkit-scrollbar-thumb {
+ background: rgba(0, 0, 0, .2);
+}
+
+.satus-select select::-webkit-scrollbar-thumb:hover {
+ background: rgba(0, 0, 0, .3);
+}
+
+.satus-select option {
+ color: var(--satus-select-text);
+ background: var(--satus-select-background);
+}
+/*--------------------------------------------------------------
+>>> DIVIDER
+--------------------------------------------------------------*/
+
+.satus-divider {
+ height: 1px;
+ margin: 16px 0 12px;
+ background: var(--satus-divider);
+}
+/*--------------------------------------------------------------
+>>> SECTION
+----------------------------------------------------------------
+# Variants
+ # Align start
+ # Align end
+ # Card
+# Media
+--------------------------------------------------------------*/
+
+.satus-section {
+ display: flex;
+
+ flex-wrap: wrap;
+}
+
+
+/*--------------------------------------------------------------
+# ALIGN START
+--------------------------------------------------------------*/
+
+.satus-section--align-start {
+ align-items: center;
+}
+
+.satus-section--align-start>*:not(:last-child) {
+ margin-right: 8px;
+}
+
+
+/*--------------------------------------------------------------
+# ALIGN END
+--------------------------------------------------------------*/
+
+.satus-section--align-end {
+ align-items: center;
+ justify-content: flex-end;
+}
+
+.satus-section--align-end>*:not(:first-child) {
+ margin-left: 8px;
+}
+
+
+/*--------------------------------------------------------------
+# CARD
+--------------------------------------------------------------*/
+
+.satus-section--card {
+ flex-direction: column;
+
+ max-width: 900px;
+ margin: 12px;
+ padding: 8px 0;
+
+ border: 1px solid var(--satus-section-border);
+ border-radius: 3px;
+ background: var(--satus-section-background);
+}
+
+.satus-section--transparent-card {
+ max-width: 900px;
+ margin: 8px 12px;
+}
+
+.satus-section--card[data-title],
+.satus-section--transparent-card[data-title]
+{
+ position: relative;
+
+ margin-top: 32px;
+}
+
+.satus-section--card[data-title]::before,
+.satus-section--transparent-card::before
+{
+ position: absolute;
+ top: -8px;
+ left: 0;
+
+ content: attr(data-title);
+ transform: translateY(-100%);
+}
+
+
+.satus-section--transparent-card > [class^='satus'] {
+ width: 100%;
+}
+
+.satus-section--card>[class^='satus']:not(.satus-list):not(.satus-section) {
+ display: flex;
+
+ width: 100%;
+ min-height: 48px;
+ padding: 8px 12px;
+
+ transition: background-color .18s cubic-bezier(.25, .8, .5, 1);
+ text-align: left;
+
+ border-radius: 0;
+
+ align-items: center;
+}
+
+.satus-section--card>[class^='satus']:not(.satus-list):hover {
+ background-color: rgba(var(--satus-light), .06);
+}
+
+.satus-section--card>.satus-button {
+ justify-content: flex-start;
+}
+
+.satus-section--card>.satus-button>svg,
+.satus-section--card>.satus-select>svg
+{
+ width: 20px;
+ margin: 0 14px 0 0;
+
+ color: var(--satus-primary);
+}
+
+.satus-section--card>.satus-span {
+ display: flex;
+
+ align-items: center;
+}
+
+.satus-section--transparent {
+ background: unset;
+ border: unset;
+ padding: 0;
+ border-radius: unset;
+}
+
+
+/*--------------------------------------------------------------
+# MEDIA
+--------------------------------------------------------------*/
+
+@media (min-width: 901px) {
+ .satus-section--card,
+ .satus-section--transparent-card {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+/*--------------------------------------------------------------
+>>> BASE
+--------------------------------------------------------------*/
+
+.satus-base {
+ display: flex;
+ flex-direction: column;
+
+ width: 100%;
+ height: 100%;
+
+ color: var(--satus-base-foreground);
+ background: var(--satus-base-background);
+}
+/*--------------------------------------------------------------
+>>> ALERT
+----------------------------------------------------------------
+# Media
+--------------------------------------------------------------*/
+
+.satus-alert {
+ display: flex;
+ min-height: 48px;
+ margin: 12px;
+ padding: 8px 12px;
+ border-radius: 3px;
+ align-items: center;
+ max-width: 900px;
+}
+
+.satus-alert--error {
+ color: hsl(var(--satus-alert-hue-error), 56%, 64%);
+ border: 1px solid hsl(var(--satus-alert-hue-error), 56%, 28%);
+ background: hsl(var(--satus-alert-hue-error), 56%, 20%);
+}
+
+.satus-alert--success {
+ color: hsl(var(--satus-alert-hue-success), 56%, 56%);
+ border: 1px solid hsl(var(--satus-alert-hue-success), 56%, 26%);
+ background: hsl(var(--satus-alert-hue-success), 56%, 18%);
+}
+
+
+/*--------------------------------------------------------------
+# MEDIA
+--------------------------------------------------------------*/
+
+@media (min-width: 901px) {
+ .satus-alert {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+/*--------------------------------------------------------------
+>>> MAIN
+--------------------------------------------------------------*/
+
+.satus-main {
+ display: flex;
+ background: var(--satus-base-background);
+ flex: 1
+}
+/*--------------------------------------------------------------
+>>> SIDEBAR
+--------------------------------------------------------------*/
+
+.satus-sidebar {
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+ width: 56px;
+ padding: 12px 0;
+ color: var(--satus-sidebar-foreground);
+ background: var(--satus-sidebar-background);
+ box-shadow: 1px 0 0 var(--satus-sidebar-shadow)
+}
+/*--------------------------------------------------------------
+>>> LAYERS
+--------------------------------------------------------------*/
+
+.satus-layers {
+ position: relative;
+
+ overflow: hidden;
+
+ flex: 1;
+}
+
+.satus-layers__layer {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ overflow: auto;
+
+ width: 100%;
+ height: 100%;
+
+ color: var(--satus-layers-foreground);
+ background: var(--satus-layers-background);
+}
+/*--------------------------------------------------------------
+>>> LIST
+--------------------------------------------------------------*/
+
+.satus-list {
+ margin: 0;
+
+ list-style: none;
+}
+
+.satus-list__item {
+ display: flex;
+
+ min-height: 48px;
+ padding: 0 16px;
+
+ align-items: center;
+ justify-content: space-between;
+}
+
+.satus-list__item>*:not(:first-child) {
+ margin-left: 8px;
+}
+
+.satus-list__item>*:last-child {
+ font-size: 92%;
+
+ text-align: right;
+
+ opacity: .64;
+}
+/*--------------------------------------------------------------
+>>> COLOR PICKER:
+----------------------------------------------------------------
+# Button
+# Modal
+--------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------
+# BUTTON
+--------------------------------------------------------------*/
+
+.satus-color-picker {
+ font-size: inherit;
+
+ position: relative;
+
+ display: flex;
+
+ box-sizing: border-box;
+ margin: 0;
+
+ cursor: pointer;
+
+ color: inherit;
+ border: none;
+ outline: none;
+ background-color: var(--satus-theme-button);
+
+ justify-content: space-between;
+ -webkit-tap-highlight-color: transparent;
+ align-items: center;
+ -webkit-appearance: none;
+}
+
+.satus-color-picker__value {
+ width: 22px;
+ height: 22px;
+
+ border: 2px solid rgba(0, 0, 0, .16);
+ border-radius: 50%;
+}
+
+
+/*--------------------------------------------------------------
+# MODAL
+--------------------------------------------------------------*/
+
+.satus-modal--color-picker .satus-modal__surface {
+ padding: 8px;
+}
+
+.satus-color-picker__palette {
+ position: relative;
+
+ overflow: hidden;
+
+ width: 100%;
+ height: 256px;
+ margin: 0 0 4px;
+
+ border-radius: 5px;
+ background-color: #f00;
+}
+
+.satus-color-picker__palette:before {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ width: 100%;
+ height: 100%;
+
+ content: '';
+
+ background-image: linear-gradient(0deg, black, transparent), linear-gradient(90deg, white, transparent);
+}
+
+.satus-color-picker__cursor {
+ position: absolute;
+
+ width: 5px;
+ height: 5px;
+
+ transform: translate(-50%, -50%);
+ pointer-events: none;
+
+ border: 1px solid #fff;
+ border-radius: 50%;
+ box-shadow: 0 0 0 1px #000;
+}
+
+.satus-modal--color-picker .satus-modal__surface .satus-section--color {
+ margin: 8px 4px;
+
+ align-items: center;
+}
+
+.satus-color-picker__color {
+ width: 32px;
+ height: 32px;
+ margin: 0 16px 0 0;
+
+ border: 2px solid rgba(0, 0, 0, .16);
+ border-radius: 50%;
+ background: #f00;
+}
+
+.satus-slider.satus-color-picker__hue {
+ padding: 0;
+
+ flex: 1;
+}
+
+.satus-color-picker__hue .satus-slider__track-container {
+ height: 16px;
+ margin: 0;
+
+ border-radius: 4px;
+ background-image: linear-gradient(90deg, #f00, #ff2a00, #f50, #ff7f00, #fa0, #ffd400, #ff0, #d4ff00, #af0, #80ff00, #5f0, #2bff00, #0f0, #00ff2b, #0f5, #00ff80, #0fa, #00ffd5, #0ff, #00d4ff, #0af, #007fff, #05f, #002bff, #00f, #2a00ff, #50f, #7f00ff, #a0f, #d400ff, #f0f, #ff00d4, #f0a, #ff0080, #f05, #ff002b, #f00);
+}
+
+.satus-color-picker__hue .satus-slider__track-container::before {
+ display: none;
+}
+
+.satus-color-picker__hue .satus-slider__track {
+ background: transparent;
+}
+
+.satus-color-picker__hue .satus-slider__track::after {
+ width: 16px;
+ height: 16px;
+
+ background: #fff;
+ box-shadow: 0 0 4px rgb(0, 0, 0, .64);
+}
+/*--------------------------------------------------------------
+>>> SPAN
+--------------------------------------------------------------*/
+
+.satus-span--title {
+ font-weight: 500;
+ overflow: hidden;
+
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ flex: 1;
+}
+/*--------------------------------------------------------------
+>>> BUTTON
+----------------------------------------------------------------
+# Base
+# Basic
+# Icon
+--------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------
+# BASE
+--------------------------------------------------------------*/
+
+.satus-button {
+ font: inherit;
+
+ position: relative;
+
+ display: inline-flex;
+ overflow: hidden;
+
+ height: 36px;
+ padding: 8px;
+
+ transition: background-color .3s cubic-bezier(.25, .8, .5, 1);
+
+ color: inherit;
+ border: none;
+ border-radius: 6px;
+ outline: none;
+ background: transparent;
+
+ appearance: none;
+ align-items: center;
+}
+
+.satus-button:hover {
+ cursor: pointer;
+
+ background-color: rgba(var(--satus-light), .06);
+}
+
+.satus-button:focus {
+ background-color: rgba(var(--satus-light), .08);
+}
+
+.satus-button svg {
+ width: 100%;
+ max-width: 24px;
+ height: 100%;
+ max-height: 24px;
+}
+
+
+/*--------------------------------------------------------------
+# BASIC
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# ICON
+--------------------------------------------------------------*/
+
+.satus-button--icon {
+ width: 40px;
+ height: 40px;
+
+ border-radius: 50%;
+}
+
+.satus-button--icon svg {
+ width: 24px;
+ height: 24px;
+}
+/*--------------------------------------------------------------
+>>> HEADER
+--------------------------------------------------------------*/
+
+.satus-header {
+ z-index: 1;
+
+ display: flex;
+
+ height: 56px;
+ padding: 0 12px;
+
+ color: var(--satus-header-foreground);
+ background: var(--satus-header-background);
+ box-shadow: var(--satus-header-shadow);
+
+ justify-content: space-between;
+ align-items: center;
+}
+/*--------------------------------------------------------------
+>>> RADIO
+--------------------------------------------------------------*/
+
+.satus-radio {
+ position: relative;
+ display: flex;
+}
+
+.satus-radio__input {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ margin: 0;
+ z-index: 9;
+}
+
+.satus-radio__content {
+ flex: 1;
+ padding: 0 12px;
+}
+
+.satus-radio__i {
+ width: 16px;
+ height: 16px;
+ border: 1px solid rgba(var(--satus-light),.64);
+ border-radius: 50%;
+ transition: 200ms;
+}
+
+.satus-radio__input + .satus-radio__i::before {
+ width: 8px;
+ height: 8px;
+ margin: 3px;
+ border-radius: 50%;
+ background: var(--satus-primary);
+ content: '';
+ display: block;
+ transform: scale(0);
+ transition: 200ms;
+}
+
+.satus-radio__input:checked + .satus-radio__i {
+ border-color: var(--satus-primary);
+}
+
+.satus-radio__input:checked + .satus-radio__i::before {
+ background: var(--satus-primary);
+ transform: scale(1);
+}
+/*--------------------------------------------------------------
+>>> SLIDER
+--------------------------------------------------------------*/
+
+.satus-slider {
+ display: flex;
+
+ flex-wrap: wrap;
+}
+
+.satus-slider__track-container {
+ position: relative;
+
+ width: 100%;
+ height: 20px;
+ margin: 10px 0 -2px;
+}
+
+.satus-slider__track-container::before {
+ position: absolute;
+ top: calc(50% - 1px);
+ left: 0;
+
+ width: 100%;
+ height: 2px;
+
+ content: '';
+
+ opacity: .24;
+ background: var(--satus-primary);
+}
+
+.satus-slider__input {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ width: 100%;
+ height: 100%;
+ margin: 0;
+
+ opacity: 0;
+}
+
+.satus-slider__track {
+ position: absolute;
+ top: calc(50% - 1px);
+ left: 0;
+
+ width: 0;
+ height: 2px;
+
+ background: var(--satus-primary);
+ pointer-events: none;
+}
+
+.satus-slider__track::before {
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translate(50%, -50%);
+ display: block;
+ width: 16px;
+ height: 16px;
+ content: '';
+ transition: width 200ms, height 200ms, opacity 200ms;
+ opacity: 0;
+ border-radius: 50%;
+ background: var(--satus-primary);
+}
+
+.satus-slider__input:focus + .satus-slider__track::before {
+ width: 24px;
+ height: 24px;
+ opacity: .16;
+}
+
+.satus-slider__input:active + .satus-slider__track::before {
+ width: 26px;
+ height: 26px;
+ opacity: .16;
+}
+
+.satus-slider__track::after {
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translate(50%, -50%);
+
+ width: 10px;
+ height: 10px;
+
+ content: '';
+
+ border-radius: 50%;
+ background: var(--satus-primary);
+ pointer-events: none;
+ transition: width 200ms, height 200ms, opacity 200ms;
+}
+
+.satus-slider__input:active + .satus-slider__track::after
+{
+ width: 12px;
+ height: 12px;
+}
+
+
+
+
+
+.satus-slider--row {
+ flex-wrap: nowrap;
+ justify-content: space-between;
+}
+
+.satus-slider--row .satus-slider__track-container {
+ margin: 0 0 -2px 12px;
+ max-width: 50%;
+}
+/*--------------------------------------------------------------
+>>> TABS
+--------------------------------------------------------------*/
+
+.satus-tabs {
+ position: relative;
+
+ display: flex;
+
+ border: 2px solid var(--satus-tabs-background);
+ border-radius: 4px;
+ background: var(--satus-tabs-background);
+}
+
+.satus-tabs::before {
+ position: absolute;
+ top: 0;
+ left: calc(calc(100% / var(--satus-tabs-count)) * var(--satus-tabs-current));
+
+ width: calc(100% / var(--satus-tabs-count));
+ height: 100%;
+
+ content: '';
+ transition: left .25s;
+
+ border-radius: 3px;
+ background: var(--satus-tabs-foreground);
+}
+
+.satus-tabs__button {
+ font: inherit;
+
+ position: relative;
+ z-index: 1;
+
+ overflow: hidden;
+
+ margin: 0;
+ padding: 0 8px;
+
+ text-transform: lowercase;
+ text-overflow: ellipsis;
+
+ color: inherit;
+ border: none;
+ border-radius: 3px;
+ outline: none;
+ background: transparent;
+
+ flex: 1;
+ appearance: none;
+}
+/*--------------------------------------------------------------
+>>> SHORTCUT:
+----------------------------------------------------------------
+#
+--------------------------------------------------------------*/
+
+.satus-shortcut__value {
+ font-size: 11px;
+
+ display: flex;
+
+ margin-left: 16px;
+
+ text-transform: uppercase;
+
+ align-items: center;
+ flex: 1;
+ justify-content: flex-end;
+}
+
+.satus-shortcut__actions {
+ display: flex;
+
+ justify-content: flex-end;
+}
+
+.satus-shortcut__actions .satus-button {
+ height: 32px;
+ margin: 8px 4px 0;
+
+ border-radius: 8px;
+ background: rgba(0, 0, 0, .15);
+}
+
+.satus-shortcut__actions .satus-button:hover {
+ background: rgba(0, 0, 0, .25);
+}
+
+.satus-shortcut__primary {
+ display: flex;
+
+ height: 64px;
+ margin: 0 0 12px;
+ padding: 16px;
+
+ border-radius: 3px;
+ background: rgba(0, 0, 0, .16);
+
+ align-items: center;
+}
+
+.satus-shortcut__key {
+ display: flex;
+
+ min-width: 32px;
+ height: 32px;
+ padding: 4px 8px;
+
+ color: #242424;
+ border-radius: 4px;
+ background: #fff;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1);
+
+ align-items: center;
+ justify-content: center;
+}
+
+.satus-shortcut__value>.satus-shortcut__key {
+ font-size: 14px;
+
+ min-width: 24px;
+ height: 24px;
+}
+
+.satus-shortcut__plus {
+ position: relative;
+
+ width: 12px;
+ height: 12px;
+ margin: 8px;
+}
+
+.satus-shortcut__plus::before {
+ position: absolute;
+ top: 0;
+ left: 5px;
+
+ width: 2px;
+ height: 12px;
+
+ content: '';
+
+ background-color: #aaa;
+}
+
+.satus-shortcut__plus::after {
+ position: absolute;
+ top: 5px;
+ left: 0;
+
+ width: 12px;
+ height: 2px;
+
+ content: '';
+
+ background-color: #aaa;
+}
+
+.satus-shortcut__mouse {
+ position: relative;
+
+ display: flex;
+
+ width: 28px;
+ height: 36px;
+
+ border-radius: 50%;
+ border-top-left-radius: 12px;
+ border-top-right-radius: 12px;
+ background: #fff;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1);
+}
+
+.satus-shortcut__value>.satus-shortcut__mouse {
+ width: 22px;
+ height: 28px;
+}
+
+.satus-shortcut__mouse>div {
+ position: absolute;
+ top: 0;
+ left: calc(50% - 1px);
+
+ width: 2px;
+ height: 11px;
+
+ border-radius: 2px;
+ background: #ccc;
+}
+
+.satus-shortcut__mouse::before {
+ position: absolute;
+ top: -16%;
+ right: 14%;
+
+ width: 2px;
+ height: 60%;
+
+ content: '';
+
+ background: #f96754;
+}
+
+.satus-shortcut__mouse.false::before {
+ top: -6%;
+}
+
+.satus-shortcut__mouse.false::after {
+ position: absolute;
+ top: -20%;
+ right: calc(14% - 4px);
+
+ width: 0;
+ height: 0;
+
+ content: '';
+
+ border-right: 5px solid transparent;
+ border-bottom: 8px solid #f96754;
+ border-left: 5px solid transparent;
+}
+
+.satus-shortcut__mouse.true::after {
+ position: absolute;
+ top: 40%;
+ right: calc(14% - 4px);
+
+ width: 0;
+ height: 0;
+
+ content: '';
+
+ border-top: 8px solid #f96754;
+ border-right: 5px solid transparent;
+ border-left: 5px solid transparent;
+}
+
+.satus-shortcut__mouse.click::before {
+ position: absolute;
+ top: 0;
+ left: -1px;
+
+ width: 10px;
+ height: 10px;
+
+ content: '';
+
+ border-radius: 50%;
+ background: #f96754;
+}
+
+.satus-shortcut__mouse.middle::before {
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 50%;
+
+ width: 10px;
+ height: 10px;
+
+ content: '';
+ transform: translateX(-50%);
+
+ border-radius: 50%;
+ background: #f96754;
+}
+
+.satus-shortcut__mouse.context::before {
+ position: absolute;
+ top: 0;
+ left: 15px;
+
+ width: 10px;
+ height: 10px;
+
+ content: '';
+
+ border-radius: 50%;
+ background: #f96754;
+}
+
+.satus-section_shortcut {
+ width: 100%;
+ margin: 8px 0 0;
+
+ justify-content: flex-end;
+}
+
+.satus-button_shortcut {
+ font-weight: 500;
+
+ overflow: hidden;
+
+ height: 28px;
+ min-height: 28px;
+ margin-right: 2px;
+ padding: 4px 8px;
+
+ text-transform: uppercase;
+
+ color: #f96754;
+ border-radius: 4px;
+}
+/*--------------------------------------------------------------
+>>> CHECKBOX
+--------------------------------------------------------------*/
+
+.satus-checkbox
+{
+ display: flex;
+ align-items: center;
+ position: relative;
+ cursor: pointer;
+}
+
+.satus-checkbox::before
+{
+ display: flex;
+ width: 16px;
+ min-width: 16px;
+ height: 16px;
+ margin: 0 14px 0 0;
+ content: '';
+ border: 1px solid var(--satus-checkbox-border);
+ border-radius: 3px;
+ background: var(--satus-checkbox-background);
+ align-items: center;
+ justify-content: center;
+}
+
+.satus-checkbox[data-value=true]::before
+{
+ background: var(--satus-primary);
+ border-color: var(--satus-primary);
+}
+
+.satus-checkbox[data-value=true]::after
+{
+ position: absolute;
+ top: 20px;
+ left: 20px;
+
+ width: 8px;
+ height: 4px;
+
+ content: '';
+ transform: rotate(-45deg);
+
+ border: 2px solid var(--satus-checkbox-foreground);
+ border-top: none;
+ border-right: none;
+}
+
+/*--------------------------------------------------------------
+>>> SWITCH
+----------------------------------------------------------------
+# Container
+# Track
+# Thumb
+--------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------
+# CONTAINER
+--------------------------------------------------------------*/
+
+.satus-switch {
+ font: inherit;
+
+ display: flex;
+
+ transition: background-color 75ms;
+
+ color: inherit;
+ border: none;
+ outline: none;
+ background-color: transparent;
+
+ justify-content: space-between;
+ align-items: center;
+}
+
+.satus-switch:hover {
+ cursor: pointer;
+}
+
+.satus-switch__content {
+ display: flex;
+
+ align-items: center;
+}
+
+.satus-switch__content>svg {
+ width: 20px;
+ height: 18px;
+ margin: 0 14px 0 0;
+
+ opacity: .64;
+}
+
+
+/*--------------------------------------------------------------
+# TRACK
+--------------------------------------------------------------*/
+
+.satus-switch>i {
+ width: 32px;
+ height: 18px;
+
+ transition: background-color 150ms;
+
+ border-radius: 18px;
+ background-color: var(--satus-switch-track);
+
+ flex: 0 0 32px;
+}
+
+.satus-section--card .satus-switch>i {
+ margin-left: 16px;
+}
+
+.satus-switch[data-value='true']>i {
+ background-color: var(--satus-switch-track--checked);
+}
+
+
+/*--------------------------------------------------------------
+# THUMB
+--------------------------------------------------------------*/
+
+.satus-switch>i::before {
+ display: block;
+
+ width: 14px;
+ height: 14px;
+ margin: 2px;
+
+ content: '';
+ transition: transform 150ms cubic-bezier(.4, 0, .2, 1);
+
+ border-radius: 50%;
+ background-color: var(--satus-switch-thumb);
+
+ will-change: transform;
+}
+
+.satus-switch[data-value='true']>i::before {
+ transform: translateX(14px);
+}
diff --git a/assets/satus/satus.js b/assets/satus/satus.js
new file mode 100644
index 0000000..6ce2104
--- /dev/null
+++ b/assets/satus/satus.js
@@ -0,0 +1,2979 @@
+/*--------------------------------------------------------------
+>>> CORE
+----------------------------------------------------------------
+# Global variable
+# Animations duration
+# Append
+# Attr
+# Camelize
+# Class
+# Create element
+# CSS
+# Empty
+# Element index
+# Events
+# Get property
+# Is
+# On
+# Render
+# Sort
+# Storage
+ # Clear
+ # Get
+ # Import
+ # Set
+ # Remove
+ # On changed
+# Localization
+# Log
+# Text
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# GLOBAL VARIABLE
+--------------------------------------------------------------*/
+
+var satus = {
+ components: {},
+ events: {
+ data: {}
+ },
+ locale: {
+ data: {}
+ },
+ storage: {
+ data: {},
+ type: 'extension'
+ }
+};
+
+
+/*--------------------------------------------------------------
+# ANIMATION DURATION
+--------------------------------------------------------------*/
+
+satus.getAnimationDuration = function (element) {
+ return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000;
+};
+
+
+/*--------------------------------------------------------------
+# APPEND
+--------------------------------------------------------------*/
+
+satus.append = function (child, parent) {
+ (parent || document.body).appendChild(child);
+};
+
+
+/*--------------------------------------------------------------
+# ATTR
+--------------------------------------------------------------*/
+
+satus.attr = function (element, attributes) {
+ if (attributes) {
+ for (var name in attributes) {
+ var value = attributes[name];
+
+ if (satus.isFunction(value)) {
+ value = value();
+ }
+
+ if (element.namespaceURI) {
+ if (value === false) {
+ element.removeAttributeNS(null, name);
+ } else {
+ element.setAttributeNS(null, name, value);
+ }
+ } else {
+ if (value === false) {
+ element.removeAttribute(name);
+ } else {
+ element.setAttribute(name, value);
+ }
+ }
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# CAMELIZE
+--------------------------------------------------------------*/
+
+satus.camelize = function (string) {
+ var result = '';
+
+ for (var i = 0, l = string.length; i < l; i++) {
+ var character = string[i];
+
+ if (character === '_' || character === '-') {
+ i++;
+
+ result += string[i].toUpperCase();
+ } else {
+ result += character;
+ }
+ }
+
+ return result;
+};
+
+
+/*--------------------------------------------------------------
+# CLASS
+--------------------------------------------------------------*/
+
+satus.class = function (element, className) {
+ if (className) {
+ element.classList.add(className);
+ }
+};
+
+
+/*--------------------------------------------------------------
+# CREATE ELEMENT
+--------------------------------------------------------------*/
+
+satus.createElement = function (tagName, componentName, namespaceURI) {
+ var camelizedTagName = this.camelize(tagName),
+ className = 'satus-' + (componentName || tagName),
+ element,
+ match = className.match(/__[^__]+/g);
+
+ if (!namespaceURI) {
+ if (tagName === 'svg') {
+ namespaceURI = 'http://www.w3.org/2000/svg';
+ }
+ }
+
+ if (namespaceURI) {
+ element = document.createElementNS(namespaceURI, tagName);
+ } else if (this.components[camelizedTagName]) {
+ element = document.createElement('div');
+ } else {
+ element = document.createElement(tagName);
+ }
+
+ if (match && match.length > 1) {
+ className = className.slice(0, className.indexOf('__')) + match[match.length - 1];
+ }
+
+ element.componentName = componentName;
+ element.className = className;
+
+ element.createChildElement = function (tagName, componentName, namespaceURI) {
+ var element = satus.createElement(tagName, this.componentName + '__' + (componentName || tagName), namespaceURI);
+
+ this.appendChild(element);
+
+ return element;
+ };
+
+ return element;
+};
+
+
+/*--------------------------------------------------------------
+# CSS
+--------------------------------------------------------------*/
+
+satus.css = function (element, property) {
+ return window.getComputedStyle(element).getPropertyValue(property);
+};
+
+
+/*--------------------------------------------------------------
+# DATA
+--------------------------------------------------------------*/
+
+satus.data = function (element, data) {
+ if (data) {
+ for (var key in data) {
+ var value = data[key];
+
+ if (satus.isFunction(value)) {
+ value = value();
+ }
+
+ element.dataset[key] = value;
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# EMPTY
+--------------------------------------------------------------*/
+
+satus.empty = function (element, exclude = []) {
+ for (var i = element.childNodes.length - 1; i > -1; i--) {
+ var child = element.childNodes[i];
+
+ if (exclude.indexOf(child) === -1) {
+ child.remove();
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# ELEMENT INDEX
+--------------------------------------------------------------*/
+
+satus.elementIndex = function (element) {
+ return Array.prototype.slice.call(element.parentNode.children).indexOf(element);
+};
+
+
+/*--------------------------------------------------------------
+# EVENTS
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# ON
+--------------------------------------------------------------*/
+
+satus.events.on = function (type, handler) {
+ if (!this.data[type]) {
+ this.data[type] = [];
+ }
+
+ this.data[type].push(handler);
+};
+
+
+/*--------------------------------------------------------------
+# TRIGGER
+--------------------------------------------------------------*/
+
+satus.events.trigger = function (type) {
+ var handlers = this.data[type];
+
+ if (handlers) {
+ for (var i = 0, l = handlers.length; i < l; i++) {
+ handlers[i]();
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# FETCH
+--------------------------------------------------------------*/
+
+satus.fetch = function (url, success, error, type) {
+ fetch(url).then(function (response) {
+ if (response.ok) {
+ response[type || 'json']().then(success);
+ } else {
+ error();
+ }
+ }).catch(function () {
+ error(success);
+ });
+};
+
+
+/*--------------------------------------------------------------
+# GET PROPERTY
+--------------------------------------------------------------*/
+
+satus.getProperty = function (object, string) {
+ var properties = string.split('.');
+
+ for (var i = 0, l = properties.length; i < l; i++) {
+ var property = properties[i];
+
+ console.log(object);
+
+ if (object = object[property]) {
+ if (i === l - 1) {
+ return object;
+ }
+ } else {
+ return false;
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# ISSET
+--------------------------------------------------------------*/
+
+satus.isset = function (target, is_object) {
+ if (is_object === true) {
+ var keys = target.split('.').filter(function (value) {
+ return value != '';
+ });
+
+ for (var i = 0, l = keys.length; i < l; i++) {
+ if (satus.isset(target[keys[i]])) {
+ target = target[keys[i]];
+ } else {
+ return undefined;
+ }
+ }
+
+ return target;
+ } else {
+ if (target === null || target === undefined) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+
+/*--------------------------------------------------------------
+# IS
+--------------------------------------------------------------*/
+
+satus.isArray = function (target) {
+ if (Array.isArray(target)) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+satus.isBoolean = function (target) {
+ return target === false || target === true;
+};
+
+satus.isElement = function (target) {
+ return target instanceof Element || target instanceof HTMLDocument;
+};
+
+satus.isFunction = function (target) {
+ return typeof target === 'function';
+};
+
+satus.isNodeList = function (target) {
+ return target instanceof NodeList;
+};
+
+satus.isNumber = function (target) {
+ if (typeof target === 'number' && isNaN(target) === false) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+satus.isObject = function (target) {
+ return target instanceof Object && target !== null;
+};
+
+satus.isString = function (target) {
+ if (typeof target === 'string') {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+
+/*--------------------------------------------------------------
+# ON
+--------------------------------------------------------------*/
+
+satus.on = function (element, listeners) {
+ if (listeners) {
+ for (var type in listeners) {
+ var listener = listeners[type];
+
+ if (type === 'selectionchange') {
+ element = document;
+ }
+
+ if (satus.isFunction(listener)) {
+ element.addEventListener(type, listener);
+ } else if (satus.isArray(listener) || satus.isObject(listener)) {
+ element.addEventListener(type, function (event) {
+ var target = this.skeleton.on[event.type],
+ parent = this.parentNode;
+
+ target.parentSkeleton = this.skeleton;
+ target.parentElement = this;
+
+ while (parent.componentName !== 'layers' && parent.componentName !== 'base' && parent !== document.body && parent.parentNode) {
+ parent = parent.parentNode;
+ }
+
+ if (parent.componentName === 'layers' && target.component !== 'modal') {
+ parent.open(target);
+ } else if (this.baseProvider && this.baseProvider.layers.length === 1) {
+ satus.render(target, this.baseProvider.layers[0]);
+ } else {
+ satus.render(target, this.baseProvider);
+ }
+ });
+ } else if (satus.isString(listener)) {
+ element.addEventListener(type, function () {
+ var match = this.skeleton.on[event.type].match(/(["'`].+["'`]|[^.()]+)/g),
+ target = this.baseProvider;
+
+ for (var i = 0, l = match.length; i < l; i++) {
+ var key = match[i];
+
+ if (target.skeleton[key]) {
+ target = target.skeleton[key];
+ } else {
+ if (typeof target[key] === 'function') {
+ target[key]();
+ } else {
+ target = target[key];
+ }
+ }
+
+ if (target.rendered) {
+ target = target.rendered;
+ }
+ }
+ });
+ }
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# PARENTIFY
+--------------------------------------------------------------*/
+
+satus.parentify = function (parentObject, exclude) {
+ for (var key in parentObject) {
+ if (exclude.indexOf(key) === -1) {
+ var child = parentObject[key];
+
+ child.parentObject = parentObject;
+
+ if (typeof child === 'object' && child.component !== 'shortcut') {
+ this.parentify(child, exclude);
+ }
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# PREPEND
+--------------------------------------------------------------*/
+
+satus.prepend = function (child, parent) {
+ if (this.isElement(child)) {
+ parent.prepend(child);
+ } else if (this.isObject(child)) {
+ this.render(child, parent, undefined, undefined, true);
+ }
+};
+
+
+/*--------------------------------------------------------------
+# PROPERTIES
+--------------------------------------------------------------*/
+
+satus.properties = function (element, properties) {
+ if (properties) {
+ for (var key in properties) {
+ var property = properties[key];
+
+ if (['placeholder', 'title'].indexOf(key) !== -1) {
+ property = satus.locale.get(property);
+ }
+
+ element[key] = property;
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# RENDER
+--------------------------------------------------------------*/
+
+satus.render = function (skeleton, container, property, childrenOnly, prepend) {
+ var element;
+
+ if (skeleton.component && childrenOnly !== true) {
+ var tagName = skeleton.component,
+ camelizedTagName = this.camelize(tagName),
+ namespaceURI = skeleton.namespaceURI;
+
+ if (!namespaceURI) {
+ if (tagName === 'svg') {
+ namespaceURI = 'http://www.w3.org/2000/svg';
+ } else if (skeleton.parentSkeleton && skeleton.parentSkeleton.namespaceURI) {
+ namespaceURI = skeleton.parentSkeleton.namespaceURI;
+ }
+
+ skeleton.namespaceURI = namespaceURI;
+ }
+
+ element = this.createElement(tagName, tagName, namespaceURI);
+
+ skeleton.rendered = element;
+ element.skeleton = skeleton;
+ element.childrenContainer = element;
+ element.componentName = tagName;
+
+ if (skeleton.variant) {
+ var variant = skeleton.variant;
+
+ if (this.isFunction(variant)) {
+ variant = variant();
+ }
+
+ if (satus.isArray(variant)) {
+ for (var i = 0, l = variant.length; i < l; i++) {
+ element.className += ' satus-' + tagName + '--' + variant[i];
+ }
+ } else {
+ element.className += ' satus-' + tagName + '--' + variant;
+ }
+ }
+
+ if (skeleton.id) {
+ element.id = skeleton.id;
+ }
+
+ if (container) {
+ element.baseProvider = container.baseProvider;
+ }
+
+ this.attr(element, skeleton.attr);
+ this.style(element, skeleton.style);
+ this.data(element, skeleton.data);
+ this.class(element, skeleton.class);
+ this.properties(element, skeleton.properties);
+ this.on(element, skeleton.on);
+
+ element.storage = (function () {
+ var parent = element,
+ key = skeleton.storage || property || false,
+ value;
+
+ if (satus.isFunction(key)) {
+ key = key();
+ }
+
+ if (skeleton.storage !== false) {
+ if (key) {
+ value = satus.storage.get(key);
+ }
+
+ if (skeleton.hasOwnProperty('value') && value === undefined) {
+ value = skeleton.value;
+ }
+ }
+
+ return Object.defineProperties({}, {
+ key: {
+ get: function () {
+ return key;
+ },
+ set: function (string) {
+ key = string;
+ }
+ },
+ value: {
+ get: function () {
+ return value;
+ },
+ set: function (val) {
+ value = val;
+
+ if (skeleton.storage !== false) {
+ satus.storage.set(key, val);
+
+ parent.dispatchEvent(new CustomEvent('change'));
+ }
+ }
+ }
+ });
+ }());
+
+ if (this.components[camelizedTagName]) {
+ this.components[camelizedTagName](element, skeleton);
+ }
+
+ this.text(element.childrenContainer, skeleton.text);
+ this.prepend(skeleton.before, element.childrenContainer);
+
+ if (prepend) {
+ this.prepend(element, container);
+ } else {
+ this.append(element, container);
+ }
+
+ element.dispatchEvent(new CustomEvent('render'));
+
+ container = element.childrenContainer || element;
+ }
+
+ if (!element || element.renderChildren !== false) {
+ for (var key in skeleton) {
+ var item = skeleton[key];
+
+ if (key !== 'parentSkeleton' && key !== 'parentElement' && key !== 'parentObject' && key !== 'before') {
+ if (item && item.component) {
+ item.parentSkeleton = skeleton;
+
+ if (element) {
+ item.parentElement = element;
+ }
+
+ this.render(item, container, key, undefined, prepend);
+ }
+ }
+ }
+ }
+
+ return element;
+};
+
+
+/*--------------------------------------------------------------
+# SORT
+--------------------------------------------------------------*/
+
+satus.sort = function (array, order, property) {
+ var type;
+
+ if (property) {
+ type = typeof array[0][property];
+ } else {
+ type = typeof array[0];
+ }
+
+ if (order !== 'desc') {
+ if (type === 'number') {
+ if (property) {
+ return array.sort(function (a, b) {
+ return a[property] - b[property];
+ });
+ } else {
+ return array.sort(function (a, b) {
+ return a - b;
+ });
+ }
+ } else if (type === 'string') {
+ if (property) {
+ return array.sort(function (a, b) {
+ return a[property].localeCompare(b[property]);
+ });
+ } else {
+ return array.sort(function (a, b) {
+ return a.localeCompare(b);
+ });
+ }
+ }
+ } else {
+ if (type === 'number') {
+ if (property) {
+ return array.sort(function (a, b) {
+ return b[property] - a[property];
+ });
+ } else {
+ return array.sort(function (a, b) {
+ return b - a;
+ });
+ }
+ } else if (type === 'string') {
+ if (property) {
+ return array.sort(function (a, b) {
+ return b[property].localeCompare(a[property]);
+ });
+ } else {
+ return array.sort(function (a, b) {
+ return b.localeCompare(a);
+ });
+ }
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# STORAGE
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# CLEAR
+--------------------------------------------------------------*/
+
+satus.storage.clear = function (callback) {
+ this.data = {};
+
+ chrome.storage.local.clear(function () {
+ satus.events.trigger('storage-clear');
+
+ if (callback) {
+ callback();
+ }
+ });
+};
+
+
+/*--------------------------------------------------------------
+# GET
+--------------------------------------------------------------*/
+
+satus.storage.get = function (key, callback) {
+ var target = this.data;
+
+ if (typeof key !== 'string') {
+ return;
+ }
+
+ key = key.split('/').filter(function (value) {
+ return value != '';
+ });
+
+ for (var i = 0, l = key.length; i < l; i++) {
+ if (satus.isset(target[key[i]])) {
+ target = target[key[i]];
+ } else {
+ return undefined;
+ }
+ }
+
+ if (typeof target === 'function') {
+ return target();
+ } else {
+ return target;
+ }
+};
+
+
+/*--------------------------------------------------------------
+# IMPORT
+--------------------------------------------------------------*/
+
+satus.storage.import = function (keys, callback) {
+ var self = this;
+
+ if (typeof keys === 'function') {
+ callback = keys;
+
+ keys = undefined;
+ }
+
+ chrome.storage.local.get(keys, function (items) {
+ for (var key in items) {
+ self.data[key] = items[key];
+ }
+
+ satus.log('STORAGE: data was successfully imported');
+
+ satus.events.trigger('storage-import');
+
+ if (callback) {
+ callback(items);
+ }
+ });
+};
+
+
+/*--------------------------------------------------------------
+# REMOVE
+--------------------------------------------------------------*/
+
+satus.storage.remove = function (key) {
+ delete this.data[key];
+
+ chrome.storage.local.remove(key, function () {
+ satus.events.trigger('storage-remove');
+ });
+};
+
+
+/*--------------------------------------------------------------
+# SET
+--------------------------------------------------------------*/
+
+satus.storage.set = function (key, value, callback) {
+ var items = {},
+ target = this.data;
+
+ if (typeof key !== 'string') {
+ return;
+ }
+
+ key = key.split('/').filter(function (value) {
+ return value != '';
+ });
+
+ for (var i = 0, l = key.length; i < l; i++) {
+ var item = key[i];
+
+ if (i < l - 1) {
+
+ if (target[item]) {
+ target = target[item];
+ } else {
+ target[item] = {};
+
+ target = target[item];
+ }
+ } else {
+ target[item] = value;
+ }
+ }
+
+ for (var key in this.data) {
+ if (typeof this.data[key] !== 'function') {
+ items[key] = this.data[key];
+ }
+ }
+
+ chrome.storage.local.set(items, function () {
+ satus.events.trigger('storage-set');
+
+ if (callback) {
+ callback();
+ }
+ });
+};
+
+
+/*--------------------------------------------------------------
+# ON CHANGED
+--------------------------------------------------------------*/
+
+satus.storage.onchanged = function (callback) {
+ chrome.storage.onChanged.addListener(function (changes) {
+ for (var key in changes) {
+ callback(key, changes[key].newValue);
+ }
+ });
+};
+
+
+/*--------------------------------------------------------------
+# LAST
+--------------------------------------------------------------*/
+
+satus.last = function (variable) {
+ if (this.isArray(variable) || this.isNodeList(variable)) {
+ return variable[variable.length - 1];
+ }
+};
+
+
+/*--------------------------------------------------------------
+# LOCALIZATION
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# GET
+--------------------------------------------------------------*/
+
+satus.locale.get = function (string) {
+ return this.data[string] || string;
+};
+
+
+/*--------------------------------------------------------------
+# IMPORT
+----------------------------------------------------------------
+satus.locale.import(url, onload, onsuccess);
+--------------------------------------------------------------*/
+
+satus.locale.import = function (code, callback, path) {
+ var language = code || window.navigator.language;
+
+ if (language.indexOf('en') === 0) {
+ language = 'en';
+ }
+
+ if (!path) {
+ path = '_locales/';
+ }
+
+ satus.fetch(chrome.runtime.getURL(path + language + '/messages.json'), function (response) {
+ for (var key in response) {
+ satus.locale.data[key] = response[key].message;
+ }
+
+ satus.log('LOCALE: data was successfully imported');
+
+ if (callback) {
+ callback();
+ }
+ }, function (success) {
+ satus.fetch(chrome.runtime.getURL(path + 'en/messages.json'), success, function () {
+ success();
+ });
+ });
+};
+
+
+/*--------------------------------------------------------------
+# LOG
+--------------------------------------------------------------*/
+
+satus.log = function () {
+ console.log.apply(null, arguments);
+};
+
+
+/*--------------------------------------------------------------
+# STYLE
+--------------------------------------------------------------*/
+
+satus.style = function (element, object) {
+ if (object) {
+ for (var key in object) {
+ element.style[key] = object[key];
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# TEXT
+--------------------------------------------------------------*/
+
+satus.text = function (element, value) {
+ if (value) {
+ if (satus.isFunction(value)) {
+ value = value();
+ }
+
+ element.appendChild(document.createTextNode(this.locale.get(value)));
+ }
+};
+/*--------------------------------------------------------------
+>>> MODAL
+----------------------------------------------------------------
+# Confirm
+--------------------------------------------------------------*/
+
+satus.components.modal = function (component, skeleton) {
+ component.scrim = component.createChildElement('div', 'scrim');
+ component.surface = component.createChildElement('div', 'surface');
+
+ component.close = function () {
+ var component = this;
+
+ this.classList.add('satus-modal--closing');
+
+ setTimeout(function () {
+ component.remove();
+
+ component.dispatchEvent(new CustomEvent('close'));
+ }, Number(satus.css(this.surface, 'animation-duration').replace(/[^0-9.]/g, '')) * 1000);
+ };
+
+ component.scrim.addEventListener('click', function () {
+ this.parentNode.close();
+ });
+
+ if (satus.isset(skeleton.content)) {
+ component.surface.content = component.surface.createChildElement('p', 'content');
+
+ if (satus.isObject(skeleton.content)) {
+ satus.render(skeleton.content, component.surface.content);
+ } else {
+ component.surface.content.textContent = satus.locale.get(skeleton.content);
+ }
+ } else {
+ component.childrenContainer = component.surface;
+ }
+
+ if (satus.components.modal[skeleton.variant]) {
+ satus.components.modal[skeleton.variant](component, skeleton);
+ }
+};
+
+
+/*--------------------------------------------------------------
+# CONFIRM
+--------------------------------------------------------------*/
+
+satus.components.modal.confirm = function (component, skeleton) {
+ component.surface.actions = satus.render({
+ component: 'section',
+ variant: 'align-end'
+ }, component.surface);
+
+ if (skeleton.buttons) {
+ for (var key in skeleton.buttons) {
+ var button = satus.render(skeleton.buttons[key], component.surface.actions);
+
+ button.modalProvider = component;
+ }
+ } else {
+ satus.render({
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ properties: {
+ modalProvider: component,
+ },
+ on: {
+ click: function () {
+ this.modalProvider.dispatchEvent(new CustomEvent('cancel'));
+ this.modalProvider.close();
+ }
+ }
+ },
+ ok: {
+ component: 'button',
+ text: 'ok',
+ properties: {
+ modalProvider: component,
+ },
+ on: {
+ click: function () {
+ this.modalProvider.dispatchEvent(new CustomEvent('confirm'));
+ this.modalProvider.close();
+ }
+ }
+ }
+ }, component.surface.actions);
+ }
+};
+/*--------------------------------------------------------------
+>>> GRID
+--------------------------------------------------------------*/
+
+satus.components.grid = function (component, skeleton) {
+ console.log(component, skeleton);
+};
+/*--------------------------------------------------------------
+>>> TEXT FIELD
+--------------------------------------------------------------*/
+
+satus.components.textField = function (component, skeleton) {
+ var container = component.createChildElement('div', 'container'),
+ input = container.createChildElement('textarea'),
+ display = container.createChildElement('div', 'display'),
+ line_numbers = display.createChildElement('div', 'line-numbers'),
+ pre = display.createChildElement('pre'),
+ selection = display.createChildElement('div', 'selection'),
+ cursor = display.createChildElement('div', 'cursor'),
+ hiddenValue = container.createChildElement('pre', 'hidden-value');
+
+ component.placeholder = skeleton.placeholder;
+ component.input = input;
+ component.display = display;
+ component.line_numbers = line_numbers;
+ component.pre = pre;
+ component.hiddenValue = hiddenValue;
+ component.selection = selection;
+ component.cursor = cursor;
+ component.syntax = {
+ current: 'text',
+ handlers: {
+ regex: function (value, target) {
+ var regex_token = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
+ char_class_token = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g,
+ char_class_parts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/,
+ quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/,
+ matches = value.match(regex_token);
+
+ function create(type, string) {
+ var span = document.createElement('span');
+
+ span.className = type;
+ span.textContent = string;
+
+ target.appendChild(span);
+ }
+
+ for (var i = 0, l = matches.length; i < l; i++) {
+ var match = matches[i];
+
+ if (match[0] === '[') {
+ create('character-class', match);
+ } else if (match[0] === '(') {
+ create('group', match);
+ } else if (match[0] === ')') {
+ create('group', match);
+ } else if (match[0] === '\\' || match === '^') {
+ create('anchor', match);
+ } else if (quantifier.test(match)) {
+ create('quantifier', match);
+ } else if (match === '|' || match === '.') {
+ create('metasequence', match);
+ } else {
+ create('text', match);
+ }
+ }
+ }
+ },
+ set: function (syntax) {
+ if (this.handlers[syntax]) {
+ this.current = syntax;
+ } else {
+ this.current = 'text';
+ }
+
+ pre.update();
+ }
+ };
+ component.focus = function () {
+ this.input.focus();
+ };
+
+ if (satus.isset(skeleton.cols)) {
+ input.cols = skeleton.cols;
+ }
+
+ if (satus.isset(skeleton.rows)) {
+ input.rows = skeleton.rows;
+ }
+
+ Object.defineProperty(component, 'value', {
+ get: function () {
+ return this.input.value;
+ },
+ set: function (value) {
+ this.input.value = value;
+ }
+ });
+
+ if (skeleton.syntax) {
+ component.syntax.set(skeleton.syntax);
+ }
+
+ selection.setAttribute('disabled', '');
+
+ line_numbers.update = function () {
+ var component = this.parentNode.parentNode.parentNode,
+ count = component.input.value.split('\n').length;
+
+ if (count !== this.children.length) {
+ satus.empty(this);
+
+ for (var i = 1; i <= count; i++) {
+ var span = document.createElement('span');
+
+ span.textContent = i;
+
+ this.appendChild(span);
+ }
+ }
+
+ component.input.style.paddingLeft = this.offsetWidth + 'px';
+ };
+
+ pre.update = function () {
+ var component = this.parentNode.parentNode.parentNode,
+ handler = component.syntax.handlers[component.syntax.current],
+ value = component.value || '';
+
+ for (var i = this.childNodes.length - 1; i > -1; i--) {
+ this.childNodes[i].remove();
+ }
+
+ if (handler) {
+ handler(value, this);
+ } else {
+ this.textContent = value;
+ }
+
+ if (value.length === 0) {
+ var placeholder = component.placeholder;
+
+ if (typeof placeholder === 'function') {
+ placeholder = component.placeholder();
+ } else {
+ placeholder = satus.locale.get(placeholder);
+ }
+
+ this.textContent = placeholder;
+ }
+ };
+
+ cursor.update = function () {
+ var component = this.parentNode.parentNode.parentNode,
+ input = component.input,
+ value = input.value,
+ rows_count = value.split('\n').length,
+ start = input.selectionStart,
+ end = input.selectionEnd,
+ rows = value.slice(0, start).split('\n'),
+ top = 0;
+
+ this.style.animation = 'none';
+
+ if (input.selectionDirection === 'forward') {
+ component.hiddenValue.textContent = value.substring(0, end);
+ } else {
+ component.hiddenValue.textContent = value.substring(0, start);
+ }
+
+ top = component.hiddenValue.offsetHeight;
+
+ component.hiddenValue.textContent = satus.last(rows);
+
+ top -= component.hiddenValue.offsetHeight;
+
+ this.style.top = top + 'px';
+ this.style.left = component.hiddenValue.offsetWidth + component.line_numbers.offsetWidth + 'px';
+
+ if (start === end) {
+ component.selection.setAttribute('disabled', '');
+ } else {
+ component.selection.removeAttribute('disabled');
+
+ /*component.hiddenValue.textContent = value.substring(0, start);
+
+ component.selection.style.left = component.hiddenValue.offsetWidth - input.scrollLeft + 'px';
+
+ component.hiddenValue.textContent = value.substring(start, end);
+
+ component.selection.style.width = component.hiddenValue.offsetWidth + 'px';*/
+ }
+
+ this.style.animation = '';
+
+ component.hiddenValue.textContent = '';
+ };
+
+ document.addEventListener('selectionchange', function (event) {
+ component.line_numbers.update();
+ component.pre.update();
+ component.cursor.update();
+ });
+
+ input.addEventListener('input', function () {
+ var component = this.parentNode.parentNode;
+
+ component.storage.value = this.value;
+
+ component.line_numbers.update();
+ component.pre.update();
+ component.cursor.update();
+ });
+
+ input.addEventListener('scroll', function (event) {
+ var component = this.parentNode.parentNode;
+
+ component.display.style.top = -this.scrollTop + 'px';
+ component.display.style.left = -this.scrollLeft + 'px';
+
+ component.line_numbers.update();
+ component.pre.update();
+ component.cursor.update();
+ });
+
+ component.addEventListener('change', function () {
+ this.line_numbers.update();
+ this.pre.update();
+ this.cursor.update();
+ });
+
+ component.value = component.storage.value || '';
+
+ component.addEventListener('render', function () {
+ component.line_numbers.update();
+ component.pre.update();
+ component.cursor.update();
+ });
+
+ if (skeleton.on) {
+ for (var type in skeleton.on) {
+ input.addEventListener(type, function (event) {
+ this.parentNode.parentNode.dispatchEvent(new Event(event.type));
+ });
+ }
+ }
+};
+/*--------------------------------------------------------------
+>>> CHART
+----------------------------------------------------------------
+# Core
+ # Bar
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# CORE
+--------------------------------------------------------------*/
+
+satus.components.chart = function (component, skeleton) {
+ var type = skeleton.type;
+
+ if (this.chart[type]) {
+ component.classList.add('satus-chart--' + type);
+
+ this.chart[type](component, skeleton);
+ }
+};
+
+
+/*--------------------------------------------------------------
+# BAR
+--------------------------------------------------------------*/
+
+satus.components.chart.bar = function (component, skeleton) {
+ var labels = skeleton.labels,
+ datasets = skeleton.datasets,
+ bars = [];
+
+ if (satus.isFunction(labels)) {
+ labels = labels();
+ }
+
+ if (satus.isFunction(datasets)) {
+ datasets = datasets();
+ }
+
+ if (satus.isArray(labels)) {
+ var container = component.createChildElement('div', 'labels');
+
+ for (var i = 0, l = labels.length; i < l; i++) {
+ var label = labels[i],
+ section = container.createChildElement('div', 'section');
+
+ section.textContent = label;
+ }
+ }
+
+ if (satus.isArray(datasets)) {
+ var container = component.createChildElement('div', 'bars');
+
+ for (var i = 0, l = datasets.length; i < l; i++) {
+ var dataset = datasets[i];
+
+ for (var j = 0, k = dataset.data.length; j < k; j++) {
+ if (!satus.isElement(bars[j])) {
+ bars.push(container.createChildElement('div', 'bar'));
+ }
+
+ var piece = bars[j].createChildElement('div', 'piece');
+
+ piece.title = dataset.label;
+ piece.style.height = dataset.data[j] + '%';
+ piece.style.backgroundColor = 'rgb(' + dataset.color.join(',') + ')';
+ }
+ }
+ }
+};
+/*--------------------------------------------------------------
+>>> SELECT
+--------------------------------------------------------------*/
+
+satus.components.select = function (component, skeleton) {
+ var content = component.createChildElement('div', 'content');
+
+ component.childrenContainer = content;
+ component.valueElement = document.createElement('span');
+ component.selectElement = document.createElement('select');
+
+ component.valueElement.className = 'satus-select__value';
+
+ component.appendChild(component.valueElement);
+ component.appendChild(component.selectElement);
+
+ component.options = skeleton.options || [];
+
+ if (satus.isFunction(component.options)) {
+ component.options = component.options();
+ }
+
+ for (var i = 0, l = component.options.length; i < l; i++) {
+ var option = document.createElement('option');
+
+ option.value = component.options[i].value;
+
+ satus.text(option, component.options[i].text);
+
+ component.selectElement.appendChild(option);
+ }
+
+ Object.defineProperty(component, 'value', {
+ get() {
+ return this.selectElement.value;
+ },
+ set(value) {
+ this.selectElement.value = value;
+ }
+ });
+
+ component.render = function () {
+ satus.empty(this.valueElement);
+
+ if (this.selectElement.options[this.selectElement.selectedIndex]) {
+ satus.text(this.valueElement, this.selectElement.options[this.selectElement.selectedIndex].text);
+ }
+
+ this.dataset.value = this.value;
+ };
+
+ component.selectElement.addEventListener('change', function () {
+ var component = this.parentNode;
+
+ component.storage.value = this.value;
+
+ component.render();
+ });
+
+ component.value = component.storage.value || component.options[0].value;
+
+ component.render();
+};
+/*--------------------------------------------------------------
+>>> DIVIDER
+--------------------------------------------------------------*/
+
+satus.components.divider = function () {};
+/*--------------------------------------------------------------
+>>> SECTION
+--------------------------------------------------------------*/
+
+satus.components.section = function (component, skeleton) {
+ if (satus.isString(skeleton.title)) {
+ component.dataset.title = satus.locale.get(skeleton.title);
+ }
+};
+/*--------------------------------------------------------------
+>>> BASE
+--------------------------------------------------------------*/
+
+satus.components.base = function (component) {
+ component.baseProvider = component;
+ component.layers = [];
+};
+/*--------------------------------------------------------------
+>>> ALERT
+--------------------------------------------------------------*/
+
+satus.components.alert = function (component, skeleton) {};
+/*--------------------------------------------------------------
+>>> TIME
+--------------------------------------------------------------*/
+
+satus.components.time = function (component, skeleton) {
+ var select_skeleton = Object.assign({}, skeleton);
+
+ select_skeleton.component = 'select';
+ select_skeleton.options = [];
+
+ if (satus.isFunction(select_skeleton.hour12)) {
+ select_skeleton.hour12 = select_skeleton.hour12();
+ }
+
+ for (var i = 0, l = 24; i < l; i++) {
+ var hour = i,
+ value = i;
+
+ if (select_skeleton.hour12 === true && i > 12) {
+ hour -= 12;
+ }
+
+ if (hour < 10) {
+ hour = '0' + hour;
+ value = '0' + value;
+ }
+
+ if (select_skeleton.hour12 === true) {
+ if (i > 12) {
+ hour += ':00 pm';
+ } else {
+ hour += ':00 am';
+ }
+ } else {
+ hour += ':00'
+ }
+
+ select_skeleton.options.push({
+ text: hour,
+ value: value + ':00'
+ });
+ }
+
+ satus.components.select(component, select_skeleton);
+
+ component.classList.add('satus-select');
+};
+/*--------------------------------------------------------------
+>>> SIDEBAR
+--------------------------------------------------------------*/
+
+satus.components.sidebar = function (component, skeleton) {};
+/*--------------------------------------------------------------
+>>> LAYERS
+--------------------------------------------------------------*/
+
+satus.components.layers = function (component, skeleton) {
+ component.path = [];
+ component.renderChildren = false;
+ component.baseProvider.layers.push(component);
+
+ component.back = function () {
+ if (this.path.length > 1) {
+ this.path.pop();
+
+ this.open(this.path[this.path.length - 1], false);
+ }
+ };
+
+ component.open = function (skeleton, history) {
+ var previous_layer = satus.last(this.querySelectorAll('.satus-layers__layer')),
+ layer = this.createChildElement('div', 'layer');
+
+ if (history !== false) {
+ if (previous_layer) {
+ previous_layer.style.animation = 'fadeOutLeft 100ms linear forwards';
+ layer.style.animation = 'fadeInRight 100ms linear forwards';
+ }
+
+ this.path.push(skeleton);
+ } else {
+ previous_layer.style.animation = 'fadeOutRight 100ms linear forwards';
+ layer.style.animation = 'fadeInLeft 100ms linear forwards';
+ }
+
+ if (previous_layer) {
+ setTimeout(function () {
+ previous_layer.remove();
+ }, satus.getAnimationDuration(previous_layer));
+ }
+
+ layer.skeleton = skeleton;
+ layer.baseProvider = this.baseProvider;
+
+ satus.render(skeleton, layer, undefined, skeleton.component === 'layers');
+
+ this.dispatchEvent(new Event('open'));
+ };
+
+ component.update = function () {
+ var layer = this.querySelector('.satus-layers__layer');
+
+ satus.empty(layer);
+ satus.render(layer.skeleton, layer);
+ };
+
+ component.open(skeleton);
+};
+/*--------------------------------------------------------------
+>>> LIST
+--------------------------------------------------------------*/
+
+satus.components.list = function (component, skeleton) {
+ for (var i = 0, l = skeleton.items.length; i < l; i++) {
+ var li = component.createChildElement('div', 'item'),
+ item = skeleton.items[i];
+
+ for (var j = 0, k = item.length; j < k; j++) {
+ var child = item[j];
+
+ if (satus.isObject(child)) {
+ satus.render(child, li);
+ } else {
+ var span = li.createChildElement('span');
+
+ span.textContent = satus.locale.get(child);
+ }
+ }
+ }
+};
+/*--------------------------------------------------------------
+>>> COLOR PICKER
+--------------------------------------------------------------*/
+
+satus.components.colorPicker = function (component, skeleton) {
+ var component_content = component.createChildElement('div', 'content'),
+ component_value = component.createChildElement('span', 'value');
+
+ component.childrenContainer = component_content;
+ component.valueElement = component_value;
+
+ component.className = 'satus-button';
+
+ component.addEventListener('click', function () {
+ var rgb = this.rgb,
+ hsl = satus.color.rgbToHsl(rgb),
+ s = hsl[1] / 100,
+ l = hsl[2] / 100;
+
+ s *= l < .5 ? l : 1 - l;
+
+ var v = l + s;
+
+ s = 2 * s / (l + s);
+
+ satus.render({
+ component: 'modal',
+ variant: 'color-picker',
+ value: hsl,
+ parentElement: this,
+
+ palette: {
+ component: 'div',
+ class: 'satus-color-picker__palette',
+ style: {
+ 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)'
+ },
+ on: {
+ mousedown: function () {
+ var palette = this,
+ rect = this.getBoundingClientRect(),
+ cursor = this.children[0];
+
+ function mousemove(event) {
+ var hsl = palette.skeleton.parentSkeleton.storage.value,
+ x = event.clientX - rect.left,
+ y = event.clientY - rect.top,
+ s;
+
+ x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100);
+ y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100);
+
+ var v = 100 - y,
+ l = (2 - x / 100) * v / 2;
+
+ hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2);
+ hsl[2] = l;
+
+ cursor.style.left = x + '%';
+ cursor.style.top = y + '%';
+
+ palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)';
+
+ event.preventDefault();
+ }
+
+ function mouseup() {
+ window.removeEventListener('mousemove', mousemove);
+ window.removeEventListener('mouseup', mouseup);
+ }
+
+ window.addEventListener('mousemove', mousemove);
+ window.addEventListener('mouseup', mouseup);
+ }
+ },
+
+ cursor: {
+ component: 'div',
+ class: 'satus-color-picker__cursor',
+ style: {
+ 'left': s * 100 + '%',
+ 'top': 100 - v * 100 + '%'
+ }
+ }
+ },
+ section: {
+ component: 'section',
+ variant: 'color',
+
+ color: {
+ component: 'div',
+ class: 'satus-color-picker__color',
+ style: {
+ 'backgroundColor': 'rgb(' + this.rgb.join(',') + ')'
+ }
+ },
+ hue: {
+ component: 'slider',
+ class: 'satus-color-picker__hue',
+ storage: false,
+ value: hsl[0],
+ max: 360,
+ on: {
+ change: function () {
+ var modal = this.skeleton.parentSkeleton.parentSkeleton,
+ hsl = modal.storage.value;
+
+ hsl[0] = this.values[0];
+
+ this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)';
+ this.parentSkeletonNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)';
+ }
+ }
+ }
+ },
+ actions: {
+ component: 'section',
+ variant: 'actions',
+
+ reset: {
+ component: 'button',
+ text: 'reset',
+ on: {
+ click: function () {
+ var modal = this.skeleton.parentSkeleton.parentSkeleton,
+ component = modal.parentSkeleton;
+
+ component.rgb = component.skeleton.value;
+
+ component.storage.value = component.rgb;
+
+ component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')';
+
+ modal.rendered.close();
+ }
+ }
+ },
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ on: {
+ click: function () {
+ this.skeleton.parentSkeleton.parentSkeleton.rendered.close();
+ }
+ }
+ },
+ ok: {
+ component: 'button',
+ text: 'OK',
+ on: {
+ click: function () {
+ var modal = this.skeleton.parentSkeleton.parentSkeleton,
+ component = modal.parentSkeleton;
+
+ component.rgb = satus.color.hslToRgb(modal.storage.value);
+
+ component.storage.value = component.rgb;
+
+ component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')';
+
+ modal.rendered.close();
+ }
+ }
+ }
+ }
+ }, this.baseProvider.layers[0]);
+ });
+
+ component.addEventListener('render', function () {
+ component.rgb = this.storage.value || [0, 100, 50];
+
+ component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')';
+ });
+};
+
+satus.components.colorPicker = function (component, skeleton) {
+ component.childrenContainer = component.createChildElement('div', 'content');
+
+ component.color = (function (element) {
+ var array;
+
+ Object.defineProperty(element, 'value', {
+ get: function () {
+ return array;
+ },
+ set: function (value) {
+ array = value;
+
+ this.parentNode.storage.value = array;
+
+ element.style.backgroundColor = 'rgb(' + value.join(',') + ')';
+ }
+ });
+
+ element.value = component.storage.value || component.skeleton.value || [0, 0, 0];
+
+ return element;
+ })(component.createChildElement('span', 'value'));
+
+ component.addEventListener('click', function () {
+ var hsl = satus.color.rgbToHsl(this.color.value),
+ s = hsl[1] / 100,
+ l = hsl[2] / 100;
+
+ s *= l < .5 ? l : 1 - l;
+
+ var v = l + s;
+
+ s = 2 * s / (l + s);
+
+ satus.render({
+ component: 'modal',
+ variant: 'color-picker',
+ value: hsl,
+ parentElement: this,
+
+ palette: {
+ component: 'div',
+ class: 'satus-color-picker__palette',
+ style: {
+ 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)'
+ },
+ on: {
+ mousedown: function (event) {
+ if (event.button !== 0) {
+ return false;
+ }
+
+ var palette = this,
+ rect = this.getBoundingClientRect(),
+ cursor = this.children[0];
+
+ function mousemove(event) {
+ var hsl = palette.skeleton.parentSkeleton.value,
+ x = event.clientX - rect.left,
+ y = event.clientY - rect.top,
+ s;
+
+ x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100);
+ y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100);
+
+ var v = 100 - y,
+ l = (2 - x / 100) * v / 2;
+
+ hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2);
+ hsl[2] = l;
+
+ cursor.style.left = x + '%';
+ cursor.style.top = y + '%';
+
+ palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)';
+
+ event.preventDefault();
+ }
+
+ function mouseup() {
+ window.removeEventListener('mousemove', mousemove);
+ window.removeEventListener('mouseup', mouseup);
+ }
+
+ window.addEventListener('mousemove', mousemove);
+ window.addEventListener('mouseup', mouseup);
+ }
+ },
+
+ cursor: {
+ component: 'div',
+ class: 'satus-color-picker__cursor',
+ style: {
+ 'left': s * 100 + '%',
+ 'top': 100 - v * 100 + '%'
+ }
+ }
+ },
+ section: {
+ component: 'section',
+ variant: 'color',
+
+ color: {
+ component: 'div',
+ class: 'satus-color-picker__color',
+ style: {
+ 'backgroundColor': 'rgb(' + this.color.value.join(',') + ')'
+ }
+ },
+ hue: {
+ component: 'slider',
+ class: 'satus-color-picker__hue',
+ storage: false,
+ value: hsl[0],
+ max: 360,
+ on: {
+ input: function () {
+ var modal = this.skeleton.parentSkeleton.parentSkeleton,
+ hsl = modal.value;
+
+ hsl[0] = this.storage.value;
+
+ this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)';
+ this.parentNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)';
+ }
+ }
+ }
+ },
+ actions: {
+ component: 'section',
+ variant: 'actions',
+
+ reset: {
+ component: 'button',
+ text: 'reset',
+ on: {
+ click: function () {
+ var modal = this.skeleton.parentSkeleton.parentSkeleton,
+ component = modal.parentElement;
+
+ component.color.value = component.skeleton.value || [0, 0, 0];
+
+ modal.rendered.close();
+ }
+ }
+ },
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ on: {
+ click: function () {
+ this.skeleton.parentSkeleton.parentSkeleton.rendered.close();
+ }
+ }
+ },
+ ok: {
+ component: 'button',
+ text: 'OK',
+ on: {
+ click: function () {
+ var modal = this.skeleton.parentSkeleton.parentSkeleton,
+ component = modal.parentElement;
+
+ component.color.value = satus.color.hslToRgb(modal.value);
+
+ modal.rendered.close();
+ }
+ }
+ }
+ }
+ }, this.baseProvider.layers[0]);
+ });
+};
+/*--------------------------------------------------------------
+>>> RADIO
+--------------------------------------------------------------*/
+
+satus.components.radio = function (component, skeleton) {
+ component.nativeControl = component.createChildElement('input', 'input');
+
+ component.createChildElement('i');
+
+ component.childrenContainer = component.createChildElement('div', 'content');
+
+ component.nativeControl.type = 'radio';
+
+ if (skeleton.group) {
+ component.storage.key = skeleton.group;
+ component.nativeControl.name = skeleton.group;
+ }
+
+ if (skeleton.value) {
+ component.nativeControl.value = skeleton.value;
+ }
+
+ component.storage.value = satus.storage.get(component.storage.key);
+
+ if (satus.isset(component.storage.value)) {
+ component.nativeControl.checked = component.storage.value === skeleton.value;
+ } else if (skeleton.checked) {
+ component.nativeControl.checked = true;
+ }
+
+ component.nativeControl.addEventListener('change', function () {
+ var component = this.parentNode;
+
+ component.storage.value = this.value;
+ });
+};
+/*--------------------------------------------------------------
+>>> SLIDER
+--------------------------------------------------------------*/
+
+satus.components.slider = function (component, skeleton) {
+ var content = component.createChildElement('div', 'content'),
+ track_container = component.createChildElement('div', 'track-container'),
+ input = track_container.createChildElement('input', 'input');
+
+ component.childrenContainer = content;
+ component.input = input;
+ component.track = track_container.createChildElement('div', 'track');
+
+ input.type = 'range';
+ input.min = skeleton.min || 0;
+ input.max = skeleton.max || 1;
+ input.step = skeleton.step || 1;
+ input.value = component.storage.value || skeleton.value || 0;
+
+ input.addEventListener('input', function () {
+ var component = this.parentNode.parentNode;
+
+ component.storage.value = Number(this.value);
+
+ component.update();
+ });
+
+ component.update = function () {
+ var input = this.input;
+
+ this.track.style.width = 100 / (input.max - input.min) * (input.value - input.min) + '%';
+ };
+
+ component.update();
+
+ if (skeleton.on) {
+ for (var type in skeleton.on) {
+ input.addEventListener(type, function (event) {
+ this.parentNode.parentNode.dispatchEvent(new Event(event.type));
+ });
+ }
+ }
+};
+/*--------------------------------------------------------------
+>>> TABS
+--------------------------------------------------------------*/
+
+satus.components.tabs = function (component, skeleton) {
+ var tabs = skeleton.items,
+ value = skeleton.value;
+
+ if (satus.isFunction(tabs)) {
+ tabs = tabs();
+ }
+
+ if (satus.isFunction(value)) {
+ value = value();
+ }
+
+ for (var i = 0, l = tabs.length; i < l; i++) {
+ var tab = tabs[i],
+ button = component.createChildElement('button');
+
+ button.addEventListener('click', function () {
+ var component = this.parentNode,
+ index = satus.elementIndex(this);
+
+ component.value = index;
+
+ component.style.setProperty('--satus-tabs-current', index);
+ });
+
+ satus.text(button, tab);
+ }
+
+ component.style.setProperty('--satus-tabs-count', tabs.length);
+ component.style.setProperty('--satus-tabs-current', value || 0);
+};
+/*--------------------------------------------------------------
+>>> SHORTCUT
+--------------------------------------------------------------*/
+
+satus.components.shortcut = function (component, skeleton) {
+ component.childrenContainer = component.createChildElement('div', 'content');
+ component.valueElement = component.createChildElement('div', 'value');
+
+ component.className = 'satus-button';
+
+ component.render = function (parent) {
+ var self = this,
+ parent = parent || self.primary,
+ children = parent.children;
+
+ satus.empty(parent);
+
+ function createElement(name) {
+ var element = document.createElement('div');
+
+ element.className = 'satus-shortcut__' + name;
+
+ parent.appendChild(element);
+
+ return element;
+ }
+
+ if (this.data.alt) {
+ createElement('key').textContent = 'Alt';
+ }
+
+ if (this.data.ctrl) {
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ createElement('key').textContent = 'Ctrl';
+ }
+
+ if (this.data.shift) {
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ createElement('key').textContent = 'Shift';
+ }
+
+ for (var code in this.data.keys) {
+ var key = this.data.keys[code].key,
+ arrows = ['ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft'],
+ index = arrows.indexOf(key);
+
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ if (index !== -1) {
+ createElement('key').textContent = ['↑', '→', '↓', '←'][index];
+ } else if (key === ' ') {
+ createElement('key').textContent = '␣';
+ } else if (key) {
+ createElement('key').textContent = key.toUpperCase();
+ }
+ }
+
+ if (this.data.wheel) {
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ var mouse = createElement('mouse'),
+ div = document.createElement('div');
+
+ mouse.appendChild(div);
+
+ mouse.className += ' ' + (this.data.wheel > 0);
+ }
+
+ if (this.data.click) {
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ var mouse = createElement('mouse'),
+ div = document.createElement('div');
+
+ mouse.appendChild(div);
+
+ mouse.className += ' click';
+ }
+
+ if (this.data.middle) {
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ var mouse = createElement('mouse'),
+ div = document.createElement('div');
+
+ mouse.appendChild(div);
+
+ mouse.className += ' middle';
+ }
+
+ if (this.data.context) {
+ if (children.length && children[children.length - 1].className.indexOf('plus') === -1) {
+ createElement('plus');
+ }
+
+ var mouse = createElement('mouse'),
+ div = document.createElement('div');
+
+ mouse.appendChild(div);
+
+ mouse.className += ' context';
+ }
+ };
+
+ component.keydown = function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ component.data = {
+ alt: event.altKey,
+ ctrl: event.ctrlKey,
+ shift: event.shiftKey,
+ keys: {}
+ };
+
+ if (['control', 'alt', 'altgraph', 'shift'].indexOf(event.key.toLowerCase()) === -1) {
+ component.data.keys[event.keyCode] = {
+ code: event.code,
+ key: event.key
+ };
+ }
+
+ component.data.wheel = 0;
+
+ component.render();
+
+ return false;
+ };
+
+ if (skeleton.wheel !== false) {
+ component.mousewheel = function (event) {
+ event.stopPropagation();
+
+ if (
+ (
+ component.data.wheel === 0 &&
+ (
+ Object.keys(component.data.keys).length === 0 &&
+ component.data.alt === false &&
+ component.data.ctrl === false &&
+ component.data.shift === false
+ )
+ ) ||
+ component.data.wheel < 0 && event.deltaY > 0 ||
+ component.data.wheel > 0 && event.deltaY < 0) {
+ component.data = {
+ alt: false,
+ ctrl: false,
+ shift: false,
+ keys: {}
+ };
+ }
+
+ component.data.wheel = event.deltaY < 0 ? -1 : 1;
+
+ component.render();
+
+ return false;
+ };
+ }
+
+ component.addEventListener('click', function () {
+ satus.render({
+ component: 'modal',
+ properties: {
+ parent: this
+ },
+ on: {
+ close: function () {
+ window.removeEventListener('keydown', component.keydown);
+ window.removeEventListener('wheel', component.mousewheel);
+ }
+ },
+
+ primary: {
+ component: 'div',
+ class: 'satus-shortcut__primary',
+ on: {
+ render: function () {
+ component.primary = this;
+
+ if (component.skeleton.mouseButtons === true) {
+ this.addEventListener('mousedown', function (event) {
+ if (
+ component.data.click && event.button === 0 ||
+ component.data.middle && event.button === 1
+ ) {
+ component.data = {
+ alt: false,
+ ctrl: false,
+ shift: false,
+ keys: {}
+ };
+ }
+
+ component.data.click = false;
+ component.data.middle = false;
+ component.data.context = false;
+
+ if (event.button === 0) {
+ component.data.click = true;
+
+ component.render();
+ } else if (event.button === 1) {
+ component.data.middle = true;
+
+ component.render();
+ }
+ });
+
+ this.addEventListener('contextmenu', function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (component.data.context) {
+ component.data = {
+ alt: false,
+ ctrl: false,
+ shift: false,
+ keys: {}
+ };
+ }
+
+ component.data.context = true;
+ component.data.middle = false;
+ component.data.click = false;
+
+ component.render();
+
+ return false;
+ });
+ }
+
+ component.render();
+ }
+ }
+ },
+ actions: {
+ component: 'section',
+ variant: 'actions',
+
+ reset: {
+ component: 'button',
+ text: 'reset',
+ on: {
+ click: function () {
+ var component = this.parentNode.parentNode.parentNode.parent;
+
+ component.data = component.skeleton.value || {};
+
+ component.render(component.valueElement);
+
+ satus.storage.remove(component.storage);
+
+ this.parentNode.parentNode.parentNode.close();
+
+ window.removeEventListener('keydown', component.keydown);
+ window.removeEventListener('wheel', component.mousewheel);
+ }
+ }
+ },
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ on: {
+ click: function () {
+ component.data = satus.storage.get(component.storage) || component.skeleton.value || {};
+
+ component.render(component.valueElement);
+
+ this.parentNode.parentNode.parentNode.close();
+
+ window.removeEventListener('keydown', component.keydown);
+ window.removeEventListener('wheel', component.mousewheel);
+ }
+ }
+ },
+ save: {
+ component: 'button',
+ text: 'save',
+ on: {
+ click: function () {
+ component.storage.value = component.data;
+
+ component.render(component.valueElement);
+
+ this.parentNode.parentNode.parentNode.close();
+
+ window.removeEventListener('keydown', component.keydown);
+ window.removeEventListener('wheel', component.mousewheel);
+ }
+ }
+ }
+ }
+ }, this.baseProvider);
+
+ window.addEventListener('keydown', this.keydown);
+ window.addEventListener('wheel', this.mousewheel);
+ });
+
+ component.data = component.storage.value || {
+ alt: false,
+ ctrl: false,
+ shift: false,
+ keys: {},
+ wheel: 0
+ };
+
+ component.render(component.valueElement);
+};
+/*--------------------------------------------------------------
+>>> CHECKBOX
+--------------------------------------------------------------*/
+
+satus.components.checkbox = function (component, skeleton) {
+ component.addEventListener('click', function () {
+ if (this.dataset.value === 'true') {
+ this.storage.value = false;
+ this.dataset.value = 'false';
+ } else {
+ this.storage.value = true;
+ this.dataset.value = 'true';
+ }
+ });
+
+ component.addEventListener('render', function () {
+ this.dataset.value = this.storage.value;
+ });
+};
+/*--------------------------------------------------------------
+>>> SWITCH
+--------------------------------------------------------------*/
+
+satus.components.switch = function (component, skeleton) {
+ var content = component.createChildElement('div', 'content'),
+ component_thumb = component.createChildElement('i');
+
+ component.childrenContainer = content;
+
+ component.addEventListener('click', function () {
+ if (this.dataset.value === 'true') {
+ this.storage.value = false;
+ this.dataset.value = 'false';
+ } else {
+ this.storage.value = true;
+ this.dataset.value = 'true';
+ }
+ }, true);
+
+ component.addEventListener('render', function () {
+ this.dataset.value = this.storage.value;
+ });
+};
+/*--------------------------------------------------------------
+>>> MANIFEST
+--------------------------------------------------------------*/
+
+satus.manifest = function () {
+ var object = {};
+
+ if (this.isset('chrome.runtime.getManifest')) {
+ object = chrome.runtime.getManifest();
+ }
+
+ return object;
+};
+/*--------------------------------------------------------------
+>>> COLOR:
+----------------------------------------------------------------
+# String to array
+# RGB to HSL
+# HUE to RGB
+# HSL to RGB
+--------------------------------------------------------------*/
+
+satus.color = {};
+
+
+/*--------------------------------------------------------------
+# STRING TO ARRAY
+--------------------------------------------------------------*/
+
+satus.color.stringToArray = function (string) {
+ var match = string.match(/[0-9.]+/g);
+
+ if (match) {
+ for (var i = 0, l = match.length; i < l; i++) {
+ match[i] = parseFloat(match[i]);
+ }
+ }
+
+ return match;
+};
+
+
+/*--------------------------------------------------------------
+# RGB TO HSL
+--------------------------------------------------------------*/
+
+satus.color.rgbToHsl = function (array) {
+ var r = array[0] / 255,
+ g = array[1] / 255,
+ b = array[2] / 255,
+ min = Math.min(r, g, b),
+ max = Math.max(r, g, b),
+ h = 0,
+ s = 0,
+ l = (min + max) / 2;
+
+ if (min === max) {
+ h = 0;
+ s = 0;
+ } else {
+ var delta = max - min;
+
+ s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min);
+
+ if (max === r) {
+ h = (g - b) / delta + (g < b ? 6 : 0);
+ } else if (max === g) {
+ h = (b - r) / delta + 2;
+ } else if (max === b) {
+ h = (r - g) / delta + 4;
+ }
+
+ h /= 6;
+ }
+
+ h *= 360;
+ s *= 100;
+ l *= 100;
+
+ if (array.length === 3) {
+ return [h, s, l];
+ } else {
+ return [h, s, l, array[3]];
+ }
+};
+
+
+/*--------------------------------------------------------------
+# HUE TO RGB
+--------------------------------------------------------------*/
+
+satus.color.hueToRgb = function (array) {
+ var t1 = array[0],
+ t2 = array[1],
+ hue = array[2];
+
+ if (hue < 0) {
+ hue += 6;
+ }
+
+ if (hue >= 6) {
+ hue -= 6;
+ }
+
+ if (hue < 1) {
+ return (t2 - t1) * hue + t1;
+ } else if (hue < 3) {
+ return t2;
+ } else if (hue < 4) {
+ return (t2 - t1) * (4 - hue) + t1;
+ } else {
+ return t1;
+ }
+};
+
+
+/*--------------------------------------------------------------
+# HSL TO RGB
+--------------------------------------------------------------*/
+
+satus.color.hslToRgb = function (array) {
+ var h = array[0] / 360,
+ s = array[1] / 100,
+ l = array[2] / 100,
+ r, g, b;
+
+ if (s == 0) {
+ r = g = b = l;
+ } else {
+ var hue2rgb = function (p, q, t) {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
+ if (t < 1 / 2) return q;
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
+ return p;
+ };
+
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1 / 3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1 / 3);
+ }
+
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
+};
+/*--------------------------------------------------------------
+>>> USER
+----------------------------------------------------------------
+# OS
+ # Name
+ # Bitness
+# Browser
+ # Name
+ # Version
+ # Platform
+ # Manifest
+ # Languages
+ # Cookies
+ # Flash
+ # Java
+ # Audio
+ # Video
+ # WebGL
+# Device
+ # Screen
+ # RAM
+ # GPU
+ # Cores
+ # Touch
+ # Connection
+--------------------------------------------------------------*/
+
+satus.user = {
+ browser: {},
+ device: {},
+ os: {}
+};
+
+/*--------------------------------------------------------------
+# OS
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# NAME
+--------------------------------------------------------------*/
+
+satus.user.os.name = function () {
+ var app_version = navigator.appVersion;
+
+ if (app_version.indexOf('Win') !== -1) {
+ if (app_version.match(/(Windows 10.0|Windows NT 10.0)/)) {
+ return 'Windows 10';
+ } else if (app_version.match(/(Windows 8.1|Windows NT 6.3)/)) {
+ return 'Windows 8.1';
+ } else if (app_version.match(/(Windows 8|Windows NT 6.2)/)) {
+ return 'Windows 8';
+ } else if (app_version.match(/(Windows 7|Windows NT 6.1)/)) {
+ return 'Windows 7';
+ } else if (app_version.match(/(Windows NT 6.0)/)) {
+ return 'Windows Vista';
+ } else if (app_version.match(/(Windows NT 5.1|Windows XP)/)) {
+ return 'Windows XP';
+ } else {
+ return 'Windows';
+ }
+ } else if (app_version.indexOf('(iPhone|iPad|iPod)') !== -1) {
+ return 'iOS';
+ } else if (app_version.indexOf('Mac') !== -1) {
+ return 'macOS';
+ } else if (app_version.indexOf('Android') !== -1) {
+ return 'Android';
+ } else if (app_version.indexOf('OpenBSD') !== -1) {
+ return 'OpenBSD';
+ } else if (app_version.indexOf('SunOS') !== -1) {
+ return 'SunOS';
+ } else if (app_version.indexOf('Linux') !== -1) {
+ return 'Linux';
+ } else if (app_version.indexOf('X11') !== -1) {
+ return 'UNIX';
+ }
+};
+
+
+/*--------------------------------------------------------------
+# BITNESS
+--------------------------------------------------------------*/
+
+satus.user.os.bitness = function () {
+ if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) {
+ return '64-bit';
+ } else {
+ return '32-bit';
+ }
+};
+
+
+/*--------------------------------------------------------------
+# BROWSER
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# NAME
+--------------------------------------------------------------*/
+
+satus.user.browser.name = function () {
+ var user_agent = navigator.userAgent;
+
+ if (user_agent.indexOf('Opera') !== -1) {
+ return 'Opera';
+ } else if (user_agent.indexOf('Vivaldi') !== -1) {
+ return 'Vivaldi';
+ } else if (user_agent.indexOf('Edge') !== -1) {
+ return 'Edge';
+ } else if (user_agent.indexOf('Chrome') !== -1) {
+ return 'Chrome';
+ } else if (user_agent.indexOf('Safari') !== -1) {
+ return 'Safari';
+ } else if (user_agent.indexOf('Firefox') !== -1) {
+ return 'Firefox';
+ } else if (user_agent.indexOf('MSIE') !== -1) {
+ return 'IE';
+ }
+};
+
+
+/*--------------------------------------------------------------
+# VERSION
+--------------------------------------------------------------*/
+
+satus.user.browser.version = function () {
+ var browser_name = satus.user.browser.name(),
+ browser_version = navigator.userAgent.match(new RegExp(browser_name + '/([0-9.]+)'));
+
+ return browser_version[1];
+};
+
+
+/*--------------------------------------------------------------
+# PLATFORM
+--------------------------------------------------------------*/
+
+satus.user.browser.platform = function () {
+ return navigator.platform;
+};
+
+
+/*--------------------------------------------------------------
+# MANIFEST
+--------------------------------------------------------------*/
+
+satus.user.browser.manifest = function () {
+ return chrome.runtime.getManifest() || {};
+};
+
+
+/*--------------------------------------------------------------
+# LANGUAGES
+--------------------------------------------------------------*/
+
+satus.user.browser.languages = function () {
+ return navigator.languages;
+};
+
+
+/*--------------------------------------------------------------
+# COOKIES
+--------------------------------------------------------------*/
+
+satus.user.browser.cookies = function () {
+ if (document.cookie) {
+ var random_cookie = 'ta{t`nX6cMXK,Wsc';
+
+ document.cookie = random_cookie;
+
+ if (document.cookie.indexOf(random_cookie) !== -1) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+
+/*--------------------------------------------------------------
+# FLASH
+--------------------------------------------------------------*/
+
+satus.user.browser.flash = function () {
+ try {
+ if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) {
+ return true;
+ }
+ } catch (error) {
+ if (navigator.mimeTypes['application/x-shockwave-flash']) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+
+/*--------------------------------------------------------------
+# JAVA
+--------------------------------------------------------------*/
+
+satus.user.browser.java = function () {
+ if (satus.isFunction(navigator.javaEnabled) && navigator.javaEnabled()) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+
+/*--------------------------------------------------------------
+# AUDIO
+--------------------------------------------------------------*/
+
+satus.user.browser.audio = function () {
+ var audio = document.createElement('audio'),
+ types = {
+ mp3: 'audio/mpeg',
+ mp4: 'audio/mp4',
+ aif: 'audio/x-aiff'
+ },
+ result = [];
+
+ if (satus.isFunction(audio.canPlayType)) {
+ for (var key in types) {
+ var can_play_type = audio.canPlayType(types[key]);
+
+ if (can_play_type !== '') {
+ result.push(key);
+ }
+ }
+ }
+
+ return result;
+};
+
+
+/*--------------------------------------------------------------
+# VIDEO
+--------------------------------------------------------------*/
+
+satus.user.browser.video = function () {
+ var video = document.createElement('video'),
+ types = {
+ ogg: 'video/ogg; codecs="theora"',
+ h264: 'video/mp4; codecs="avc1.42E01E"',
+ webm: 'video/webm; codecs="vp8, vorbis"',
+ vp9: 'video/webm; codecs="vp9"',
+ hls: 'application/x-mpegURL; codecs="avc1.42E01E"'
+ },
+ result = [];
+
+ if (satus.isFunction(video.canPlayType)) {
+ for (var key in types) {
+ var can_play_type = video.canPlayType(types[key]);
+
+ if (can_play_type !== '') {
+ result.push(key);
+ }
+ }
+ }
+
+ return result;
+};
+
+
+/*--------------------------------------------------------------
+# WEBGL
+--------------------------------------------------------------*/
+
+satus.user.browser.webgl = function () {
+ var cvs = document.createElement('canvas'),
+ ctx = cvs.getContext('webgl');
+
+ return ctx && ctx instanceof WebGLRenderingContext;
+};
+
+
+/*--------------------------------------------------------------
+# HARDWARE
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# SCREEN
+--------------------------------------------------------------*/
+
+satus.user.device.screen = function () {
+ if (screen) {
+ return screen.width + 'x' + screen.height;
+ }
+};
+
+
+/*--------------------------------------------------------------
+# RAM
+--------------------------------------------------------------*/
+
+satus.user.device.ram = function () {
+ if ('deviceMemory' in navigator) {
+ return navigator.deviceMemory + ' GB';
+ }
+};
+
+
+/*--------------------------------------------------------------
+# GPU
+--------------------------------------------------------------*/
+
+satus.user.device.gpu = function () {
+ var cvs = document.createElement('canvas'),
+ ctx = cvs.getContext('webgl');
+
+ if (
+ ctx &&
+ ctx instanceof WebGLRenderingContext &&
+ 'getParameter' in ctx &&
+ 'getExtension' in ctx
+ ) {
+ var info = ctx.getExtension('WEBGL_debug_renderer_info');
+
+ if (info) {
+ return ctx.getParameter(info.UNMASKED_RENDERER_WEBGL);
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# CORES
+--------------------------------------------------------------*/
+
+satus.user.device.cores = function () {
+ return navigator.deviceConcurrency;
+};
+
+
+/*--------------------------------------------------------------
+# TOUCH
+--------------------------------------------------------------*/
+
+satus.user.device.touch = function () {
+ var result = {};
+
+ if (
+ window.hasOwnProperty('ontouchstart') ||
+ window.DocumentTouch && document instanceof window.DocumentTouch ||
+ navigator.maxTouchPoints > 0 ||
+ window.navigator.msMaxTouchPoints > 0
+ ) {
+ result.touch = true;
+ result.maxTouchPoints = navigator.maxTouchPoints;
+ }
+
+ return result;
+};
+
+
+/*--------------------------------------------------------------
+# CONNECTION
+--------------------------------------------------------------*/
+
+satus.user.device.connection = function () {
+ var result = {};
+
+ if (typeof navigator.connection === 'object') {
+ result.type = navigator.connection.effectiveType || null;
+
+ if (navigator.connection.downlink) {
+ result.speed = navigator.connection.downlink + ' Mbps';
+ }
+ }
+
+ return result;
+};
+/*--------------------------------------------------------------
+# SEARCH
+--------------------------------------------------------------*/
+
+satus.search = function (query, object, callback) {
+ var elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker'],
+ threads = 0,
+ results = {},
+ excluded = [
+ 'baseProvider',
+ 'childrenContainer',
+ 'parentElement',
+ 'parentObject',
+ 'parentSkeleton',
+ 'rendered',
+ 'namespaceURI'
+ ];
+
+ query = query.toLowerCase();
+
+ function parse(items, parent) {
+ threads++;
+
+ for (var key in items) {
+ if (excluded.indexOf(key) === -1) {
+ var item = items[key];
+
+ if (item.component) {
+ //console.log(key, item.component);
+
+ if (elements.indexOf(item.component) !== -1 && key.indexOf(query) !== -1) {
+ results[key] = Object.assign({}, item);
+ }
+ }
+
+ if (typeof item === 'object') {
+ parse(item, items);
+ }
+ }
+ }
+
+ threads--;
+
+ if (threads === 0) {
+ callback(results);
+ }
+ }
+
+ parse(object);
+};
diff --git a/background.js b/background.js
index f326631..d35f06f 100644
--- a/background.js
+++ b/background.js
@@ -1,57 +1,107 @@
/*--------------------------------------------------------------
>>> BACKGROUND
+----------------------------------------------------------------
+# Global variable
+# Update user agent
+# Messages
+# Storage
+ # Get
+ # On change
--------------------------------------------------------------*/
-var ext_storage = {};
-
-chrome.storage.local.get(function(items) {
- ext_storage = items;
-
- function requestListener(request) {
- if (typeof request.requestHeaders === 'object') {
- for (var header of request.requestHeaders) {
- if (header.name.toLowerCase() === 'user-agent') {
- if (ext_storage['user-agent'] && ext_storage['user-agent'] !== '') {
- header.value = ext_storage['user-agent'];
- }
- }
- }
- }
-
- return {
- requestHeaders: request.requestHeaders
- };
- }
-
- chrome.webRequest.onBeforeSendHeaders.addListener(
- requestListener, {
- urls: ['']
- }, ['blocking', 'requestHeaders']
- );
-
- chrome.storage.onChanged.addListener(function(changes) {
- for (var key in changes) {
- var value = changes[key].newValue;
-
- ext_storage[key] = changes[key].newValue;
- }
-
- chrome.webRequest.onBeforeSendHeaders.removeListener(
- requestListener, {
- urls: ['']
- }, ['blocking', 'requestHeaders']
- );
-
- chrome.webRequest.onBeforeSendHeaders.addListener(
- requestListener, {
- urls: ['']
- }, ['blocking', 'requestHeaders']
- );
- });
+/*--------------------------------------------------------------
+# GLOBAL VARIABLE
+--------------------------------------------------------------*/
+
+var extension = {};
+
+
+/*--------------------------------------------------------------
+# UPDATE USER AGENT
+--------------------------------------------------------------*/
+
+extension.updateUserAgent = function (string) {
+ if (typeof string === 'string') {
+ chrome.declarativeNetRequest.updateDynamicRules({
+ addRules: [{
+ 'id': 1001,
+ 'priority': 1,
+ 'action': {
+ 'type': 'modifyHeaders',
+ 'requestHeaders': [{
+ 'header': 'User-Agent',
+ 'operation': 'set',
+ 'value': string
+ }]
+ },
+ 'condition': {
+ 'urlFilter': '*://*/*',
+ 'resourceTypes': [
+ 'main_frame',
+ 'sub_frame',
+ 'stylesheet',
+ 'script',
+ 'image',
+ 'font',
+ 'object',
+ 'xmlhttprequest',
+ 'ping',
+ 'csp_report',
+ 'media',
+ 'websocket',
+ 'webtransport',
+ 'webbundle',
+ 'other'
+ ]
+ }
+ }],
+ removeRuleIds: [1001]
+ });
+ } else {
+ chrome.declarativeNetRequest.updateDynamicRules({
+ removeRuleIds: [1001]
+ });
+ }
+};
+
+
+/*--------------------------------------------------------------
+# MESSAGES
+--------------------------------------------------------------*/
+
+chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
+ var action = message.action;
+
+ if (action === 'options-page-connected') {
+ sendResponse({
+ isPopup: sender.hasOwnProperty('tab') === false
+ });
+ }
});
+
+/*--------------------------------------------------------------
+# STORAGE
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# GET
+--------------------------------------------------------------*/
+
+
+chrome.storage.local.get(function (items) {
+ extension.updateUserAgent(items['user-agent']);
+});
+
+
+/*--------------------------------------------------------------
+# ON CHANGE
+--------------------------------------------------------------*/
+
chrome.storage.onChanged.addListener(function (changes) {
- for (var key in changes) {
- ext_storage[key] = changes[key].newValue;
- }
+ for (var key in changes) {
+ if (key === 'user-agent') {
+ extension.updateUserAgent(changes[key].newValue);
+ }
+ }
});
\ No newline at end of file
diff --git a/data/user-agents.js b/data/user-agents.js
deleted file mode 100644
index cab86fe..0000000
--- a/data/user-agents.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/*--------------------------------------------------------------
->>> USER AGENTS
---------------------------------------------------------------*/
-
-var user_agents = {
- 'car': {
- 'Tesla': 'Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/88.0.4324.150 Chrome/88.0.4324.150 Safari/537.36 Tesla/2021.4.18.2-6c676ce09ea5'
- },
- 'computer': {
- 'Windows': {
- 'Windows 10': {
- 'Chrome': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Windows NT 10.0; rv:95.0) Gecko/20171102 Firefox/95.0',
- 'Opera': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 OPR/79.0.4143.61',
- 'Edge': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31/PmaOHqHf-37',
- 'Vivaldi': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.83 Safari/537.36 Vivaldi/4.2.2406.48',
- 'Whale': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.232 Whale/2.10.124.26 Safari/537.36'
- },
- 'Windows 8.1': {
- 'Chrome': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.8948.8989 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0/10csO9CgK-99',
- 'Opera': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.50 (Edition Yx 02)',
- 'Edge': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31',
- 'Vivaldi': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.122 Safari/537.36 Vivaldi/2.3.1440.60',
- 'Whale': 'Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.229 Whale/2.10.123.42 Safari/537.36'
- },
- 'Windows 8': {
- 'Chrome': 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.48 CitizenFX/1.0.0.4590 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0/10csO9CgK-99',
- 'Opera': 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.66',
- 'Edge': 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31',
- 'Vivaldi': 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.143 Safari/537.36 Vivaldi/1.95.1077.45',
- 'Whale': 'Mozilla/5.0 (Windows NT 6.2; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Whale/2.8.108.15 Safari/537.36'
- },
- 'Windows 7': {
- 'Chrome': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.48 CitizenFX/1.0.0.4590 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0/CZyfq6zd2FAGsZdS0An',
- 'Opera': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.66 (Edition Campaign 70)',
- 'Edge': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31',
- 'Vivaldi': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.183 Safari/537.36 Vivaldi/6969562071AB',
- 'Whale': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.232 Whale/2.10.124.26 Safari/537.36',
- 'Internet Explorer': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.2)'
- },
- 'Windows Vista': {
- 'Chrome': 'Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9.1b2pre) Gecko/20081026 Minefield/3.1b2pre',
- 'Opera': 'Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 OPR/78.0.4093.231',
- 'Edge': 'Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299',
- 'Vivaldi': 'Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 Vivaldi/1.0.435.46',
- 'Internet Explorer': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; BOIE9;FRFR)'
- },
- 'Windows XP': {
- 'Chrome': 'Mozilla/5.0 (Windows XP) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a',
- 'Opera': 'Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.99',
- 'Internet Explorer': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'
- },
- 'Windows 2000': {
- 'Firefox': 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8) Gecko/20051111 Firefox/1.5',
- 'Opera': 'Opera/9.80 (Windows NT 5.0; U; MRA 5.9 (build 4930); ru) Presto/2.10.229 Version/11.62',
- 'Internet Explorer': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)'
- },
- 'Windows 98': {
- 'Firefox': 'Mozilla/5.0 (Windows; U; Win98; bg; rv:1.8.1.10) Gecko/20100526 Firefox/3.7a5pre',
- 'Opera': 'Opera/8.20.(Windows 98; ro-RO) Presto/2.9.186 Version/11.00',
- 'Internet Explorer': 'Mozilla/4.0 (compatible; MSIE 4.01; MSN 2.5; Windows 98)'
- }
- },
- 'macOS': {
- 'Safari': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.7 Safari/605.1.15',
- 'Chrome': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4653.2 Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4; rv:87.0) Gecko/20100101 Firefox/87.0',
- 'Opera': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 OPR/79.0.4143.50',
- 'Edge': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36 Edg/94.0.992.31',
- 'Vivaldi': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.88 Safari/537.36 Vivaldi/2.4.1488.36',
- 'Whale': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Whale/2.8.108.15 Safari/537.36'
- },
- 'Linux': {
- 'Chrome': 'Mozilla/5.0 (Linux; 7.0; P2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.8) Gecko/20051111 Firefox/54.0',
- 'Vivaldi': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Vivaldi/4.1.2369.21'
- }
- },
- 'gameConsole': {
- 'PlayStation': {
- 'PlayStation 4': 'Mozilla/5.0 (PlayStation 4 5.05) AppleWebKit/601.2 (KHTML, like Gecko)',
- 'PlayStation 3': 'Mozilla/5.0 (PLAYSTATION 3 4.81) AppleWebKit/531.22.8 (KHTML, like Gecko)',
- 'PlayStation Vita': 'Mozilla/5.0 (PlayStation Vita 3.50) AppleWebKit/537.73 (KHTML, like Gecko) Silk/3.2',
- 'PlayStation Portable': 'Mozilla/4.0 (PSP (PlayStation Portable); 2.00)'
- },
- 'Xbox': {
- 'Xbox One': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299',
- 'Xbox 360': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)'
- },
- 'Nintendo': {
- 'Nintendo Switch': 'Mozilla/5.0 (Nintendo Switch; WebApplet) AppleWebKit/606.4 (KHTML, like Gecko) NF/6.0.1.18.3 NintendoBrowser/5.1.0.21481',
- 'Nintendo Wii U': 'Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.4.2.13 NintendoBrowser/4.3.2.11274.US',
- 'Nintendo Wii': 'Opera/9.30 (Nintendo Wii; U; ; 3642; en)',
- 'Nintendo 3DS': 'Mozilla/5.0 (New Nintendo 3DS like iPhone) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.0.5.22 Mobile NintendoBrowser/1.10.10166.US'
- }
- },
- 'phone': {
- 'Android': {
- 'Chrome': 'Mozilla/5.0 (Linux; Android 10; W-V680-OPE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Mobile Safari/537.36',
- 'Firefox': 'Mozilla/5.0 (Android 10.0; Mobile; rv:90.0) Gecko/90.0 Firefox/90.0',
- 'Opera': 'Mozilla/5.0 (Linux; Android 11; CPH1979) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36 OPR/64.3.3282.60839',
- 'Edge': 'Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Mobile Safari/537.36 EdgA/93.0.961.62'
- },
- 'iOS': {
- 'Safari': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.2 Mobile/15E148 Safari/604.1',
- 'Chrome': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/93.0.4577.78 Mobile/15E148 Safari/604.1',
- 'Firefox': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/37.0 Mobile/15E148 Safari/605.1.15'
- },
- 'Symbian': {
- 'Opera': 'Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1204232254; U; en-GB) Presto/2.10.254 Version/12.00',
- 'Nokia Browser': 'Nokia7610/2.0 (5.0509.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0',
- 'Ovi 2.0': 'Mozilla/5.0 (Series40; Nokia200/11.64; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.0.2.68.14'
- }
- },
- 'tv': {
- 'Google TV': 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/90.0.4430.212 Large Screen Safari/534.24 GoogleTV/092754youtube.com/tv#',
- 'Samsung TV': 'Mozilla/5.0 (SMART-TV; Linux; Tizen 2.4.0) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.1 TV Safari/538.1'
- },
- 'watch': {
- 'watchOS': 'atc/1.0 watchOS/7.5 model/Watch3,3 hwp/t8004 build/18T567 (6; dt:155)'
- }
-};
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 77d9a67..8d00254 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,28 +1,26 @@
{
- "manifest_version": 2,
+ "manifest_version": 3,
"name": "User-Agent",
- "version": "2.0",
+ "version": "3.0",
"default_locale": "en",
"icons": {
- "16": "assets/icons/16.png",
- "32": "assets/icons/32.png",
- "48": "assets/icons/48.png",
- "128": "assets/icons/128.png"
- },
+ "16": "assets/icons/16.png",
+ "32": "assets/icons/32.png",
+ "48": "assets/icons/48.png",
+ "128": "assets/icons/128.png"
+ },
"background": {
- "scripts": [
- "background.js"
- ]
+ "service_worker": "background.js"
},
- "browser_action": {
- "default_popup": "popup.html"
+ "action": {
+ "default_popup": "options-page/index.html"
},
- "options_page": "options.html",
+ "options_page": "options-page/index.html",
+ "host_permissions": [
+ ""
+ ],
"permissions": [
"storage",
- "",
- "webNavigation",
- "webRequest",
- "webRequestBlocking"
+ "declarativeNetRequest"
]
-}
+}
\ No newline at end of file
diff --git a/options-page/functions.js b/options-page/functions.js
new file mode 100644
index 0000000..928784b
--- /dev/null
+++ b/options-page/functions.js
@@ -0,0 +1,187 @@
+/*--------------------------------------------------------------
+>>> FUNCTIONS
+----------------------------------------------------------------
+# Render
+# Export settings
+# Import settings
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# RENDER
+--------------------------------------------------------------*/
+
+extension.icons = {
+ car: 'M18.92 5.01C18.72 4.42 18.16 4 17.5 4h-11c-.66 0-1.21.42-1.42 1.01L3 11v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 15c-.83 0-1.5-.67-1.5-1.5S5.67 12 6.5 12s1.5.67 1.5 1.5S7.33 15 6.5 15zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 10l1.5-4.5h11L19 10H5z',
+ computer: 'M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z',
+ gameConsole: 'm21.58 16.09-1.09-7.66A3.996 3.996 0 0 0 16.53 5H7.47C5.48 5 3.79 6.46 3.51 8.43l-1.09 7.66C2.2 17.63 3.39 19 4.94 19c.68 0 1.32-.27 1.8-.75L9 16h6l2.25 2.25c.48.48 1.13.75 1.8.75 1.56 0 2.75-1.37 2.53-2.91zM11 11H9v2H8v-2H6v-1h2V8h1v2h2v1zm4-1c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2 3c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z',
+ phone: 'M17 1.01 7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z',
+ tv: 'M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z',
+ watch: 'M20 12c0-2.54-1.19-4.81-3.04-6.27L16 0H8l-.95 5.73C5.19 7.19 4 9.45 4 12s1.19 4.81 3.05 6.27L8 24h8l.96-5.73A7.976 7.976 0 0 0 20 12zM6 12c0-3.31 2.69-6 6-6s6 2.69 6 6-2.69 6-6 6-6-2.69-6-6z'
+};
+
+extension.render = function (object, skeleton) {
+ skeleton.section = {
+ component: 'section',
+ variant: 'card'
+ };
+
+ for (var key in object) {
+ var item = object[key];
+
+ if (typeof item === 'object') {
+ skeleton.section[key] = {
+ component: 'button',
+ text: key,
+ on: {
+ click: {}
+ }
+ };
+
+ if (extension.icons[key]) {
+ skeleton.section[key].before = {
+ component: 'svg',
+ attr: {
+ 'fill': 'currentColor',
+ 'viewBox': '0 0 24 24'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': extension.icons[key]
+ }
+ }
+ };
+ }
+
+ extension.render(item, skeleton.section[key].on.click);
+ } else {
+ skeleton.section[key] = {
+ component: 'radio',
+ group: 'user-agent',
+ text: key,
+ value: item
+ };
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# EXPORT SETTINGS
+--------------------------------------------------------------*/
+
+extension.exportSettings = function () {
+ if (location.href.indexOf('action=export-settings') !== -1) {
+ satus.render({
+ component: 'modal',
+ variant: 'confirm',
+ content: 'areYouSureYouWantToExportTheData',
+ buttons: {
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ on: {
+ click: function () {
+ this.modalProvider.close();
+ }
+ }
+ },
+ ok: {
+ component: 'button',
+ text: 'ok',
+ on: {
+ click: function () {
+ try {
+ var blob = new Blob([JSON.stringify(satus.storage.data)], {
+ type: 'application/json;charset=utf-8'
+ });
+
+ chrome.permissions.request({
+ permissions: ['downloads']
+ }, function (granted) {
+ if (granted) {
+ chrome.downloads.download({
+ url: URL.createObjectURL(blob),
+ filename: 'user-agent.json',
+ saveAs: true
+ }, function () {
+ setTimeout(function () {
+ close();
+ }, 1000);
+ });
+ }
+ });
+ } catch (error) {
+ console.error(error);
+ }
+ }
+ }
+ }
+ }
+ }, extension.skeleton.rendered);
+ }
+};
+
+
+/*--------------------------------------------------------------
+# IMPORT SETTINGS
+--------------------------------------------------------------*/
+
+extension.importSettings = function () {
+ if (location.href.indexOf('action=import-settings') !== -1) {
+ satus.render({
+ component: 'modal',
+ variant: 'confirm',
+ content: 'areYouSureYouWantToImportTheData',
+ buttons: {
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ on: {
+ click: function () {
+ this.modalProvider.close();
+ }
+ }
+ },
+ ok: {
+ component: 'button',
+ text: 'ok',
+ on: {
+ click: function () {
+ var input = document.createElement('input');
+
+ input.type = 'file';
+
+ input.addEventListener('change', function () {
+ var file_reader = new FileReader();
+
+ file_reader.onload = function () {
+ var data = JSON.parse(this.result);
+
+ for (var key in data) {
+ satus.storage.set(key, data[key]);
+ }
+
+ setTimeout(function () {
+ chrome.runtime.sendMessage({
+ action: 'import-settings'
+ });
+
+ setTimeout(function () {
+ close();
+ }, 128);
+ }, 256);
+ };
+
+ file_reader.readAsText(this.files[0]);
+ });
+
+ input.click();
+ }
+ }
+ }
+ }
+ }, extension.skeleton.rendered);
+ }
+};
\ No newline at end of file
diff --git a/options-page/index.css b/options-page/index.css
new file mode 100644
index 0000000..c1e5220
--- /dev/null
+++ b/options-page/index.css
@@ -0,0 +1,95 @@
+/*--------------------------------------------------------------
+>>> OPTIONS PAGE
+----------------------------------------------------------------
+# Fonts
+ # Regular
+ # Medium
+ # Bold
+# Theme
+# Vertical menu
+# Tab mode
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# REGULAR
+--------------------------------------------------------------*/
+
+@font-face {
+ font-family: Roboto;
+
+ src: url(../assets/fonts/Roboto-Regular.ttf);
+}
+
+
+/*--------------------------------------------------------------
+# MEDIUM
+--------------------------------------------------------------*/
+
+@font-face {
+ font-family: Roboto;
+ font-weight: 500;
+
+ src: url(../assets/fonts/Roboto-Medium.ttf);
+}
+
+
+/*--------------------------------------------------------------
+# BOLD
+--------------------------------------------------------------*/
+
+@font-face {
+ font-family: Roboto;
+ font-weight: 700;
+
+ src: url(../assets/fonts/Roboto-Bold.ttf);
+}
+
+
+/*--------------------------------------------------------------
+# THEME
+--------------------------------------------------------------*/
+
+.satus-base {
+ --satus-light: 255, 255, 255;
+ --satus-primary: #c92c46;
+ --satus-base-background: #1b1528;
+ --satus-base-foreground: #fafafa;
+ --satus-header-background: #473172;
+ --satus-header-shadow: transparent;
+ --satus-section-background: #2e2343;
+ --satus-section-border: #2e2343;
+ --satus-modal-background: #473172;
+ --satus-modal-shadow: 0 1px 4px #222;
+ --satus-text-field-background: #2e2343;
+}
+
+
+/*--------------------------------------------------------------
+# VERTICAL MENU
+--------------------------------------------------------------*/
+
+.satus-modal--vertical-menu .satus-modal__surface {
+ max-width: 200px;
+}
+
+
+/*--------------------------------------------------------------
+# TAB MODE
+--------------------------------------------------------------*/
+
+
+body[tab] {
+ overflow: hidden;
+
+ width: 100vw;
+ height: 100vh;
+}
+
+body[tab] .satus-base {
+ width: 100%;
+ height: 100%;
+}
+
+body[tab] .satus-alert {
+ display: none;
+}
\ No newline at end of file
diff --git a/options-page/index.html b/options-page/index.html
new file mode 100644
index 0000000..8abf39d
--- /dev/null
+++ b/options-page/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+ User-Agent
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/options-page/index.js b/options-page/index.js
new file mode 100644
index 0000000..8f8ea43
--- /dev/null
+++ b/options-page/index.js
@@ -0,0 +1,129 @@
+/*--------------------------------------------------------------
+>>> OPTIONS PAGE
+----------------------------------------------------------------
+# Global variable
+# Initialization
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# GLOBAL VARIABLE
+--------------------------------------------------------------*/
+
+var extension = {};
+
+
+/*--------------------------------------------------------------
+# INITIALIZATION
+--------------------------------------------------------------*/
+
+satus.storage.import(function (items) {
+ var language = items.language;
+
+ if (!language) {
+ language = window.navigator.language;
+ }
+
+ satus.locale.import(language, function () {
+ satus.fetch(chrome.runtime.getURL('assets/data/user-agent.json'), function (response) {
+ extension.render(response, extension.skeleton.main.layers);
+
+ extension.skeleton.main.layers.section.custom = {
+ component: 'button',
+ text: 'custom',
+ before: {
+ component: 'svg',
+ attr: {
+ 'fill': 'currentColor',
+ 'viewBox': '0 0 24 24'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': 'M5 4v3h5.5v12h3V7H19V4z'
+ }
+ }
+ },
+ on: {
+ click: {
+ component: 'section',
+ variant: 'transparent-card',
+ style: {
+ 'height': 'calc(100% - 24px)',
+ 'margin': '12px'
+ },
+
+ textField: {
+ component: 'text-field',
+ storage: 'user-agent',
+ style: {
+ 'height': '100%'
+ }
+ }
+ }
+ }
+ };
+
+ extension.skeleton.main.layers.section.reset = {
+ component: 'button',
+ text: 'reset',
+ before: {
+ component: 'svg',
+ attr: {
+ 'fill': 'currentColor',
+ 'viewBox': '0 0 24 24'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': 'm13 11.6 2.5 2.5q.275.275.275.7 0 .425-.275.7-.275.275-.7.275-.425 0-.7-.275l-2.8-2.8q-.15-.15-.225-.338-.075-.187-.075-.387V8q0-.425.288-.713Q11.575 7 12 7t.713.287Q13 7.575 13 8ZM12 21q-3.025 0-5.425-1.788-2.4-1.787-3.225-4.662-.125-.45.088-.85.212-.4.662-.5.425-.1.763.187.337.288.462.713.65 2.2 2.513 3.55Q9.7 19 12 19q2.925 0 4.962-2.038Q19 14.925 19 12t-2.038-4.963Q14.925 5 12 5q-1.725 0-3.225.8T6.25 8H8q.425 0 .713.287Q9 8.575 9 9t-.287.712Q8.425 10 8 10H4q-.425 0-.712-.288Q3 9.425 3 9V5q0-.425.288-.713Q3.575 4 4 4t.713.287Q5 4.575 5 5v1.35q1.275-1.6 3.113-2.475Q9.95 3 12 3q1.875 0 3.513.712 1.637.713 2.85 1.925 1.212 1.213 1.925 2.85Q21 10.125 21 12t-.712 3.512q-.713 1.638-1.925 2.85-1.213 1.213-2.85 1.926Q13.875 21 12 21Z'
+ }
+ }
+ },
+ on: {
+ click: {
+ component: 'modal',
+ variant: 'confirm',
+ content: 'allYourSettingsWillBeErasedAndCanTBeRecovered',
+ buttons: {
+ cancel: {
+ component: 'button',
+ text: 'cancel',
+ on: {
+ click: function () {
+ this.modalProvider.close();
+ }
+ }
+ },
+ reset: {
+ component: 'button',
+ text: 'reset',
+ on: {
+ click: function () {
+ satus.storage.clear(function () {
+ close();
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ satus.render(extension.skeleton);
+
+ extension.exportSettings();
+ extension.importSettings();
+ });
+ }, '_locales/');
+});
+
+chrome.runtime.sendMessage({
+ action: 'options-page-connected'
+}, function (response) {
+ if (response.isPopup === false) {
+ document.body.setAttribute('tab', '');
+ }
+});
\ No newline at end of file
diff --git a/options-page/skeleton.js b/options-page/skeleton.js
new file mode 100644
index 0000000..0d6c959
--- /dev/null
+++ b/options-page/skeleton.js
@@ -0,0 +1,492 @@
+/*--------------------------------------------------------------
+>>> SKELETON
+----------------------------------------------------------------
+# Base
+# Header
+# Main
+--------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+# BASE
+--------------------------------------------------------------*/
+
+extension.skeleton = {
+ component: 'base'
+};
+
+
+/*--------------------------------------------------------------
+# HEADER
+--------------------------------------------------------------*/
+
+extension.skeleton.header = {
+ component: 'header',
+
+ sectionStart: {
+ component: 'section',
+ variant: 'align-start',
+
+ back: {
+ component: 'button',
+ variant: 'icon',
+ attr: {
+ 'hidden': 'true'
+ },
+ on: {
+ click: 'main.layers.back'
+ },
+
+ svg: {
+ component: 'svg',
+ attr: {
+ 'viewBox': '0 0 24 24',
+ 'stroke-width': '1.5',
+ 'stroke': 'currentColor',
+ 'fill': 'none'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': 'M14 18l-6-6 6-6'
+ }
+ }
+ }
+ },
+ title: {
+ component: 'span',
+ variant: 'title'
+ }
+ },
+ sectionEnd: {
+ component: 'section',
+ variant: 'align-end',
+
+ menu: {
+ component: 'button',
+ variant: 'icon',
+ on: {
+ click: {
+ component: 'modal',
+ variant: 'vertical-menu',
+
+ language: {
+ component: 'select',
+ on: {
+ change: function () {
+ var language = satus.storage.get('language');
+
+ if (!language || language === 'default') {
+ language = window.navigator.language;
+ }
+
+ satus.locale.import(language, function () {
+ var layers = document.querySelector('.satus-layers');
+
+ extension.skeleton.main.layers.rendered.dispatchEvent(new CustomEvent('open'));
+
+ satus.empty(layers.firstChild);
+
+ satus.render(satus.last(layers.path), layers.firstChild, undefined, true);
+ }, '_locales/');
+ }
+ },
+ options: [{
+ value: "en",
+ text: "English"
+ }, {
+ value: "es",
+ text: "Español (España)"
+ }, {
+ value: "es-419",
+ text: "Español (Latinoamérica)"
+ }, {
+ value: "es-US",
+ text: "Español (US)"
+ }, {
+ value: "ru",
+ text: "Русский"
+ }, {
+ value: "de",
+ text: "Deutsch"
+ }, {
+ value: "pt-PT",
+ text: "Português"
+ }, {
+ value: "pt",
+ text: "Português (Brasil)"
+ }, {
+ value: "fr",
+ text: "Français"
+ }, {
+ value: "pl",
+ text: "Polski"
+ }, {
+ value: "ja",
+ text: "日本語"
+ }, {
+ value: "af",
+ text: "Afrikaans"
+ }, {
+ value: "az",
+ text: "Azərbaycan"
+ }, {
+ value: "id",
+ text: "Bahasa Indonesia"
+ }, {
+ value: "ms",
+ text: "Bahasa Malaysia"
+ }, {
+ value: "bs",
+ text: "Bosanski"
+ }, {
+ value: "ca",
+ text: "Català"
+ }, {
+ value: "cs",
+ text: "Čeština"
+ }, {
+ value: "da",
+ text: "Dansk"
+ }, {
+ value: "et",
+ text: "Eesti"
+ }, {
+ value: "eu",
+ text: "Euskara"
+ }, {
+ value: "fil",
+ text: "Filipino"
+ }, {
+ value: "fr-CA",
+ text: "Français (Canada)"
+ }, {
+ value: "gl",
+ text: "Galego"
+ }, {
+ value: "hr",
+ text: "Hrvatski"
+ }, {
+ value: "zu",
+ text: "IsiZulu"
+ }, {
+ value: "is",
+ text: "Íslenska"
+ }, {
+ value: "it",
+ text: "Italiano"
+ }, {
+ value: "sw",
+ text: "Kiswahili"
+ }, {
+ value: "lv",
+ text: "Latviešu valoda"
+ }, {
+ value: "lt",
+ text: "Lietuvių"
+ }, {
+ value: "hu",
+ text: "Magyar"
+ }, {
+ value: "nl",
+ text: "Nederlands"
+ }, {
+ value: "no",
+ text: "Norsk"
+ }, {
+ value: "uz",
+ text: "O‘zbek"
+ }, {
+ value: "ro",
+ text: "Română"
+ }, {
+ value: "sq",
+ text: "Shqip"
+ }, {
+ value: "sk",
+ text: "Slovenčina"
+ }, {
+ value: "sl",
+ text: "Slovenščina"
+ }, {
+ value: "sr-Latn",
+ text: "Srpski"
+ }, {
+ value: "fi",
+ text: "Suomi"
+ }, {
+ value: "sv",
+ text: "Svenska"
+ }, {
+ value: "vi",
+ text: "Tiếng Việt"
+ }, {
+ value: "tr",
+ text: "Türkçe"
+ }, {
+ value: "be",
+ text: "Беларуская"
+ }, {
+ value: "bg",
+ text: "Български"
+ }, {
+ value: "ky",
+ text: "Кыргызча"
+ }, {
+ value: "kk",
+ text: "Қазақ Тілі"
+ }, {
+ value: "mk",
+ text: "Македонски"
+ }, {
+ value: "mn",
+ text: "Монгол"
+ }, {
+ value: "sr",
+ text: "Српски"
+ }, {
+ value: "uk",
+ text: "Українська"
+ }, {
+ value: "el",
+ text: "Ελληνικά"
+ }, {
+ value: "hy",
+ text: "Հայերեն"
+ }, {
+ value: "iw",
+ text: "עברית"
+ }, {
+ value: "ur",
+ text: "اردو"
+ }, {
+ value: "ar",
+ text: "العربية"
+ }, {
+ value: "fa",
+ text: "فارسی"
+ }, {
+ value: "ne",
+ text: "नेपाली"
+ }, {
+ value: "mr",
+ text: "मराठी"
+ }, {
+ value: "hi",
+ text: "हिन्दी"
+ }, {
+ value: "bn",
+ text: "বাংলা"
+ }, {
+ value: "pa",
+ text: "ਪੰਜਾਬੀ"
+ }, {
+ value: "gu",
+ text: "ગુજરાતી"
+ }, {
+ value: "ta",
+ text: "தமிழ்"
+ }, {
+ value: "te",
+ text: "తెలుగు"
+ }, {
+ value: "kn",
+ text: "ಕನ್ನಡ"
+ }, {
+ value: "ml",
+ text: "മലയാളം"
+ }, {
+ value: "si",
+ text: "සිංහල"
+ }, {
+ value: "th",
+ text: "ภาษาไทย"
+ }, {
+ value: "lo",
+ text: "ລາວ"
+ }, {
+ value: "my",
+ text: "ဗမာ"
+ }, {
+ value: "ka",
+ text: "ქართული"
+ }, {
+ value: "am",
+ text: "አማርኛ"
+ }, {
+ value: "km",
+ text: "ខ្មែរ"
+ }, {
+ value: "zh-CN",
+ text: "中文 (简体)"
+ }, {
+ value: "zh-TW",
+ text: "中文 (繁體)"
+ }, {
+ value: "zh-HK",
+ text: "中文 (香港)"
+ }, {
+ value: "ko",
+ text: "한국어"
+ }],
+ before: {
+ component: 'svg',
+ attr: {
+ 'viewBox': '0 0 24 24',
+ 'fill': 'currentColor'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': 'M12.9 15l-2.6-2.4c1.8-2 3-4.2 3.8-6.6H17V4h-7V2H8v2H1v2h11.2c-.7 2-1.8 3.8-3.2 5.3-1-1-1.7-2.1-2.3-3.3h-2c.7 1.6 1.7 3.2 3 4.6l-5.1 5L4 19l5-5 3.1 3.1.8-2zm5.6-5h-2L12 22h2l1.1-3H20l1.1 3h2l-4.5-12zm-2.6 7l1.6-4.3 1.6 4.3H16z'
+ }
+ }
+ },
+ text: 'language'
+ },
+ export: {
+ component: 'button',
+ text: 'export',
+ before: {
+ component: 'svg',
+ attr: {
+ 'viewBox': '0 0 24 24',
+ 'fill': 'none',
+ 'stroke': 'currentColor',
+ 'stroke-linecap': 'round',
+ 'stroke-linejoin': 'round',
+ 'stroke-width': '2'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12'
+ }
+ }
+ },
+ on: {
+ click: function () {
+ if (location.href.indexOf('options-page/index.html?action=export-settings') !== -1) {
+ extension.exportSettings();
+ } else {
+ chrome.tabs.create({
+ url: 'options-page/index.html?action=export-settings'
+ });
+ }
+ }
+ }
+ },
+ import: {
+ component: 'button',
+ text: 'import',
+ before: {
+ component: 'svg',
+ attr: {
+ 'viewBox': '0 0 24 24',
+ 'fill': 'none',
+ 'stroke': 'currentColor',
+ 'stroke-linecap': 'round',
+ 'stroke-linejoin': 'round',
+ 'stroke-width': '2'
+ },
+
+ path: {
+ component: 'path',
+ attr: {
+ 'd': 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3'
+ }
+ }
+ },
+ on: {
+ click: function () {
+ if (location.href.indexOf('options-page/index.html?action=import-settings') !== -1) {
+ extension.importSettings();
+ } else {
+ chrome.tabs.create({
+ url: 'options-page/index.html?action=import-settings'
+ });
+ }
+ }
+ }
+ }
+ }
+ },
+
+ svg: {
+ component: 'svg',
+ attr: {
+ 'viewBox': '0 0 24 24',
+ 'stroke-width': '2',
+ 'stroke': 'currentColor',
+ 'fill': 'none'
+ },
+
+ circle1: {
+ component: 'circle',
+ attr: {
+ 'cx': '12',
+ 'cy': '5.25',
+ 'r': '0.45'
+ }
+ },
+ circle2: {
+ component: 'circle',
+ attr: {
+ 'cx': '12',
+ 'cy': '12',
+ 'r': '0.45'
+ }
+ },
+ circle3: {
+ component: 'circle',
+ attr: {
+ 'cx': '12',
+ 'cy': '18.75',
+ 'r': '0.45'
+ }
+ }
+ }
+ }
+ }
+};
+
+
+/*--------------------------------------------------------------
+# MAIN
+--------------------------------------------------------------*/
+
+extension.skeleton.main = {
+ component: 'main',
+
+ layers: {
+ component: 'layers',
+ on: {
+ open: function () {
+ var skeleton = satus.last(this.path),
+ section = this.baseProvider.skeleton.header.sectionStart,
+ title = satus.manifest().name;
+
+ if (skeleton.parentSkeleton) {
+ if (skeleton.parentSkeleton.label) {
+ title = skeleton.parentSkeleton.label.text;
+ } else if (skeleton.parentSkeleton.text) {
+ title = skeleton.parentSkeleton.text;
+ }
+ }
+
+ section.back.rendered.hidden = this.path.length <= 1;
+ section.title.rendered.innerText = satus.locale.get(title);
+
+ var vertical_menu = document.querySelector('.satus-modal--vertical-menu');
+
+ if (vertical_menu) {
+ vertical_menu.close();
+ }
+ }
+ },
+
+ toolbar: {}
+ }
+};
\ No newline at end of file
diff --git a/options.html b/options.html
deleted file mode 100644
index 6e501b6..0000000
--- a/options.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
- ImprovedTube
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/popup.css b/popup.css
deleted file mode 100644
index 37873ac..0000000
--- a/popup.css
+++ /dev/null
@@ -1,158 +0,0 @@
-/*---------------------------------------------------------------
->>> USER AGENT
------------------------------------------------------------------
-#
----------------------------------------------------------------*/
-
-html {
- --satus-primary: #764e7e;
- --satus-modal-background: #3b273f;
- --satus-modal-text: #faeaed;
- --satus-header-background: #ed2c4c;
- --satus-header-text: #faeaed;
- --satus-layers-background: #28102d;
- --satus-layers-text: #faeaed;
- --satus-section-card-background: #3b273f;
- --satus-hover: rgba(255, 255, 255, .12);
- --satus-switch-track: #28102d;
- --satus-switch-track--active: #ed2c4c;
- --satus-switch-thumb: #c6cad2;
- --satus-tabs: #3b273f;
- --satus-pluviam-background: #fff;
- --satus-pluviam-opacity: .12;
-}
-
-.satus-header {
- font-weight: 600;
- z-index: 1;
- box-shadow: 0 2px 0 #b81430;
-}
-
-.satus-header .satus-h1--title {
- font-size: 16px;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- text-shadow: 2px 1px #b81430;
- flex: 1;
-}
-
-.satus-header .satus-button>.satus-span {
- position: absolute;
- left: 18px;
- width: 3px;
- height: 3px;
- border-radius: 50%;
- background: currentColor;
- box-shadow: 2px 1px #b81430;
-}
-
-.satus-header .satus-button>.satus-span:nth-child(1) {
- top: 11px;
-}
-
-.satus-header .satus-button>.satus-span:nth-child(2) {
- top: 19px;
-}
-
-.satus-header .satus-button>.satus-span:nth-child(3) {
- bottom: 10px;
-}
-
-.satus-modal--vertical .satus-modal__surface {
- position: absolute;
- top: 8px;
- right: 8px;
- left: auto;
- min-width: 180px;
- max-width: 180px;
- transform-origin: right top;
- padding: 8px 0;
-}
-
-.satus-modal--vertical .satus-button {
- display: flex;
- height: 36px;
- padding: 0 16px;
- align-items: center;
-}
-
-.satus-modal--vertical .satus-button svg {
- width: 20px;
- height: 18px;
- margin: 0 14px 0 0;
- opacity: .75;
- fill: none;
- stroke: var(--satus-primary);
- flex: 0 0 20px;
-}
-
-.satus-modal--vertical .satus-button .satus-span {
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
-}
-
-.satus-section--column {
- width: 100%;
- height: 100%;
-}
-
-.satus-textarea {
- font-family: monospace;
- font-size: inherit;
- width: calc(100% - 32px);
- height: calc(100% - 32px);
- padding: 8px;
- resize: none;
- color: inherit;
- border-radius: 8px;
- outline: none;
- background: var(--satus-section-card-background);
- appearance: none;
- margin: 16px;
- box-sizing: border-box;
-}
-
-
-/*--------------------------------------------------------------
-# STAR US ON GITHUB
---------------------------------------------------------------*/
-
-.star-us-on-github {
- font-size: 13px;
- font-weight: 500;
- position: absolute;
- bottom: 16px;
- left: 50%;
- width: 100%;
- height: auto;
- min-height: auto;
- padding: 0;
- cursor: pointer;
- transition: 150ms;
- transform: translateX(-50%);
- text-align: center;
- text-decoration: none;
- color: #9595b2;
- justify-content: center;
-}
-
-[hide-star-us-on-github=true] .star-us-on-github {
- display: none;
-}
-
-.star-us-on-github svg {
- position: relative;
- top: 4px;
- width: 20px;
- height: 20px;
-}
-
-.star-us-on-github span:first-child {
- margin: 0 4px 0 0;
-}
-
-.star-us-on-github span:last-child {
- margin: 0 0 0 4px;
-}
\ No newline at end of file
diff --git a/popup.html b/popup.html
deleted file mode 100644
index e66affa..0000000
--- a/popup.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
- ImprovedTube
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/popup.js b/popup.js
deleted file mode 100644
index e5bb3a1..0000000
--- a/popup.js
+++ /dev/null
@@ -1,724 +0,0 @@
-/*--------------------------------------------------------------
->>> POPUP:
-----------------------------------------------------------------
-# Skeleton
-# Initialization
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# SKELETON
---------------------------------------------------------------*/
-
-var skeleton = {
- component: 'base',
-
- header: {
- component: 'header',
-
- section_1: {
- component: 'section',
- variant: 'align-start',
-
- back: {
- component: 'button',
- attr: {
- 'hidden': 'true'
- },
- on: {
- click: 'layers.back'
- },
- pluviam: true,
-
- svg: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'none',
- 'stroke-width': '1.5',
- 'stroke': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M14 18l-6-6 6-6'
- }
- }
- }
- },
- title: {
- component: 'h1',
- variant: 'title'
- }
- },
- section_2: {
- component: 'section',
- variant: 'align-end',
-
- menu: {
- component: 'button',
- on: {
- click: {
- component: 'modal',
- variant: 'vertical',
-
- settings: {
- component: 'button',
- on: {
- click: {
- section: {
- component: 'section',
- variant: 'card',
- on: {
- render: function () {
- document.querySelector('.satus-modal').close();
- }
- },
-
- appearance: {
- component: 'button',
- on: {
- click: {
- section: {
- component: 'section',
- variant: 'card',
-
- hide_made_with_love: {
- component: 'switch',
- text: 'hideStarUs',
- storage: 'hide-star-us-on-github'
- }
- }
- }
- },
-
- svg: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M7 16c.6 0 1 .5 1 1a2 2 0 0 1-2 2h-.5a4 4 0 0 0 .5-2c0-.6.5-1 1-1M18.7 3a1 1 0 0 0-.7.3l-9 9 2.8 2.7 9-9c.3-.4.3-1 0-1.4l-1.4-1.3a1 1 0 0 0-.7-.3zM7 14a3 3 0 0 0-3 3c0 1.3-1.2 2-2 2 1 1.2 2.5 2 4 2a4 4 0 0 0 4-4 3 3 0 0 0-3-3z'
- }
- }
- },
- label: {
- component: 'span',
- text: 'appearance'
- }
- },
- languages: {
- component: 'button',
- on: {
- click: {
- section: {
- component: 'section',
- variant: 'card',
-
- language: {
- text: 'language',
- component: 'select',
- on: {
- change: function (name, value) {
- var self = this;
-
- satus.ajax('_locales/' + this.querySelector('select').value + '/messages.json', function (response) {
- try {
- response = JSON.parse(response);
-
- for (var key in response) {
- satus.locale.strings[key] = response[key].message;
- }
-
- self.base.skeleton.header.section_1.title.rendered.textContent = satus.locale.get('languages');
-
- self.base.skeleton.layers.rendered.update();
- } catch (error) {
- console.log(error);
- //close();
- }
- });
- }
- },
- options: [{
- value: 'en',
- text: 'English'
- }, {
- value: 'ko',
- text: '한국어'
- }, {
- value: 'es',
- text: 'Español (España)'
- }, {
- value: 'ru',
- text: 'Русский'
- }, {
- value: 'de',
- text: 'Deutsch'
- }, {
- value: 'zh_TW',
- text: '中文 (繁體)'
- }, {
- value: 'pt_PT',
- text: 'Português'
- }, {
- value: 'pt_BR',
- text: 'Português (Brasil)'
- }, {
- value: 'zh_CN',
- text: '中文 (简体)'
- }, {
- value: 'fr',
- text: 'Français'
- }, {
- value: 'ja',
- text: '日本語'
- }, {
- value: 'tr',
- text: 'Türkçe'
- }, {
- value: 'tr',
- text: 'Italiano'
- }, {
- value: 'nl',
- text: 'Nederlands'
- }, {
- value: 'ar',
- text: 'العربية'
- }, {
- value: 'id',
- text: 'Bahasa Indonesia'
- }, {
- value: 'nb',
- text: 'Norsk'
- }, {
- value: 'nb_NO',
- text: 'Norsk (Bokmål)'
- }, {
- value: 'el',
- text: 'Ελληνικά'
- }, {
- value: 'bn',
- text: 'বাংলা'
- }, {
- value: 'hin',
- text: 'हिन्दी'
- }, {
- value: 'sk',
- text: 'Slovenčina'
- }, {
- value: 'pl',
- text: 'Polski'
- }]
- }
- }
- }
- },
-
- svg: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M12.9 15l-2.6-2.4c1.8-2 3-4.2 3.8-6.6H17V4h-7V2H8v2H1v2h11.2c-.7 2-1.8 3.8-3.2 5.3-1-1-1.7-2.1-2.3-3.3h-2c.7 1.6 1.7 3.2 3 4.6l-5.1 5L4 19l5-5 3.1 3.1.8-2zm5.6-5h-2L12 22h2l1.1-3H20l1.1 3h2l-4.5-12zm-2.6 7l1.6-4.3 1.6 4.3H16z'
- }
- }
- },
- label: {
- component: 'span',
- text: 'languages'
- }
- },
- about: {
- component: 'button',
- on: {
- click: {
- component: 'span',
-
- on: {
- render: function () {
- var component = this,
- manifest = chrome.runtime.getManifest(),
- user = satus.user(),
- skeleton_about = {
- extension_section_label: {
- component: 'span',
- class: 'satus-section--label',
- text: 'extension'
- },
- extension_section: {
- component: 'section',
- variant: 'card',
-
- list: {
- component: 'list',
- items: [
- ['version', manifest.version],
- ['permissions', manifest.permissions.join(', ').replace('https://www.youtube.com/', 'YouTube')]
- ]
- }
- },
- browser_section_label: {
- component: 'span',
- class: 'satus-section--label',
- text: 'browser'
- },
- browser_section: {
- component: 'section',
- variant: 'card',
-
- list: {
- component: 'list',
- items: [
- ['name', user.browser.name],
- ['version', user.browser.version],
- ['platform', user.browser.platform],
- ['videoFormats', {
- component: 'span',
- on: {
- render: function () {
- var formats = [];
-
- for (var key in user.browser.video) {
- if (user.browser.video[key] !== false) {
- formats.push(key);
- }
- }
-
- this.textContent = formats.join(', ');
- }
- }
- }],
- ['audioFormats', {
- component: 'span',
- on: {
- render: function () {
- var formats = [];
-
- for (var key in user.browser.audio) {
- if (user.browser.audio[key] !== false) {
- formats.push(key);
- }
- }
-
- this.textContent = formats.join(', ');
- }
- }
- }],
- ['flash', !!user.browser.flash ? 'true' : 'false']
- ]
- }
- },
- os_section_label: {
- component: 'span',
- class: 'satus-section--label',
- text: 'os'
- },
- os_section: {
- component: 'section',
- variant: 'card',
-
- list: {
- component: 'list',
- items: [
- ['name', user.os.name],
- ['type', user.os.type]
- ]
- }
- },
- device_section_label: {
- component: 'span',
- class: 'satus-section--label',
- text: 'device'
- },
- device_section: {
- component: 'section',
- variant: 'card',
-
- list: {
- component: 'list',
- items: [
- ['screen', user.device.screen],
- ['cores', user.device.cores],
- ['gpu', user.device.gpu],
- ['ram', user.device.ram]
- ]
- }
- }
- };
-
- setTimeout(function () {
- satus.render(skeleton_about, component.parentNode);
-
- component.remove();
- });
- }
- }
- }
- },
-
- svg: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M11 7h2v2h-2zm0 4h2v6h-2zm1-9a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm0 18a8 8 0 1 1 0-16 8 8 0 0 1 0 16z'
- }
- }
- },
- label: {
- component: 'span',
- text: 'about'
- }
- }
- }
- }
- },
-
- icon: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'var(--satus-primary)'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M19.4 13l.1-1v-1l2-1.6c.2-.2.3-.5.2-.7l-2-3.4c-.2-.3-.4-.3-.6-.3l-2.5 1-1.7-1-.4-2.6c0-.2-.3-.4-.5-.4h-4c-.3 0-.5.2-.5.4l-.4 2.7c-.6.2-1.1.6-1.7 1L5 5c-.2-.1-.4 0-.6.2l-2 3.4c0 .3 0 .5.2.7l2 1.6a8 8 0 0 0 0 2l-2 1.6c-.2.2-.3.5-.2.7l2 3.4c.2.3.4.3.6.3l2.5-1 1.7 1 .4 2.6c0 .2.2.4.5.4h4c.3 0 .5-.2.5-.4l.4-2.7c.6-.2 1.1-.6 1.7-1l2.5 1c.2.1.4 0 .6-.2l2-3.4c0-.2 0-.5-.2-.7l-2-1.6zM12 15.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7z'
- }
- }
- },
- label: {
- component: 'span',
- text: 'settings'
- }
- }
- }
- },
- pluviam: true,
-
- dot_1: {
- component: 'span'
- },
- dot_2: {
- component: 'span'
- },
- dot_3: {
- component: 'span'
- }
- }
- }
- },
- layers: {
- component: 'layers',
- on: {
- open: function () {
- var parent = this.path[this.path.length - 1].parent,
- section = this.base.skeleton.header.section_1,
- title = 'User Agent';
-
- if (parent) {
- if (parent.label) {
- title = parent.label.text;
- } else if (parent.text) {
- title = parent.text;
- }
- }
-
- section.back.rendered.hidden = this.path.length <= 1;
- section.title.rendered.innerText = satus.locale.get(title);
- }
- }
- }
-};
-
-
-/*--------------------------------------------------------------
-# INITIALIZATION
---------------------------------------------------------------*/
-
-satus.storage.attributes = {
- 'hide-star-us-on-github': true
-};
-
-satus.storage.import(function (items) {
- var language = items.language || window.navigator.language || 'en';
-
- satus.ajax('_locales/' + language + '/messages.json', function (response) {
- try {
- response = JSON.parse(response);
-
- for (var key in response) {
- satus.locale.strings[key] = response[key].message;
- }
-
- function parse(target, source) {
- source.section = {
- component: 'section',
- variant: 'card'
- };
-
- source = source.section;
-
- for (var key in target) {
- var item = target[key];
-
- if (typeof item === 'object') {
- source[key] = {
- component: 'button',
- text: key,
- on: {
- click: {}
- }
- };
-
- parse(item, source[key].on.click);
- } else {
- source[key] = {
- component: 'radio',
- group: 'user-agent',
- text: key,
- value: item
- };
- }
- }
- }
-
- parse(user_agents, skeleton.layers);
-
- delete skeleton.layers.section.car.text;
-
- skeleton.layers.section.car.icon = {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M18.92 5.01C18.72 4.42 18.16 4 17.5 4h-11c-.66 0-1.21.42-1.42 1.01L3 11v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 15c-.83 0-1.5-.67-1.5-1.5S5.67 12 6.5 12s1.5.67 1.5 1.5S7.33 15 6.5 15zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 10l1.5-4.5h11L19 10H5z'
- }
- }
- };
-
- skeleton.layers.section.car.label = {
- component: 'span',
- text: 'car'
- };
-
- delete skeleton.layers.section.computer.text;
-
- skeleton.layers.section.computer.icon = {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z'
- }
- }
- };
-
- skeleton.layers.section.computer.label = {
- component: 'span',
- text: 'computer'
- };
-
- delete skeleton.layers.section.gameConsole.text;
-
- skeleton.layers.section.gameConsole.icon = {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'm21.58 16.09-1.09-7.66A3.996 3.996 0 0 0 16.53 5H7.47C5.48 5 3.79 6.46 3.51 8.43l-1.09 7.66C2.2 17.63 3.39 19 4.94 19c.68 0 1.32-.27 1.8-.75L9 16h6l2.25 2.25c.48.48 1.13.75 1.8.75 1.56 0 2.75-1.37 2.53-2.91zM11 11H9v2H8v-2H6v-1h2V8h1v2h2v1zm4-1c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2 3c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z'
- }
- }
- };
-
- skeleton.layers.section.gameConsole.label = {
- component: 'span',
- text: 'gameConsole'
- };
-
- delete skeleton.layers.section.phone.text;
-
- skeleton.layers.section.phone.icon = {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M17 1.01 7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z'
- }
- }
- };
-
- skeleton.layers.section.phone.label = {
- component: 'span',
- text: 'phone'
- };
-
- delete skeleton.layers.section.tv.text;
-
- skeleton.layers.section.tv.icon = {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z'
- }
- }
- };
-
- skeleton.layers.section.tv.label = {
- component: 'span',
- text: 'tv'
- };
-
- delete skeleton.layers.section.watch.text;
-
- skeleton.layers.section.watch.icon = {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M20 12c0-2.54-1.19-4.81-3.04-6.27L16 0H8l-.95 5.73C5.19 7.19 4 9.45 4 12s1.19 4.81 3.05 6.27L8 24h8l.96-5.73A7.976 7.976 0 0 0 20 12zM6 12c0-3.31 2.69-6 6-6s6 2.69 6 6-2.69 6-6 6-6-2.69-6-6z'
- }
- }
- };
-
- skeleton.layers.section.watch.label = {
- component: 'span',
- text: 'watch'
- };
-
- skeleton.layers.section.custom = {
- component: 'button',
- on: {
- click: {
- component: 'section',
- variant: 'column',
-
- textarea: {
- component: 'textarea',
- storage: 'user-agent',
- properties: {
- placeholder: '...'
- },
- on: {
- render: function () {
- this.value = satus.storage.get(this.skeleton.storage) || '';
- },
- keydown: function () {
- var self = this;
-
- setTimeout(function () {
- satus.storage.set(self.skeleton.storage, self.value);
- });
- }
- }
- }
- }
- },
-
- icon: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': 'currentColor'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'M5 4v3h5.5v12h3V7H19V4z'
- }
- }
- },
- label: {
- component: 'span',
- text: 'custom'
- }
- };
-
- skeleton.layers.star_us_on_github = {
- component: 'a',
- class: 'star-us-on-github',
- attr: {
- target: '_blank',
- href: 'https://github.com/victor-savinov/user-agent'
- },
-
- span_1: {
- component: 'span',
- text: 'Star us'
- },
- svg: {
- component: 'svg',
- attr: {
- 'viewBox': '0 0 24 24',
- 'fill': '#ed2c4c'
- },
-
- path: {
- component: 'path',
- attr: {
- 'd': 'm14.43 10-1.47-4.84c-.29-.95-1.63-.95-1.91 0L9.57 10H5.12c-.97 0-1.37 1.25-.58 1.81l3.64 2.6-1.43 4.61c-.29.93.79 1.68 1.56 1.09l3.69-2.8 3.69 2.81c.77.59 1.85-.16 1.56-1.09l-1.43-4.61 3.64-2.6c.79-.57.39-1.81-.58-1.81h-4.45z'
- }
- }
- },
- span_2: {
- component: 'span',
- text: 'on GitHub'
- }
- };
-
- satus.render(skeleton);
- } catch (error) {
- console.error(error);
- }
- }, function (success) {
- satus.ajax('_locales/en/messages.json', success);
- });
-});
\ No newline at end of file
diff --git a/py/locale.py b/py/locale.py
index 10b38b0..f484f75 100644
--- a/py/locale.py
+++ b/py/locale.py
@@ -1,22 +1,23 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# >>> TABLE OF CONTENTS:
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# 1.0 Import modules
# 2.0 Lower camel case
# 3.0 Get list of files
# 4.0 Add item
# 5.0 Remove item
-# 6.0 Decode
-# 7.0 Add locales
-# 8.0 Initialization
-# --------------------------------------------------------------
+# 6.0 Change key
+# 7.0 Decode
+# 8.0 Upgrade
+# 9.0 Initialization
+# ------------------------------------------------------------------------------
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# 1.0 IMPORT MODULES
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
import io
import json
@@ -26,9 +27,9 @@
import sys
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# 2.0 LOWER CAMEL CASE
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
def lowerCamelCase(string):
string = re.sub(r"(-|_)+", ' ', string).title()
@@ -37,21 +38,21 @@ def lowerCamelCase(string):
return string[0].lower() + string[1:]
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# 3.0 GET LIST OF FILES
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
-def getListOfFiles(dirName):
+def getListOfFiles(path):
allFiles = list()
- for entry in os.listdir(dirName):
- fullPath = os.path.join(dirName, entry)
+ for entry in os.listdir(path):
+ fullPath = os.path.join(path, entry)
if not os.path.isdir(fullPath):
allFiles.append(fullPath)
- for entry in os.listdir(dirName):
- fullPath = os.path.join(dirName, entry)
+ for entry in os.listdir(path):
+ fullPath = os.path.join(path, entry)
if os.path.isdir(fullPath):
allFiles = allFiles + getListOfFiles(fullPath)
@@ -59,9 +60,9 @@ def getListOfFiles(dirName):
return allFiles
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# 4.0 ADD ITEM
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
def addItem(allFiles):
message = input('Enter your message: ')
@@ -75,14 +76,13 @@ def addItem(allFiles):
data[camelized_message] = {'message': message}
json_file.seek(0)
- json.dump(data, json_file, ensure_ascii=False, indent=4,
- sort_keys=True)
+ json.dump(data, json_file, ensure_ascii=False, indent=4, sort_keys=True)
json_file.truncate()
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
# 5.0 REMOVE ITEM
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
def removeItem(allFiles):
key = input('Enter your key (lowerCamelCase): ')
@@ -100,9 +100,31 @@ def removeItem(allFiles):
json_file.truncate()
-# --------------------------------------------------------------
-# 6.0 DECODE
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
+# 6.0 CHANGE KEY
+# ------------------------------------------------------------------------------
+
+def changeKey(allFiles):
+ old_key = input('Enter key: ')
+ new_key = input('Enter new key: ')
+
+ for keyFile in allFiles:
+ with open(keyFile, 'r+') as file:
+ data = json.load(file)
+
+ if old_key in data:
+ data[new_key] = data[old_key]
+
+ del data[old_key]
+
+ file.seek(0)
+ json.dump(data, file, ensure_ascii=False, indent=4, sort_keys=True)
+ file.truncate()
+
+
+# ------------------------------------------------------------------------------
+# 7.0 DECODE
+# ------------------------------------------------------------------------------
def decodeCharacters(allFiles):
for keyFile in allFiles:
@@ -115,11 +137,11 @@ def decodeCharacters(allFiles):
json_file.truncate()
-# --------------------------------------------------------------
-# 7.0 ADD LOCALES
-# --------------------------------------------------------------
+# ------------------------------------------------------------------------------
+# 8.0 UPGRADE
+# ------------------------------------------------------------------------------
-def addLocales():
+def upgrade():
locales = [
'am',
'ar',
@@ -176,24 +198,49 @@ def addLocales():
'zh_TW'
]
+ if os.path.exists('../_locales/en/messages.json'):
+ file = open('../_locales/en/messages.json', 'r+')
+
+ default_locale = json.load(file)
+
+ file.close()
+ else:
+ default_locale = {}
+
for locale in locales:
- if not os.path.exists('../_locales/' + locale):
- pathlib.Path('../_locales/' + locale).mkdir(parents=True,
- exist_ok=True)
+ path = '../_locales/' + locale
- file = io.open('../_locales/' + locale + '/messages.json',
- mode='w', encoding='utf-8')
+ if not os.path.exists(path):
+ pathlib.Path(path).mkdir(parents=True, exist_ok=True)
- file.write('{}')
+ file = io.open(path + '/messages.json', mode='w', encoding='utf-8')
+ json.dump(default_locale, file, ensure_ascii=False, indent=4, sort_keys=True)
+
file.close()
+ else:
+ with open(path + '/messages.json', 'r+') as file:
+ data = json.load(file)
+
+ file.seek(0)
+
+ for key in default_locale:
+ if (key in data) == False:
+ data[key] = default_locale[key]
+
+ json.dump(data, file, ensure_ascii=False, indent=4, sort_keys=True)
+
+ file.truncate()
+
+ file.close()
- print(locale)
+# ------------------------------------------------------------------------------
+# 9.0 INITIALIZATION
+# ------------------------------------------------------------------------------
-# --------------------------------------------------------------
-# 8.0 INITIALIZATION
-# --------------------------------------------------------------
+if not os.path.exists('../_locales/'):
+ pathlib.Path('../_locales/').mkdir(parents=True, exist_ok=True)
allFiles = getListOfFiles('../_locales/')
@@ -204,5 +251,7 @@ def addLocales():
removeItem(allFiles)
elif arg == '-decode':
decodeCharacters(allFiles)
- elif arg == '-generate':
- addLocales()
\ No newline at end of file
+ elif arg == '-change-key':
+ changeKey(allFiles)
+ elif arg == '-upgrade':
+ upgrade()
\ No newline at end of file
diff --git a/satus.css b/satus.css
deleted file mode 100644
index eb8c652..0000000
--- a/satus.css
+++ /dev/null
@@ -1,1147 +0,0 @@
-
-/*--------------------------------------------------------------
->>> THEMES:
-----------------------------------------------------------------
-# Default
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# DEFAULT
---------------------------------------------------------------*/
-
-html {
- --satus-primary: #ff4158;
- --satus-switch-background: rgba(0,0,0,.08);
- --satus-header-background: #fff;
- --satus-header-text: #777;
- --satus-layers-background: #f7f7f6;
- --satus-layers-text: #777;
- --satus-section-card-background: #fff;
- --satus-modal-background: #fff;
- --satus-modal-text: #777;
- --satus-hover: rgba(0, 0, 0, .04);
-
- --satus-switch-track: #b8b8b8;
- --satus-switch-track--active: var(--satus-primary);
- --satus-switch-thumb: #fff;
-
- --satus-tabs: #fff;
-}
-/*--------------------------------------------------------------
->>> COLOR PICKER
---------------------------------------------------------------*/
-
-.satus-color-picker {
- font-size: inherit;
- position: relative;
- display: flex;
- box-sizing: border-box;
- margin: 0;
- cursor: pointer;
- color: inherit;
- border: none;
- outline: none;
- background-color: var(--satus-theme-button);
- justify-content: space-between;
- -webkit-tap-highlight-color: transparent;
- align-items: center;
- -webkit-appearance: none;
-}
-
-.satus-color-picker__value {
- width: 22px;
- height: 22px;
- border: 2px solid rgba(255, 255, 255, .4);
- border-radius: 50%;
-}
-
-.satus-modal--color-picker {
- position: relative;
-}
-
-.satus-modal--color-picker .satus-modal__surface {
- display: flex;
- flex-direction: column;
- align-items: center;
-}
-
-.satus-modal--color-picker canvas {
- width: 256px;
- height: 256px;
-}
-
-.satus-color-picker__dim {
- position: absolute;
- width: 256px;
- height: 256px;
- pointer-events: none;
- opacity: 0;
- border-radius: 50%;
- background: #000;
-}
-
-.satus-color-picker__cursor {
- position: absolute;
- width: 5px;
- height: 5px;
- transform: translate(-50%, -50%);
- pointer-events: none;
- border: 1px solid #fff;
- border-radius: 50%;
- box-shadow: 0 0 0 1px #000;
-}
-
-.satus-color-picker__slider .satus-slider__container {
- height: 18px;
-}
-
-.satus-color-picker__slider .satus-slider__track-container {
- top: calc(50% - 9px);
- height: 18px;
-}
-
-.satus-color-picker__slider .satus-slider__track-container::before {
- height: 16px;
- opacity: 1;
- border: 1px solid #bfbfbf;
- border-radius: 4px;
- background: linear-gradient(90deg, #fff, #000);
-}
-
-.satus-color-picker__slider .satus-slider__track {
- background: transparent;
-}
-
-.satus-color-picker__slider .satus-slider__thumb {
- top: 0;
- height: 18px;
- border-radius: 4px;
- background: #fff;
- box-shadow: 0 0 2px rgb(0, 0, 0, .2);
-}
-
-.satus-color-picker__slider .satus-slider__thumb:before {
- display: none;
-}
-
-.satus-color-picker__actions {
- display: flex;
- width: 100%;
- justify-content: flex-end;
-}
-
-.satus-color-picker__actions .satus-button {
- height: 32px;
- margin: 8px 4px 0;
- border-radius: 8px;
- background: rgba(0, 0, 0, .15);
-}
-
-.satus-color-picker__actions .satus-button:hover {
- background: rgba(0, 0, 0, .25);
-}
-/*--------------------------------------------------------------
-# MAIN
---------------------------------------------------------------*/
-
-.satus-main {
- color: var(--satus-main-text);
- background: var(--satus-main-background);
- overflow-y: auto;
- box-sizing: border-box;
-}
-/*--------------------------------------------------------------
->>> TABS
---------------------------------------------------------------*/
-
-.satus-tabs {
- position: relative;
- display: flex;
- overflow: hidden;
- box-sizing: border-box;
- width: calc(100% - 16px);
- margin: 16px 8px 4px;
- border: 1px solid var(--satus-tabs);
- border-radius: 18px;
-}
-
-.satus-tabs__selection {
- position: absolute;
- z-index: 0;
- left: 0;
- width: 50%;
- height: 32px;
- transition: left .25s;
- border-radius: 18px;
- background: var(--satus-tabs);
- box-shadow: 1px 0 4px rgb(0,0,0,.8);
-}
-
-.satus-tabs__button {
- background: transparent;
- border: none;
- font-family: inherit;
- font-weight: 500;
- font-size: 12px;
- color: inherit;
- height: 32px;
- flex: 1;
- text-transform: uppercase;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- position: relative;
- z-index: 1;
- padding: 0 16px;
-}
-
-.satus-tabs__button:hover {
- cursor: pointer;
-}
-/*--------------------------------------------------------------
->>> RADIO
---------------------------------------------------------------*/
-/*--------------------------------------------------------------
-# BUTTON
---------------------------------------------------------------*/
-
-.satus-button {
- font: inherit;
- position: relative;
- overflow: hidden;
- height: 48px;
- margin: 0;
- padding: 8px;
- color: var(--satus-button-text, inherit);
- border: none;
- background: var(--satus-button-background, transparent);
- appearance: none;
- text-align: left;
-}
-
-.satus-button:hover {
- cursor: pointer;
- background-color: var(--satus-hover);
-}
-
-.satus-button>* {
- pointer-events: none;
-}
-
-.satus-header .satus-button {
- width: 40px;
- min-width: 40px;
- height: 40px;
- padding: 8px;
- color: inherit;
- border-radius: 50%;
-}
-
-.satus-header .satus-section--align-start>* {
- margin-right: 8px;
-}
-/*--------------------------------------------------------------
->>> LIST:
---------------------------------------------------------------*/
-
-.satus-list {
- list-style: none;
- margin: 0;
-}
-
-.satus-list__item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- min-height: 48px;
-}
-
-.satus-list__item>*:last-child {
- text-align: right;
-}
-/*--------------------------------------------------------------
->>> SECTION:
-----------------------------------------------------------------
-#
---------------------------------------------------------------*/
-
-.satus-section {
- display: flex;
- flex-wrap: wrap;
- box-sizing: border-box;
-}
-
-.satus-section--align-start {
- justify-content: flex-start;
-}
-
-.satus-section--align-end {
- justify-content: flex-end;
-}
-
-.satus-section--column {
- flex-direction: column;
-}
-
-.satus-header>.satus-section {
- align-items: center;
-}
-
-.satus-section--card {
- flex-direction: column;
- width: calc(100% - 24px);
- max-width: 900px;
- margin: 12px auto 0;
- padding: 8px 0;
- border: 1px solid rgba(0,0,0,.1);
- border-radius: 8px;
- background: var(--satus-section-card-background);
- color: var(--satus-section-card-text);
- box-sizing: border-box;
-}
-
-.satus-section--card:last-child {
- margin: 12px auto;
-}
-
-.satus-section--card>* {
- min-height: 48px;
- padding: 0 16px;
- text-align: left;
- box-sizing: border-box;
- width: 100%;
-}
-
-.satus-section--card>.satus-switch,
-.satus-section--card>.satus-select,
-.satus-section--card>.satus-slider,
-.satus-section--card>.satus-radio
-{
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.satus-section--card>.satus-button:hover,
-.satus-section--card>.satus-switch:hover,
-.satus-section--card>.satus-select:hover,
-.satus-section--card>.satus-slider:hover,
-.satus-section--card>.satus-radio:hover
-{
- background-color: var(--satus-hover);
-}
-
-.satus-section--card>.satus-button {
- display: flex;
- padding: 0 16px;
- align-items: center;
-}
-
-.satus-section--card>.satus-button>svg {
- width: 20px;
- margin: 2px 16px 0 0;
- color: var(--satus-primary);
-}
-
-.satus-section--label,
-.satus-h2--section-label {
- font-size: 14px;
- display: block;
- max-width: 900px;
- margin: 16px 16px 8px;
- width: 100%;
- font-weight: 600;
-}
-/*--------------------------------------------------------------
-# SCROLLBAR
---------------------------------------------------------------*/
-
-::-webkit-scrollbar {
- width: 4px;
-}
-
-::-webkit-scrollbar:hover {
- width: 8px;
-}
-
-::-webkit-scrollbar-thumb {
- background: rgba(0, 0, 0, .3);
-}
-/*--------------------------------------------------------------
->>> MODAL
---------------------------------------------------------------*/
-
-.satus-modal {
- position: absolute;
- z-index: 100;
- top: 0;
- left: 0;
- display: flex;
- width: 100%;
- height: 100vh;
- justify-content: center;
- align-items: center;
-}
-
-.satus-modal__scrim {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- animation: modalFadeIn 150ms linear forwards;
- opacity: 0;
- background: rgba(0, 0, 0, .2);
- backdrop-filter: blur(8px);
-}
-
-.satus-modal__surface {
- font-size: 14px;
- display: flex;
- overflow-y: auto;
- flex-direction: column;
- width: 95%;
- min-width: 240px;
- max-width: 560px;
- max-height: 80%;
- margin: 0 16px;
- padding: 8px 16px;
- transform: scale(.8);
- animation: modalZoomIn 150ms linear forwards;
- animation-delay: 20ms;
- opacity: 0;
- color: var(--satus-modal-text);
- border-radius: 6px;
- background-color: var(--satus-modal-background);
- box-shadow: inset 0 -1px 1px 1px rgb(0, 0, 0, .1), 0 2px 6px rgb(0, 0, 0, .15);
-}
-
-.satus-modal__surface .satus-section--actions {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- margin-top: 16px;
-}
-
-.satus-modal__surface .satus-section--actions .satus-button {
- height: 32px;
- margin-left: 8px;
- border-radius: 4px;
- padding: 0 8px;
-}
-
-.satus-modal--closing .satus-modal__scrim {
- animation: modalFadeOut 70ms linear forwards;
-}
-
-.satus-modal--closing .satus-modal__surface {
- animation: modalZoomOut 70ms linear forwards;
-}
-
-
-/*--------------------------------------------------------------
-# ANIMATIONS
---------------------------------------------------------------*/
-
-@keyframes modalFadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-@keyframes modalFadeOut {
- from {
- opacity: 1;
- }
- to {
- opacity: 0;
- }
-}
-
-@keyframes modalZoomIn {
- from {
- transform: scale(.8);
- opacity: 0;
- }
- to {
- transform: scale(1);
- opacity: 1;
- }
-}
-
-@keyframes modalZoomOut {
- from {
- transform: scale(1);
- opacity: 1;
- }
- to {
- transform: scale(.8);
- opacity: 0;
- }
-}
-/*--------------------------------------------------------------
->>> SWITCH
-----------------------------------------------------------------
-# Container
-# Track
-# Thumb
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# CONTAINER
---------------------------------------------------------------*/
-
-.satus-switch {
- font: inherit;
- display: flex;
- transition: background-color 75ms;
- color: inherit;
- border: none;
- outline: none;
- background-color: transparent;
- justify-content: space-between;
- align-items: center;
-}
-
-.satus-switch:hover {
- cursor: pointer;
-}
-
-
-/*--------------------------------------------------------------
-# TRACK
---------------------------------------------------------------*/
-
-.satus-switch > i {
- width: 38px;
- height: 20px;
- transition: background-color 150ms;
- border-radius: 20px;
- background-color: var(--satus-switch-track);
- flex: 0 0 38px;
-}
-
-.satus-section--card .satus-switch > i {
- margin-left: 16px;
-}
-
-.satus-switch[data-value='true'] > i {
- background-color: var(--satus-switch-track--active);
-}
-
-
-/*--------------------------------------------------------------
-# THUMB
---------------------------------------------------------------*/
-
-.satus-switch > i::before {
- display: block;
- width: 16px;
- height: 16px;
- margin: 2px;
- content: '';
- transition: transform 150ms cubic-bezier(.4, 0, .2, 1);
- border-radius: 50%;
- background-color: var(--satus-switch-thumb);
- will-change: transform;
-}
-
-.satus-switch[data-value='true'] > i::before {
- transform: translateX(18px);
-}
-/*--------------------------------------------------------------
->>> SLIDER:
-----------------------------------------------------------------
-#
---------------------------------------------------------------*/
-
-.satus-slider {
- position: relative;
- display: flex;
- flex-direction: column;
- box-sizing: border-box;
- width: 100%;
- min-height: 64px;
- padding: 0 16px;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- outline: none;
- align-items: flex-start;
- justify-content: center;
-}
-
-.satus-slider:hover {
- cursor: pointer;
- background-color: rgba(0, 0, 0, .04);
-}
-
-
-/* LABEL */
-
-.satus-slider__label {
- cursor: default;
-}
-
-.satus-slider>input {
- position: absolute;
- z-index: 1;
- top: 0;
- left: 0;
- box-sizing: border-box;
- width: 100%;
- height: 100%;
- margin: 0;
- padding: 0;
- opacity: 0;
-}
-
-
-/* TRACK */
-
-.satus-slider__container {
- position: relative;
- width: 100%;
- height: 12px;
- margin: 8px 0 0;
-}
-
-.satus-slider__track-container {
- position: absolute;
- top: calc(50% - 1px);
- width: 100%;
- height: 2px;
- pointer-events: none;
-}
-
-.satus-slider__track-container::before {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 2px;
- content: '';
- opacity: .26;
- background-color: var(--satus-primary);
-}
-
-.satus-slider__track {
- position: relative;
- width: 0;
- height: 100%;
- background-color: var(--satus-primary);
- will-change: width;
-}
-
-.satus-slider:not(.satus-slider--dragging) .satus-slider__track {
- transition: width 100ms ease-out;
-}
-
-.satus-slider__thumb {
- position: absolute;
- top: -5px;
- right: -12px;
- width: 12px;
- height: 12px;
- border-radius: 50%;
- background-color: var(--satus-primary);
- box-shadow: 0 1px 5px rgba(0, 0, 0, .15);
-}
-
-.satus-slider .satus-slider__thumb::before {
- font-size: 13px;
- position: absolute;
- top: -34px;
- left: 50%;
- visibility: hidden;
- box-sizing: border-box;
- min-width: 28px;
- padding: 4px 4px;
- content: attr(data-value);
- transform: translateX(-50%);
- text-align: center;
- pointer-events: none;
- color: #fff;
- border-radius: 4px;
- background: var(--satus-theme-tooltip);
-}
-
-.satus-slider:hover .satus-slider__thumb::before,
-.satus-slider>input:focus .satus-slider__container .satus-slider__thumb::before {
- visibility: visible;
-}
-
-.satus-slider__ring {
- position: absolute;
- top: -11px;
- right: -18px;
- width: 24px;
- height: 24px;
- transition: 100ms;
- transform: scale(0);
- opacity: 0;
- border-radius: 50%;
- background-color: var(--satus-primary);
-}
-
-.satus-slider>input:focus+.satus-slider__container .satus-slider__ring {
- transform: scale(1);
- opacity: .25;
-}
-/*--------------------------------------------------------------
->>> SHORTCUT:
-----------------------------------------------------------------
-#
---------------------------------------------------------------*/
-
-.satus-shortcut {
- justify-content: space-between;
-}
-
-.satus-shortcut__value {
- text-transform: uppercase;
- font-size: 11px;
- opacity: .5;
-}
-
-.satus-shortcut__actions {
- display: flex;
- justify-content: flex-end;
-}
-
-.satus-shortcut__actions .satus-button {
- height: 32px;
- background: rgba(0,0,0,.15);
- margin: 8px 4px 0;
- border-radius: 8px;
-}
-
-.satus-shortcut__actions .satus-button:hover {
- background: rgba(0,0,0,.25);
-}
-
-.satus-shortcut__primary {
- display: flex;
- box-sizing: border-box;
- width: 100%;
- height: 68px;
- padding: 16px;
- background: rgba(0,0,0,.16);
- align-items: center;
-}
-
-.satus-shortcut__key {
- display: flex;
- box-sizing: border-box;
- min-width: 32px;
- height: 32px;
- padding: 4px 8px;
- border-radius: 4px;
- background: #fff;
- box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1);
- align-items: center;
- justify-content: center;
-}
-
-.satus-shortcut__plus {
- position: relative;
- width: 12px;
- height: 12px;
- margin: 8px;
-}
-
-.satus-shortcut__plus::before {
- position: absolute;
- top: 0;
- left: 5px;
- width: 2px;
- height: 12px;
- content: '';
- background-color: #aaa;
-}
-
-.satus-shortcut__plus::after {
- position: absolute;
- top: 5px;
- left: 0;
- width: 12px;
- height: 2px;
- content: '';
- background-color: #aaa;
-}
-
-.satus-shortcut__mouse {
- position: relative;
- display: flex;
- width: 28px;
- height: 36px;
- border-radius: 50%;
- border-top-left-radius: 12px;
- border-top-right-radius: 12px;
- background: #fff;
- box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1);
-}
-
-.satus-shortcut__mouse>div {
- position: absolute;
- top: 0;
- left: 13px;
- width: 2px;
- height: 11px;
- border-radius: 2px;
- background: #ccc;
-}
-
-.satus-shortcut__mouse::before {
- position: absolute;
- top: -4px;
- left: 21px;
- width: 2px;
- height: 18px;
- content: '';
- background: #f96754;
-}
-
-.satus-shortcut__mouse.false::after {
- position: absolute;
- top: -12px;
- left: 17px;
- width: 0;
- height: 0;
- content: '';
- border-right: 5px solid transparent;
- border-bottom: 8px solid #f96754;
- border-left: 5px solid transparent;
-}
-
-.satus-shortcut__mouse.true::after {
- position: absolute;
- top: 14px;
- left: 17px;
- width: 0;
- height: 0;
- content: '';
- border-top: 8px solid #f96754;
- border-right: 5px solid transparent;
- border-left: 5px solid transparent;
-}
-
-.satus-section_shortcut {
- width: 100%;
- margin: 8px 0 0;
- justify-content: flex-end;
-}
-
-.satus-button_shortcut {
- font-weight: 500;
- overflow: hidden;
- height: 28px;
- min-height: 28px;
- margin-right: 2px;
- padding: 4px 8px;
- text-transform: uppercase;
- color: #f96754;
- border-radius: 4px;
-}
-/*--------------------------------------------------------------
->>> BASE
---------------------------------------------------------------*/
-
-.satus-base{
- display: flex;
- flex-direction: column;
- width: 100%;
- height: 100%;
-}
-/*--------------------------------------------------------------
->>> TEXT FIELD
---------------------------------------------------------------*/
-
-.satus-text-field {
- position: relative;
- padding: 0 16px;
- background-color: #333347;
- border-radius: 8px;
- color: #c4c4d4;
- overflow: hidden;
- display: flex;
-}
-
-.satus-text-field__pre {
- display: flex;
- position: relative;
- height: 100%;
- margin: 0;
- padding: 0;
- overflow: hidden;
- align-items: center;
- flex: 1;
-}
-
-.satus-text-field__input {
- font: inherit;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- min-width: 0;
- max-width: none;
- height: 100%;
- min-height: 0;
- max-height: none;
- margin: 0;
- padding: 0;
- opacity: 0;
- border: none;
- appearance: none;
- z-index: 9;
-}
-
-.satus-text-field__hidden-text {
- position: absolute;
- pointer-events: none;
- opacity: 0;
-}
-
-.satus-text-field__text {
- position: absolute;
- top: 0;
- left: 0;
- display: flex;
- height: 100%;
- margin: 0;
- align-items: center;
-}
-
-.satus-text-field__cursor {
- position: absolute;
- top: 6px;
- left: 0;
- display: none;
- width: 2px;
- height: 25px;
- animation: blink 1s step-end 8;
- background: #fa0;
-}
-
-.satus-text-field__selection {
- position: absolute;
- top: 5px;
- left: 0;
- display: none;
- width: 0;
- height: 25px;
- border: 1px solid rgba(255, 255, 255, .2);
- border-radius: 3px;
- background: rgba(255, 255, 255, .1);
-}
-
-.satus-text-field__input:focus + * + * + * + .satus-text-field__cursor,
-.satus-text-field__selection:not([disabled]) {
- display: block;
-}
-
-@keyframes blink {
- from,
- to {
- opacity: 1;
- }
- 50% {
- opacity: 0;
- }
-}
-
-
-/*--------------------------------------------------------------
-# SYNTAX HIGHLIGHTING
---------------------------------------------------------------*/
-
-.satus-text-field__text>.group {
- color: #47ff47;
- background-color: rgb(71, 255, 71, .16);
-}
-
-.satus-text-field__text>.character-class {
- color: #ffc247;
- background-color: rgb(255, 170, 0, .16);
-}
-
-.satus-text-field__text>.quantifier {
- color: #47c2ff;
- background-color: rgb(71, 194, 255, .16);
-}
-
-.satus-text-field__text>.anchor {
- color: #47c2ff;
- background-color: rgb(71, 194, 255, .16);
-}
-
-.satus-text-field__text>.metasequence {
- color: #47ff47;
- background-color: rgb(71, 255, 71, .16);
-}
-
-.satus-text-field__text>.text {
- color: #c4c4d4;
- background-color: rgb(196, 196, 212, .16);
-}
-/*--------------------------------------------------------------
-# HEADER
---------------------------------------------------------------*/
-
-.satus-header {
- display: flex;
- box-sizing: border-box;
- height: 56px;
- padding: 0 16px;
- color: var(--satus-header-text);
- background: var(--satus-header-background);
- align-items: center;
- justify-content: space-between;
-}
-
-.satus-header .satus-h1--title {
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- flex: 1;
-}
-/*--------------------------------------------------------------
->>> ALERT
---------------------------------------------------------------*/
-
-.satus-alert {
- display: flex;
- box-sizing: border-box;
- min-height: 48px;
- margin: 8px;
- padding: 8px 16px;
- border-radius: 8px;
- align-items: center;
-}
-
-.satus-alert--error {
- color: #c55959;
- border: 1px solid #641616;
- background: #430f0f;
-}
-/*--------------------------------------------------------------
->>> LAYERS
---------------------------------------------------------------*/
-
-.satus-layers {
- position: relative;
- overflow: hidden;
- color: var(--satus-layers-text);
- background: var(--satus-layers-background);
- flex: 1;
-}
-
-.satus-layer {
- position: absolute;
- top: 0;
- left: 0;
- display: flex;
- overflow-y: auto;
- width: 100%;
- height: 100%;
- flex-wrap: wrap;
- align-content: flex-start;
-}
-/*--------------------------------------------------------------
-# INPUT
---------------------------------------------------------------*/
-
-.satus-input[type=text] {
- font: inherit;
- box-sizing: border-box;
- width: 100%;
- margin: 0;
- padding: 0;
- padding: 0 8px;
- color: inherit;
- border: none;
- outline: none;
- background: none;
- appearance: none;
-}
-/**/
-
-.satus-aside {
- color: var(--satus-aside-text);
- background: var(--satus-aside-background);
- box-sizing: border-box;
-}
-/*--------------------------------------------------------------
->>> SELECT
---------------------------------------------------------------*/
-
-.satus-select {
- position: relative;
- display: flex;
- box-sizing: border-box;
- align-items: center;
- justify-content: space-between;
-}
-
-.satus-select__value {
- margin-left: 16px;
- text-align: right;
- opacity: .75;
-}
-
-.satus-select select {
- font: inherit;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- margin: 0;
- padding: 0;
- padding: inherit;
- cursor: pointer;
- opacity: 0;
- color: inherit;
- border: none;
- outline: none;
- background: none;
- appearance: none;
-}
-
-.satus-select:hover {
- cursor: pointer;
- background-color: var(--satus-hover);
-}
-/*--------------------------------------------------------------
->>> PLUVIAM
---------------------------------------------------------------*/
-
-.satus-pluviam {
- position: absolute;
- transform: scale(0);
- animation-name: pluviam;
- animation-duration: 1000ms;
- opacity: var(--satus-pluviam-opacity, .08);
- border-radius: 50%;
- background: var(--satus-pluviam-background, #000);
- animation-fill-mode: forwards;
-}
-
-@keyframes pluviam {
- 0% {
- transform: scale(0);
- opacity: var(--satus-pluviam-opacity, .08);
- }
- 70% {
- transform: scale(.8);
- opacity: var(--satus-pluviam-opacity, .08);
- }
- 100% {
- transform: scale(1);
- opacity: 0;
- }
-}
\ No newline at end of file
diff --git a/satus.js b/satus.js
deleted file mode 100644
index 67b97b5..0000000
--- a/satus.js
+++ /dev/null
@@ -1,2074 +0,0 @@
-
-/*--------------------------------------------------------------
->>> CORE:
-----------------------------------------------------------------
-# Global variable
-# Functions
-# Render
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# GLOBAL VARIABLE
---------------------------------------------------------------*/
-
-var satus = {
- components: {},
- events: {},
- locale: {
- strings: {}
- },
- storage: {
- attributes: {},
- data: {}
- }
-};
-
-
-/*--------------------------------------------------------------
-# FUNCTIONS
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# APPEND
---------------------------------------------------------------*/
-
-satus.append = function (element, container) {
- (container || document.body).appendChild(element);
-};
-
-
-/*--------------------------------------------------------------
-# ANIMATION DURATION
---------------------------------------------------------------*/
-
-satus.getAnimationDuration = function (element) {
- return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000;
-};
-
-
-/*--------------------------------------------------------------
-# APPEND
---------------------------------------------------------------*/
-
-satus.attr = function (element, attributes) {
- if (attributes) {
- for (var key in attributes) {
- if (element.is_svg) {
- element.setAttributeNS(null, key, attributes[key]);
- } else {
- var value = attributes[key];
-
- if (['placeholder', 'title'].indexOf(key) !== -1) {
- value = satus.locale.get(value);
- }
-
- element.setAttribute(key, value);
- }
- }
- }
-};
-
-satus.elementIndex = function (element) {
- return Array.prototype.slice.call(element.parentNode.children).indexOf(element);
-};
-
-
-/*--------------------------------------------------------------
-# DATA
---------------------------------------------------------------*/
-
-satus.data = function (element, data) {
- if (data) {
- for (var key in data) {
- element.dataset[key] = data[key];
- }
- }
-};
-
-
-/*--------------------------------------------------------------
-# PROPERTIES
---------------------------------------------------------------*/
-
-satus.properties = function (element, properties) {
- if (properties) {
- for (var key in properties) {
- element[key] = properties[key];
- }
- }
-};
-
-
-/*--------------------------------------------------------------
-# CAMELIZE
---------------------------------------------------------------*/
-
-satus.camelize = function (string) {
- var result = '';
-
- for (var i = 0, l = string.length; i < l; i++) {
- var character = string[i];
-
- if (character === '-') {
- i++;
-
- result += string[i].toUpperCase();
- } else {
- result += character;
- }
- }
-
- return result;
-};
-
-
-/*--------------------------------------------------------------
-# SNAKELIZE
---------------------------------------------------------------*/
-
-satus.snakelize = function (string) {
- return string.replace(/([A-Z])/g, '-$1').toLowerCase();
-};
-
-
-/*--------------------------------------------------------------
-# CLASS
---------------------------------------------------------------*/
-
-satus.class = function (element, string) {
- if (string) {
- element.className += ' ' + string;
- }
-};
-
-
-/*--------------------------------------------------------------
-# EMPTY
---------------------------------------------------------------*/
-
-satus.empty = function (element) {
- for (var i = element.childNodes.length - 1; i > -1; i--) {
- element.childNodes[i].remove();
- }
-};
-
-
-/*--------------------------------------------------------------
-# EVENTS
---------------------------------------------------------------*/
-
-Object.defineProperty(satus.events, 'add', {
- value: function (type, listener) {
- if (this.hasOwnProperty(type) === false) {
- this[type] = [];
- }
-
- this[type].push(listener);
- }
-});
-
-
-/*--------------------------------------------------------------
-# ISSET
---------------------------------------------------------------*/
-
-satus.isset = function (variable) {
- if (variable === null || variable === undefined) {
- return false;
- }
-
- return true;
-};
-
-
-/*--------------------------------------------------------------
-# FETCH
---------------------------------------------------------------*/
-
-satus.fetch = function (url, success, error) {
- fetch(url).then(function (response) {
- if (response.ok) {
- response.json().then(success);
- } else {
- error();
- }
- });
-};
-
-
-/*--------------------------------------------------------------
-# AJAX
---------------------------------------------------------------*/
-
-satus.ajax = function (url, success, error) {
- var xhr = new XMLHttpRequest();
-
- xhr.onload = function () {
- success(this.response);
- };
- xhr.onerror = function () {
- error(success);
- };
-
- xhr.open('GET', url, true);
- xhr.send();
-};
-
-
-/*--------------------------------------------------------------
-# STORAGE
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# GET
---------------------------------------------------------------*/
-
-satus.storage.get = function (name) {
- var target = satus.storage.data;
-
- if (satus.isset(name) === false) {
- return;
- }
-
- name = name.split('/').filter(function (value) {
- return value != '';
- });
-
- for (var i = 0, l = name.length; i < l; i++) {
- if (satus.isset(target[name[i]])) {
- target = target[name[i]];
- } else {
- return undefined;
- }
- }
-
- return target;
-};
-
-
-/*--------------------------------------------------------------
-# SET
---------------------------------------------------------------*/
-
-satus.storage.set = function (name, value) {
- var items = {},
- target = satus.storage.data;
-
- if (satus.isset(name) === false) {
- return;
- }
-
- name = name.split('/').filter(function (value) {
- return value != '';
- });
-
- for (var i = 0, l = name.length; i < l; i++) {
- var item = name[i];
-
- if (i < l - 1) {
-
- if (target[item]) {
- target = target[item];
- } else {
- target[item] = {};
-
- target = target[item];
- }
- } else {
- target[item] = value;
- }
- }
-
- for (var key in this.data) {
- if (typeof this.data[key] !== 'function') {
- items[key] = this.data[key];
- }
- }
-
- if (satus.storage.attributes[name]) {
- document.body.setAttribute(name, value);
- }
-
- chrome.storage.local.set(items);
-};
-
-
-/*--------------------------------------------------------------
-# IMPORT
---------------------------------------------------------------*/
-
-satus.storage.import = function (callback) {
- chrome.storage.local.get(function (items) {
- for (var key in items) {
- if (satus.storage.attributes[key]) {
- document.body.setAttribute(key, items[key]);
- }
-
- satus.storage.data[key] = items[key];
- }
-
- if (callback) {
- callback(items);
- }
- });
-};
-
-
-/*--------------------------------------------------------------
-# CLEAR
---------------------------------------------------------------*/
-
-satus.storage.clear = function (callback) {
- chrome.storage.local.clear(callback);
-};
-
-
-/*--------------------------------------------------------------
-# LOCALIZATION
---------------------------------------------------------------*/
-
-/*--------------------------------------------------------------
-# GET
---------------------------------------------------------------*/
-
-satus.locale.get = function (string) {
- return this.strings[string] || string;
-};
-
-
-/*--------------------------------------------------------------
-# ON
---------------------------------------------------------------*/
-
-satus.on = function (element, events) {
- if (this.isset(events) && typeof events === 'object') {
- for (var selector in events) {
- var type = typeof events[selector];
-
- if (type === 'function') {
- element.addEventListener(selector, events[selector]);
- } else if (type === 'object') {
- element.addEventListener(selector, function (event) {
- this.skeleton.on[event.type].parent = this.skeleton;
-
- if (this.skeleton.on[event.type].component !== 'modal' && this.base && this.base.layers) {
- this.base.layers.open(this.skeleton.on[event.type]);
- } else {
- satus.render(this.skeleton.on[event.type], this.base);
- }
- });
- } else if (type === 'string') {
- element.addEventListener(selector, function () {
- var match = this.skeleton.on[event.type].match(/(["'`].+["'`]|[^.()]+)/g),
- target = this.base;
-
- for (var i = 0, l = match.length; i < l; i++) {
- var key = match[i];
-
- if (target.skeleton[key]) {
- target = target.skeleton[key];
- } else {
- if (typeof target[key] === 'function') {
- target[key]();
- } else {
- target = target[key];
- }
- }
-
- if (target.rendered) {
- target = target.rendered;
- }
- }
- });
- }
- }
- }
-};
-
-
-/*--------------------------------------------------------------
-# STYLE
---------------------------------------------------------------*/
-
-satus.style = function (component, object) {
- for (var key in object) {
- component.style[key] = object[key];
- }
-};
-
-
-/*--------------------------------------------------------------
-# SEARCH
---------------------------------------------------------------*/
-
-satus.search = function (query, object, callback, categories) {
- var threads = 0,
- folder = '',
- results = {};
-
- query = query.toLowerCase();
-
- function parse(items) {
- threads++;
-
- for (var key in items) {
- if (key !== 'rendered' && key !== 'base' && key !== 'parent') {
- var item = items[key];
-
- if (['switch', 'select', 'slider', 'shortcut'].indexOf(item.component) !== -1 && key.indexOf(query) !== -1) {
- if (categories === true) {
- if (!results[folder]) {
- results[folder] = {};
- }
-
- results[folder][key] = item;
- } else {
- results[key] = item;
- }
- }
-
- if (typeof item === 'object') {
- parse(item);
- }
- }
- }
-
- threads--;
-
- if (threads === 0) {
- callback(results);
- }
- }
-
- parse(object);
-};
-
-
-/*--------------------------------------------------------------
-# TEXT
---------------------------------------------------------------*/
-
-satus.text = function (component, string) {
- if (string) {
- component.appendChild(document.createTextNode(this.locale.get(string)));
- }
-};
-
-
-/*--------------------------------------------------------------
-# RENDER
---------------------------------------------------------------*/
-
-satus.render = function (skeleton, container, skip, property) {
- if (skeleton.hasOwnProperty('component') && skip !== true) {
- var component,
- name = skeleton.component,
- camelized_name = this.camelize(name);
-
- if (skeleton.on && skeleton.on.beforerender) {
- skeleton.on.beforerender(skeleton);
- }
-
- if (this.components[camelized_name]) {
- component = this.components[camelized_name](skeleton);
-
- if (this.isset(component.inner) === false) {
- component.inner = component;
- }
- } else if (name === 'svg' || container && container.is_svg) {
- component = document.createElementNS('http://www.w3.org/2000/svg', name);
-
- component.is_svg = true;
-
- component.inner = component;
- } else {
- component = document.createElement(skeleton.component);
-
- component.inner = component;
- }
-
- if (component.inner.hasOwnProperty('base') === false && container) {
- component.inner.base = container.base;
- }
-
- if (component.inner.base && name === 'layers') {
- component.inner.base.layers = component;
- }
-
- skeleton.rendered = component;
- component.skeleton = skeleton;
-
- if (skeleton.hasOwnProperty('storage')) {
- component.storage = skeleton.storage;
- } else if (property) {
- component.storage = property;
- }
-
- component.className = (component.className + ' satus-' + skeleton.component).trim();
-
- component.change = function (value) {
- satus.storage.set(this.storage, value);
- };
-
- if (skeleton.variant) {
- component.className += ' satus-' + skeleton.component + '--' + skeleton.variant;
- }
-
- this.append(component, container);
-
- container = component.inner || component;
-
- this.class(component, skeleton.class);
- this.style(component, skeleton.style);
- this.attr(component, skeleton.attr);
- this.data(component, skeleton.data);
- this.properties(component, skeleton.properties);
- this.on(component, skeleton.on);
- this.text(container, skeleton.text);
-
- component.dispatchEvent(new CustomEvent('render'));
-
- if (this.events.hasOwnProperty('render')) {
- for (var i = 0, l = this.events['render'].length; i < l; i++) {
- this.events['render'][i](component, skeleton);
- }
- }
- }
-
- if (!component || component.render_children !== false) {
- for (var key in skeleton) {
- if (key !== 'parent' && skeleton[key] && skeleton[key].hasOwnProperty('component')) {
- skeleton[key].parent = skeleton;
-
- this.render(skeleton[key], container, false, key);
- }
- }
- }
-};
-/*--------------------------------------------------------------
->>> COLOR PICKER
---------------------------------------------------------------*/
-
-satus.components.colorPicker = function (skeleton) {
- var component = document.createElement('button'),
- component_value = document.createElement('span');
-
- component.className = 'satus-button';
- component_value.className = 'satus-color-picker__value';
-
- component.valueElement = component_value;
-
- component.addEventListener('render', function () {
- var data = satus.storage.get(this.storage) || this.skeleton.value || {
- rgb: [0, 0, 0]
- };
-
- this.valueElement.style.backgroundColor = 'rgb(' + data.rgb[0] + ',' + data.rgb[1] + ',' + data.rgb[2] + ')';
- });
-
- component.addEventListener('click', function () {
- satus.render({
- component: 'modal',
- class: 'satus-modal--color-picker',
- properties: {
- parentComponent: this
- },
-
- canvas: {
- component: 'canvas',
- on: {
- render: function () {
- var data = satus.storage.get(this.parentNode.parentNode.parentComponent.storage) || this.parentNode.parentNode.parentComponent.skeleton.value || {
- rgb: [0, 0, 0]
- },
- ctx = this.getContext('2d'),
- image = new Image();
-
- this.parentNode.data = data;
-
- image.addEventListener('load', function () {
- ctx.drawImage(this, 0, 0);
- });
-
- image.src = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNzAgMjcwIj48ZGVmcz48cmFkaWFsR3JhZGllbnQgaWQ9ImEiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iMCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMTMzIiBjbGFzcz0iSXJvV2hlZWxIdWUiPjxwYXRoIHN0cm9rZT0iaHNsKDI0MCwgMTAwJSwgNTAlKSIgZD0iTTIwMS40NzcgMTM2Ljc0YTY2LjUgNjYuNSAwIDAwLjAyMy0xLjc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQxLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjQzNyAxMzcuOWE2Ni41IDY2LjUgMCAwMC4wNTMtMS43NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI0MiwgMTAwJSwgNTAlKSIgZD0iTTIwMS4zNzYgMTM5LjA2YTY2LjUgNjYuNSAwIDAwLjA4My0xLjc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQzLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjI5NSAxNDAuMjE4YTY2LjUgNjYuNSAwIDAwLjExNC0xLjczOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI0NCwgMTAwJSwgNTAlKSIgZD0iTTIwMS4xOTQgMTQxLjM3NGE2Ni41IDY2LjUgMCAwMC4xNDQtMS43MzUiLz48cGF0aCBzdHJva2U9ImhzbCgyNDUsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuMDczIDE0Mi41MjhhNjYuNSA2Ni41IDAgMDAuMTc0LTEuNzMyIi8+PHBhdGggc3Ryb2tlPSJoc2woMjQ2LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjkzMSAxNDMuNjhhNjYuNSA2Ni41IDAgMDAuMjA1LTEuNzI5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQ3LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjc3IDE0NC44M2E2Ni41IDY2LjUgMCAwMC4yMzQtMS43MjYiLz48cGF0aCBzdHJva2U9ImhzbCgyNDgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDAuNTg4IDE0NS45NzZhNjYuNSA2Ni41IDAgMDAuMjY1LTEuNzIxIi8+PHBhdGggc3Ryb2tlPSJoc2woMjQ5LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjM4NiAxNDcuMTE5YTY2LjUgNjYuNSAwIDAwLjI5NS0xLjcxNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1MCwgMTAwJSwgNTAlKSIgZD0iTTIwMC4xNjUgMTQ4LjI1OGE2Ni41IDY2LjUgMCAwMC4zMjUtMS43MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1MSwgMTAwJSwgNTAlKSIgZD0iTTE5OS45MjQgMTQ5LjM5M2E2Ni41IDY2LjUgMCAwMC4zNTQtMS43MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuNjYzIDE1MC41MjRhNjYuNSA2Ni41IDAgMDAuMzg0LTEuNjk4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjUzLCAxMDAlLCA1MCUpIiBkPSJNMTk5LjM4MiAxNTEuNjVhNjYuNSA2Ni41IDAgMDAuNDE0LTEuNjkiLz48cGF0aCBzdHJva2U9ImhzbCgyNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuMDgxIDE1Mi43NzFhNjYuNSA2Ni41IDAgMDAuNDQ0LTEuNjgzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjU1LCAxMDAlLCA1MCUpIiBkPSJNMTk4Ljc2MiAxNTMuODg3YTY2LjUgNjYuNSAwIDAwLjQ3Mi0xLjY3NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1NiwgMTAwJSwgNTAlKSIgZD0iTTE5OC40MjIgMTU0Ljk5N2E2Ni41IDY2LjUgMCAwMC41MDItMS42NjciLz48cGF0aCBzdHJva2U9ImhzbCgyNTcsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguMDY0IDE1Ni4xYTY2LjUgNjYuNSAwIDAwLjUzLTEuNjU3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjU4LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjY4NiAxNTcuMTk4YTY2LjUgNjYuNSAwIDAwLjU2LTEuNjQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjU5LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjI4OSAxNTguMjg5YTY2LjUgNjYuNSAwIDAwLjU4OC0xLjYzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2MCwgMTAwJSwgNTAlKSIgZD0iTTE5Ni44NzMgMTU5LjM3MmE2Ni41IDY2LjUgMCAwMC42MTctMS42MjgiLz48cGF0aCBzdHJva2U9ImhzbCgyNjEsIDEwMCUsIDUwJSkiIGQ9Ik0xOTYuNDM4IDE2MC40NDhhNjYuNSA2Ni41IDAgMDAuNjQ1LTEuNjE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjYyLCAxMDAlLCA1MCUpIiBkPSJNMTk1Ljk4NCAxNjEuNTE3YTY2LjUgNjYuNSAwIDAwLjY3NC0xLjYwNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2MywgMTAwJSwgNTAlKSIgZD0iTTE5NS41MTIgMTYyLjU3N2E2Ni41IDY2LjUgMCAwMC43MDItMS41OTMiLz48cGF0aCBzdHJva2U9ImhzbCgyNjQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTUuMDIyIDE2My42MjlhNjYuNSA2Ni41IDAgMDAuNzI5LTEuNTgxIi8+PHBhdGggc3Ryb2tlPSJoc2woMjY1LCAxMDAlLCA1MCUpIiBkPSJNMTk0LjUxMyAxNjQuNjcyYTY2LjUgNjYuNSAwIDAwLjc1Ni0xLjU2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2NiwgMTAwJSwgNTAlKSIgZD0iTTE5My45ODYgMTY1LjcwNmE2Ni41IDY2LjUgMCAwMC43ODQtMS41NTQiLz48cGF0aCBzdHJva2U9ImhzbCgyNjcsIDEwMCUsIDUwJSkiIGQ9Ik0xOTMuNDQxIDE2Ni43MzFhNjYuNSA2Ni41IDAgMDAuODEtMS41NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2OCwgMTAwJSwgNTAlKSIgZD0iTTE5Mi44NzkgMTY3Ljc0NmE2Ni41IDY2LjUgMCAwMC44MzctMS41MjYiLz48cGF0aCBzdHJva2U9ImhzbCgyNjksIDEwMCUsIDUwJSkiIGQ9Ik0xOTIuMjk4IDE2OC43NTFhNjYuNSA2Ni41IDAgMDAuODY0LTEuNTExIi8+PHBhdGggc3Ryb2tlPSJoc2woMjcwLCAxMDAlLCA1MCUpIiBkPSJNMTkxLjcgMTY5Ljc0NmE2Ni41IDY2LjUgMCAwMC44OS0xLjQ5NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3MSwgMTAwJSwgNTAlKSIgZD0iTTE5MS4wODYgMTcwLjczYTY2LjUgNjYuNSAwIDAwLjkxNi0xLjQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjcyLCAxMDAlLCA1MCUpIiBkPSJNMTkwLjQ1MyAxNzEuNzA0YTY2LjUgNjYuNSAwIDAwLjk0Mi0xLjQ2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3MywgMTAwJSwgNTAlKSIgZD0iTTE4OS44MDQgMTcyLjY2NmE2Ni41IDY2LjUgMCAwMC45NjgtMS40NDgiLz48cGF0aCBzdHJva2U9ImhzbCgyNzQsIDEwMCUsIDUwJSkiIGQ9Ik0xODkuMTM5IDE3My42MTdhNjYuNSA2Ni41IDAgMDAuOTkyLTEuNDMiLz48cGF0aCBzdHJva2U9ImhzbCgyNzUsIDEwMCUsIDUwJSkiIGQ9Ik0xODguNDU2IDE3NC41NTZhNjYuNSA2Ni41IDAgMDAxLjAxOC0xLjQxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3NiwgMTAwJSwgNTAlKSIgZD0iTTE4Ny43NTggMTc1LjQ4M2E2Ni41IDY2LjUgMCAwMDEuMDQyLTEuMzk1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjc3LCAxMDAlLCA1MCUpIiBkPSJNMTg3LjA0MyAxNzYuMzk3YTY2LjUgNjYuNSAwIDAwMS4wNjYtMS4zNzYiLz48cGF0aCBzdHJva2U9ImhzbCgyNzgsIDEwMCUsIDUwJSkiIGQ9Ik0xODYuMzEzIDE3Ny4zYTY2LjUgNjYuNSAwIDAwMS4wOS0xLjM1OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3OSwgMTAwJSwgNTAlKSIgZD0iTTE4NS41NjcgMTc4LjE4OGE2Ni41IDY2LjUgMCAwMDEuMTEzLTEuMzM4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjgwLCAxMDAlLCA1MCUpIiBkPSJNMTg0LjgwNiAxNzkuMDY0YTY2LjUgNjYuNSAwIDAwMS4xMzYtMS4zMTkiLz48cGF0aCBzdHJva2U9ImhzbCgyODEsIDEwMCUsIDUwJSkiIGQ9Ik0xODQuMDI5IDE3OS45MjdhNjYuNSA2Ni41IDAgMDAxLjE2LTEuMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4MiwgMTAwJSwgNTAlKSIgZD0iTTE4My4yMzcgMTgwLjc3NmE2Ni41IDY2LjUgMCAwMDEuMTgyLTEuMjc5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjgzLCAxMDAlLCA1MCUpIiBkPSJNMTgyLjQzMSAxODEuNjFhNjYuNSA2Ni41IDAgMDAxLjIwNC0xLjI1NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4NCwgMTAwJSwgNTAlKSIgZD0iTTE4MS42MSAxODIuNDMxYTY2LjUgNjYuNSAwIDAwMS4yMjYtMS4yMzYiLz48cGF0aCBzdHJva2U9ImhzbCgyODUsIDEwMCUsIDUwJSkiIGQ9Ik0xODAuNzc2IDE4My4yMzdhNjYuNSA2Ni41IDAgMDAxLjI0Ny0xLjIxNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4NiwgMTAwJSwgNTAlKSIgZD0iTTE3OS45MjcgMTg0LjAyOWE2Ni41IDY2LjUgMCAwMDEuMjY4LTEuMTkzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjg3LCAxMDAlLCA1MCUpIiBkPSJNMTc5LjA2NCAxODQuODA2YTY2LjUgNjYuNSAwIDAwMS4yODktMS4xNzEiLz48cGF0aCBzdHJva2U9ImhzbCgyODgsIDEwMCUsIDUwJSkiIGQ9Ik0xNzguMTg4IDE4NS41NjdhNjYuNSA2Ni41IDAgMDAxLjMxLTEuMTQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjg5LCAxMDAlLCA1MCUpIiBkPSJNMTc3LjMgMTg2LjMxM2E2Ni41IDY2LjUgMCAwMDEuMzI4LTEuMTI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjkwLCAxMDAlLCA1MCUpIiBkPSJNMTc2LjM5NyAxODcuMDQzYTY2LjUgNjYuNSAwIDAwMS4zNDgtMS4xMDEiLz48cGF0aCBzdHJva2U9ImhzbCgyOTEsIDEwMCUsIDUwJSkiIGQ9Ik0xNzUuNDgzIDE4Ny43NThhNjYuNSA2Ni41IDAgMDAxLjM2Ny0xLjA3OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI5MiwgMTAwJSwgNTAlKSIgZD0iTTE3NC41NTYgMTg4LjQ1NmE2Ni41IDY2LjUgMCAwMDEuMzg1LTEuMDUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjkzLCAxMDAlLCA1MCUpIiBkPSJNMTczLjYxNyAxODkuMTM5YTY2LjUgNjYuNSAwIDAwMS40MDQtMS4wMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI5NCwgMTAwJSwgNTAlKSIgZD0iTTE3Mi42NjYgMTg5LjgwNGE2Ni41IDY2LjUgMCAwMDEuNDIyLTEuMDA0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk1LCAxMDAlLCA1MCUpIiBkPSJNMTcxLjcwNCAxOTAuNDUzYTY2LjUgNjYuNSAwIDAwMS40MzktLjk4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk2LCAxMDAlLCA1MCUpIiBkPSJNMTcwLjczIDE5MS4wODZhNjYuNSA2Ni41IDAgMDAxLjQ1Ni0uOTU1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk3LCAxMDAlLCA1MCUpIiBkPSJNMTY5Ljc0NiAxOTEuN2E2Ni41IDY2LjUgMCAwMDEuNDcyLS45MjgiLz48cGF0aCBzdHJva2U9ImhzbCgyOTgsIDEwMCUsIDUwJSkiIGQ9Ik0xNjguNzUxIDE5Mi4yOThhNjYuNSA2Ni41IDAgMDAxLjQ4OS0uOTAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjk5LCAxMDAlLCA1MCUpIiBkPSJNMTY3Ljc0NiAxOTIuODc5YTY2LjUgNjYuNSAwIDAwMS41MDQtLjg3NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwMCwgMTAwJSwgNTAlKSIgZD0iTTE2Ni43MzEgMTkzLjQ0MWE2Ni41IDY2LjUgMCAwMDEuNTE5LS44NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwMSwgMTAwJSwgNTAlKSIgZD0iTTE2NS43MDYgMTkzLjk4NmE2Ni41IDY2LjUgMCAwMDEuNTM0LS44MjQiLz48cGF0aCBzdHJva2U9ImhzbCgzMDIsIDEwMCUsIDUwJSkiIGQ9Ik0xNjQuNjcyIDE5NC41MTNhNjYuNSA2Ni41IDAgMDAxLjU0OC0uNzk3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzAzLCAxMDAlLCA1MCUpIiBkPSJNMTYzLjYyOSAxOTUuMDIyYTY2LjUgNjYuNSAwIDAwMS41NjEtLjc3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzA0LCAxMDAlLCA1MCUpIiBkPSJNMTYyLjU3NyAxOTUuNTEyYTY2LjUgNjYuNSAwIDAwMS41NzUtLjc0MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwNSwgMTAwJSwgNTAlKSIgZD0iTTE2MS41MTcgMTk1Ljk4NGE2Ni41IDY2LjUgMCAwMDEuNTg3LS43MTUiLz48cGF0aCBzdHJva2U9ImhzbCgzMDYsIDEwMCUsIDUwJSkiIGQ9Ik0xNjAuNDQ4IDE5Ni40MzhhNjYuNSA2Ni41IDAgMDAxLjYtLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwNywgMTAwJSwgNTAlKSIgZD0iTTE1OS4zNzIgMTk2Ljg3M2E2Ni41IDY2LjUgMCAwMDEuNjEyLS42NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwOCwgMTAwJSwgNTAlKSIgZD0iTTE1OC4yODkgMTk3LjI4OWE2Ni41IDY2LjUgMCAwMDEuNjIyLS42MzEiLz48cGF0aCBzdHJva2U9ImhzbCgzMDksIDEwMCUsIDUwJSkiIGQ9Ik0xNTcuMTk4IDE5Ny42ODZhNjYuNSA2Ni41IDAgMDAxLjYzMy0uNjAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzEwLCAxMDAlLCA1MCUpIiBkPSJNMTU2LjEgMTk4LjA2NGE2Ni41IDY2LjUgMCAwMDEuNjQ0LS41NzQiLz48cGF0aCBzdHJva2U9ImhzbCgzMTEsIDEwMCUsIDUwJSkiIGQ9Ik0xNTQuOTk3IDE5OC40MjJhNjYuNSA2Ni41IDAgMDAxLjY1My0uNTQ1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzEyLCAxMDAlLCA1MCUpIiBkPSJNMTUzLjg4NyAxOTguNzYyYTY2LjUgNjYuNSAwIDAwMS42NjMtLjUxNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxMywgMTAwJSwgNTAlKSIgZD0iTTE1Mi43NzEgMTk5LjA4MWE2Ni41IDY2LjUgMCAwMDEuNjcyLS40ODciLz48cGF0aCBzdHJva2U9ImhzbCgzMTQsIDEwMCUsIDUwJSkiIGQ9Ik0xNTEuNjUgMTk5LjM4MmE2Ni41IDY2LjUgMCAwMDEuNjgtLjQ1OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxNSwgMTAwJSwgNTAlKSIgZD0iTTE1MC41MjQgMTk5LjY2M2E2Ni41IDY2LjUgMCAwMDEuNjg3LS40MjkiLz48cGF0aCBzdHJva2U9ImhzbCgzMTYsIDEwMCUsIDUwJSkiIGQ9Ik0xNDkuMzkzIDE5OS45MjRhNjYuNSA2Ni41IDAgMDAxLjY5NS0uNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxNywgMTAwJSwgNTAlKSIgZD0iTTE0OC4yNTggMjAwLjE2NWE2Ni41IDY2LjUgMCAwMDEuNzAxLS4zNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxOCwgMTAwJSwgNTAlKSIgZD0iTTE0Ny4xMTkgMjAwLjM4NmE2Ni41IDY2LjUgMCAwMDEuNzA3LS4zNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxOSwgMTAwJSwgNTAlKSIgZD0iTTE0NS45NzYgMjAwLjU4OGE2Ni41IDY2LjUgMCAwMDEuNzEzLS4zMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMCwgMTAwJSwgNTAlKSIgZD0iTTE0NC44MyAyMDAuNzdhNjYuNSA2Ni41IDAgMDAxLjcxOC0uMjgiLz48cGF0aCBzdHJva2U9ImhzbCgzMjEsIDEwMCUsIDUwJSkiIGQ9Ik0xNDMuNjggMjAwLjkzMWE2Ni41IDY2LjUgMCAwMDEuNzIzLS4yNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMiwgMTAwJSwgNTAlKSIgZD0iTTE0Mi41MjggMjAxLjA3M2E2Ni41IDY2LjUgMCAwMDEuNzI3LS4yMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMywgMTAwJSwgNTAlKSIgZD0iTTE0MS4zNzQgMjAxLjE5NGE2Ni41IDY2LjUgMCAwMDEuNzMtLjE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI0LCAxMDAlLCA1MCUpIiBkPSJNMTQwLjIxOCAyMDEuMjk1YTY2LjUgNjYuNSAwIDAwMS43MzMtLjE2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI1LCAxMDAlLCA1MCUpIiBkPSJNMTM5LjA2IDIwMS4zNzZhNjYuNSA2Ni41IDAgMDAxLjczNi0uMTMiLz48cGF0aCBzdHJva2U9ImhzbCgzMjYsIDEwMCUsIDUwJSkiIGQ9Ik0xMzcuOSAyMDEuNDM3YTY2LjUgNjYuNSAwIDAwMS43MzktLjA5OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyNywgMTAwJSwgNTAlKSIgZD0iTTEzNi43NCAyMDEuNDc3YTY2LjUgNjYuNSAwIDAwMS43NC0uMDY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI4LCAxMDAlLCA1MCUpIiBkPSJNMTM1LjU4IDIwMS40OTdhNjYuNSA2Ni41IDAgMDAxLjc0LS4wMzgiLz48cGF0aCBzdHJva2U9ImhzbCgzMjksIDEwMCUsIDUwJSkiIGQ9Ik0xMzQuNDIgMjAxLjQ5N2E2Ni41IDY2LjUgMCAwMDEuNzQtLjAwNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMzMCwgMTAwJSwgNTAlKSIgZD0iTTEzMy4yNiAyMDEuNDc3YTY2LjUgNjYuNSAwIDAwMS43NC4wMjMiLz48cGF0aCBzdHJva2U9ImhzbCgzMzEsIDEwMCUsIDUwJSkiIGQ9Ik0xMzIuMSAyMDEuNDM3YTY2LjUgNjYuNSAwIDAwMS43NC4wNTMiLz48cGF0aCBzdHJva2U9ImhzbCgzMzIsIDEwMCUsIDUwJSkiIGQ9Ik0xMzAuOTQgMjAxLjM3NmE2Ni41IDY2LjUgMCAwMDEuNzQuMDgzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzMzLCAxMDAlLCA1MCUpIiBkPSJNMTI5Ljc4MiAyMDEuMjk1YTY2LjUgNjYuNSAwIDAwMS43MzguMTE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM0LCAxMDAlLCA1MCUpIiBkPSJNMTI4LjYyNiAyMDEuMTk0YTY2LjUgNjYuNSAwIDAwMS43MzUuMTQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM1LCAxMDAlLCA1MCUpIiBkPSJNMTI3LjQ3MiAyMDEuMDczYTY2LjUgNjYuNSAwIDAwMS43MzIuMTc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM2LCAxMDAlLCA1MCUpIiBkPSJNMTI2LjMyIDIwMC45MzFhNjYuNSA2Ni41IDAgMDAxLjcyOS4yMDUiLz48cGF0aCBzdHJva2U9ImhzbCgzMzcsIDEwMCUsIDUwJSkiIGQ9Ik0xMjUuMTcgMjAwLjc3YTY2LjUgNjYuNSAwIDAwMS43MjYuMjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM4LCAxMDAlLCA1MCUpIiBkPSJNMTI0LjAyNCAyMDAuNTg4YTY2LjUgNjYuNSAwIDAwMS43MjEuMjY1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM5LCAxMDAlLCA1MCUpIiBkPSJNMTIyLjg4MSAyMDAuMzg2YTY2LjUgNjYuNSAwIDAwMS43MTYuMjk1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQwLCAxMDAlLCA1MCUpIiBkPSJNMTIxLjc0MiAyMDAuMTY1YTY2LjUgNjYuNSAwIDAwMS43MS4zMjUiLz48cGF0aCBzdHJva2U9ImhzbCgzNDEsIDEwMCUsIDUwJSkiIGQ9Ik0xMjAuNjA3IDE5OS45MjRhNjYuNSA2Ni41IDAgMDAxLjcwNC4zNTQiLz48cGF0aCBzdHJva2U9ImhzbCgzNDIsIDEwMCUsIDUwJSkiIGQ9Ik0xMTkuNDc2IDE5OS42NjNhNjYuNSA2Ni41IDAgMDAxLjY5OC4zODQiLz48cGF0aCBzdHJva2U9ImhzbCgzNDMsIDEwMCUsIDUwJSkiIGQ9Ik0xMTguMzUgMTk5LjM4MmE2Ni41IDY2LjUgMCAwMDEuNjkuNDE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQ0LCAxMDAlLCA1MCUpIiBkPSJNMTE3LjIyOSAxOTkuMDgxYTY2LjUgNjYuNSAwIDAwMS42ODMuNDQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQ1LCAxMDAlLCA1MCUpIiBkPSJNMTE2LjExMyAxOTguNzYyYTY2LjUgNjYuNSAwIDAwMS42NzYuNDcyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ2LCAxMDAlLCA1MCUpIiBkPSJNMTE1LjAwMyAxOTguNDIyYTY2LjUgNjYuNSAwIDAwMS42NjcuNTAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ3LCAxMDAlLCA1MCUpIiBkPSJNMTEzLjkgMTk4LjA2NGE2Ni41IDY2LjUgMCAwMDEuNjU3LjUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ4LCAxMDAlLCA1MCUpIiBkPSJNMTEyLjgwMiAxOTcuNjg2YTY2LjUgNjYuNSAwIDAwMS42NDguNTYiLz48cGF0aCBzdHJva2U9ImhzbCgzNDksIDEwMCUsIDUwJSkiIGQ9Ik0xMTEuNzExIDE5Ny4yODlhNjYuNSA2Ni41IDAgMDAxLjYzOS41ODgiLz48cGF0aCBzdHJva2U9ImhzbCgzNTAsIDEwMCUsIDUwJSkiIGQ9Ik0xMTAuNjI4IDE5Ni44NzNhNjYuNSA2Ni41IDAgMDAxLjYyOC42MTciLz48cGF0aCBzdHJva2U9ImhzbCgzNTEsIDEwMCUsIDUwJSkiIGQ9Ik0xMDkuNTUyIDE5Ni40MzhhNjYuNSA2Ni41IDAgMDAxLjYxNy42NDUiLz48cGF0aCBzdHJva2U9ImhzbCgzNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xMDguNDgzIDE5NS45ODRhNjYuNSA2Ni41IDAgMDAxLjYwNi42NzQiLz48cGF0aCBzdHJva2U9ImhzbCgzNTMsIDEwMCUsIDUwJSkiIGQ9Ik0xMDcuNDIzIDE5NS41MTJhNjYuNSA2Ni41IDAgMDAxLjU5My43MDIiLz48cGF0aCBzdHJva2U9ImhzbCgzNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xMDYuMzcxIDE5NS4wMjJhNjYuNSA2Ni41IDAgMDAxLjU4MS43MjkiLz48cGF0aCBzdHJva2U9ImhzbCgzNTUsIDEwMCUsIDUwJSkiIGQ9Ik0xMDUuMzI4IDE5NC41MTNhNjYuNSA2Ni41IDAgMDAxLjU2OC43NTYiLz48cGF0aCBzdHJva2U9ImhzbCgzNTYsIDEwMCUsIDUwJSkiIGQ9Ik0xMDQuMjk0IDE5My45ODZhNjYuNSA2Ni41IDAgMDAxLjU1NC43ODQiLz48cGF0aCBzdHJva2U9ImhzbCgzNTcsIDEwMCUsIDUwJSkiIGQ9Ik0xMDMuMjY5IDE5My40NDFhNjYuNSA2Ni41IDAgMDAxLjU0LjgxIi8+PHBhdGggc3Ryb2tlPSJoc2woMzU4LCAxMDAlLCA1MCUpIiBkPSJNMTAyLjI1NCAxOTIuODc5YTY2LjUgNjYuNSAwIDAwMS41MjYuODM3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzU5LCAxMDAlLCA1MCUpIiBkPSJNMTAxLjI0OSAxOTIuMjk4YTY2LjUgNjYuNSAwIDAwMS41MTEuODY0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMCwgMTAwJSwgNTAlKSIgZD0iTTEwMC4yNTQgMTkxLjdhNjYuNSA2Ni41IDAgMDAxLjQ5Ni44OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEsIDEwMCUsIDUwJSkiIGQ9Ik05OS4yNyAxOTEuMDg2YTY2LjUgNjYuNSAwIDAwMS40OC45MTYiLz48cGF0aCBzdHJva2U9ImhzbCgyLCAxMDAlLCA1MCUpIiBkPSJNOTguMjk2IDE5MC40NTNhNjYuNSA2Ni41IDAgMDAxLjQ2NC45NDIiLz48cGF0aCBzdHJva2U9ImhzbCgzLCAxMDAlLCA1MCUpIiBkPSJNOTcuMzM0IDE4OS44MDRhNjYuNSA2Ni41IDAgMDAxLjQ0OC45NjgiLz48cGF0aCBzdHJva2U9ImhzbCg0LCAxMDAlLCA1MCUpIiBkPSJNOTYuMzgzIDE4OS4xMzlhNjYuNSA2Ni41IDAgMDAxLjQzLjk5MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDUsIDEwMCUsIDUwJSkiIGQ9Ik05NS40NDQgMTg4LjQ1NmE2Ni41IDY2LjUgMCAwMDEuNDEzIDEuMDE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woNiwgMTAwJSwgNTAlKSIgZD0iTTk0LjUxNyAxODcuNzU4YTY2LjUgNjYuNSAwIDAwMS4zOTUgMS4wNDIiLz48cGF0aCBzdHJva2U9ImhzbCg3LCAxMDAlLCA1MCUpIiBkPSJNOTMuNjAzIDE4Ny4wNDNhNjYuNSA2Ni41IDAgMDAxLjM3NiAxLjA2NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDgsIDEwMCUsIDUwJSkiIGQ9Ik05Mi43IDE4Ni4zMTNhNjYuNSA2Ni41IDAgMDAxLjM1OSAxLjA5Ii8+PHBhdGggc3Ryb2tlPSJoc2woOSwgMTAwJSwgNTAlKSIgZD0iTTkxLjgxMiAxODUuNTY3YTY2LjUgNjYuNSAwIDAwMS4zMzggMS4xMTMiLz48cGF0aCBzdHJva2U9ImhzbCgxMCwgMTAwJSwgNTAlKSIgZD0iTTkwLjkzNiAxODQuODA2YTY2LjUgNjYuNSAwIDAwMS4zMTkgMS4xMzYiLz48cGF0aCBzdHJva2U9ImhzbCgxMSwgMTAwJSwgNTAlKSIgZD0iTTkwLjA3MyAxODQuMDI5YTY2LjUgNjYuNSAwIDAwMS4zIDEuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxMiwgMTAwJSwgNTAlKSIgZD0iTTg5LjIyNCAxODMuMjM3YTY2LjUgNjYuNSAwIDAwMS4yNzkgMS4xODIiLz48cGF0aCBzdHJva2U9ImhzbCgxMywgMTAwJSwgNTAlKSIgZD0iTTg4LjM5IDE4Mi40MzFhNjYuNSA2Ni41IDAgMDAxLjI1NyAxLjIwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE0LCAxMDAlLCA1MCUpIiBkPSJNODcuNTY5IDE4MS42MWE2Ni41IDY2LjUgMCAwMDEuMjM2IDEuMjI2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTUsIDEwMCUsIDUwJSkiIGQ9Ik04Ni43NjMgMTgwLjc3NmE2Ni41IDY2LjUgMCAwMDEuMjE0IDEuMjQ3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTYsIDEwMCUsIDUwJSkiIGQ9Ik04NS45NzEgMTc5LjkyN2E2Ni41IDY2LjUgMCAwMDEuMTkzIDEuMjY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTcsIDEwMCUsIDUwJSkiIGQ9Ik04NS4xOTQgMTc5LjA2NGE2Ni41IDY2LjUgMCAwMDEuMTcxIDEuMjg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTgsIDEwMCUsIDUwJSkiIGQ9Ik04NC40MzMgMTc4LjE4OGE2Ni41IDY2LjUgMCAwMDEuMTQ4IDEuMzEiLz48cGF0aCBzdHJva2U9ImhzbCgxOSwgMTAwJSwgNTAlKSIgZD0iTTgzLjY4NyAxNzcuM2E2Ni41IDY2LjUgMCAwMDEuMTI1IDEuMzI4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjAsIDEwMCUsIDUwJSkiIGQ9Ik04Mi45NTcgMTc2LjM5N2E2Ni41IDY2LjUgMCAwMDEuMTAxIDEuMzQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjEsIDEwMCUsIDUwJSkiIGQ9Ik04Mi4yNDIgMTc1LjQ4M2E2Ni41IDY2LjUgMCAwMDEuMDc4IDEuMzY3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjIsIDEwMCUsIDUwJSkiIGQ9Ik04MS41NDQgMTc0LjU1NmE2Ni41IDY2LjUgMCAwMDEuMDUzIDEuMzg1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjMsIDEwMCUsIDUwJSkiIGQ9Ik04MC44NjEgMTczLjYxN2E2Ni41IDY2LjUgMCAwMDEuMDMgMS40MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyNCwgMTAwJSwgNTAlKSIgZD0iTTgwLjE5NiAxNzIuNjY2YTY2LjUgNjYuNSAwIDAwMS4wMDQgMS40MjIiLz48cGF0aCBzdHJva2U9ImhzbCgyNSwgMTAwJSwgNTAlKSIgZD0iTTc5LjU0NyAxNzEuNzA0YTY2LjUgNjYuNSAwIDAwLjk4IDEuNDM5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjYsIDEwMCUsIDUwJSkiIGQ9Ik03OC45MTQgMTcwLjczYTY2LjUgNjYuNSAwIDAwLjk1NSAxLjQ1NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3LCAxMDAlLCA1MCUpIiBkPSJNNzguMyAxNjkuNzQ2YTY2LjUgNjYuNSAwIDAwLjkyOCAxLjQ3MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4LCAxMDAlLCA1MCUpIiBkPSJNNzcuNzAyIDE2OC43NTFhNjYuNSA2Ni41IDAgMDAuOTAzIDEuNDg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjksIDEwMCUsIDUwJSkiIGQ9Ik03Ny4xMjEgMTY3Ljc0NmE2Ni41IDY2LjUgMCAwMC44NzcgMS41MDQiLz48cGF0aCBzdHJva2U9ImhzbCgzMCwgMTAwJSwgNTAlKSIgZD0iTTc2LjU1OSAxNjYuNzMxYTY2LjUgNjYuNSAwIDAwLjg1IDEuNTE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzEsIDEwMCUsIDUwJSkiIGQ9Ik03Ni4wMTQgMTY1LjcwNmE2Ni41IDY2LjUgMCAwMC44MjQgMS41MzQiLz48cGF0aCBzdHJva2U9ImhzbCgzMiwgMTAwJSwgNTAlKSIgZD0iTTc1LjQ4NyAxNjQuNjcyYTY2LjUgNjYuNSAwIDAwLjc5NyAxLjU0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMzLCAxMDAlLCA1MCUpIiBkPSJNNzQuOTc4IDE2My42MjlhNjYuNSA2Ni41IDAgMDAuNzcgMS41NjEiLz48cGF0aCBzdHJva2U9ImhzbCgzNCwgMTAwJSwgNTAlKSIgZD0iTTc0LjQ4OCAxNjIuNTc3YTY2LjUgNjYuNSAwIDAwLjc0MiAxLjU3NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDM1LCAxMDAlLCA1MCUpIiBkPSJNNzQuMDE2IDE2MS41MTdhNjYuNSA2Ni41IDAgMDAuNzE1IDEuNTg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzYsIDEwMCUsIDUwJSkiIGQ9Ik03My41NjIgMTYwLjQ0OGE2Ni41IDY2LjUgMCAwMC42ODcgMS42Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzcsIDEwMCUsIDUwJSkiIGQ9Ik03My4xMjcgMTU5LjM3MmE2Ni41IDY2LjUgMCAwMC42NiAxLjYxMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDM4LCAxMDAlLCA1MCUpIiBkPSJNNzIuNzExIDE1OC4yODlhNjYuNSA2Ni41IDAgMDAuNjMxIDEuNjIyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzksIDEwMCUsIDUwJSkiIGQ9Ik03Mi4zMTQgMTU3LjE5OGE2Ni41IDY2LjUgMCAwMC42MDMgMS42MzMiLz48cGF0aCBzdHJva2U9ImhzbCg0MCwgMTAwJSwgNTAlKSIgZD0iTTcxLjkzNiAxNTYuMWE2Ni41IDY2LjUgMCAwMC41NzQgMS42NDQiLz48cGF0aCBzdHJva2U9ImhzbCg0MSwgMTAwJSwgNTAlKSIgZD0iTTcxLjU3OCAxNTQuOTk3YTY2LjUgNjYuNSAwIDAwLjU0NSAxLjY1MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDQyLCAxMDAlLCA1MCUpIiBkPSJNNzEuMjM4IDE1My44ODdhNjYuNSA2Ni41IDAgMDAuNTE3IDEuNjYzIi8+PHBhdGggc3Ryb2tlPSJoc2woNDMsIDEwMCUsIDUwJSkiIGQ9Ik03MC45MTkgMTUyLjc3MWE2Ni41IDY2LjUgMCAwMC40ODcgMS42NzIiLz48cGF0aCBzdHJva2U9ImhzbCg0NCwgMTAwJSwgNTAlKSIgZD0iTTcwLjYxOCAxNTEuNjVhNjYuNSA2Ni41IDAgMDAuNDU4IDEuNjgiLz48cGF0aCBzdHJva2U9ImhzbCg0NSwgMTAwJSwgNTAlKSIgZD0iTTcwLjMzNyAxNTAuNTI0YTY2LjUgNjYuNSAwIDAwLjQyOSAxLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDQ2LCAxMDAlLCA1MCUpIiBkPSJNNzAuMDc2IDE0OS4zOTNhNjYuNSA2Ni41IDAgMDAuNCAxLjY5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDQ3LCAxMDAlLCA1MCUpIiBkPSJNNjkuODM1IDE0OC4yNThhNjYuNSA2Ni41IDAgMDAuMzcgMS43MDEiLz48cGF0aCBzdHJva2U9ImhzbCg0OCwgMTAwJSwgNTAlKSIgZD0iTTY5LjYxNCAxNDcuMTE5YTY2LjUgNjYuNSAwIDAwLjM0IDEuNzA3Ii8+PHBhdGggc3Ryb2tlPSJoc2woNDksIDEwMCUsIDUwJSkiIGQ9Ik02OS40MTIgMTQ1Ljk3NmE2Ni41IDY2LjUgMCAwMC4zMSAxLjcxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDUwLCAxMDAlLCA1MCUpIiBkPSJNNjkuMjMgMTQ0LjgzYTY2LjUgNjYuNSAwIDAwLjI4IDEuNzE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woNTEsIDEwMCUsIDUwJSkiIGQ9Ik02OS4wNjkgMTQzLjY4YTY2LjUgNjYuNSAwIDAwLjI1IDEuNzIzIi8+PHBhdGggc3Ryb2tlPSJoc2woNTIsIDEwMCUsIDUwJSkiIGQ9Ik02OC45MjcgMTQyLjUyOGE2Ni41IDY2LjUgMCAwMC4yMiAxLjcyNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDUzLCAxMDAlLCA1MCUpIiBkPSJNNjguODA2IDE0MS4zNzRhNjYuNSA2Ni41IDAgMDAuMTkgMS43MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDU0LCAxMDAlLCA1MCUpIiBkPSJNNjguNzA1IDE0MC4yMThhNjYuNSA2Ni41IDAgMDAuMTYgMS43MzMiLz48cGF0aCBzdHJva2U9ImhzbCg1NSwgMTAwJSwgNTAlKSIgZD0iTTY4LjYyNCAxMzkuMDZhNjYuNSA2Ni41IDAgMDAuMTMgMS43MzYiLz48cGF0aCBzdHJva2U9ImhzbCg1NiwgMTAwJSwgNTAlKSIgZD0iTTY4LjU2MyAxMzcuOWE2Ni41IDY2LjUgMCAwMC4wOTkgMS43MzkiLz48cGF0aCBzdHJva2U9ImhzbCg1NywgMTAwJSwgNTAlKSIgZD0iTTY4LjUyMyAxMzYuNzRhNjYuNSA2Ni41IDAgMDAuMDY4IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg1OCwgMTAwJSwgNTAlKSIgZD0iTTY4LjUwMyAxMzUuNThhNjYuNSA2Ni41IDAgMDAuMDM4IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg1OSwgMTAwJSwgNTAlKSIgZD0iTTY4LjUwMyAxMzQuNDJhNjYuNSA2Ni41IDAgMDAuMDA3IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg2MCwgMTAwJSwgNTAlKSIgZD0iTTY4LjUyMyAxMzMuMjZBNjYuNSA2Ni41IDAgMDA2OC41IDEzNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDYxLCAxMDAlLCA1MCUpIiBkPSJNNjguNTYzIDEzMi4xYTY2LjUgNjYuNSAwIDAwLS4wNTMgMS43NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDYyLCAxMDAlLCA1MCUpIiBkPSJNNjguNjI0IDEzMC45NGE2Ni41IDY2LjUgMCAwMC0uMDgzIDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg2MywgMTAwJSwgNTAlKSIgZD0iTTY4LjcwNSAxMjkuNzgyYTY2LjUgNjYuNSAwIDAwLS4xMTQgMS43MzgiLz48cGF0aCBzdHJva2U9ImhzbCg2NCwgMTAwJSwgNTAlKSIgZD0iTTY4LjgwNiAxMjguNjI2YTY2LjUgNjYuNSAwIDAwLS4xNDQgMS43MzUiLz48cGF0aCBzdHJva2U9ImhzbCg2NSwgMTAwJSwgNTAlKSIgZD0iTTY4LjkyNyAxMjcuNDcyYTY2LjUgNjYuNSAwIDAwLS4xNzQgMS43MzIiLz48cGF0aCBzdHJva2U9ImhzbCg2NiwgMTAwJSwgNTAlKSIgZD0iTTY5LjA2OSAxMjYuMzJhNjYuNSA2Ni41IDAgMDAtLjIwNSAxLjcyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDY3LCAxMDAlLCA1MCUpIiBkPSJNNjkuMjMgMTI1LjE3YTY2LjUgNjYuNSAwIDAwLS4yMzQgMS43MjYiLz48cGF0aCBzdHJva2U9ImhzbCg2OCwgMTAwJSwgNTAlKSIgZD0iTTY5LjQxMiAxMjQuMDI0YTY2LjUgNjYuNSAwIDAwLS4yNjUgMS43MjEiLz48cGF0aCBzdHJva2U9ImhzbCg2OSwgMTAwJSwgNTAlKSIgZD0iTTY5LjYxNCAxMjIuODgxYTY2LjUgNjYuNSAwIDAwLS4yOTUgMS43MTYiLz48cGF0aCBzdHJva2U9ImhzbCg3MCwgMTAwJSwgNTAlKSIgZD0iTTY5LjgzNSAxMjEuNzQyYTY2LjUgNjYuNSAwIDAwLS4zMjUgMS43MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDcxLCAxMDAlLCA1MCUpIiBkPSJNNzAuMDc2IDEyMC42MDdhNjYuNSA2Ni41IDAgMDAtLjM1NCAxLjcwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDcyLCAxMDAlLCA1MCUpIiBkPSJNNzAuMzM3IDExOS40NzZhNjYuNSA2Ni41IDAgMDAtLjM4NCAxLjY5OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDczLCAxMDAlLCA1MCUpIiBkPSJNNzAuNjE4IDExOC4zNWE2Ni41IDY2LjUgMCAwMC0uNDE0IDEuNjkiLz48cGF0aCBzdHJva2U9ImhzbCg3NCwgMTAwJSwgNTAlKSIgZD0iTTcwLjkxOSAxMTcuMjI5YTY2LjUgNjYuNSAwIDAwLS40NDQgMS42ODMiLz48cGF0aCBzdHJva2U9ImhzbCg3NSwgMTAwJSwgNTAlKSIgZD0iTTcxLjIzOCAxMTYuMTEzYTY2LjUgNjYuNSAwIDAwLS40NzIgMS42NzYiLz48cGF0aCBzdHJva2U9ImhzbCg3NiwgMTAwJSwgNTAlKSIgZD0iTTcxLjU3OCAxMTUuMDAzYTY2LjUgNjYuNSAwIDAwLS41MDIgMS42NjciLz48cGF0aCBzdHJva2U9ImhzbCg3NywgMTAwJSwgNTAlKSIgZD0iTTcxLjkzNiAxMTMuOWE2Ni41IDY2LjUgMCAwMC0uNTMgMS42NTciLz48cGF0aCBzdHJva2U9ImhzbCg3OCwgMTAwJSwgNTAlKSIgZD0iTTcyLjMxNCAxMTIuODAyYTY2LjUgNjYuNSAwIDAwLS41NiAxLjY0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDc5LCAxMDAlLCA1MCUpIiBkPSJNNzIuNzExIDExMS43MTFhNjYuNSA2Ni41IDAgMDAtLjU4OCAxLjYzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDgwLCAxMDAlLCA1MCUpIiBkPSJNNzMuMTI3IDExMC42MjhhNjYuNSA2Ni41IDAgMDAtLjYxNyAxLjYyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDgxLCAxMDAlLCA1MCUpIiBkPSJNNzMuNTYyIDEwOS41NTJhNjYuNSA2Ni41IDAgMDAtLjY0NSAxLjYxNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDgyLCAxMDAlLCA1MCUpIiBkPSJNNzQuMDE2IDEwOC40ODNhNjYuNSA2Ni41IDAgMDAtLjY3NCAxLjYwNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDgzLCAxMDAlLCA1MCUpIiBkPSJNNzQuNDg4IDEwNy40MjNhNjYuNSA2Ni41IDAgMDAtLjcwMiAxLjU5MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDg0LCAxMDAlLCA1MCUpIiBkPSJNNzQuOTc4IDEwNi4zNzFhNjYuNSA2Ni41IDAgMDAtLjcyOSAxLjU4MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDg1LCAxMDAlLCA1MCUpIiBkPSJNNzUuNDg3IDEwNS4zMjhhNjYuNSA2Ni41IDAgMDAtLjc1NiAxLjU2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDg2LCAxMDAlLCA1MCUpIiBkPSJNNzYuMDE0IDEwNC4yOTRhNjYuNSA2Ni41IDAgMDAtLjc4NCAxLjU1NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDg3LCAxMDAlLCA1MCUpIiBkPSJNNzYuNTU5IDEwMy4yNjlhNjYuNSA2Ni41IDAgMDAtLjgxIDEuNTQiLz48cGF0aCBzdHJva2U9ImhzbCg4OCwgMTAwJSwgNTAlKSIgZD0iTTc3LjEyMSAxMDIuMjU0YTY2LjUgNjYuNSAwIDAwLS44MzcgMS41MjYiLz48cGF0aCBzdHJva2U9ImhzbCg4OSwgMTAwJSwgNTAlKSIgZD0iTTc3LjcwMiAxMDEuMjQ5YTY2LjUgNjYuNSAwIDAwLS44NjQgMS41MTEiLz48cGF0aCBzdHJva2U9ImhzbCg5MCwgMTAwJSwgNTAlKSIgZD0iTTc4LjMgMTAwLjI1NGE2Ni41IDY2LjUgMCAwMC0uODkgMS40OTYiLz48cGF0aCBzdHJva2U9ImhzbCg5MSwgMTAwJSwgNTAlKSIgZD0iTTc4LjkxNCA5OS4yN2E2Ni41IDY2LjUgMCAwMC0uOTE2IDEuNDgiLz48cGF0aCBzdHJva2U9ImhzbCg5MiwgMTAwJSwgNTAlKSIgZD0iTTc5LjU0NyA5OC4yOTZhNjYuNSA2Ni41IDAgMDAtLjk0MiAxLjQ2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDkzLCAxMDAlLCA1MCUpIiBkPSJNODAuMTk2IDk3LjMzNGE2Ni41IDY2LjUgMCAwMC0uOTY4IDEuNDQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woOTQsIDEwMCUsIDUwJSkiIGQ9Ik04MC44NjEgOTYuMzgzYTY2LjUgNjYuNSAwIDAwLS45OTIgMS40MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDk1LCAxMDAlLCA1MCUpIiBkPSJNODEuNTQ0IDk1LjQ0NGE2Ni41IDY2LjUgMCAwMC0xLjAxOCAxLjQxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDk2LCAxMDAlLCA1MCUpIiBkPSJNODIuMjQyIDk0LjUxN2E2Ni41IDY2LjUgMCAwMC0xLjA0MiAxLjM5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDk3LCAxMDAlLCA1MCUpIiBkPSJNODIuOTU3IDkzLjYwM2E2Ni41IDY2LjUgMCAwMC0xLjA2NiAxLjM3NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDk4LCAxMDAlLCA1MCUpIiBkPSJNODMuNjg3IDkyLjdhNjYuNSA2Ni41IDAgMDAtMS4wOSAxLjM1OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDk5LCAxMDAlLCA1MCUpIiBkPSJNODQuNDMzIDkxLjgxMmE2Ni41IDY2LjUgMCAwMC0xLjExMyAxLjMzOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwMCwgMTAwJSwgNTAlKSIgZD0iTTg1LjE5NCA5MC45MzZhNjYuNSA2Ni41IDAgMDAtMS4xMzYgMS4zMTkiLz48cGF0aCBzdHJva2U9ImhzbCgxMDEsIDEwMCUsIDUwJSkiIGQ9Ik04NS45NzEgOTAuMDczYTY2LjUgNjYuNSAwIDAwLTEuMTYgMS4zIi8+PHBhdGggc3Ryb2tlPSJoc2woMTAyLCAxMDAlLCA1MCUpIiBkPSJNODYuNzYzIDg5LjIyNGE2Ni41IDY2LjUgMCAwMC0xLjE4MiAxLjI3OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwMywgMTAwJSwgNTAlKSIgZD0iTTg3LjU2OSA4OC4zOWE2Ni41IDY2LjUgMCAwMC0xLjIwNCAxLjI1NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwNCwgMTAwJSwgNTAlKSIgZD0iTTg4LjM5IDg3LjU2OWE2Ni41IDY2LjUgMCAwMC0xLjIyNiAxLjIzNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwNSwgMTAwJSwgNTAlKSIgZD0iTTg5LjIyNCA4Ni43NjNhNjYuNSA2Ni41IDAgMDAtMS4yNDcgMS4yMTQiLz48cGF0aCBzdHJva2U9ImhzbCgxMDYsIDEwMCUsIDUwJSkiIGQ9Ik05MC4wNzMgODUuOTcxYTY2LjUgNjYuNSAwIDAwLTEuMjY4IDEuMTkzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTA3LCAxMDAlLCA1MCUpIiBkPSJNOTAuOTM2IDg1LjE5NGE2Ni41IDY2LjUgMCAwMC0xLjI4OSAxLjE3MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwOCwgMTAwJSwgNTAlKSIgZD0iTTkxLjgxMiA4NC40MzNhNjYuNSA2Ni41IDAgMDAtMS4zMSAxLjE0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwOSwgMTAwJSwgNTAlKSIgZD0iTTkyLjcgODMuNjg3YTY2LjUgNjYuNSAwIDAwLTEuMzI4IDEuMTI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTEwLCAxMDAlLCA1MCUpIiBkPSJNOTMuNjAzIDgyLjk1N2E2Ni41IDY2LjUgMCAwMC0xLjM0OCAxLjEwMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDExMSwgMTAwJSwgNTAlKSIgZD0iTTk0LjUxNyA4Mi4yNDJhNjYuNSA2Ni41IDAgMDAtMS4zNjcgMS4wNzgiLz48cGF0aCBzdHJva2U9ImhzbCgxMTIsIDEwMCUsIDUwJSkiIGQ9Ik05NS40NDQgODEuNTQ0YTY2LjUgNjYuNSAwIDAwLTEuMzg1IDEuMDUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTEzLCAxMDAlLCA1MCUpIiBkPSJNOTYuMzgzIDgwLjg2MWE2Ni41IDY2LjUgMCAwMC0xLjQwNCAxLjAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTE0LCAxMDAlLCA1MCUpIiBkPSJNOTcuMzM0IDgwLjE5NmE2Ni41IDY2LjUgMCAwMC0xLjQyMiAxLjAwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDExNSwgMTAwJSwgNTAlKSIgZD0iTTk4LjI5NiA3OS41NDdhNjYuNSA2Ni41IDAgMDAtMS40MzkuOTgiLz48cGF0aCBzdHJva2U9ImhzbCgxMTYsIDEwMCUsIDUwJSkiIGQ9Ik05OS4yNyA3OC45MTRhNjYuNSA2Ni41IDAgMDAtMS40NTYuOTU1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTE3LCAxMDAlLCA1MCUpIiBkPSJNMTAwLjI1NCA3OC4zYTY2LjUgNjYuNSAwIDAwLTEuNDcyLjkyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDExOCwgMTAwJSwgNTAlKSIgZD0iTTEwMS4yNDkgNzcuNzAyYTY2LjUgNjYuNSAwIDAwLTEuNDg5LjkwMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDExOSwgMTAwJSwgNTAlKSIgZD0iTTEwMi4yNTQgNzcuMTIxYTY2LjUgNjYuNSAwIDAwLTEuNTA0Ljg3NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEyMCwgMTAwJSwgNTAlKSIgZD0iTTEwMy4yNjkgNzYuNTU5YTY2LjUgNjYuNSAwIDAwLTEuNTE5Ljg1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIxLCAxMDAlLCA1MCUpIiBkPSJNMTA0LjI5NCA3Ni4wMTRhNjYuNSA2Ni41IDAgMDAtMS41MzQuODI0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIyLCAxMDAlLCA1MCUpIiBkPSJNMTA1LjMyOCA3NS40ODdhNjYuNSA2Ni41IDAgMDAtMS41NDguNzk3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIzLCAxMDAlLCA1MCUpIiBkPSJNMTA2LjM3MSA3NC45NzhhNjYuNSA2Ni41IDAgMDAtMS41NjEuNzciLz48cGF0aCBzdHJva2U9ImhzbCgxMjQsIDEwMCUsIDUwJSkiIGQ9Ik0xMDcuNDIzIDc0LjQ4OGE2Ni41IDY2LjUgMCAwMC0xLjU3NS43NDIiLz48cGF0aCBzdHJva2U9ImhzbCgxMjUsIDEwMCUsIDUwJSkiIGQ9Ik0xMDguNDgzIDc0LjAxNmE2Ni41IDY2LjUgMCAwMC0xLjU4Ny43MTUiLz48cGF0aCBzdHJva2U9ImhzbCgxMjYsIDEwMCUsIDUwJSkiIGQ9Ik0xMDkuNTUyIDczLjU2MmE2Ni41IDY2LjUgMCAwMC0xLjYuNjg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTI3LCAxMDAlLCA1MCUpIiBkPSJNMTEwLjYyOCA3My4xMjdhNjYuNSA2Ni41IDAgMDAtMS42MTIuNjYiLz48cGF0aCBzdHJva2U9ImhzbCgxMjgsIDEwMCUsIDUwJSkiIGQ9Ik0xMTEuNzExIDcyLjcxMWE2Ni41IDY2LjUgMCAwMC0xLjYyMi42MzEiLz48cGF0aCBzdHJva2U9ImhzbCgxMjksIDEwMCUsIDUwJSkiIGQ9Ik0xMTIuODAyIDcyLjMxNGE2Ni41IDY2LjUgMCAwMC0xLjYzMy42MDMiLz48cGF0aCBzdHJva2U9ImhzbCgxMzAsIDEwMCUsIDUwJSkiIGQ9Ik0xMTMuOSA3MS45MzZhNjYuNSA2Ni41IDAgMDAtMS42NDQuNTc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMxLCAxMDAlLCA1MCUpIiBkPSJNMTE1LjAwMyA3MS41NzhhNjYuNSA2Ni41IDAgMDAtMS42NTMuNTQ1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMyLCAxMDAlLCA1MCUpIiBkPSJNMTE2LjExMyA3MS4yMzhhNjYuNSA2Ni41IDAgMDAtMS42NjMuNTE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMzLCAxMDAlLCA1MCUpIiBkPSJNMTE3LjIyOSA3MC45MTlhNjYuNSA2Ni41IDAgMDAtMS42NzIuNDg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTM0LCAxMDAlLCA1MCUpIiBkPSJNMTE4LjM1IDcwLjYxOGE2Ni41IDY2LjUgMCAwMC0xLjY4LjQ1OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzNSwgMTAwJSwgNTAlKSIgZD0iTTExOS40NzYgNzAuMzM3YTY2LjUgNjYuNSAwIDAwLTEuNjg3LjQyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzNiwgMTAwJSwgNTAlKSIgZD0iTTEyMC42MDcgNzAuMDc2YTY2LjUgNjYuNSAwIDAwLTEuNjk1LjQiLz48cGF0aCBzdHJva2U9ImhzbCgxMzcsIDEwMCUsIDUwJSkiIGQ9Ik0xMjEuNzQyIDY5LjgzNWE2Ni41IDY2LjUgMCAwMC0xLjcwMS4zNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzOCwgMTAwJSwgNTAlKSIgZD0iTTEyMi44ODEgNjkuNjE0YTY2LjUgNjYuNSAwIDAwLTEuNzA3LjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTM5LCAxMDAlLCA1MCUpIiBkPSJNMTI0LjAyNCA2OS40MTJhNjYuNSA2Ni41IDAgMDAtMS43MTMuMzEiLz48cGF0aCBzdHJva2U9ImhzbCgxNDAsIDEwMCUsIDUwJSkiIGQ9Ik0xMjUuMTcgNjkuMjNhNjYuNSA2Ni41IDAgMDAtMS43MTguMjgiLz48cGF0aCBzdHJva2U9ImhzbCgxNDEsIDEwMCUsIDUwJSkiIGQ9Ik0xMjYuMzIgNjkuMDY5YTY2LjUgNjYuNSAwIDAwLTEuNzIzLjI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQyLCAxMDAlLCA1MCUpIiBkPSJNMTI3LjQ3MiA2OC45MjdhNjYuNSA2Ni41IDAgMDAtMS43MjcuMjIiLz48cGF0aCBzdHJva2U9ImhzbCgxNDMsIDEwMCUsIDUwJSkiIGQ9Ik0xMjguNjI2IDY4LjgwNmE2Ni41IDY2LjUgMCAwMC0xLjczLjE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQ0LCAxMDAlLCA1MCUpIiBkPSJNMTI5Ljc4MiA2OC43MDVhNjYuNSA2Ni41IDAgMDAtMS43MzMuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxNDUsIDEwMCUsIDUwJSkiIGQ9Ik0xMzAuOTQgNjguNjI0YTY2LjUgNjYuNSAwIDAwLTEuNzM2LjEzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTQ2LCAxMDAlLCA1MCUpIiBkPSJNMTMyLjEgNjguNTYzYTY2LjUgNjYuNSAwIDAwLTEuNzM5LjA5OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE0NywgMTAwJSwgNTAlKSIgZD0iTTEzMy4yNiA2OC41MjNhNjYuNSA2Ni41IDAgMDAtMS43NC4wNjgiLz48cGF0aCBzdHJva2U9ImhzbCgxNDgsIDEwMCUsIDUwJSkiIGQ9Ik0xMzQuNDIgNjguNTAzYTY2LjUgNjYuNSAwIDAwLTEuNzQuMDM4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQ5LCAxMDAlLCA1MCUpIiBkPSJNMTM1LjU4IDY4LjUwM2E2Ni41IDY2LjUgMCAwMC0xLjc0LjAwNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MCwgMTAwJSwgNTAlKSIgZD0iTTEzNi43NCA2OC41MjNBNjYuNSA2Ni41IDAgMDAxMzUgNjguNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MSwgMTAwJSwgNTAlKSIgZD0iTTEzNy45IDY4LjU2M2E2Ni41IDY2LjUgMCAwMC0xLjc0LS4wNTMiLz48cGF0aCBzdHJva2U9ImhzbCgxNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xMzkuMDYgNjguNjI0YTY2LjUgNjYuNSAwIDAwLTEuNzQtLjA4MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MywgMTAwJSwgNTAlKSIgZD0iTTE0MC4yMTggNjguNzA1YTY2LjUgNjYuNSAwIDAwLTEuNzM4LS4xMTQiLz48cGF0aCBzdHJva2U9ImhzbCgxNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xNDEuMzc0IDY4LjgwNmE2Ni41IDY2LjUgMCAwMC0xLjczNS0uMTQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTU1LCAxMDAlLCA1MCUpIiBkPSJNMTQyLjUyOCA2OC45MjdhNjYuNSA2Ni41IDAgMDAtMS43MzItLjE3NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1NiwgMTAwJSwgNTAlKSIgZD0iTTE0My42OCA2OS4wNjlhNjYuNSA2Ni41IDAgMDAtMS43MjktLjIwNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1NywgMTAwJSwgNTAlKSIgZD0iTTE0NC44MyA2OS4yM2E2Ni41IDY2LjUgMCAwMC0xLjcyNi0uMjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTU4LCAxMDAlLCA1MCUpIiBkPSJNMTQ1Ljk3NiA2OS40MTJhNjYuNSA2Ni41IDAgMDAtMS43MjEtLjI2NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1OSwgMTAwJSwgNTAlKSIgZD0iTTE0Ny4xMTkgNjkuNjE0YTY2LjUgNjYuNSAwIDAwLTEuNzE2LS4yOTUiLz48cGF0aCBzdHJva2U9ImhzbCgxNjAsIDEwMCUsIDUwJSkiIGQ9Ik0xNDguMjU4IDY5LjgzNWE2Ni41IDY2LjUgMCAwMC0xLjcxLS4zMjUiLz48cGF0aCBzdHJva2U9ImhzbCgxNjEsIDEwMCUsIDUwJSkiIGQ9Ik0xNDkuMzkzIDcwLjA3NmE2Ni41IDY2LjUgMCAwMC0xLjcwNC0uMzU0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTYyLCAxMDAlLCA1MCUpIiBkPSJNMTUwLjUyNCA3MC4zMzdhNjYuNSA2Ni41IDAgMDAtMS42OTgtLjM4NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2MywgMTAwJSwgNTAlKSIgZD0iTTE1MS42NSA3MC42MThhNjYuNSA2Ni41IDAgMDAtMS42OS0uNDE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTY0LCAxMDAlLCA1MCUpIiBkPSJNMTUyLjc3MSA3MC45MTlhNjYuNSA2Ni41IDAgMDAtMS42ODMtLjQ0NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2NSwgMTAwJSwgNTAlKSIgZD0iTTE1My44ODcgNzEuMjM4YTY2LjUgNjYuNSAwIDAwLTEuNjc2LS40NzIiLz48cGF0aCBzdHJva2U9ImhzbCgxNjYsIDEwMCUsIDUwJSkiIGQ9Ik0xNTQuOTk3IDcxLjU3OGE2Ni41IDY2LjUgMCAwMC0xLjY2Ny0uNTAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTY3LCAxMDAlLCA1MCUpIiBkPSJNMTU2LjEgNzEuOTM2YTY2LjUgNjYuNSAwIDAwLTEuNjU3LS41MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2OCwgMTAwJSwgNTAlKSIgZD0iTTE1Ny4xOTggNzIuMzE0YTY2LjUgNjYuNSAwIDAwLTEuNjQ4LS41NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2OSwgMTAwJSwgNTAlKSIgZD0iTTE1OC4yODkgNzIuNzExYTY2LjUgNjYuNSAwIDAwLTEuNjM5LS41ODgiLz48cGF0aCBzdHJva2U9ImhzbCgxNzAsIDEwMCUsIDUwJSkiIGQ9Ik0xNTkuMzcyIDczLjEyN2E2Ni41IDY2LjUgMCAwMC0xLjYyOC0uNjE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTcxLCAxMDAlLCA1MCUpIiBkPSJNMTYwLjQ0OCA3My41NjJhNjYuNSA2Ni41IDAgMDAtMS42MTctLjY0NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE3MiwgMTAwJSwgNTAlKSIgZD0iTTE2MS41MTcgNzQuMDE2YTY2LjUgNjYuNSAwIDAwLTEuNjA2LS42NzQiLz48cGF0aCBzdHJva2U9ImhzbCgxNzMsIDEwMCUsIDUwJSkiIGQ9Ik0xNjIuNTc3IDc0LjQ4OGE2Ni41IDY2LjUgMCAwMC0xLjU5My0uNzAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTc0LCAxMDAlLCA1MCUpIiBkPSJNMTYzLjYyOSA3NC45NzhhNjYuNSA2Ni41IDAgMDAtMS41ODEtLjcyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE3NSwgMTAwJSwgNTAlKSIgZD0iTTE2NC42NzIgNzUuNDg3YTY2LjUgNjYuNSAwIDAwLTEuNTY4LS43NTYiLz48cGF0aCBzdHJva2U9ImhzbCgxNzYsIDEwMCUsIDUwJSkiIGQ9Ik0xNjUuNzA2IDc2LjAxNGE2Ni41IDY2LjUgMCAwMC0xLjU1NC0uNzg0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTc3LCAxMDAlLCA1MCUpIiBkPSJNMTY2LjczMSA3Ni41NTlhNjYuNSA2Ni41IDAgMDAtMS41NC0uODEiLz48cGF0aCBzdHJva2U9ImhzbCgxNzgsIDEwMCUsIDUwJSkiIGQ9Ik0xNjcuNzQ2IDc3LjEyMWE2Ni41IDY2LjUgMCAwMC0xLjUyNi0uODM3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTc5LCAxMDAlLCA1MCUpIiBkPSJNMTY4Ljc1MSA3Ny43MDJhNjYuNSA2Ni41IDAgMDAtMS41MTEtLjg2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4MCwgMTAwJSwgNTAlKSIgZD0iTTE2OS43NDYgNzguM2E2Ni41IDY2LjUgMCAwMC0xLjQ5Ni0uODkiLz48cGF0aCBzdHJva2U9ImhzbCgxODEsIDEwMCUsIDUwJSkiIGQ9Ik0xNzAuNzMgNzguOTE0YTY2LjUgNjYuNSAwIDAwLTEuNDgtLjkxNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4MiwgMTAwJSwgNTAlKSIgZD0iTTE3MS43MDQgNzkuNTQ3YTY2LjUgNjYuNSAwIDAwLTEuNDY0LS45NDIiLz48cGF0aCBzdHJva2U9ImhzbCgxODMsIDEwMCUsIDUwJSkiIGQ9Ik0xNzIuNjY2IDgwLjE5NmE2Ni41IDY2LjUgMCAwMC0xLjQ0OC0uOTY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTg0LCAxMDAlLCA1MCUpIiBkPSJNMTczLjYxNyA4MC44NjFhNjYuNSA2Ni41IDAgMDAtMS40My0uOTkyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTg1LCAxMDAlLCA1MCUpIiBkPSJNMTc0LjU1NiA4MS41NDRhNjYuNSA2Ni41IDAgMDAtMS40MTMtMS4wMTgiLz48cGF0aCBzdHJva2U9ImhzbCgxODYsIDEwMCUsIDUwJSkiIGQ9Ik0xNzUuNDgzIDgyLjI0MmE2Ni41IDY2LjUgMCAwMC0xLjM5NS0xLjA0MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4NywgMTAwJSwgNTAlKSIgZD0iTTE3Ni4zOTcgODIuOTU3YTY2LjUgNjYuNSAwIDAwLTEuMzc2LTEuMDY2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTg4LCAxMDAlLCA1MCUpIiBkPSJNMTc3LjMgODMuNjg3YTY2LjUgNjYuNSAwIDAwLTEuMzU5LTEuMDkiLz48cGF0aCBzdHJva2U9ImhzbCgxODksIDEwMCUsIDUwJSkiIGQ9Ik0xNzguMTg4IDg0LjQzM2E2Ni41IDY2LjUgMCAwMC0xLjMzOC0xLjExMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5MCwgMTAwJSwgNTAlKSIgZD0iTTE3OS4wNjQgODUuMTk0YTY2LjUgNjYuNSAwIDAwLTEuMzE5LTEuMTM2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTkxLCAxMDAlLCA1MCUpIiBkPSJNMTc5LjkyNyA4NS45NzFhNjYuNSA2Ni41IDAgMDAtMS4zLTEuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxOTIsIDEwMCUsIDUwJSkiIGQ9Ik0xODAuNzc2IDg2Ljc2M2E2Ni41IDY2LjUgMCAwMC0xLjI3OS0xLjE4MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5MywgMTAwJSwgNTAlKSIgZD0iTTE4MS42MSA4Ny41NjlhNjYuNSA2Ni41IDAgMDAtMS4yNTctMS4yMDQiLz48cGF0aCBzdHJva2U9ImhzbCgxOTQsIDEwMCUsIDUwJSkiIGQ9Ik0xODIuNDMxIDg4LjM5YTY2LjUgNjYuNSAwIDAwLTEuMjM2LTEuMjI2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTk1LCAxMDAlLCA1MCUpIiBkPSJNMTgzLjIzNyA4OS4yMjRhNjYuNSA2Ni41IDAgMDAtMS4yMTQtMS4yNDciLz48cGF0aCBzdHJva2U9ImhzbCgxOTYsIDEwMCUsIDUwJSkiIGQ9Ik0xODQuMDI5IDkwLjA3M2E2Ni41IDY2LjUgMCAwMC0xLjE5My0xLjI2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5NywgMTAwJSwgNTAlKSIgZD0iTTE4NC44MDYgOTAuOTM2YTY2LjUgNjYuNSAwIDAwLTEuMTcxLTEuMjg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTk4LCAxMDAlLCA1MCUpIiBkPSJNMTg1LjU2NyA5MS44MTJhNjYuNSA2Ni41IDAgMDAtMS4xNDgtMS4zMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5OSwgMTAwJSwgNTAlKSIgZD0iTTE4Ni4zMTMgOTIuN2E2Ni41IDY2LjUgMCAwMC0xLjEyNS0xLjMyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwMCwgMTAwJSwgNTAlKSIgZD0iTTE4Ny4wNDMgOTMuNjAzYTY2LjUgNjYuNSAwIDAwLTEuMTAxLTEuMzQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjAxLCAxMDAlLCA1MCUpIiBkPSJNMTg3Ljc1OCA5NC41MTdhNjYuNSA2Ni41IDAgMDAtMS4wNzgtMS4zNjciLz48cGF0aCBzdHJva2U9ImhzbCgyMDIsIDEwMCUsIDUwJSkiIGQ9Ik0xODguNDU2IDk1LjQ0NGE2Ni41IDY2LjUgMCAwMC0xLjA1My0xLjM4NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwMywgMTAwJSwgNTAlKSIgZD0iTTE4OS4xMzkgOTYuMzgzYTY2LjUgNjYuNSAwIDAwLTEuMDMtMS40MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMDQsIDEwMCUsIDUwJSkiIGQ9Ik0xODkuODA0IDk3LjMzNGE2Ni41IDY2LjUgMCAwMC0xLjAwNC0xLjQyMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNSwgMTAwJSwgNTAlKSIgZD0iTTE5MC40NTMgOTguMjk2YTY2LjUgNjYuNSAwIDAwLS45OC0xLjQzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNiwgMTAwJSwgNTAlKSIgZD0iTTE5MS4wODYgOTkuMjdhNjYuNSA2Ni41IDAgMDAtLjk1NS0xLjQ1NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNywgMTAwJSwgNTAlKSIgZD0iTTE5MS43IDEwMC4yNTRhNjYuNSA2Ni41IDAgMDAtLjkyOC0xLjQ3MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwOCwgMTAwJSwgNTAlKSIgZD0iTTE5Mi4yOTggMTAxLjI0OWE2Ni41IDY2LjUgMCAwMC0uOTAzLTEuNDg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjA5LCAxMDAlLCA1MCUpIiBkPSJNMTkyLjg3OSAxMDIuMjU0YTY2LjUgNjYuNSAwIDAwLS44NzctMS41MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMTAsIDEwMCUsIDUwJSkiIGQ9Ik0xOTMuNDQxIDEwMy4yNjlhNjYuNSA2Ni41IDAgMDAtLjg1LTEuNTE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjExLCAxMDAlLCA1MCUpIiBkPSJNMTkzLjk4NiAxMDQuMjk0YTY2LjUgNjYuNSAwIDAwLS44MjQtMS41MzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMTIsIDEwMCUsIDUwJSkiIGQ9Ik0xOTQuNTEzIDEwNS4zMjhhNjYuNSA2Ni41IDAgMDAtLjc5Ny0xLjU0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxMywgMTAwJSwgNTAlKSIgZD0iTTE5NS4wMjIgMTA2LjM3MWE2Ni41IDY2LjUgMCAwMC0uNzctMS41NjEiLz48cGF0aCBzdHJva2U9ImhzbCgyMTQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTUuNTEyIDEwNy40MjNhNjYuNSA2Ni41IDAgMDAtLjc0Mi0xLjU3NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxNSwgMTAwJSwgNTAlKSIgZD0iTTE5NS45ODQgMTA4LjQ4M2E2Ni41IDY2LjUgMCAwMC0uNzE1LTEuNTg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjE2LCAxMDAlLCA1MCUpIiBkPSJNMTk2LjQzOCAxMDkuNTUyYTY2LjUgNjYuNSAwIDAwLS42ODctMS42Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjE3LCAxMDAlLCA1MCUpIiBkPSJNMTk2Ljg3MyAxMTAuNjI4YTY2LjUgNjYuNSAwIDAwLS42Ni0xLjYxMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxOCwgMTAwJSwgNTAlKSIgZD0iTTE5Ny4yODkgMTExLjcxMWE2Ni41IDY2LjUgMCAwMC0uNjMxLTEuNjIyIi8+PHBhdGggc3Ryb2tlPSJoc2woMjE5LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjY4NiAxMTIuODAyYTY2LjUgNjYuNSAwIDAwLS42MDMtMS42MzMiLz48cGF0aCBzdHJva2U9ImhzbCgyMjAsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguMDY0IDExMy45YTY2LjUgNjYuNSAwIDAwLS41NzQtMS42NDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMjEsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguNDIyIDExNS4wMDNhNjYuNSA2Ni41IDAgMDAtLjU0NS0xLjY1MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyMiwgMTAwJSwgNTAlKSIgZD0iTTE5OC43NjIgMTE2LjExM2E2Ni41IDY2LjUgMCAwMC0uNTE3LTEuNjYzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjIzLCAxMDAlLCA1MCUpIiBkPSJNMTk5LjA4MSAxMTcuMjI5YTY2LjUgNjYuNSAwIDAwLS40ODctMS42NzIiLz48cGF0aCBzdHJva2U9ImhzbCgyMjQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuMzgyIDExOC4zNWE2Ni41IDY2LjUgMCAwMC0uNDU4LTEuNjgiLz48cGF0aCBzdHJva2U9ImhzbCgyMjUsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuNjYzIDExOS40NzZhNjYuNSA2Ni41IDAgMDAtLjQyOS0xLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyNiwgMTAwJSwgNTAlKSIgZD0iTTE5OS45MjQgMTIwLjYwN2E2Ni41IDY2LjUgMCAwMC0uNC0xLjY5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyNywgMTAwJSwgNTAlKSIgZD0iTTIwMC4xNjUgMTIxLjc0MmE2Ni41IDY2LjUgMCAwMC0uMzctMS43MDEiLz48cGF0aCBzdHJva2U9ImhzbCgyMjgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDAuMzg2IDEyMi44ODFhNjYuNSA2Ni41IDAgMDAtLjM0LTEuNzA3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjI5LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjU4OCAxMjQuMDI0YTY2LjUgNjYuNSAwIDAwLS4zMS0xLjcxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzMCwgMTAwJSwgNTAlKSIgZD0iTTIwMC43NyAxMjUuMTdhNjYuNSA2Ni41IDAgMDAtLjI4LTEuNzE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjMxLCAxMDAlLCA1MCUpIiBkPSJNMjAwLjkzMSAxMjYuMzJhNjYuNSA2Ni41IDAgMDAtLjI1LTEuNzIzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjMyLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjA3MyAxMjcuNDcyYTY2LjUgNjYuNSAwIDAwLS4yMi0xLjcyNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzMywgMTAwJSwgNTAlKSIgZD0iTTIwMS4xOTQgMTI4LjYyNmE2Ni41IDY2LjUgMCAwMC0uMTktMS43MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzNCwgMTAwJSwgNTAlKSIgZD0iTTIwMS4yOTUgMTI5Ljc4MmE2Ni41IDY2LjUgMCAwMC0uMTYtMS43MzMiLz48cGF0aCBzdHJva2U9ImhzbCgyMzUsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuMzc2IDEzMC45NGE2Ni41IDY2LjUgMCAwMC0uMTMtMS43MzYiLz48cGF0aCBzdHJva2U9ImhzbCgyMzYsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDM3IDEzMi4xYTY2LjUgNjYuNSAwIDAwLS4wOTktMS43MzkiLz48cGF0aCBzdHJva2U9ImhzbCgyMzcsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDc3IDEzMy4yNmE2Ni41IDY2LjUgMCAwMC0uMDY4LTEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMzgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDk3IDEzNC40MmE2Ni41IDY2LjUgMCAwMC0uMDM4LTEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMzksIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDk3IDEzNS41OGE2Ni41IDY2LjUgMCAwMC0uMDA3LTEuNzQiLz48L2c+PGNpcmNsZSBjeD0iMTM1IiBjeT0iMTM1IiByPSIxMzMiIGZpbGw9InVybCgjYSkiIGNsYXNzPSJJcm9XaGVlbFNhdHVyYXRpb24iLz48Y2lyY2xlIGN4PSIxMzUiIGN5PSIxMzUiIHI9IjEzMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIGNsYXNzPSJJcm9XaGVlbEJvcmRlciIvPjwvc3ZnPg==';
-
- this.width = this.offsetWidth;
- this.height = this.offsetHeight;
- },
- mousedown: function (event) {
- var cvs = this,
- ctx = this.getContext('2d');
-
- function update(x, y) {
- var cursor = cvs.nextSibling.nextSibling;
-
- cursor.style.left = x + cvs.offsetLeft + 'px';
- cursor.style.top = y + cvs.offsetTop + 'px';
- }
-
- function mousemove(event) {
- update(event.layerX, event.layerY);
- }
-
- function mouseup(event) {
- cvs.parentNode.data = {
- rgb: ctx.getImageData(event.layerX, event.layerY, 1, 1).data,
- cursor: [event.layerX, event.layerY]
- };
-
- this.removeEventListener('mousemove', mousemove);
- this.removeEventListener('mouseup', mouseup);
- }
-
- this.addEventListener('mousemove', mousemove);
- this.addEventListener('mouseup', mouseup);
-
- update(event.layerX, event.layerY);
-
- cvs.nextSibling.nextSibling.hidden = false;
- }
- }
- },
- shadow: {
- component: 'div',
- class: 'satus-color-picker__dim'
- },
- cursor: {
- component: 'div',
- class: 'satus-color-picker__cursor',
- attr: {
- hidden: true
- },
- on: {
- render: function () {
- var data = this.parentNode.data;
-
- if (data.cursor) {
- this.style.left = data.cursor[0] + 'px';
- this.style.top = data.cursor[1] + 'px';
-
- this.hidden = false;
- }
- }
- }
- },
- slider: {
- component: 'slider',
- class: 'satus-color-picker__slider',
- step: .01,
- on: {
- render: function () {
- var data = this.parentNode.data;
-
- function rgbToHsv(r, g, b) {
- r /= 255, g /= 255, b /= 255;
-
- var max = Math.max(r, g, b),
- min = Math.min(r, g, b);
- var h, s, v = max;
-
- var d = max - min;
- s = max == 0 ? 0 : d / max;
-
- if (max == min) {
- h = 0; // achromatic
- } else {
- switch (max) {
- case r:
- h = (g - b) / d + (g < b ? 6 : 0);
- break;
- case g:
- h = (b - r) / d + 2;
- break;
- case b:
- h = (r - g) / d + 4;
- break;
- }
-
- h /= 6;
- }
-
- return [h, s, v];
- }
-
- this.value = 1 - rgbToHsv(data.rgb[0], data.rgb[1], data.rgb[2])[2];
- },
- change: function () {
- this.previousSibling.previousSibling.style.opacity = this.value;
- }
- }
- },
- actions: {
- component: 'section',
- class: 'satus-color-picker__actions',
-
- reset: {
- component: 'button',
- text: 'reset',
-
- on: {
- click: function () {
- var modal = this.parentNode.parentNode.parentNode,
- component = modal.parentComponent;
-
- component.data = component.skeleton.value;
-
- if (component.storage) {
- satus.storage.set(component.storage, false);
- }
-
- var data = component.skeleton.value || {
- rgb: [0, 0, 0]
- };
-
- component.valueElement.style.backgroundColor = 'rgb(' + data.rgb[0] + ',' + data.rgb[1] + ',' + data.rgb[2] + ')';
-
- modal.close();
-
- component.colorValue = data;
-
- component.dispatchEvent(new CustomEvent('change'));
- }
- }
- },
- cancel: {
- component: 'button',
- text: 'cancel',
-
- on: {
- click: function () {
- var modal = this.parentNode.parentNode.parentNode;
-
- modal.close();
- }
- }
- },
- ok: {
- component: 'button',
- text: 'OK',
-
- on: {
- click: function () {
- var modal = this.parentNode.parentNode.parentNode,
- data = this.parentNode.parentNode.data;
-
- function rgbToHsv(r, g, b) {
- r /= 255, g /= 255, b /= 255;
-
- var max = Math.max(r, g, b),
- min = Math.min(r, g, b);
- var h, s, v = max;
-
- var d = max - min;
- s = max == 0 ? 0 : d / max;
-
- if (max == min) {
- h = 0; // achromatic
- } else {
- switch (max) {
- case r:
- h = (g - b) / d + (g < b ? 6 : 0);
- break;
- case g:
- h = (b - r) / d + 2;
- break;
- case b:
- h = (r - g) / d + 4;
- break;
- }
-
- h /= 6;
- }
-
- return [h, s, v];
- }
-
- function hsvToRgb(h, s, v) {
- var r, g, b;
-
- var i = Math.floor(h * 6);
- var f = h * 6 - i;
- var p = v * (1 - s);
- var q = v * (1 - f * s);
- var t = v * (1 - (1 - f) * s);
-
- switch (i % 6) {
- case 0:
- r = v, g = t, b = p;
- break;
- case 1:
- r = q, g = v, b = p;
- break;
- case 2:
- r = p, g = v, b = t;
- break;
- case 3:
- r = p, g = q, b = v;
- break;
- case 4:
- r = t, g = p, b = v;
- break;
- case 5:
- r = v, g = p, b = q;
- break;
- }
-
- return [r * 255, g * 255, b * 255];
- }
-
- var hsv = rgbToHsv(data.rgb[0], data.rgb[1], data.rgb[2]);
-
- hsv[2] = 1 - this.parentNode.previousSibling.value;
-
- data.rgb = hsvToRgb(hsv[0], hsv[1], hsv[2]);
-
- modal.parentComponent.valueElement.style.backgroundColor = 'rgb(' + data.rgb[0] + ',' + data.rgb[1] + ',' + data.rgb[2] + ')';
-
- if (modal.parentComponent.storage) {
- satus.storage.set(modal.parentComponent.storage, data);
- }
-
- modal.parentComponent.colorValue = data;
-
- modal.close();
-
- modal.parentComponent.dispatchEvent(new CustomEvent('change'));
- }
- }
- }
- }
- });
- });
-
- component.appendChild(component_value);
-
- return component;
-};
-/*--------------------------------------------------------------
->>> TABS
---------------------------------------------------------------*/
-
-satus.components.tabs = function (skeleton) {
- var component = document.createElement('div'),
- selection = document.createElement('div');
-
- selection.className = 'satus-tabs__selection';
-
- component.appendChild(selection);
-
- component.selection = selection;
-
- for (var i = 0, l = skeleton.items.length; i < l; i++) {
- var item = skeleton.items[i],
- button = document.createElement('button');
-
- button.className = 'satus-tabs__button';
- button.value = item;
-
- satus.text(button, item);
-
- button.addEventListener('click', function () {
- var component = this.parentNode;
-
- component.value = this.value;
-
- component.selection.style.left = this.offsetLeft + 'px';
-
- component.dispatchEvent(new CustomEvent('change'));
- });
-
- if (skeleton.value === item) {
- selection.style.left = i * 50 + '%';
- }
-
- component.appendChild(button);
- }
-
- return component;
-};
-/*--------------------------------------------------------------
->>> RADIO
---------------------------------------------------------------*/
-
-satus.components.radio = function (skeleton) {
- var component = document.createElement('label'),
- content = document.createElement('span'),
- radio = document.createElement('input'),
- value = satus.storage.get(skeleton.group);
-
- component.inner = content;
-
- radio.type = 'radio';
-
- if (skeleton.group) {
- radio.name = skeleton.group;
- }
-
- if (skeleton.value) {
- radio.value = skeleton.value;
- }
-
- if (satus.isset(value)) {
- radio.checked = value === skeleton.value;
- }
-
- radio.addEventListener('change', function () {
- satus.storage.set(this.name, this.value);
- });
-
- component.appendChild(content);
- component.appendChild(radio);
-
- return component;
-};
-/*--------------------------------------------------------------
->>> LIST
---------------------------------------------------------------*/
-
-satus.components.list = function (skeleton) {
- var ul = document.createElement('ul');
-
- for (var i = 0, l = skeleton.items.length; i < l; i++) {
- var li = document.createElement('li'),
- item = skeleton.items[i];
-
- li.className = 'satus-list__item';
-
- for (var j = 0, k = item.length; j < k; j++) {
- var child = item[j];
-
- if (typeof child === 'string') {
- var span = document.createElement('span');
-
- span.textContent = satus.locale.get(child);
-
- li.appendChild(span);
- } else {
- satus.render(child, li);
- }
- }
-
- ul.appendChild(li);
- }
-
- return ul;
-};
-/*--------------------------------------------------------------
->>> MODAL
---------------------------------------------------------------*/
-
-satus.components.modal = function (skeleton) {
- var component = document.createElement('div'),
- scrim = document.createElement('div'),
- surface = document.createElement('div');
-
- scrim.className = 'satus-modal__scrim';
- surface.className = 'satus-modal__surface';
-
- component.close = function () {
- var component = this,
- component_surface = this.children[1];
-
- this.classList.add('satus-modal--closing');
-
- setTimeout(function () {
- component.remove();
-
- component.dispatchEvent(new CustomEvent('close'));
- }, satus.getAnimationDuration(component_surface));
- };
-
- scrim.addEventListener('click', function () {
- this.parentNode.close();
- });
-
- component.appendChild(scrim);
- component.appendChild(surface);
-
- component.inner = surface;
-
- return component;
-};
-/*--------------------------------------------------------------
->>> SWITCH
---------------------------------------------------------------*/
-
-satus.components.switch = function (skeleton) {
- var component = document.createElement('button'),
- component_content = document.createElement('span'),
- component_thumb = document.createElement('i'),
- value = satus.storage.get(skeleton.storage);
-
- component.inner = component_content;
-
- if (satus.isset(value)) {
- component.dataset.value = value;
- } else if (skeleton.hasOwnProperty('value')) {
- component.dataset.value = skeleton.value;
- }
-
- component.addEventListener('click', function () {
- if (this.dataset.value === 'true') {
- this.dataset.value = 'false';
- } else {
- this.dataset.value = 'true';
- }
-
- this.change(this.dataset.value === 'true');
- });
-
- component.appendChild(component_content);
- component.appendChild(component_thumb);
-
- return component;
-};
-/*--------------------------------------------------------------
->>> SLIDER:
-----------------------------------------------------------------
-#
---------------------------------------------------------------*/
-
-satus.components.slider = function (skeleton) {
- var component = document.createElement('div'),
- container = document.createElement('div'),
- track_container = document.createElement('div'),
- track = document.createElement('div'),
- ring = document.createElement('div'),
- thumb = document.createElement('div'),
- range = document.createElement('input'),
- value = satus.storage.get(skeleton.storage);
-
- container.className = 'satus-slider__container';
- track_container.className = 'satus-slider__track-container';
- track.className = 'satus-slider__track';
- ring.className = 'satus-slider__ring';
- thumb.className = 'satus-slider__thumb';
-
- range.type = 'range';
- range.step = skeleton.step || 1;
- range.max = skeleton.max || 1;
- range.min = skeleton.min || 0;
-
- component.input = range;
-
- if (satus.isset(value)) {
- range.value = value;
- } else if (skeleton.hasOwnProperty('value')) {
- range.value = skeleton.value;
- } else {
- range.value = 0;
- }
-
- component.appendChild(container);
- track_container.appendChild(track);
- container.appendChild(track_container);
- track.appendChild(ring);
- track.appendChild(thumb);
- component.appendChild(range);
-
- component.update = function () {
- var track = this.querySelector('.satus-slider__track'),
- thumb = this.querySelector('.satus-slider__thumb'),
- min = Number(this.input.min) || 0,
- max = Number(this.input.max) || 1,
- step = Number(this.input.step) || 1,
- value = Number(this.input.value) || 0,
- offset = (value - min) / (max - min) * 100;
-
- track.style.width = 'calc(' + offset + '% - ' + Math.floor(offset * 12 / 100) + 'px)';
-
- thumb.dataset.value = this.input.value;
- };
-
- Object.defineProperty(component, 'value', {
- get: function () {
- return this.input.value;
- },
- set: function (value) {
- this.input.value = value;
-
- this.update();
-
- satus.storage.set(this.skeleton.storage, Number(value));
-
- this.dispatchEvent(new CustomEvent('change'));
- }
- });
-
- range.addEventListener('input', function () {
- var component = this.parentNode;
-
- console.log(this.value);
-
- component.value = this.value;
- });
-
- component.update();
-
- return component;
-};
-/*--------------------------------------------------------------
->>> SHORTCUT
---------------------------------------------------------------*/
-
-satus.components.shortcut = function (skeleton) {
- var component = document.createElement('button'),
- value = document.createElement('div');
-
- component.className = 'satus-button';
- value.className = 'satus-shortcut__value';
-
- component.update = function () {
- var object = satus.storage.get(this.storage) || this.skeleton.value || {},
- array = [];
-
- if (object.shift) {
- array.push('Shift');
- }
-
- if (object.ctrl) {
- array.push('Ctrl');
- }
-
- if (object.alt) {
- array.push('Alt');
- }
-
- if (typeof object.keys === 'object') {
- for (var key in object.keys) {
- var char = object.keys[key].key || object.keys[key].code;
-
- if (key === 32) {
- char = 'space';
- }
-
- array.push(char);
- }
- }
-
- this.valueElement.textContent = array.join(' + ');
- };
-
- component.render = function () {
- var self = this,
- children = this.primary.children;
-
- satus.empty(this.primary);
-
- function createElement(name) {
- var element = document.createElement('div');
-
- element.className = 'satus-shortcut__' + name;
-
- self.primary.appendChild(element);
-
- return element;
- }
-
- if (this.data.alt) {
- createElement('key').textContent = 'Alt';
- }
-
- if (this.data.ctrl) {
- if (children.length && children[children.length - 1].className.indexOf('key') !== -1) {
- createElement('plus');
- }
-
- createElement('key').textContent = 'Ctrl';
- }
-
- if (this.data.shift) {
- if (children.length && children[children.length - 1].className.indexOf('key') !== -1) {
- createElement('plus');
- }
-
- createElement('key').textContent = 'Shift';
- }
-
- for (var code in this.data.keys) {
- if (children.length && children[children.length - 1].className.indexOf('key') !== -1) {
- createElement('plus');
- }
-
- createElement('key').textContent = this.data.keys[code].key.toUpperCase();
- }
-
- if (this.data.wheel) {
- if (children.length && children[children.length - 1].className.indexOf('key') !== -1) {
- createElement('plus');
- }
-
- var mouse = createElement('mouse'),
- div = document.createElement('div');
-
- mouse.appendChild(div);
-
- mouse.className += ' ' + (this.data.wheel > 0);
- }
- };
-
- component.valueElement = value;
-
- component.data = satus.storage.get(skeleton.storage) || skeleton.value || {
- alt: false,
- ctrl: false,
- shift: false,
- keys: {},
- wheel: 0
- };
-
- component.appendChild(value);
-
- component.keydown = function (event) {
- event.preventDefault();
- event.stopPropagation();
-
- component.data = {
- alt: event.altKey,
- ctrl: event.ctrlKey,
- shift: event.shiftKey,
- keys: {}
- };
-
- component.data.keys[event.keyCode] = {
- code: event.code,
- key: event.key
- };
-
- component.data.wheel = 0;
-
- component.render();
-
- return false;
- };
-
- component.mousewheel = function (event) {
- event.preventDefault();
- event.stopPropagation();
-
- component.data.wheel = event.deltaY;
-
- component.render();
-
- return false;
- };
-
- component.addEventListener('click', function () {
- satus.render({
- component: 'modal',
- on: {
- close: function () {
- window.removeEventListener('keydown', this.keydown);
- window.removeEventListener('mousewheel', this.mousewheel);
- }
- },
-
- primary: {
- component: 'div',
- class: 'satus-shortcut__primary',
- on: {
- render: function () {
- component.primary = this;
-
- component.render();
- }
- }
- },
- actions: {
- component: 'div',
- class: 'satus-shortcut__actions',
-
- reset: {
- component: 'button',
- text: 'reset',
- on: {
- click: function () {
- component.data = component.skeleton.value;
-
- component.update();
-
- satus.storage.set(component.storage, false);
-
- this.parentNode.parentNode.parentNode.close();
-
- window.removeEventListener('keydown', this.keydown);
- window.removeEventListener('mousewheel', this.mousewheel);
- }
- }
- },
- cancel: {
- component: 'button',
- text: 'cancel',
- on: {
- click: function () {
- component.data = satus.storage.get(skeleton.storage) || component.skeleton.value;
-
- component.update();
-
- this.parentNode.parentNode.parentNode.close();
-
- window.removeEventListener('keydown', this.keydown);
- window.removeEventListener('mousewheel', this.mousewheel);
- }
- }
- },
- save: {
- component: 'button',
- text: 'save',
- on: {
- click: function () {
- satus.storage.set(component.storage, component.data);
-
- component.update();
-
- this.parentNode.parentNode.parentNode.close();
-
- window.removeEventListener('keydown', this.keydown);
- window.removeEventListener('mousewheel', this.mousewheel);
- }
- }
- }
- }
- });
-
- window.addEventListener('keydown', this.keydown);
- window.addEventListener('mousewheel', this.mousewheel);
- });
-
- component.addEventListener('render', component.update);
-
- return component;
-};
-/*--------------------------------------------------------------
->>> BASE
---------------------------------------------------------------*/
-
-satus.components.base = function (skeleton) {
- var component = document.createElement('div');
-
- component.base = component;
-
- return component;
-};
-/*--------------------------------------------------------------
->>> TEXT FIELD
---------------------------------------------------------------*/
-
-satus.components.textField = function (skeleton) {
- var component = document.createElement('div'),
- pre = document.createElement('pre'),
- input = document.createElement('textarea'),
- hidden_text = document.createElement('span'),
- text = document.createElement('span'),
- selection = document.createElement('div'),
- cursor = document.createElement('div'),
- value = satus.storage.get(skeleton.storage);
-
- input.className = 'satus-text-field__input';
- pre.className = 'satus-text-field__pre';
- hidden_text.className = 'satus-text-field__hidden-text';
- text.className = 'satus-text-field__text';
- selection.className = 'satus-text-field__selection';
- cursor.className = 'satus-text-field__cursor';
-
- component.inputElement = input;
- component.textElement = text;
- component.languages = {
- regex: function (component) {
- var regex_token = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
- char_class_token = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g,
- char_class_parts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/,
- quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/,
- matches = component.inputElement.value.match(regex_token);
-
- function create(type, string) {
- var span = document.createElement('span');
-
- span.className = type;
- span.textContent = string;
-
- component.textElement.appendChild(span);
- }
-
- for (var i = 0, l = matches.length; i < l; i++) {
- var match = matches[i];
-
- if (match[0] === '[') {
- create('character-class', match);
- } else if (match[0] === '(') {
- create('group', match);
- } else if (match[0] === ')') {
- create('group', match);
- } else if (match[0] === '\\' || match === '^') {
- create('anchor', match);
- } else if (quantifier.test(match)) {
- create('quantifier', match);
- } else if (match === '|' || match === '.') {
- create('metasequence', match);
- } else {
- create('text', match);
- }
- }
- }
- };
- component._syntax = skeleton.syntax;
-
- Object.defineProperty(component, 'value', {
- get: function () {
- return this.inputElement.value;
- },
- set: function (value) {
- var input = this.inputElement;
-
- input.value = value;
-
- input.updateValue();
- input.updateCursor();
- }
- });
-
- Object.defineProperty(component, 'syntax', {
- get: function () {
- return this._syntax;
- },
- set: function (value) {
- var input = this.inputElement;
-
- this._syntax = value;
-
- input.updateValue();
- input.updateCursor();
- }
- });
-
- input.rows = skeleton.rows || 1;
- input.autocapitalize = 'none';
- input.autocomplete = 'off';
- input.autocorrect = 'off';
- input.spellcheck = false;
- input.autofocus = true;
- input.textElement = text;
- input.hiddenTextElement = hidden_text;
- input.selectionElement = selection;
- input.cursorElement = cursor;
-
- input.updateValue = function () {
- var component = this.parentNode.parentNode;
-
- for (var i = this.textElement.childNodes.length - 1; i > -1; i--) {
- this.textElement.childNodes[i].remove();
- }
-
- if (this.value.length > 0) {
- if (component.languages[component._syntax]) {
- component.languages[component._syntax](component);
- } else {
- this.textElement.textContent = this.value;
- }
- }
-
- component.dispatchEvent(new Event('change'));
- };
-
- input.updateCursor = function () {
- var cursor = this.cursorElement,
- selection = this.selectionElement,
- hidden_text = this.hiddenTextElement,
- start = this.selectionStart,
- end = this.selectionEnd;
-
- cursor.style.animation = 'none';
-
- if (start === end) {
- selection.setAttribute('disabled', '');
- } else {
- selection.removeAttribute('disabled');
-
- hidden_text.textContent = this.value.substring(0, start);
-
- selection.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px';
-
- hidden_text.textContent = this.value.substring(start, end);
-
- selection.style.width = hidden_text.offsetWidth + 'px';
- }
-
- if (this.selectionDirection === 'forward') {
- hidden_text.textContent = this.value.substring(0, end);
- } else {
- hidden_text.textContent = this.value.substring(0, start);
- }
-
- cursor.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px';
-
- cursor.style.animation = '';
-
- hidden_text.textContent = '';
- };
-
- input.addEventListener('keydown', function () {
- var self = this;
-
- setTimeout(function () {
- var component = self.parentNode.parentNode;
-
- if (component.skeleton && component.skeleton.storage) {
- satus.storage.set(component.skeleton.storage, self.value);
- }
-
- self.updateValue();
- self.updateCursor();
- });
- });
-
- input.addEventListener('scroll', function (event) {
- this.textElement.style.left = -this.scrollLeft + 'px';
- });
-
- document.addEventListener('selectionchange', function () {
- input.updateCursor();
- });
-
- selection.setAttribute('disabled', '');
-
- pre.appendChild(input);
- pre.appendChild(hidden_text);
- pre.appendChild(text);
- pre.appendChild(selection);
- pre.appendChild(cursor);
- component.appendChild(pre);
-
- if (satus.isset(value)) {
- component.value = value;
- } else if (skeleton.hasOwnProperty('value')) {
- if (typeof skeleton.value === 'function') {
- input.value = skeleton.value();
- } else if (skeleton.value) {
- input.value = skeleton.value;
- }
- }
-
- component.addEventListener('render', function () {
- this.inputElement.updateValue();
- this.inputElement.updateCursor();
- });
-
- return component;
-};
-/*--------------------------------------------------------------
->>> ALERT
---------------------------------------------------------------*/
-
-satus.components.alert = function (skeleton) {
- var component = document.createElement('div');
-
- return component;
-};
-/*--------------------------------------------------------------
->>> LAYERS
---------------------------------------------------------------*/
-
-satus.components.layers = function (skeleton) {
- var component = document.createElement('div');
-
- component.path = [skeleton];
-
- component.back = function () {
- if (this.path.length > 1) {
- this.path.pop();
-
- this.open();
- }
- };
-
- component.open = function (skeleton) {
- var layer = document.createElement('div');
-
- if (skeleton) {
- this.path.push(skeleton);
- } else {
- skeleton = this.path[this.path.length - 1];
- }
-
- layer.className = 'satus-layer';
-
- layer.skeleton = skeleton;
- layer.base = this.base;
-
- satus.render(skeleton, layer, skeleton.component === 'layers');
-
- satus.empty(this);
-
- this.appendChild(layer);
-
- this.dispatchEvent(new Event('open'));
- };
-
- component.update = function () {
- var layer = this.querySelector('.satus-layer');
-
- satus.empty(layer);
-
- satus.render(layer.skeleton, layer);
- };
-
- component.render_children = false;
-
- component.addEventListener('render', function () {
- this.open();
- });
-
- return component;
-};
-/*--------------------------------------------------------------
->>> INPUT
---------------------------------------------------------------*/
-
-satus.components.input = function (skeleton) {
- var component = document.createElement('input');
-
- if (skeleton.attr) {
- var key = skeleton.attr.name || skeleton.storage,
- value;
-
- if (satus.isset(satus.storage.get(key))) {
- value = satus.storage.get(key);
- } else {
- value = skeleton.value;
- }
-
- if (skeleton.attr.type === 'radio') {
- component.checked = value === skeleton.attr.value || skeleton.value;
- } else if (satus.isset(value)) {
- component.value = value;
- }
-
- component.addEventListener('change', function () {
- var key = this.skeleton.attr.name || this.skeleton.storage;
-
- satus.storage.set(key, this.value);
- });
- }
-
- return component;
-};
-/*--------------------------------------------------------------
->>> SELECT
---------------------------------------------------------------*/
-
-satus.components.select = function (skeleton) {
- var component = document.createElement('div'),
- component_label = document.createElement('span'),
- component_value = document.createElement('span'),
- select = document.createElement('select');
-
- component_value.className = 'satus-select__value';
-
- for (var i = 0, l = skeleton.options.length; i < l; i++) {
- var option = document.createElement('option');
-
- option.value = skeleton.options[i].value;
-
- satus.text(option, skeleton.options[i].text);
-
- select.appendChild(option);
- }
-
- component.selectElement = select;
- select.valueElement = component_value;
-
- select.addEventListener('change', function () {
- satus.empty(this.valueElement);
-
- satus.text(this.valueElement, this.options[this.selectedIndex].text);
-
- this.parentNode.change(this.value);
- });
-
- component.appendChild(component_label);
- component.appendChild(component_value);
- component.appendChild(select);
-
- component.addEventListener('render', function () {
- var select = this.selectElement,
- value = satus.storage.get(this.storage) || this.skeleton.options[0].value;
-
- select.value = value;
-
- satus.text(select.valueElement, select.options[select.selectedIndex].text);
- });
-
- component.inner = component_label;
-
- return component;
-};
-/*--------------------------------------------------------------
->>> USER
---------------------------------------------------------------*/
-
-satus.user = function () {
- /*--------------------------------------------------------------
- 1.0 VARIABLES
- --------------------------------------------------------------*/
-
- var user_agent = navigator.userAgent,
- random_cookie = 'ta{t`nX6cMXK,Wsc',
- video = document.createElement('video'),
- video_formats = {
- ogg: 'video/ogg; codecs="theora"',
- h264: 'video/mp4; codecs="avc1.42E01E"',
- webm: 'video/webm; codecs="vp8, vorbis"',
- vp9: 'video/webm; codecs="vp9"',
- hls: 'application/x-mpegURL; codecs="avc1.42E01E"'
- },
- audio = document.createElement('audio'),
- audio_formats = {
- mp3: 'audio/mpeg',
- mp4: 'audio/mp4',
- aif: 'audio/x-aiff'
- },
- cvs = document.createElement('canvas'),
- ctx = cvs.getContext('webgl'),
- data = {
- browser: {
- audio: null,
- cookies: null,
- flash: null,
- java: null,
- languages: null,
- name: null,
- platform: null,
- version: null,
- video: null,
- webgl: null
- },
- os: {
- name: null,
- type: null
- },
- device: {
- connection: {
- type: null,
- speed: null
- },
- cores: null,
- gpu: null,
- max_touch_points: null,
- ram: null,
- screen: null,
- touch: null
- }
- };
-
-
- /*--------------------------------------------------------------
- 2.0 SOFTWARE
- --------------------------------------------------------------*/
-
- /*--------------------------------------------------------------
- 2.1.0 OS
- --------------------------------------------------------------*/
-
- /*--------------------------------------------------------------
- 2.1.1 NAME
- --------------------------------------------------------------*/
-
- if (navigator.appVersion.indexOf('Win') !== -1) {
- if (navigator.appVersion.match(/(Windows 10.0|Windows NT 10.0)/)) {
- data.os.name = 'Windows 10';
- } else if (navigator.appVersion.match(/(Windows 8.1|Windows NT 6.3)/)) {
- data.os.name = 'Windows 8.1';
- } else if (navigator.appVersion.match(/(Windows 8|Windows NT 6.2)/)) {
- data.os.name = 'Windows 8';
- } else if (navigator.appVersion.match(/(Windows 7|Windows NT 6.1)/)) {
- data.os.name = 'Windows 7';
- } else if (navigator.appVersion.match(/(Windows NT 6.0)/)) {
- data.os.name = 'Windows Vista';
- } else if (navigator.appVersion.match(/(Windows NT 5.1|Windows XP)/)) {
- data.os.name = 'Windows XP';
- } else {
- data.os.name = 'Windows';
- }
- } else if (navigator.appVersion.indexOf('(iPhone|iPad|iPod)') !== -1) {
- data.os.name = 'iOS';
- } else if (navigator.appVersion.indexOf('Mac') !== -1) {
- data.os.name = 'macOS';
- } else if (navigator.appVersion.indexOf('Android') !== -1) {
- data.os.name = 'Android';
- } else if (navigator.appVersion.indexOf('OpenBSD') !== -1) {
- data.os.name = 'OpenBSD';
- } else if (navigator.appVersion.indexOf('SunOS') !== -1) {
- data.os.name = 'SunOS';
- } else if (navigator.appVersion.indexOf('Linux') !== -1) {
- data.os.name = 'Linux';
- } else if (navigator.appVersion.indexOf('X11') !== -1) {
- data.os.name = 'UNIX';
- }
-
- /*--------------------------------------------------------------
- 2.1.2 TYPE
- --------------------------------------------------------------*/
-
- if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) {
- data.os.type = '64-bit';
- } else {
- data.os.type = '32-bit';
- }
-
-
- /*--------------------------------------------------------------
- 2.2.0 BROWSER
- --------------------------------------------------------------*/
-
- /*--------------------------------------------------------------
- 2.2.1 NAME
- --------------------------------------------------------------*/
-
- if (user_agent.indexOf('Opera') !== -1) {
- data.browser.name = 'Opera';
- } else if (user_agent.indexOf('Vivaldi') !== -1) {
- data.browser.name = 'Vivaldi';
- } else if (user_agent.indexOf('Edge') !== -1) {
- data.browser.name = 'Edge';
- } else if (user_agent.indexOf('Chrome') !== -1) {
- data.browser.name = 'Chrome';
- } else if (user_agent.indexOf('Safari') !== -1) {
- data.browser.name = 'Safari';
- } else if (user_agent.indexOf('Firefox') !== -1) {
- data.browser.name = 'Firefox';
- } else if (user_agent.indexOf('MSIE') !== -1) {
- data.browser.name = 'IE';
- }
-
-
- /*--------------------------------------------------------------
- 2.2.2 VERSION
- --------------------------------------------------------------*/
-
- var browser_version = user_agent.match(new RegExp(data.browser.name + '/([0-9.]+)'));
-
- if (browser_version[1]) {
- data.browser.version = browser_version[1];
- }
-
-
- /*--------------------------------------------------------------
- 2.2.3 PLATFORM
- --------------------------------------------------------------*/
-
- data.browser.platform = navigator.platform || null;
-
-
- /*--------------------------------------------------------------
- 2.2.4 LANGUAGES
- --------------------------------------------------------------*/
-
- data.browser.languages = navigator.languages || null;
-
-
- /*--------------------------------------------------------------
- 2.2.5 COOKIES
- --------------------------------------------------------------*/
-
- if (document.cookie) {
- document.cookie = random_cookie;
-
- if (document.cookie.indexOf(random_cookie) !== -1) {
- data.browser.cookies = true;
- }
- }
-
-
- /*--------------------------------------------------------------
- 2.2.6 FLASH
- --------------------------------------------------------------*/
-
- try {
- if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) {
- data.browser.flash = true;
- }
- } catch (e) {
- if (navigator.mimeTypes['application/x-shockwave-flash']) {
- data.browser.flash = true;
- }
- }
-
-
- /*--------------------------------------------------------------
- 2.2.7 JAVA
- --------------------------------------------------------------*/
-
- if (typeof navigator.javaEnabled === 'function' && navigator.javaEnabled()) {
- data.browser.java = true;
- }
-
-
- /*--------------------------------------------------------------
- 2.2.8 VIDEO FORMATS
- --------------------------------------------------------------*/
-
- if (typeof video.canPlayType === 'function') {
- data.browser.video = {};
-
- for (var i in video_formats) {
- var can_play_type = video.canPlayType(video_formats[i]);
-
- if (can_play_type === '') {
- data.browser.video[i] = false;
- } else {
- data.browser.video[i] = can_play_type;
- }
- }
- }
-
-
- /*--------------------------------------------------------------
- 2.2.9 AUDIO FORMATS
- --------------------------------------------------------------*/
-
- if (typeof audio.canPlayType === 'function') {
- data.browser.audio = {};
-
- for (var i in audio_formats) {
- var can_play_type = audio.canPlayType(audio_formats[i]);
-
- if (can_play_type == '') {
- data.browser.audio[i] = false;
- } else {
- data.browser.audio[i] = can_play_type;
- }
- }
- }
-
-
- /*--------------------------------------------------------------
- 2.2.10 WEBGL
- --------------------------------------------------------------*/
-
- if (ctx && ctx instanceof WebGLRenderingContext) {
- data.browser.webgl = true;
- }
-
-
- /*--------------------------------------------------------------
- 3.0 HARDWARE
- --------------------------------------------------------------*/
-
- /*--------------------------------------------------------------
- 3.1 SCREEN
- --------------------------------------------------------------*/
-
- if (screen) {
- data.device.screen = screen.width + 'x' + screen.height;
- }
-
-
- /*--------------------------------------------------------------
- 3.2 RAM
- --------------------------------------------------------------*/
-
- if ('deviceMemory' in navigator) {
- data.device.ram = navigator.deviceMemory + ' GB';
- }
-
-
- /*--------------------------------------------------------------
- 3.3 GPU
- --------------------------------------------------------------*/
-
- if (
- ctx &&
- ctx instanceof WebGLRenderingContext &&
- 'getParameter' in ctx &&
- 'getExtension' in ctx
- ) {
- var info = ctx.getExtension('WEBGL_debug_renderer_info');
-
- if (info) {
- data.device.gpu = ctx.getParameter(info.UNMASKED_RENDERER_WEBGL);
- }
- }
-
-
- /*--------------------------------------------------------------
- 3.4 CORES
- --------------------------------------------------------------*/
-
- if (navigator.hardwareConcurrency) {
- data.device.cores = navigator.hardwareConcurrency;
- }
-
-
- /*--------------------------------------------------------------
- 3.5 TOUCH
- --------------------------------------------------------------*/
-
- if (
- window.hasOwnProperty('ontouchstart') ||
- window.DocumentTouch && document instanceof window.DocumentTouch ||
- navigator.maxTouchPoints > 0 ||
- window.navigator.msMaxTouchPoints > 0
- ) {
- data.device.touch = true;
- data.device.max_touch_points = navigator.maxTouchPoints;
- }
-
-
- /*--------------------------------------------------------------
- 3.6 CONNECTION
- --------------------------------------------------------------*/
-
- if (typeof navigator.connection === 'object') {
- data.device.connection.type = navigator.connection.effectiveType || null;
-
- if (navigator.connection.downlink) {
- data.device.connection.speed = navigator.connection.downlink + ' Mbps';
- }
- }
-
-
- /*--------------------------------------------------------------
- 4.0 CLEARING
- --------------------------------------------------------------*/
-
- video.remove();
- audio.remove();
- cvs.remove();
-
-
- return data;
-};
-/*--------------------------------------------------------------
->>> EXTENSION STORAGE
---------------------------------------------------------------*/
-/*--------------------------------------------------------------
->>> PLUVIAM
---------------------------------------------------------------*/
-
-satus.events.add('render', function (component, skeleton) {
- if (skeleton.pluviam === true) {
- function createPluviam(event) {
- var pluviam = document.createElement('span'),
- rect = this.getBoundingClientRect(),
- x = event.clientX - rect.left,
- y = event.clientY - rect.top,
- diameter = Math.sqrt(Math.pow(rect.width * 2, 2) + Math.pow(rect.height * 2, 2));
-
- pluviam.className = 'satus-pluviam';
-
- pluviam.style.left = x - diameter / 2 + 'px';
- pluviam.style.top = y - diameter / 2 + 'px';
- pluviam.style.width = diameter + 'px';
- pluviam.style.height = diameter + 'px';
-
- this.appendChild(pluviam);
-
- setTimeout(function () {
- pluviam.remove();
- }, 1000);
- }
-
- component.addEventListener('mousedown', createPluviam);
- component.addEventListener('mouseover', createPluviam);
- }
-});
\ No newline at end of file