You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
4.9 KiB
178 lines
4.9 KiB
'use strict';
|
|
|
|
const {Gio, GLib} = imports.gi;
|
|
const Params = imports.params;
|
|
const System = imports.system;
|
|
|
|
function initActions(actionMap, simpleActionEntries, context) {
|
|
simpleActionEntries.forEach(function(entry) {
|
|
let filtered = Params.filter(entry, {
|
|
activate: null
|
|
, change_state: null
|
|
, context: null
|
|
});
|
|
let action = new Gio.SimpleAction(entry);
|
|
|
|
let context = filtered.context || actionMap;
|
|
if (filtered.activate) {
|
|
action.connect('activate', filtered.activate.bind(context));
|
|
}
|
|
if (filtered.change_state) {
|
|
action.connect('change-state', filtered.change_state.bind(context));
|
|
}
|
|
|
|
actionMap.add_action(action);
|
|
});
|
|
}
|
|
|
|
function toTitleCase(s) {
|
|
s = s.replace(/[_-]+/g, " ");
|
|
return s.replace( /\w\S*/g, function(t) {return t.charAt(0).toUpperCase() + t.substr(1).toLowerCase()} );
|
|
};
|
|
function time_ago(time) {
|
|
|
|
switch (typeof time) {
|
|
case 'number':
|
|
break;
|
|
case 'string':
|
|
time = +new Date(time);
|
|
break;
|
|
case 'object':
|
|
if (time.constructor === Date) time = time.getTime();
|
|
break;
|
|
default:
|
|
time = +new Date();
|
|
}
|
|
var time_formats = [
|
|
[60, 'seconds', 1], // 60
|
|
[120, '1 minute ago', '1 minute from now'], // 60*2
|
|
[3600, 'minutes', 60], // 60*60, 60
|
|
[7200, '1 hour ago', '1 hour from now'], // 60*60*2
|
|
[86400, 'hours', 3600], // 60*60*24, 60*60
|
|
[172800, 'Yesterday', 'Tomorrow'], // 60*60*24*2
|
|
[604800, 'days', 86400], // 60*60*24*7, 60*60*24
|
|
[1209600, 'Last week', 'Next week'], // 60*60*24*7*4*2
|
|
[2419200, 'weeks', 604800], // 60*60*24*7*4, 60*60*24*7
|
|
[4838400, 'Last month', 'Next month'], // 60*60*24*7*4*2
|
|
[29030400, 'months', 2419200], // 60*60*24*7*4*12, 60*60*24*7*4
|
|
[58060800, 'Last year', 'Next year'], // 60*60*24*7*4*12*2
|
|
[2903040000, 'years', 29030400], // 60*60*24*7*4*12*100, 60*60*24*7*4*12
|
|
[5806080000, 'Last century', 'Next century'], // 60*60*24*7*4*12*100*2
|
|
[58060800000, 'centuries', 2903040000] // 60*60*24*7*4*12*100*20, 60*60*24*7*4*12*100
|
|
];
|
|
var seconds = (+new Date() - time) / 1000,
|
|
token = 'ago',
|
|
list_choice = 1;
|
|
|
|
if (seconds == 0) {
|
|
return 'Just now'
|
|
}
|
|
if (seconds < 0) {
|
|
seconds = Math.abs(seconds);
|
|
token = 'from now';
|
|
list_choice = 2;
|
|
}
|
|
var i = 0, format;
|
|
while ((format = time_formats[i++]) !== undefined) {
|
|
if (seconds < format[0]) {
|
|
if (typeof format[2] == 'string')
|
|
return format[list_choice];
|
|
else
|
|
return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;
|
|
}
|
|
}
|
|
return time;
|
|
}
|
|
|
|
function time_ago_sec(sec) {
|
|
return time_ago(sec * 1000);
|
|
}
|
|
|
|
function getAppFileInfo() {
|
|
let stack = (new Error()).stack,
|
|
stackLine = stack.split('\n')[1],
|
|
coincidence, path, file;
|
|
|
|
if (!stackLine) throw new Error('Could not find current file (1)');
|
|
|
|
coincidence = new RegExp('@(.+):\\d+').exec(stackLine);
|
|
if (!coincidence) throw new Error('Could not find current file (2)');
|
|
|
|
path = coincidence[1];
|
|
file = Gio.File.new_for_path(path);
|
|
return [file.get_path(), file.get_parent().get_path(), file.get_basename()];
|
|
}
|
|
|
|
function getSettings(schemaId, path) {
|
|
const GioSSS = Gio.SettingsSchemaSource;
|
|
let schemaSource;
|
|
|
|
if (!pkg.moduledir.startsWith('resource://')) {
|
|
// Running from the source tree
|
|
schemaSource = GioSSS.new_from_directory(pkg.pkgdatadir,
|
|
GioSSS.get_default(),
|
|
false);
|
|
} else {
|
|
schemaSource = GioSSS.get_default();
|
|
}
|
|
|
|
let schemaObj = schemaSource.lookup(schemaId, true);
|
|
if (!schemaObj) {
|
|
log('Missing GSettings schema ' + schemaId);
|
|
System.exit(1);
|
|
}
|
|
|
|
if (path === undefined)
|
|
return new Gio.Settings({ settings_schema: schemaObj });
|
|
else
|
|
return new Gio.Settings({
|
|
settings_schema: schemaObj
|
|
, path: path
|
|
});
|
|
}
|
|
|
|
function loadIcon(iconName, size) {
|
|
let theme = Gtk.IconTheme.get_default();
|
|
|
|
return theme.load_icon(iconName,
|
|
size,
|
|
Gtk.IconLookupFlags.GENERIC_FALLBACK);
|
|
}
|
|
|
|
function normalizeCasefoldAndUnaccent(str) {
|
|
// The one and only!
|
|
// Travelled all over gnome, from tracker to gnome-shell to gnome-control-center,
|
|
// to seahorse, epiphany...
|
|
//
|
|
// Originally written by Aleksander Morgado <aleksander@gnu.org>
|
|
|
|
str = GLib.utf8_normalize(str, -1, GLib.NormalizeMode.NFKD);
|
|
str = GLib.utf8_casefold(str, -1);
|
|
|
|
/* Combining diacritical mark?
|
|
* Basic range: [0x0300,0x036F]
|
|
* Supplement: [0x1DC0,0x1DFF]
|
|
* For Symbols: [0x20D0,0x20FF]
|
|
* Half marks: [0xFE20,0xFE2F]
|
|
*/
|
|
return str.replace(/[\u0300-\u036f]|[\u1dc0-\u1dff]|[\u20d0-\u20ff]|[\ufe20-\ufe2f]/, '');
|
|
}
|
|
|
|
let t = imports.searchPath[0].split('/');
|
|
let run_local = (t[t.length - 1] === 'src');
|
|
|
|
function getBuilderFile(filename) {
|
|
let ret = filename;
|
|
if (run_local) {
|
|
let t = imports.searchPath[0].split('/');
|
|
let p = t.splice(0, t.length - 1).concat(['data', filename]);
|
|
let fp = GLib.DIR_SEPARATOR_S + GLib.build_filenamev(p);
|
|
let file = Gio.file_new_for_path(fp);
|
|
let [success, data, length] = file.load_contents(null);
|
|
ret = data;
|
|
} else {
|
|
ret = 'resource:///org/snapcast/control/gtk/' + filename;
|
|
}
|
|
return ret;
|
|
}
|