diff options
author | David Phillips <dbphillipsnz@gmail.com> | 2016-02-18 19:24:32 +1300 |
---|---|---|
committer | David Phillips <dbphillipsnz@gmail.com> | 2016-02-18 20:54:57 +1300 |
commit | fc3c7e2a7769dcc433e47450455f604442e88631 (patch) | |
tree | cafb1002e711682bb621cc35515bbfdf0660fd4a | |
download | petrichor-fc3c7e2a7769dcc433e47450455f604442e88631.tar.xz |
Import
-rw-r--r-- | LICENSE | 23 | ||||
-rw-r--r-- | bg.jpg | bin | 0 -> 156967 bytes | |||
-rw-r--r-- | iec5009.svg | 14 | ||||
-rw-r--r-- | index.html | 168 | ||||
-rw-r--r-- | index.theme | 7 | ||||
-rw-r--r-- | petrichor.css | 134 | ||||
-rw-r--r-- | petrichor.js | 150 |
7 files changed, 496 insertions, 0 deletions
@@ -0,0 +1,23 @@ +Copyright © 2016 David Phillips. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Binary files differdiff --git a/iec5009.svg b/iec5009.svg new file mode 100644 index 0000000..ec62caa --- /dev/null +++ b/iec5009.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.2" baseProfile="tiny"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="177px" height="202px" viewBox="-0.8 -0.5 177 202" xml:space="preserve">
+<defs>
+</defs>
+<path fill="none" stroke="#FFFFFF" stroke-width="30" stroke-linecap="round" d="M33.7,64.3C22.1,77.2,15,94.3,15,113
+ c0,40.1,32.5,72.7,72.7,72.7c40.1,0,72.7-32.5,72.7-72.7c0-18.7-7.1-35.8-18.7-48.7"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="30" stroke-linecap="round" x1="87.8" y1="15" x2="87.8" y2="113"/>
+</svg>
diff --git a/index.html b/index.html new file mode 100644 index 0000000..ef7ddc0 --- /dev/null +++ b/index.html @@ -0,0 +1,168 @@ +<html> + <head> + <link rel="stylesheet" type="text/css" href="petrichor.css" /> + <script type="text/javascript"> + + password_prompt = false; + selected_user = null; + time_remaining = 0 + + function show_prompt(text, type) + { + password_prompt = true; + label = document.getElementById('password_label'); + label.innerHTML = text; + + users = document.getElementById('users'); + for (i in users.children) + { + user = users.children[i]; + if (user.id != ('user_' + selected_user) && user.style != null) + user.style.opacity = 0.1; + } + + entry = document.getElementById('password_entry'); + entry.value = ''; + + var selected = document.getElementById("user_" + selected_user); + rect = selected.getBoundingClientRect(); + cont = document.getElementById('password_container'); + + cont.style.top = rect.top; + if (cont.style.left != rect.right) + cont.style.left = rect.right; + cont.classList.add('shown'); + + entry.focus(); + } + + function show_message(text, type) + { + cont = document.getElementById('message_container'); + document.getElementById('message_label').innerHTML = text; + + if (text.length > 0) + { + var selected = document.getElementById("user_" + selected_user); + rect = selected.getBoundingClientRect(); + + cont.style.top = rect.top; + if (cont.style.left != rect.right) + cont.style.left = rect.right; + cont.style.top = rect.top; + cont.classList.add("shown"); + } else { + cont.classList.remove("shown"); + } + } + + function reset() + { + users = document.getElementById('users'); + for (i in users.children) + { + child = users.children[i]; + if (child.style != null) + child.style.opacity = 1; + } + document.getElementById('password_container').classList.remove("shown"); + password_prompt = false; + } + + function authentication_complete() + { +// document.getElementById('password_entry').value = ''; + if (lightdm.is_authenticated) + lightdm.start_session_sync(lightdm.authentication_user, lightdm.default_session); + else + show_message('<span class="error-icon">⚠</span> Authentication Failed'); + + reset(); + } + + function start_authentication(username) + { + document.getElementById('message_container').classList.remove("shown"); + + if (!password_prompt) { + selected_user = username; + lightdm.authenticate(username); + } + } + + function provide_secret() + { + entry = document.getElementById('password_entry'); + lightdm.respond(entry.value); + } + + function autologin_timer_expired(username) + { + lightdm.authenticate(lightdm.autologin_user); + } + + function countdown() + { + label = document.getElementById('countdown_label'); + label.innerHTML = ' in ' + time_remaining + ' seconds'; + time_remaining--; + if (time_remaining >= 0) + setTimeout('countdown()', 1000); + } + + function update_time() + { + var days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; + var months = ["January","February","March","April","May","June","July","August","September","October","November","December"]; + var d = new Date(); + niceHours = d.getHours(); + niceMinutes = d.getMinutes(); + // I'm yearning for strftime + if (niceHours < 10) + niceHours = "0"+niceHours; + if (niceMinutes < 10) + niceMinutes = "0"+niceMinutes; + document.getElementById('date').innerHTML = days[d.getDay()] + ", " + d.getDate() + " " + months[d.getMonth()]; + document.getElementById('time').innerHTML = niceHours + ":" + niceMinutes; + setTimeout('update_time()', 1000); + } + + document.write('<div id="users">'); + for (i in lightdm.users) + { + user = lightdm.users[i]; + + image = user.image; + + document.write('<div class="user" id="user_' + user.name +'"onclick="start_authentication(\'' + user.name + '\')" style="cursor: pointer;">'); + document.write('<img class="avatar" src="file:///' + image + '" /><span class="name">'+user.display_name+'</span>'); + if (user.name == lightdm.autologin_user && lightdm.autologin_timeout > 0) + document.write('<span id="countdown_label"></span>'); + document.write(' </div>'); + } + document.write('</div>'); + + + time_remaining = lightdm.autologin_timeout; + if (time_remaining > 0) + countdown(); + </script> + </head> + + <body onclick="reset();" onload="update_time();"> + <div id="date-container"> + <div id="date"></div> + <div id="time"></div> + </div> + <div id="password_container"> + <form action="javascript:provide_secret()"> + <span id="password_label"></span> + <input id="password_entry" type="password" /> + </form> + </div> + <div id="message_container"> + <span id="message_label"></span> + </div> + <img id="shutdown" src="iec5009.svg" onclick="lightdm.shutdown();" /> + </body> +</html> diff --git a/index.theme b/index.theme new file mode 100644 index 0000000..2ef8456 --- /dev/null +++ b/index.theme @@ -0,0 +1,7 @@ +[theme] +name=Petrichor +version=1.0 +description=Petrichor Theme +engine=lightdm-webkit2-greeter +url=index.html +session=dwm diff --git a/petrichor.css b/petrichor.css new file mode 100644 index 0000000..36dc4d9 --- /dev/null +++ b/petrichor.css @@ -0,0 +1,134 @@ +html +{ + color: #FFF; + background-image: url('bg.jpg'); + background-size: cover; + font-family: "Roboto Condensed"; +} + +body,html +{ + padding: 0px; + margin: 0px; + width: 100%; +} + +#shutdown +{ + cursor: pointer; + opacity: 0.5; + width: 96px; + position: absolute; + right: 50px; + bottom: 50px; + transition: opacity ease 0.3s; +} + +.error-icon +{ + font-size: 1.1em; + font-weight: bold; + color: #F00; +} + +#shutdown:hover +{ + opacity: 1; +} + +#users div.user +{ + transition: opacity ease 0.15s; +} + +div.user +{ + text-align: center; + color: white; + margin-top: 2em; +} + +.avatar +{ + object-fit: cover; + width: 96px; + height: 96px; + border-radius: 48px; +} + +.name +{ + display: block; +} + +#password_prompt, #password_entry +{ + display: block; + font-size: 20px; +} + +#users +{ + position: absolute; + bottom: 50px; + left: 50px; +} + +#message_container +{ + font-size: 20px; +} + +#password_entry +{ + color: #333; + opacity: inherit; + background-color: rgba(255,255,255,255,0.2); + padding: 0.2em; + border: 1px solid #DDD; + border-radius: 5px; +} + +#message_container, #password_container +{ + height: 96px; + display: table; + position: absolute; + padding-left: 2em; + visibility: hidden; + opacity: 0; + transition: visibility 0s linear 0.15s, opacity 0.15s linear; +} + +#password_container.shown, #message_container.shown +{ + visibility: visible; + opacity: 1; + transition: opacity 0.15s linear 0.05s; +} + +#message_label, #password_container > form +{ + display: table-cell; + vertical-align: middle; +} + +#date, #time +{ + font-family: Roboto; + text-align: right; + color: #FFF; +} + +#date +{ + margin-top: 50px; + margin-right: 65px; + font-size: 50px; +} + +#time +{ + margin-right: 30px; + font-size: 240px; +} diff --git a/petrichor.js b/petrichor.js new file mode 100644 index 0000000..c96c21e --- /dev/null +++ b/petrichor.js @@ -0,0 +1,150 @@ +password_prompt = false; +selected_user = null; +time_remaining = 0 + +function show_prompt(text, type) +{ + password_prompt = true; + label = document.getElementById('password_label'); + label.innerHTML = text; + + users = document.getElementById('users'); + for (i in users.children) + { + user = users.children[i]; + if (user.id != ('user_' + selected_user) && user.style != null) + user.style.opacity = 0.1; + } + + entry = document.getElementById('password_entry'); + entry.value = ''; + + var selected = document.getElementById("user_" + selected_user); + rect = selected.getBoundingClientRect(); + cont = document.getElementById('password_container'); + + cont.style.top = rect.top; + if (cont.style.left != rect.right) + cont.style.left = rect.right; + cont.classList.add('shown'); + + entry.focus(); +} + +function show_message(text, type) +{ + cont = document.getElementById('message_container'); + document.getElementById('message_label').innerHTML = text; + + if (text.length > 0) + { + var selected = document.getElementById("user_" + selected_user); + rect = selected.getBoundingClientRect(); + + cont.style.top = rect.top; + if (cont.style.left != rect.right) + cont.style.left = rect.right; + cont.style.top = rect.top; + cont.classList.add("shown"); + } else { + cont.classList.remove("shown"); + } +} + +function reset() +{ + users = document.getElementById('users'); + for (i in users.children) + { + child = users.children[i]; + if (child.style != null) + child.style.opacity = 1; + } + document.getElementById('password_container').classList.remove("shown"); + password_prompt = false; +} + +function authentication_complete() +{ + if (lightdm.is_authenticated) + lightdm.start_session_sync(lightdm.authentication_user, lightdm.default_session); + else + show_message('<span class="error-icon">⚠</span> Authentication Failed'); + + reset(); +} + +function start_authentication(username) +{ + document.getElementById('message_container').classList.remove("shown"); + + if (!password_prompt) { + selected_user = username; + lightdm.authenticate(username); + } +} + +function provide_secret() +{ + entry = document.getElementById('password_entry'); + lightdm.respond(entry.value); +} + +function autologin_timer_expired(username) +{ + lightdm.authenticate(lightdm.autologin_user); +} + +function countdown() +{ + label = document.getElementById('countdown_label'); + label.innerHTML = ' in ' + time_remaining + ' seconds'; + time_remaining--; + if (time_remaining >= 0) + setTimeout('countdown()', 1000); +} + +function update_time() +{ + var days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; + var months = ["January","February","March","April","May","June","July","August","September","October","November","December"]; + var d = new Date(); + niceHours = d.getHours(); + niceMinutes = d.getMinutes(); + // I'm yearning for strftime + if (niceHours < 10) + niceHours = "0"+niceHours; + if (niceMinutes < 10) + niceMinutes = "0"+niceMinutes; + document.getElementById('date').innerHTML = days[d.getDay()] + ", " + d.getDate() + " " + months[d.getMonth()]; + document.getElementById('time').innerHTML = niceHours + ":" + niceMinutes; + setTimeout('update_time()', 1000); +} + +function start() +{ + document.write('<div id="users">'); + for (i in lightdm.users) + { + user = lightdm.users[i]; + + if (user.image.match(/\.face$/)) + image = '/usr/share/icons/Adwaita/256x256/emotes/face-laugh.png'; + else + image = user.image; + + document.write('<div class="user" id="user_' + user.name +'"onclick="start_authentication(\'' + user.name + '\')" style="cursor: pointer;">'); + document.write('<img class="avatar" src="file:///' + image + '" /><span class="name">'+user.display_name+'</span>'); + + if (user.name == lightdm.autologin_user && lightdm.autologin_timeout > 0) + document.write('<span id="countdown_label"></span>'); + + document.write(' </div>'); + } + document.write('</div>'); + + + time_remaining = lightdm.autologin_timeout; + if (time_remaining > 0) + countdown(); +} |