diff --git a/themes/_vendor/js/mock.js b/themes/_vendor/js/mock.js
index 457f778..c001f64 100644
--- a/themes/_vendor/js/mock.js
+++ b/themes/_vendor/js/mock.js
@@ -1,3 +1,29 @@
+/*
+ * ThemeUtils.js
+ *
+ * Copyright © 2021 JezerM
+ *
+ * This file is part of Web Greeter.
+ *
+ * Web Greeter is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Web Greeter is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * The following additional terms are in effect as per Section 7 of the license:
+ *
+ * The preservation of all legal notices and author attributions in
+ * the material or in the Appropriate Legal Notices displayed
+ * by works containing it is required.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with web-greeter; If not, see .
+ */
class LightDMLanguage {
constructor( {code, name, territory} ) {
this.code = code;
@@ -793,8 +819,72 @@ class ThemeUtils {
return context;
}
- dirlist(path, noDir, callback) {
- callback([])
+ /**
+ * Returns the contents of directory found at `path` provided that the (normalized) `path`
+ * meets at least one of the following conditions:
+ * * Is located within the greeter themes' root directory.
+ * * Has been explicitly allowed in the greeter's config file.
+ * * Is located within the greeter's shared data directory (`/var/lib/lightdm-data`).
+ * * Is located in `/tmp`.
+ *
+ * @param {String} path The abs path to desired directory.
+ * @param {Boolean} only_images Include only images in the results. Default `true`.
+ * @param {function(String[])} callback Callback function to be called with the result.
+ */
+ dirlist( path, only_images = true, callback ) {
+ if ( '' === path || 'string' !== typeof path ) {
+ console.error(`theme_utils.dirlist(): path must be a non-empty string!`);
+ return callback([]);
+
+ } else if ( null !== path.match(/^[^/].+/) ) {
+ console.error(`theme_utils.dirlist(): path must be absolute!`);
+ return callback([]);
+ }
+
+ if ( null !== path.match(/\/\.+(?=\/)/) ) {
+ // No special directory names allowed (eg ../../)
+ path = path.replace(/\/\.+(?=\/)/g, '' );
+ }
+
+ try {
+ return callback([])
+ } catch( err ) {
+ console.error(`theme_utils.dirlist(): ${err}`);
+ return callback([]);
+ }
+ }
+
+ /**
+ * Binds `this` to class, `context`, for all of the class's methods.
+ *
+ * @param {Object} context An ES6 class instance with at least one method.
+ *
+ * @return {Object} `context` with `this` bound to it for all of its methods.
+ */
+ bind_this( context ) {
+ let excluded_methods = ['constructor'];
+
+ function not_excluded( _method, _context ) {
+ let is_excluded = excluded_methods.findIndex( excluded_method => _method === excluded_method ) > -1,
+ is_method = 'function' === typeof _context[_method];
+
+ return is_method && !is_excluded;
+ }
+
+ for ( let obj = context; obj; obj = Object.getPrototypeOf( obj ) ) {
+ // Stop once we have traveled all the way up the inheritance chain
+ if ( 'Object' === obj.constructor.name ) {
+ break;
+ }
+
+ for ( let method of Object.getOwnPropertyNames( obj ) ) {
+ if ( not_excluded( method, context ) ) {
+ context[method] = context[method].bind( context );
+ }
+ }
+ }
+
+ return context;
}
/**
diff --git a/themes/gruvbox/css/style.css b/themes/gruvbox/css/style.css
index 002b6ca..c7366b7 100644
--- a/themes/gruvbox/css/style.css
+++ b/themes/gruvbox/css/style.css
@@ -68,7 +68,7 @@ body {
.button {
background: var(--bg4);
border: 0;
- padding: 0.8em;
+ padding: 0.5em;
font-size: inherit;
cursor: pointer;
border-radius: 5px;
@@ -381,6 +381,12 @@ li {
#sessions-button:hover, #sessions-button:focus {
background: var(--light_blue);
}
+.button:hover span::before, .button:focus span::before {
+ transform: rotate(180deg);
+}
+.button span::before {
+ transition: var(--animation-duration);
+}
::-webkit-scrollbar {
width: 6px;
diff --git a/themes/gruvbox/index.html b/themes/gruvbox/index.html
index 0d3ce3d..33f5f1d 100644
--- a/themes/gruvbox/index.html
+++ b/themes/gruvbox/index.html
@@ -36,7 +36,7 @@
@@ -44,7 +44,7 @@
@@ -53,7 +53,7 @@