diff --git a/themes/dracula/assets/dracula.png b/themes/dracula/assets/dracula.png
new file mode 100644
index 0000000..19bf67e
Binary files /dev/null and b/themes/dracula/assets/dracula.png differ
diff --git a/themes/dracula/css/DRACULA b/themes/dracula/css/DRACULA
new file mode 100644
index 0000000..dcaf6d7
--- /dev/null
+++ b/themes/dracula/css/DRACULA
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Dracula Theme
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/themes/dracula/css/style.css b/themes/dracula/css/style.css
new file mode 100644
index 0000000..429de2f
--- /dev/null
+++ b/themes/dracula/css/style.css
@@ -0,0 +1,546 @@
+:root {
+
+ --bg0: #282A36;
+ --bg1: #44475A;
+ --bg2: #585C74;
+ --bg3: #666e99;
+
+ --alt0: #6272A4;
+ --alt1: #7A88B3;
+
+ --fg0: #F8F8F2;
+ --fg1: #EAEAE0;
+ --fg2: #DEDED2;
+
+ --cyan: #8BE9fD;
+ --green: #50FA7B;
+ --orange: #FFb86C;
+ --pink: #FF79C6;
+ --purple: #BD93F9;
+ --red: #FF5555;
+ --yellow: #F1FA8C;
+
+ --animation-duration: 300ms;
+}
+
+/* High DPI */
+
+@media screen and (min-width: 3000px) and (min-height: 1200px) {
+ html {
+ zoom: 2.0;
+ }
+}
+
+/* Basic */
+
+html {
+ height: 100vh;
+ width: 100vw;
+ background-color: black;
+ font-size: 16px;
+}
+html * {
+ font-family: system-ui;
+ font-size: 16px;
+ transition: var(--animation-duration);
+ color: var(--fg0);
+}
+
+body {
+ height: 100vh;
+ width: 100vw;
+ margin: 0;
+ overflow-x: hidden;
+ background-color: var(--bg0);
+}
+
+.hide {
+ opacity: 0;
+ visibility: hidden;
+ max-height: 0;
+ max-width: 0;
+ display: none;
+}
+
+/* Scrollbar */
+
+::-webkit-scrollbar {
+ width: 6px;
+}
+::-webkit-scrollbar-thumb {
+ background-color: var(--fg2);
+}
+::-webkit-scrollbar-thumb:hover {
+ background-color: var(--fg0);
+}
+
+/* Background */
+
+#background {
+ height: 100vh;
+ width: 100vw;
+ position: absolute;
+
+ background-color: var(--bg0);
+}
+
+#background img {
+ width: inherit;
+ height: inherit;
+ object-fit: cover;
+ object-position: center;
+}
+
+#bg-cover {
+ backdrop-filter: blur(4px);
+ position: absolute;
+ height: inherit;
+ width: inherit;
+}
+
+#screen {
+ height: 100vh;
+ width: 100vw;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+#cover {
+ height: 100vh;
+ width: 100vw;
+ position: absolute;
+ z-index: 10;
+ transition: var(--animation-duration);
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ background-color: #282A36aa;
+ backdrop-filter: blur(5px);
+}
+#cover > #message {
+ font-size: 4em;
+ font-weight: bold;
+ cursor: default;
+}
+
+/* Login form */
+
+#login-wrapper {
+ position: relative;
+ background: var(--bg1);
+ border-radius: 2px;
+ max-height: 90vh;
+ width: 30em;
+ box-sizing: border-box;
+ transition: var(--animation-duration);
+
+ /*display: flex;*/
+ /*justify-content: center;*/
+ /*align-items: flex-start;*/
+}
+body.success #login-wrapper {
+ background-color: #79d28f;
+}
+body.failed #login-wrapper {
+ background-color: #dd7878;
+}
+
+#login-wrapper-box {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 1.8em 3em;
+ height: 8em;
+}
+
+#login-form {
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+ flex-direction: column;
+ height: 10em;
+ max-width: fit-content;
+}
+
+input {
+ background-color: var(--bg2);
+ color: var(--fg0);
+ border: 0;
+ border-radius: 2px;
+ padding: 1em;
+ margin: 0.5em;
+ font-size: inherit;
+ font-family: inherit;
+}
+input:focus, input:focus-visible {
+ border: 0;
+ outline: auto var(--fg0);
+}
+:focus {
+ outline: auto var(--fg0) !important;
+}
+
+#pass-form.hide {
+ visibility: hidden;
+ max-height: initial;
+ max-width: initial;
+ display: flex;
+}
+
+#input-password {
+ box-shadow: 0 2px var(--cyan);
+ box-sizing: border-box;
+ margin: 0;
+}
+
+#input-username {
+ box-sizing: border-box;
+ width: 100%;
+ margin: 0;
+ box-shadow: 0 2px var(--orange);
+}
+
+::placeholder {
+ color: var(--fg2);
+}
+
+#pass-wrapper {
+ display: flex;
+ width: 100%;
+ flex-direction: row;
+}
+
+#user-wrapper {
+ display: flex;
+ width: 100%;
+ flex-direction: row;
+ position: relative;
+}
+
+#submit-button {
+ background-color: #72bece;
+}
+#submit-button:hover, #submit-button:focus {
+ background-color: var(--purple);
+}
+
+#users-button-wrapper {
+ display: flex;
+ flex-direction: column;
+}
+
+#users-button {
+ background-color: var(--orange);
+ height: 100%;
+}
+#users-button:hover, #users-button:focus {
+ background-color: var(--red);
+}
+
+#users-dropdown {
+ height: 0;
+}
+
+#users-dropdown .dropdown {
+ background-color: var(--bg2);
+ right: 0;
+ z-index: 2;
+}
+#users-dropdown .dropdown button:hover, #users-dropdown .dropdown button:focus {
+ background-color: var(--orange);
+}
+
+/* Time and date */
+
+#time-date {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background-color: transparent;
+ transition: var(--animation-duration);
+ overflow: hidden;
+ cursor: pointer;
+}
+
+#time-date:hover, #time-date:focus {
+ filter: drop-shadow(2px 2px 6px black);
+ /*animation-name: shake;*/
+ animation-duration: 1s;
+ animation-direction: normal;
+ animation-iteration-count: 1;
+ animation-timing-function: ease-in-out;
+}
+#time-date:hover *, #time-date:focus * {
+ /*color: var(--cyan);*/
+}
+#time-date.hide {
+ display: flex;
+ max-height: initial;
+ max-width: initial;
+ opacity: 0;
+}
+
+#time-label {
+ font-size: 4em;
+ margin: 0;
+}
+
+/* Buttons */
+button {
+ /*color: var(--fg0);*/
+ border: 0;
+ /*font-size: inherit;*/
+ /*font-family: inherit;*/
+}
+
+.button {
+ background: var(--purple);
+ border: 0;
+ padding: 0.5em;
+ font-size: inherit;
+ cursor: pointer;
+ border-radius: 2px;
+ transition: var(--animation-duration);
+}
+
+.button-group {
+ background: var(--purple);
+ border: 0;
+ padding: 0;
+ font-size: inherit;
+ border-radius: 2px;
+ transition: var(--animation-duration);
+}
+.button-group > * {
+ background-color: transparent;
+ cursor: pointer;
+ padding: 0.5em 0.8em;
+ transition: inherit;
+}
+.button-group > *:hover, .button-group > *:focus {
+ background-color: var(--orange);
+}
+
+/* Auth message */
+
+#auth-message {
+ position: absolute;
+ font-size: 4em;
+ font-weight: bold;
+}
+#auth-message.hide {
+ display: block;
+ max-width: initial;
+ max-height: initial;
+}
+
+/* Bottom bar */
+#bottom-bar {
+ background-color: #585c7480;
+ backdrop-filter: blur(10px);
+ width: -webkit-fill-available;
+ min-height: 2em;
+
+ display: flex;
+ align-items: stretch;
+ padding: 0.5em;
+}
+#bottom-bar * {
+ font-weight: bold;
+}
+
+#bottom-bar .button {
+ display: flex;
+ align-items: center;
+ padding: 0.5em 0.75em;
+}
+
+#sessions-button {
+ background-color: var(--bg3);
+}
+#sessions-button > span {
+ margin-left: 0.3em;
+}
+
+#sessions-button:hover, #sessions-button:focus {
+ background-color: var(--purple);
+}
+
+#sessions-dropdown {
+ max-height: 25vh;
+}
+
+#bottom-right {
+ background-color: var(--bg3);
+ margin-left: auto;
+ display: flex;
+}
+
+/* Top bar */
+#top-bar {
+ background-color: transparent;
+ width: -webkit-fill-available;
+ min-height: 2em;
+ padding: 1em;
+ padding-bottom: 0;
+ font-weight: bold;
+
+ transition: var(--animation-duration);
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+#bottom-bar.hide, #top-bar.hide {
+ min-height: 0;
+ max-height: 0;
+ max-width: initial;
+ display: flex;
+ overflow: hidden;
+ padding: 0;
+ margin: 0;
+ opacity: 0;
+}
+
+/* Panel */
+
+#panel-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin: 1em;
+
+ background-color: var(--bg1);
+}
+#panel-button:hover, #panel-button:focus {
+ background-color: var(--green);
+}
+
+.panel {
+ position: fixed;
+ width: 350px;
+ height: -webkit-fill-available;
+ background: var(--bg2);
+ right: 0;
+
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-content: flex-start;
+ padding: 1.5em;
+
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.panel.hide {
+ transform: translateX(100%);
+ display: flex;
+ visibility: hidden;
+ opacity: 100%;
+ max-width: 100vw;
+ max-height: 100vh;
+}
+
+.panel .image {
+ display: flex;
+ flex-direction: column;
+ width: 48%;
+ background-color: transparent;
+ margin-top: 1em;
+ padding: 0;
+ cursor: pointer;
+ border-color: var(--fg0);
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 0;
+}
+
+.panel .image > img {
+ background-color: var(--alt1);
+ width: -webkit-fill-available;
+ max-height: 200px;
+ object-fit: cover;
+ filter: brightness(0.8);
+}
+.panel .image:hover, .panel .image:focus {
+ filter: drop-shadow(2px 2px 6px black);
+}
+.panel .image:hover > img, .panel .image:focus > img {
+ filter: brightness(1);
+}
+
+.panel h3 {
+ width: 80%;
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 1.2em;
+ align-self: center;
+}
+
+#close-panel-button {
+ background-color: var(--alt1);
+ height: fit-content;
+ align-self: center;
+}
+#close-panel-button:hover, #close-panel-button:focus {
+ background-color: var(--red);
+}
+
+/* Dropdown */
+.dropdown {
+ position: absolute;
+ background-color: var(--bg2);
+ min-width: 8em;
+ max-height: 60vh;
+ overflow-y: auto;
+ margin: 0;
+ padding: 0;
+ transition: var(--animation-duration);
+}
+.dropdown button {
+ background-color: transparent;
+ color: var(--fg0);
+ padding: 0.8em;
+ width: -webkit-fill-available;
+ cursor: pointer;
+}
+.dropdown button:hover, .dropdown button:focus {
+ background-color: var(--purple);
+}
+
+.dropdown li {
+ text-decoration: none;
+ display: block;
+}
+
+.dropdown.hide {
+ visibility: hidden;
+ opacity: 100%;
+ display: block;
+ max-height: 0 !important;
+ overflow-y: hidden;
+}
+
+/* Animations */
+
+@keyframes shake {
+ 0% {
+ transform: rotateZ(0deg);
+ }
+ 25% {
+ transform: rotateZ(10deg);
+ }
+ 75% {
+ transform: rotateZ(-10deg);
+ }
+ 100% {
+ transform: rotateZ(0deg);
+ }
+}
diff --git a/themes/dracula/index.html b/themes/dracula/index.html
new file mode 100644
index 0000000..d257ad1
--- /dev/null
+++ b/themes/dracula/index.html
@@ -0,0 +1,135 @@
+
+
+
+
+
+ Dracula theme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Welcome!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/themes/dracula/js/accounts.js b/themes/dracula/js/accounts.js
new file mode 100644
index 0000000..4d84b69
--- /dev/null
+++ b/themes/dracula/js/accounts.js
@@ -0,0 +1,89 @@
+class Accounts {
+ constructor() {
+ this._localStorage = window.localStorage
+ this._userWrapper = document.querySelector("#user-wrapper")
+ this._accountsList = document.querySelector("#users-dropdown")
+ this._accountsButton = document.querySelector("#users-button")
+ this._defaultUser = null
+ this._usersObject = null
+ this._init()
+ }
+
+ getDefaultUserName() {
+ return this._defaultUser.username
+ }
+
+ _setAccountDefault() {
+ let input = this._userWrapper.querySelector("input")
+ if (this._defaultUser.username != "") {
+ //input.classList.add("hide")
+ input.value = this._defaultUser.username
+ } else {
+ input.value = ""
+ }
+ if (this._usersObject.length > 0) {
+ this._accountsButton.classList.remove("hide")
+ }
+ }
+
+ _updateOnStartup() {
+ var username = ""
+ if (this._usersObject.length > 0) {
+ username = this._localStorage.getItem("defaultUser") || this._usersObject[0].username
+ }
+ var user = this._usersObject.find((val) => {return val.username === username})
+ if (user === undefined) {
+ this._defaultUser = {username: "", display_name: ""}
+ } else {
+ this._defaultUser = user
+ }
+ this._setAccountDefault()
+ }
+
+ _setAccountList() {
+ var dropdown = this._accountsList.querySelector(".dropdown")
+ dropdown.innerHTML = ""
+
+ for (let i = 0; i < this._usersObject.length; i++) {
+ var name = this._usersObject[i].display_name
+ var li = document.createElement("li")
+ var button = document.createElement("button")
+ button.type = "button"
+ button.innerText = name
+ button.addEventListener("click", () => {
+ this._updateDefaults(this._usersObject[i])
+ this._setAccountDefault()
+ //authenticate.startAuthentication()
+ })
+
+ li.appendChild(button)
+ dropdown.appendChild(li)
+ }
+ }
+
+ _setButton() {
+ var dropdown = this._accountsList.querySelector(".dropdown")
+ document.querySelector("#screen").addEventListener("click", (ev) => {
+ if (ev.target == this._accountsButton || ev.target.parentElement == this._accountsButton) {
+ dropdown.classList.toggle("hide")
+ } else
+ if (ev.target != this._accountsList && ev.target.closest(".dropdown") == null) {
+ dropdown.classList.add("hide")
+ }
+ })
+ }
+
+ _updateDefaults(userObject) {
+ if (!userObject) return
+ this._defaultUser = userObject
+
+ this._localStorage.setItem("defaultUser", this._defaultUser.username)
+ }
+
+ _init() {
+ this._usersObject = lightdm.users
+ this._updateOnStartup()
+ this._setAccountList()
+ this._setButton()
+ }
+}
diff --git a/themes/dracula/js/authenticate.js b/themes/dracula/js/authenticate.js
new file mode 100644
index 0000000..318032a
--- /dev/null
+++ b/themes/dracula/js/authenticate.js
@@ -0,0 +1,112 @@
+class Authenticate {
+ constructor() {
+ this._form = document.querySelector("#login-form")
+ this._username = ""
+ this._password = ""
+ this._init()
+ }
+
+ _setForm() {
+ this._form.addEventListener("submit", (ev) => {
+ ev.preventDefault()
+ var inputs = this._form.querySelectorAll("input")
+ var data = getArrayForm(inputs)
+ if (!data) return false
+ this._username = data.username
+ this._password = data.password
+ this._respond()
+ })
+ }
+
+ _respond() {
+ let inputUser = document.querySelector("#input-username")
+ let inputPass = document.querySelector("#input-password")
+ inputUser.blur(); inputUser.disabled = true;
+ inputPass.blur(); inputPass.disabled = true;
+
+ lightdm.cancel_authentication()
+ lightdm.authenticate(String(this._username))
+ lightdm.respond(this._password)
+ }
+
+ _showMessage(msg) {
+ let message = document.querySelector("#auth-message")
+ message.innerText = msg
+ message.classList.remove("hide")
+ }
+
+ _hideMessage() {
+ let message = document.querySelector("#auth-message")
+ message.classList.add("hide")
+ }
+
+ async _authentication_done() {
+ let body = document.querySelector("body")
+ body.classList.add("success")
+
+ this._showMessage("Welcome!")
+
+ let form = document.querySelector("#pass-form")
+ let topbar = document.querySelector("#top-bar")
+ let bottombar = document.querySelector("#bottom-bar")
+ form.style.transition = "0ms"
+ form.classList.add("hide")
+ topbar.classList.add("hide")
+ bottombar.classList.add("hide")
+
+ await wait(1000)
+ let defSession = String(sessions.getDefaultSession())
+ document.querySelector("body").style.opacity = 0
+
+ await wait(1000)
+ console.log("Session started with", defSession)
+ lightdm.start_session(defSession)
+ }
+
+ async _authentication_failed() {
+ lightdm.cancel_authentication()
+ let body = document.querySelector("body")
+ body.classList.add("failed")
+
+ this._showMessage("Try again")
+
+ let form = document.querySelector("#pass-form")
+ let topbar = document.querySelector("#top-bar")
+ let bottombar = document.querySelector("#bottom-bar")
+ form.style.transition = "0ms"
+ form.classList.add("hide")
+ topbar.classList.add("hide")
+ bottombar.classList.add("hide")
+
+ await wait(1500)
+
+ this._hideMessage()
+ form.style.transition = ""
+ form.classList.remove("hide")
+ topbar.classList.remove("hide")
+ bottombar.classList.remove("hide")
+
+ let inputUser = document.querySelector("#input-username")
+ let inputPass = document.querySelector("#input-password")
+ inputUser.blur(); inputUser.disabled = false;
+ inputPass.blur(); inputPass.disabled = false;
+ inputPass.value = ""
+
+ body.classList.remove("failed")
+ }
+
+ _setAuthentication_done() {
+ window.authentication_done = () => {
+ if (lightdm.is_authenticated) {
+ this._authentication_done()
+ } else {
+ this._authentication_failed()
+ }
+ }
+ }
+
+ _init() {
+ this._setForm()
+ this._setAuthentication_done()
+ }
+}
diff --git a/themes/dracula/js/debug.js b/themes/dracula/js/debug.js
new file mode 100644
index 0000000..49e047c
--- /dev/null
+++ b/themes/dracula/js/debug.js
@@ -0,0 +1,155 @@
+class Debug {
+ constructor() {
+ this._debugPass = "tepes"
+ this._init()
+ }
+
+ _init() {
+ console.log("DEBUG")
+
+ if (!window.greeter_config) {
+ window.greeter_config = {
+ greeter: {
+ debug_mode: true,
+ },
+ branding: {
+ background_images_dir: "",
+ }
+ }
+ }
+
+ if (!window.theme_utils) {
+ window.theme_utils = {}
+ window.theme_utils.dirlist = function(path, mode, callback) {
+ var result = []
+ callback(result)
+ };
+ window.theme_utils.bind_this = function(context) {return context}
+ }
+
+ if (!window.lightdm) {
+ window.lightdm = {}
+ }
+
+ var local_lightdm = {
+ default_password: "tepes",
+ is_authenticated: false,
+ authentication_user: null,
+ default_session: "awesome",
+ can_suspend: true,
+ can_hibernate: true,
+ can_shutdown: true,
+ can_restart: true,
+ can_access_battery: true,
+ can_access_brightness: true,
+ sessions: [
+ {
+ name: "awesome wm",
+ key: "awesome"
+ },
+ {
+ name: "Ubuntu",
+ key: "ubuntu"
+ },
+ {
+ name: "i3wm",
+ key: "i3"
+ },
+ {
+ name: "bspwm",
+ key: "bspwm"
+ }
+ ],
+ users: [
+ {
+ display_name: "Vlad Tepes",
+ username: "dracula",
+ image: ""
+ },
+ {
+ display_name: "Trevor Belmont",
+ username: "treffy",
+ image: ""
+ },
+ {
+ display_name: "Sypha Belnades",
+ username: "speaker",
+ image: ""
+ }
+ ],
+ languages: [
+ {
+ name: 'American English',
+ code: 'en_US.utf8'
+ }
+ ],
+ language: 'American English',
+ authenticate: username => {
+ console.log(`Starting authentication with user: "${username}"`)
+ },
+ cancel_authentication: () => {
+ console.log(`Authentication cancelled`)
+ },
+ respond: async (password) => {
+ console.log(`Password provided: "${password}"`)
+ if (password == this._debugPass) {
+ lightdm.is_authenticated = true
+ } else {
+ await wait(2000)
+ }
+ authentication_done()
+ },
+ start_session: session => {
+ alert(`Logged with session: "${session}"`)
+ location.reload()
+ },
+ shutdown: () => {
+ console.log("System is shutting down...")
+ setTimeout(() => location.reload(), 2000)
+ },
+ restart: () => {
+ console.log("System is rebooting...")
+ setTimeout(() => location.reload(), 2000)
+ },
+ hibernate: () => {
+ console.log("System is hibernating")
+ setTimeout(() => location.reload(), 2000)
+ },
+ suspend: () => {
+ console.log("System is suspending")
+ setTimeout(() => location.reload(), 2000)
+ },
+ batteryData: {
+ name: "Battery 0",
+ level: 85,
+ state: "Discharging"
+ },
+ batteryUpdate: () => {
+ console.log("Battery updated")
+ },
+ brightness: 50,
+ brightnessSet: (quantity) => {
+ lightdm.brightness = quantity
+ },
+ brightnessIncrease: (quantity) => {
+ lightdm.brightness += quantity
+ if (lightdm.brightness > 100) lightdm.brightness = 100
+ },
+ brightnessDecrease: (quantity) => {
+ lightdm.brightness -= quantity
+ if (lightdm.brightness < 0) lightdm.brightness = 0
+ }
+ }
+
+ if (lightdm.mock == undefined) {
+ window.lightdm = {}
+ Object.assign(window.lightdm, local_lightdm)
+ } else {
+ Object.keys(local_lightdm).forEach((key) => {
+ var realKey = `_${key}`
+ lightdm[realKey] = local_lightdm[key]
+ })
+ }
+
+ }
+}
diff --git a/themes/dracula/js/index.js b/themes/dracula/js/index.js
new file mode 100644
index 0000000..e985072
--- /dev/null
+++ b/themes/dracula/js/index.js
@@ -0,0 +1,130 @@
+
+function getArrayForm(inputs) {
+ if (!inputs) return false
+ var data = {}
+ inputs.forEach((x) => {
+ data[x.name] = x.value
+ })
+ return data
+}
+
+async function wait(ms) {
+ return new Promise( resolve => {
+ setTimeout(() => {
+ resolve()
+ }, ms)
+ })
+}
+
+
+async function initGreeter() {
+
+ if (greeter_config.greeter.debug_mode) {
+ debug = new Debug()
+ }
+
+ lightdm.authentication_complete?.connect(() => authentication_done())
+
+ lightdm.brightness_update?.connect(() => brightness._updateData())
+
+ accounts = new Accounts()
+
+ sessions = new Sessions()
+
+ authenticate = new Authenticate()
+
+ sidebar = new Sidebar()
+
+ //power = new Power()
+
+ //battery = new Battery()
+
+ //brightness = new Brightness()
+
+}
+
+window.addEventListener("GreeterReady", initGreeter)
+
+//const panel_button = document.querySelector("#panel-button")
+//const close_panel_button = document.querySelector("#close-panel-button")
+const panel = document.querySelector(".panel")
+const screen = document.querySelector("#screen")
+
+const sessions_button = document.querySelector("#sessions-button")
+const sessions_dropdown = document.querySelector("#sessions-dropdown")
+
+const time_date_button = document.querySelector("#time-date")
+const pass_form = document.querySelector("#pass-form")
+
+//screen.addEventListener("click", (ev) => {
+ //if (ev.target == panel_button || ev.target.parentElement == panel_button) {
+ //panel.classList.toggle("hide")
+ //panel_button.blur()
+ //wait(100).then(() => {close_panel_button.focus()})
+ //} else
+ //if (ev.target != panel && ev.target.closest(".panel") == null) {
+ //panel.classList.add("hide")
+ //}
+
+ //if (ev.target == close_panel_button || ev.target.parentElement == close_panel_button) {
+ //panel.classList.toggle("hide")
+ //panel_button.focus()
+ //}
+
+ //if (ev.target == sessions_button || ev.target.parentElement == sessions_button) {
+ //sessions_dropdown.classList.toggle("hide")
+ //} else
+ //if (ev.target != sessions_dropdown && ev.target.closest(".dropdown") == null) {
+ //sessions_dropdown.classList.add("hide")
+ //}
+//})
+
+async function toggleTimeDate() {
+ time_date_button.blur()
+ pass_form.blur()
+ if (time_date_button.classList.contains("hide")) {
+ pass_form.classList.add("hide")
+ await wait(300)
+ time_date_button.classList.remove("hide")
+ await wait(100)
+ time_date_button.focus()
+ } else {
+ time_date_button.classList.add("hide")
+ await wait(300)
+ pass_form.classList.remove("hide")
+ }
+}
+
+time_date_button.addEventListener("click", async (ev) => {
+ toggleTimeDate()
+})
+
+pass_form.addEventListener("keydown", (ev) => {
+ if (ev.keyCode == 27) {
+ toggleTimeDate()
+ }
+})
+
+//sessions_dropdown.addEventListener("keydown", (ev) => {
+ //if (ev.keyCode == 27) {
+ //sessions_dropdown.classList.toggle("hide")
+ //sessions_button.focus()
+ //}
+//})
+
+//panel.addEventListener("keydown", (ev) => {
+ //if (ev.keyCode == 27) {
+ //panel.classList.toggle("hide")
+ //panel_button.focus()
+ //}
+//})
+
+//const time_label = document.querySelector("#time-label")
+//const date_label = document.querySelector("#date-label")
+
+//function updateTimeDate() {
+ //time_label.innerText = theme_utils.get_current_localized_time()
+ //date_label.innerText = theme_utils.get_current_localized_date()
+//}
+
+//setInterval(updateTimeDate, 1000)
diff --git a/themes/dracula/js/sessions.js b/themes/dracula/js/sessions.js
new file mode 100644
index 0000000..9ae0d8a
--- /dev/null
+++ b/themes/dracula/js/sessions.js
@@ -0,0 +1,91 @@
+class Sessions {
+ constructor() {
+ this._localStorage = window.localStorage
+ this._sessionsButton = document.querySelector("#sessions-button")
+ this._sessionList = document.querySelector("#sessions-dropdown")
+ this._sessionLabel = document.querySelector("#sessions-button > .text")
+ this._defaultSession = null
+ this._sessionsObject = null
+ this._init()
+ }
+
+ getDefaultSession() {
+ return this._defaultSession.key
+ }
+
+ _setSessionDefault() {
+ this._sessionLabel.innerText = this._defaultSession.name
+ }
+
+ _updateOnStartup() {
+ var key = this._localStorage.getItem("defaultSession") || this._sessionsObject[0].key || lightdm.default_session
+
+ var session = this._sessionsObject.find((val) => {return val.key === key})
+ if (session === undefined) {
+ // This should never happen
+ this._defaultSession = {key: "awesome", name: "Awesome WM"}
+ } else {
+ this._defaultSession = session
+ }
+ this._setSessionDefault()
+ }
+
+ _updateDefaults(sessionObj) {
+ if (!sessionObj) return
+ this._defaultSession = sessionObj
+ this._localStorage.setItem("defaultSession", this._defaultSession.key)
+ }
+
+ _setSessionList() {
+ var dropdown = this._sessionList
+ dropdown.innerHTML = ""
+ for (let i = 0; i < this._sessionsObject.length; i++) {
+ var name = this._sessionsObject[i].name
+ var li = document.createElement("li")
+ var button = document.createElement("button")
+ button.innerText = name
+ button.addEventListener("click", () => {
+ this._updateDefaults(this._sessionsObject[i])
+ this._setSessionDefault()
+ })
+
+ li.appendChild(button)
+ dropdown.appendChild(li)
+ }
+ }
+
+ _setKeydown() {
+ var dropdown = this._sessionList
+ dropdown.addEventListener("keydown", (ev) => {
+ if (ev.keyCode == 27) {
+ sessions_dropdown.classList.add("hide")
+ this._sessionsButton.focus()
+ }
+ })
+ }
+
+ _setButton() {
+ var dropdown = this._sessionList
+ document.querySelector("#screen").addEventListener("click", (ev) => {
+ if (ev.target == this._sessionsButton || ev.target.parentElement == this._sessionsButton) {
+ dropdown.classList.toggle("hide")
+ } else
+ if (ev.target != this._sessionList && ev.target.closest(".dropdown") == null) {
+ dropdown.classList.add("hide")
+ }
+ })
+ document.querySelector("#screen").addEventListener("focusin", (ev) => {
+ if (!dropdown.contains(document.activeElement) && document.activeElement != this._sessionsButton) {
+ dropdown.classList.add("hide")
+ }
+ })
+ }
+
+ _init() {
+ this._sessionsObject = lightdm.sessions
+ this._updateOnStartup()
+ this._setSessionList()
+ this._setButton()
+ this._setKeydown()
+ }
+}
diff --git a/themes/dracula/js/sidebar.js b/themes/dracula/js/sidebar.js
new file mode 100644
index 0000000..5bc95a3
--- /dev/null
+++ b/themes/dracula/js/sidebar.js
@@ -0,0 +1,65 @@
+class Sidebar {
+ constructor() {
+ this._sidebar = document.querySelector("#sidebar")
+ this._sidebarButton = document.querySelector("#panel-button")
+ this._closeButton = document.querySelector("#close-panel-button")
+ this._visible = false
+ this._init()
+ }
+
+ showSidebar() {
+ this._sidebar.classList.remove("hide")
+ wait(100).then(() => {this._closeButton.focus()})
+ this._visible = true
+ }
+
+ hideSidebar() {
+ this._sidebar.classList.add("hide")
+ this._sidebarButton.focus()
+ this._visible = false
+ }
+
+ toggleSidebar() {
+ if (this._visible) {
+ this.hideSidebar()
+ } else {
+ this.showSidebar()
+ }
+ }
+
+ _setKeydown() {
+ this._sidebar.addEventListener("keydown", (ev) => {
+ if (ev.keyCode == 27) {
+ this.hideSidebar()
+ }
+ })
+ }
+
+ _setSidebar() {
+ document.querySelector("#screen").addEventListener("click", (ev) => {
+ if (ev.target == this._sidebarButton || ev.target.parentElement == this._sidebarButton) {
+ this.toggleSidebar()
+ } else
+ if (ev.target != this._sidebar && ev.target.closest(".panel") == null) {
+ this._sidebar.classList.add("hide")
+ this._visible = false
+ }
+
+ if (ev.target == this._closeButton || ev.target.parentElement == this._closeButton) {
+ this.hideSidebar()
+ }
+ })
+
+ document.querySelector("#screen").addEventListener("focusin", (ev) => {
+ if (!this._sidebar.contains(document.activeElement)) {
+ this._sidebar.classList.add("hide")
+ this._visible = false
+ }
+ })
+ }
+
+ _init() {
+ this._setSidebar()
+ this._setKeydown()
+ }
+}