|
|
|
/*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
class LightDMLanguage {
|
|
|
|
constructor( {code, name, territory} ) {
|
|
|
|
this.code = code;
|
|
|
|
this.name = name;
|
|
|
|
this.territory = territory;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class LightDMLayout {
|
|
|
|
constructor( {name, description, short_description} ) {
|
|
|
|
this.name = name;
|
|
|
|
this.description = description;
|
|
|
|
this.short_description = short_description;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class LightDMSession {
|
|
|
|
constructor( {key, name, comment} ) {
|
|
|
|
this.key = key;
|
|
|
|
this.name = name;
|
|
|
|
this.comment = comment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class LightDMUser {
|
|
|
|
constructor( {display_name, username, language, layout, layouts, image, home_directory, session, logged_in, background} ) {
|
|
|
|
this.display_name = display_name;
|
|
|
|
this.username = username;
|
|
|
|
this.language = language;
|
|
|
|
this.layout = layout;
|
|
|
|
this.layouts = layouts;
|
|
|
|
this.image = image;
|
|
|
|
this.home_directory = home_directory;
|
|
|
|
this.background = background;
|
|
|
|
this.session = session;
|
|
|
|
this.logged_in = logged_in;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class LightDMBattery {
|
|
|
|
constructor( {name, level, status, ac_status}) {
|
|
|
|
this.name = name;
|
|
|
|
this.level = level;
|
|
|
|
this.status = status;
|
|
|
|
this.ac_status = ac_status;
|
|
|
|
this.capacity = 100;
|
|
|
|
this.time = "00:00";
|
|
|
|
this.watt = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let allSignals = [];
|
|
|
|
|
|
|
|
class Signal {
|
|
|
|
constructor(name) {
|
|
|
|
this._name = name;
|
|
|
|
this._callbacks = [];
|
|
|
|
allSignals.push(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Connects a callback to the signal.
|
|
|
|
* @param {Function} callback The callback to attach.
|
|
|
|
*/
|
|
|
|
connect(callback) {
|
|
|
|
if (typeof callback !== 'function') return;
|
|
|
|
this._callbacks.push(callback);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Disconnects a callback to the signal.
|
|
|
|
* @param {Function} callback The callback to disattach.
|
|
|
|
*/
|
|
|
|
disconnect(callback) {
|
|
|
|
var ind = this._callbacks.findIndex( (cb) => {return cb === callback});
|
|
|
|
if (ind == -1) return;
|
|
|
|
this._callbacks.splice(ind, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
_run() {
|
|
|
|
this._callbacks.forEach( (cb) => {
|
|
|
|
if (typeof cb !== 'function') return;
|
|
|
|
cb()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emits a signal.
|
|
|
|
* @param {String} name The signal's name.
|
|
|
|
*/
|
|
|
|
function emitSignal(name) {
|
|
|
|
var signal = allSignals.find( (s) => {
|
|
|
|
return s._name === name;
|
|
|
|
})
|
|
|
|
signal._run()
|
|
|
|
}
|
|
|
|
|
|
|
|
const _mockData = {
|
|
|
|
languages: [
|
|
|
|
new LightDMLanguage({
|
|
|
|
name: 'English',
|
|
|
|
code: 'en_US.utf8',
|
|
|
|
territory: 'USA'
|
|
|
|
}),
|
|
|
|
new LightDMLanguage({
|
|
|
|
name: 'Catalan',
|
|
|
|
code: 'ca_ES.utf8',
|
|
|
|
territory: 'Spain'
|
|
|
|
}),
|
|
|
|
new LightDMLanguage({
|
|
|
|
name: 'French',
|
|
|
|
code: 'fr_FR.utf8',
|
|
|
|
territory: 'France'
|
|
|
|
})
|
|
|
|
],
|
|
|
|
layouts: [
|
|
|
|
new LightDMLayout({
|
|
|
|
name: 'us',
|
|
|
|
short_description: 'en',
|
|
|
|
description: 'English (US)'
|
|
|
|
}),
|
|
|
|
new LightDMLayout({
|
|
|
|
name: 'at',
|
|
|
|
short_description: 'de',
|
|
|
|
description: 'German (Austria)'
|
|
|
|
}),
|
|
|
|
new LightDMLayout({
|
|
|
|
name: 'us rus',
|
|
|
|
short_description: 'ru',
|
|
|
|
description: 'Russian (US, phonetic)'
|
|
|
|
})
|
|
|
|
],
|
|
|
|
sessions: [
|
|
|
|
new LightDMSession({
|
|
|
|
key: 'gnome',
|
|
|
|
name: 'GNOME',
|
|
|
|
comment: 'This session logs you into GNOME'
|
|
|
|
}),
|
|
|
|
new LightDMSession({
|
|
|
|
key: 'cinnamon',
|
|
|
|
name: 'Cinnamon',
|
|
|
|
comment: 'This session logs you into Cinnamon'
|
|
|
|
}),
|
|
|
|
new LightDMSession({
|
|
|
|
key: 'plasma',
|
|
|
|
name: 'Plasma',
|
|
|
|
comment: 'Plasma by KDE'
|
|
|
|
}),
|
|
|
|
new LightDMSession({
|
|
|
|
key: 'awesome',
|
|
|
|
name: 'Awesome wm',
|
|
|
|
comment: 'An Awesome WM'
|
|
|
|
}),
|
|
|
|
new LightDMSession({
|
|
|
|
key: 'mate',
|
|
|
|
name: 'MATE',
|
|
|
|
comment: 'This session logs you into MATE'
|
|
|
|
}),
|
|
|
|
new LightDMSession({
|
|
|
|
key: 'openbox',
|
|
|
|
name: 'Openbox',
|
|
|
|
comment: 'This session logs you into Openbox'
|
|
|
|
})
|
|
|
|
],
|
|
|
|
users: [
|
|
|
|
new LightDMUser({
|
|
|
|
display_name: 'Clark Kent',
|
|
|
|
username: 'superman',
|
|
|
|
language: null,
|
|
|
|
layout: null,
|
|
|
|
image: '/usr/share/web-greeter/themes/default/img/antergos-logo-user',
|
|
|
|
home_directory: '/home/superman',
|
|
|
|
session: 'gnome',
|
|
|
|
logged_in: false,
|
|
|
|
background: "",
|
|
|
|
layouts: [],
|
|
|
|
}),
|
|
|
|
new LightDMUser({
|
|
|
|
display_name: 'Bruce Wayne',
|
|
|
|
username: 'batman',
|
|
|
|
language: null,
|
|
|
|
layout: null,
|
|
|
|
image: '/usr/share/web-greeter/themes/default/img/antergos-logo-user',
|
|
|
|
home_directory: '/home/batman',
|
|
|
|
session: 'cinnamon',
|
|
|
|
logged_in: false,
|
|
|
|
background: "",
|
|
|
|
layouts: [],
|
|
|
|
}),
|
|
|
|
new LightDMUser({
|
|
|
|
display_name: 'Peter Parker',
|
|
|
|
username: 'spiderman',
|
|
|
|
language: null,
|
|
|
|
layout: null,
|
|
|
|
image: '/usr/share/web-greeter/themes/default/img/antergos-logo-user',
|
|
|
|
home_directory: '/home/spiderman',
|
|
|
|
session: 'MATE',
|
|
|
|
logged_in: false,
|
|
|
|
background: "",
|
|
|
|
layouts: [],
|
|
|
|
})
|
|
|
|
],
|
|
|
|
battery: new LightDMBattery({
|
|
|
|
name: "Battery 0",
|
|
|
|
level: 85,
|
|
|
|
status: "Discharging",
|
|
|
|
ac_status: 1,
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class Greeter {
|
|
|
|
constructor() {
|
|
|
|
if ('lightdm' in window) {
|
|
|
|
return window.lightdm;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.lightdm = this;
|
|
|
|
|
|
|
|
return window.lightdm;
|
|
|
|
}
|
|
|
|
|
|
|
|
mock = true;
|
|
|
|
|
|
|
|
_authentication_user = null;
|
|
|
|
/**
|
|
|
|
* The username of the user being authenticated or {@link null}
|
|
|
|
* if no authentication is in progress
|
|
|
|
* @type {String|Null}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get authentication_user() {
|
|
|
|
return this._authentication_user;
|
|
|
|
}
|
|
|
|
|
|
|
|
_autologin_guest = false;
|
|
|
|
/**
|
|
|
|
* Whether or not the guest account should be automatically logged
|
|
|
|
* into when the timer expires.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get autologin_guest() {
|
|
|
|
return this._autologin_guest;
|
|
|
|
}
|
|
|
|
|
|
|
|
_autologin_timeout = 100;
|
|
|
|
/**
|
|
|
|
* The number of seconds to wait before automatically logging in.
|
|
|
|
* @type {Number}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get autologin_timeout() {
|
|
|
|
return this._autologin_timeout;
|
|
|
|
}
|
|
|
|
|
|
|
|
_autologin_user = false;
|
|
|
|
/**
|
|
|
|
* The username with which to automattically log in when the timer expires.
|
|
|
|
* @type {String}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get autologin_user() {
|
|
|
|
return this._autologin_user;
|
|
|
|
}
|
|
|
|
|
|
|
|
_batteryData = _mockData.battery;
|
|
|
|
/**
|
|
|
|
* Gets the battery data.
|
|
|
|
* @type {LightDMBattery}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get batteryData() {
|
|
|
|
return this._batteryData;
|
|
|
|
}
|
|
|
|
|
|
|
|
_brightness = 50;
|
|
|
|
/**
|
|
|
|
* Gets the brightness
|
|
|
|
* @type {Number}
|
|
|
|
*/
|
|
|
|
get brightness() {
|
|
|
|
return this._brightness;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Sets the brightness
|
|
|
|
* @param {Number} quantity The quantity to set
|
|
|
|
*/
|
|
|
|
set brightness( quantity ) {
|
|
|
|
if (quantity > 100) quantity = 100;
|
|
|
|
if (quantity < 0) quantity = 0;
|
|
|
|
this._brightness = quantity;
|
|
|
|
emitSignal("brightness_update");
|
|
|
|
}
|
|
|
|
|
|
|
|
_can_access_battery = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter can access to battery data.
|
|
|
|
* @type {boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get can_access_battery() {
|
|
|
|
return this._can_access_battery;
|
|
|
|
}
|
|
|
|
|
|
|
|
_can_access_brightness = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter can control display brightness.
|
|
|
|
* @type {boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get can_access_brightness() {
|
|
|
|
return this._can_access_brightness;
|
|
|
|
}
|
|
|
|
|
|
|
|
_can_hibernate = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter can make the system hibernate.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get can_hibernate() {
|
|
|
|
return this._can_hibernate;
|
|
|
|
}
|
|
|
|
|
|
|
|
_can_restart = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter can make the system restart.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get can_restart() {
|
|
|
|
return this._can_restart;
|
|
|
|
}
|
|
|
|
|
|
|
|
_can_shutdown = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter can make the system shutdown.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get can_shutdown() {
|
|
|
|
return this._can_shutdown;
|
|
|
|
}
|
|
|
|
|
|
|
|
_can_suspend = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter can make the system suspend/sleep.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get can_suspend() {
|
|
|
|
return this._can_suspend;
|
|
|
|
}
|
|
|
|
|
|
|
|
_default_session = "awesome";
|
|
|
|
/**
|
|
|
|
* The name of the default session.
|
|
|
|
* @type {String}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get default_session() {
|
|
|
|
return this._default_session;
|
|
|
|
}
|
|
|
|
|
|
|
|
_has_guest_account = false;
|
|
|
|
/**
|
|
|
|
* Whether or not guest sessions are supported.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get has_guest_account() {
|
|
|
|
return this._has_guest_account;
|
|
|
|
}
|
|
|
|
|
|
|
|
_hide_users_hint = false;
|
|
|
|
/**
|
|
|
|
* Whether or not user accounts should be hidden.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get hide_users_hint() {
|
|
|
|
return this._hide_users_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
_hostname = "Web browser";
|
|
|
|
/**
|
|
|
|
* The system's hostname.
|
|
|
|
* @type {String}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get hostname() {
|
|
|
|
return this._hostname;
|
|
|
|
}
|
|
|
|
|
|
|
|
_in_authentication = false;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter is in the process of authenticating.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get in_authentication() {
|
|
|
|
return this._in_authentication;
|
|
|
|
}
|
|
|
|
|
|
|
|
_is_authenticated = true;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter has successfully authenticated.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get is_authenticated() {
|
|
|
|
return this._is_authenticated;
|
|
|
|
}
|
|
|
|
|
|
|
|
_language = null;
|
|
|
|
/**
|
|
|
|
* The current language or {@link null} if no language.
|
|
|
|
* @type {LightDMLanguage|null}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get language() {
|
|
|
|
return this._language;
|
|
|
|
}
|
|
|
|
|
|
|
|
_languages = _mockData.languages;
|
|
|
|
/**
|
|
|
|
* A list of languages to present to the user.
|
|
|
|
* @type {LightDMLanguage[]}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get languages() {
|
|
|
|
return this._languages;
|
|
|
|
}
|
|
|
|
|
|
|
|
_layout = _mockData.layouts[0];
|
|
|
|
/**
|
|
|
|
* The currently active layout for the selected user.
|
|
|
|
* @type {LightDMLayout}
|
|
|
|
*/
|
|
|
|
get layout() {
|
|
|
|
return this._layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
_layouts = _mockData.layouts;
|
|
|
|
/**
|
|
|
|
* A list of keyboard layouts to present to the user.
|
|
|
|
* @type {LightDMLayout[]}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get layouts() {
|
|
|
|
return this._layouts;
|
|
|
|
}
|
|
|
|
|
|
|
|
_lock_hint = false;
|
|
|
|
/**
|
|
|
|
* Whether or not the greeter was started as a lock screen.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get lock_hint() {
|
|
|
|
return this._lock_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
_select_guest_hint = false;
|
|
|
|
/**
|
|
|
|
* Whether or not the guest account should be selected by default.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get select_guest_hint() {
|
|
|
|
return this.select_guest_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
_select_user_hint = "";
|
|
|
|
/**
|
|
|
|
* The username to select by default.
|
|
|
|
* @type {String}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get select_user_hint() {
|
|
|
|
return this.select_user_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
_sessions = _mockData.sessions;
|
|
|
|
/**
|
|
|
|
* List of available sessions.
|
|
|
|
* @type {LightDMSession[]}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get sessions() {
|
|
|
|
return this._sessions;
|
|
|
|
}
|
|
|
|
|
|
|
|
_show_manual_login_hint = false;
|
|
|
|
/**
|
|
|
|
* Check if a manual login option should be shown. If {@link true}, the theme should
|
|
|
|
* provide a way for a username to be entered manually. Otherwise, themes that show
|
|
|
|
* a user list may limit logins to only those users.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get show_manual_login_hint() {
|
|
|
|
return this._show_manual_login_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
_show_remote_login_hint = false;
|
|
|
|
/**
|
|
|
|
* Check if a remote login option should be shown. If {@link true}, the theme should provide
|
|
|
|
* a way for a user to log into a remote desktop server.
|
|
|
|
* @type {Boolean}
|
|
|
|
* @readonly
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
get show_remote_login_hint() {
|
|
|
|
return this._show_remote_login_hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
_users = _mockData.users;
|
|
|
|
/**
|
|
|
|
* List of available users.
|
|
|
|
* @type {LightDMUser[]}
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get users() {
|
|
|
|
return this._users;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the authentication procedure for a user.
|
|
|
|
*
|
|
|
|
* @param {String|null} username A username or {@link null} to prompt for a username.
|
|
|
|
*/
|
|
|
|
authenticate( username ) {
|
|
|
|
this._in_authentication = true;
|
|
|
|
this._authentication_user = username;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the authentication procedure for the guest user.
|
|
|
|
*/
|
|
|
|
authenticate_as_guest() {
|
|
|
|
this._in_authentication = true;
|
|
|
|
this._authentication_user = "guest";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the brightness to quantity
|
|
|
|
* @param {Number} quantity The quantity to set
|
|
|
|
*/
|
|
|
|
brightnessSet( quantity ) {
|
|
|
|
this.brightness = quantity;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Increase the brightness by quantity
|
|
|
|
* @param {Number} quantity The quantity to increase
|
|
|
|
*/
|
|
|
|
brightnessIncrease( quantity ) {
|
|
|
|
this.brightness += quantity;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decrease the brightness by quantity
|
|
|
|
* @param {Number} quantity The quantity to decrease
|
|
|
|
*/
|
|
|
|
brightnessDecrease( quantity ) {
|
|
|
|
this.brightness -= quantity;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cancel user authentication that is currently in progress.
|
|
|
|
*/
|
|
|
|
cancel_authentication() {
|
|
|
|
this._in_authentication = false;
|
|
|
|
this._authentication_user = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cancel the automatic login.
|
|
|
|
*/
|
|
|
|
cancel_autologin() {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggers the system to hibernate.
|
|
|
|
* @returns {Boolean} {@link true} if hibernation initiated, otherwise {@link false}
|
|
|
|
*/
|
|
|
|
hibernate() {
|
|
|
|
alert("Hibernating system");
|
|
|
|
location.reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
_default_password = "justice";
|
|
|
|
/**
|
|
|
|
* Provide a response to a prompt.
|
|
|
|
* @param {*} response
|
|
|
|
*/
|
|
|
|
respond( response ) {
|
|
|
|
console.log("Response:", response);
|
|
|
|
if (response === this._default_password) {
|
|
|
|
this._is_authenticated = true;
|
|
|
|
emitSignal("authentication_complete")
|
|
|
|
} else {
|
|
|
|
this._is_authenticated = false;
|
|
|
|
setTimeout(() => {
|
|
|
|
emitSignal("authentication_complete")
|
|
|
|
}, 2000)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggers the system to restart.
|
|
|
|
* @returns {Boolean} {@link true} if restart initiated, otherwise {@link false}
|
|
|
|
*/
|
|
|
|
restart() {
|
|
|
|
alert("Restarting system");
|
|
|
|
location.reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the language for the currently authenticated user.
|
|
|
|
* @param {String} language The language in the form of a locale specification (e.g.
|
|
|
|
* 'de_DE.UTF-8')
|
|
|
|
* @returns {Boolean} {@link true} if successful, otherwise {@link false}
|
|
|
|
*/
|
|
|
|
set_language( language ) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggers the system to shutdown.
|
|
|
|
* @returns {Boolean} {@link true} if shutdown initiated, otherwise {@link false}
|
|
|
|
*/
|
|
|
|
shutdown() {
|
|
|
|
alert("Shutting down system");
|
|
|
|
location.reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start a session for the authenticated user.
|
|
|
|
* @param {String|null} session The session to log into or {@link null} to use the default.
|
|
|
|
* @returns {Boolean} {@link true} if successful, otherwise {@link false}
|
|
|
|
*/
|
|
|
|
start_session( session ) {
|
|
|
|
if (!this._is_authenticated) return;
|
|
|
|
alert(`Session started with: "${session}"`);
|
|
|
|
location.reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggers the system to suspend/sleep.
|
|
|
|
* @returns {Boolean} {@link true} if suspend/sleep initiated, otherwise {@link false}
|
|
|
|
*/
|
|
|
|
suspend() {
|
|
|
|
alert("Suspending system");
|
|
|
|
location.reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
authentication_complete = new Signal("authentication_complete");
|
|
|
|
|
|
|
|
autologin_timer_expired = new Signal("autologin_timer_expired");
|
|
|
|
|
|
|
|
brightness_update = new Signal("brightness_update");
|
|
|
|
|
|
|
|
battery_update = new Signal("battery_update");
|
|
|
|
|
|
|
|
idle = new Signal("idle");
|
|
|
|
|
|
|
|
reset = new Signal("reset");
|
|
|
|
|
|
|
|
show_message = new Signal("show_message");
|
|
|
|
|
|
|
|
show_prompt = new Signal("show_prompt");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class GreeterConfig {
|
|
|
|
constructor() {
|
|
|
|
if ('greeter_config' in window) {
|
|
|
|
return window.greeter_config;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.greeter_config = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
_branding = {
|
|
|
|
background_images_dir: "/usr/share/backgrounds",
|
|
|
|
logo_image: "/usr/share/web-greeter/themes/default/img/antergos-logo-user.png",
|
|
|
|
user_image: "/usr/share/web-greeter/themes/default/img/antergos.png"
|
|
|
|
}
|
|
|
|
|
|
|
|
_greeter = {
|
|
|
|
debug_mode: true,
|
|
|
|
detect_theme_errors: true,
|
|
|
|
screensaver_timeout: 300,
|
|
|
|
secure_mode: true,
|
|
|
|
time_language: "",
|
|
|
|
theme: "none"
|
|
|
|
}
|
|
|
|
|
|
|
|
_features = {
|
|
|
|
battery: true,
|
|
|
|
backlight: {
|
|
|
|
enabled: true,
|
|
|
|
value: 10,
|
|
|
|
steps: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_layouts = _mockData.layouts
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds keys/values from the `branding` section of the config file.
|
|
|
|
*
|
|
|
|
* @type {object} branding
|
|
|
|
* @property {string} background_images_dir Path to directory that contains background images
|
|
|
|
* for use in greeter themes.
|
|
|
|
* @property {string} logo Path to distro logo image for use in greeter themes.
|
|
|
|
* @property {string} user_image Default user image/avatar. This is used by greeter themes
|
|
|
|
* for users that have not configured a `.face` image.
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get branding() {
|
|
|
|
return this._branding;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds keys/values from the `greeter` section of the config file.
|
|
|
|
*
|
|
|
|
* @type {object} greeter
|
|
|
|
* @property {boolean} debug_mode Greeter theme debug mode.
|
|
|
|
* @property {boolean} detect_theme_errors Provide an option to load a fallback theme when theme
|
|
|
|
* errors are detected.
|
|
|
|
* @property {number} screensaver_timeout Blank the screen after this many seconds of inactivity.
|
|
|
|
* @property {boolean} secure_mode Don't allow themes to make remote http requests.
|
|
|
|
* generate localized time for display.
|
|
|
|
* @property {string} time_language Language to use when displaying the time or ""
|
|
|
|
* to use the system's language.
|
|
|
|
* @property {string} theme The name of the theme to be used by the greeter.
|
|
|
|
* @readonly
|
|
|
|
*/
|
|
|
|
get greeter() {
|
|
|
|
return this._greeter;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds keys/values from the `features` section of the config file.
|
|
|
|
*
|
|
|
|
* @type {Object} features
|
|
|
|
* @property {Boolean} battery Enable greeter and themes to ger battery status.
|
|
|
|
* @property {Object} backlight
|
|
|
|
* @property {Boolean} enabled Enable greeter and themes to control display backlight.
|
|
|
|
* @property {Number} value The amount to increase/decrease brightness by greeter.
|
|
|
|
* @property {Number} steps How many steps are needed to do the change.
|
|
|
|
*/
|
|
|
|
get features() {
|
|
|
|
return this._features;
|
|
|
|
}
|
|
|
|
|
|
|
|
get layouts() {
|
|
|
|
return this._layouts;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let time_language = null
|
|
|
|
|
|
|
|
class ThemeUtils {
|
|
|
|
constructor() {
|
|
|
|
if ("theme_utils" in window) {
|
|
|
|
return window.theme_utils;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.theme_utils = this
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Binds `this` to class, `context`, for all of the class's methods.
|
|
|
|
*
|
|
|
|
* @arg {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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current date in a localized format. Local language is autodetected by default, but can be set manually in the greeter config file.
|
|
|
|
* * `language` defaults to the system's language, but can be set manually in the config file.
|
|
|
|
*
|
|
|
|
* @returns {Object} The current date.
|
|
|
|
*/
|
|
|
|
get_current_localized_date() {
|
|
|
|
let config = greeter_config.greeter
|
|
|
|
|
|
|
|
var locale = []
|
|
|
|
|
|
|
|
if (time_language === null) {
|
|
|
|
time_language = config.time_language || ""
|
|
|
|
}
|
|
|
|
|
|
|
|
if (time_language != "") {
|
|
|
|
locale.push(time_language)
|
|
|
|
}
|
|
|
|
|
|
|
|
let optionsDate = { day: "2-digit", month: "2-digit", year: "2-digit" }
|
|
|
|
|
|
|
|
let fmtDate = Intl.DateTimeFormat(locale, optionsDate)
|
|
|
|
|
|
|
|
let now = new Date()
|
|
|
|
var date = fmtDate.format(now)
|
|
|
|
|
|
|
|
return date
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current time in a localized format. Local language is autodetected by default, but can be set manually in the greeter config file.
|
|
|
|
* * `language` defaults to the system's language, but can be set manually in the config file.
|
|
|
|
*
|
|
|
|
* @returns {Object} The current time.
|
|
|
|
*/
|
|
|
|
get_current_localized_time() {
|
|
|
|
let config = greeter_config.greeter
|
|
|
|
|
|
|
|
var locale = []
|
|
|
|
|
|
|
|
if (time_language === null) {
|
|
|
|
time_language = config.time_language || ""
|
|
|
|
}
|
|
|
|
|
|
|
|
if (time_language != "") {
|
|
|
|
locale.push(time_language)
|
|
|
|
}
|
|
|
|
|
|
|
|
let optionsTime = { hour: "2-digit", minute: "2-digit" }
|
|
|
|
|
|
|
|
let fmtTime = Intl.DateTimeFormat(locale, optionsTime)
|
|
|
|
|
|
|
|
let now = new Date()
|
|
|
|
var time = fmtTime.format(now)
|
|
|
|
|
|
|
|
return time
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
new ThemeUtils();
|
|
|
|
new GreeterConfig();
|
|
|
|
new Greeter();
|
|
|
|
|
|
|
|
window._ready_event = new Event("GreeterReady")
|
|
|
|
|
|
|
|
window.addEventListener("load", () => {window.dispatchEvent(_ready_event)})
|