[gnome] Fix version for gjsosk and gsconnect, add impatience

This commit is contained in:
2024-11-01 09:35:38 -04:00
parent 66e76c2764
commit 1bd891f30a
78 changed files with 804 additions and 1226 deletions

View File

@ -5,9 +5,11 @@
"name": "GJS OSK",
"settings-schema": "org.gnome.shell.extensions.gjsosk",
"shell-version": [
"45"
"45",
"46",
"47"
],
"url": "https://github.com/Vishram1123/gjs-osk",
"uuid": "gjsosk@vishram1123.com",
"version": 10
}
}

View File

@ -2,21 +2,23 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
var PACKAGE_VERSION = 56;
var PACKAGE_URL = 'https://github.com/GSConnect/gnome-shell-extension-gsconnect';
var PACKAGE_BUGREPORT = 'https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/new';
var PACKAGE_DATADIR = '/usr/share/gnome-shell/extensions/gsconnect@andyholmes.github.io';
var PACKAGE_LOCALEDIR = '/usr/share/locale';
var GSETTINGS_SCHEMA_DIR = '/usr/share/glib-2.0/schemas';
var GNOME_SHELL_LIBDIR = '/usr/lib64/';
export default {
PACKAGE_VERSION: 58,
PACKAGE_URL: 'https://github.com/GSConnect/gnome-shell-extension-gsconnect',
PACKAGE_BUGREPORT: 'https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/new',
PACKAGE_DATADIR: '/usr/local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io',
PACKAGE_LOCALEDIR: '/usr/local/share/locale',
GSETTINGS_SCHEMA_DIR: '/usr/local/share/glib-2.0/schemas',
GNOME_SHELL_LIBDIR: '/usr/local/lib64',
var APP_ID = 'org.gnome.Shell.Extensions.GSConnect';
var APP_PATH = '/org/gnome/Shell/Extensions/GSConnect';
APP_ID: 'org.gnome.Shell.Extensions.GSConnect',
APP_PATH: '/org/gnome/Shell/Extensions/GSConnect',
var IS_USER = false;
IS_USER: false,
// External binary paths
var OPENSSL_PATH = 'openssl';
var SSHADD_PATH = 'ssh-add';
var SSHKEYGEN_PATH = 'ssh-keygen';
var FFMPEG_PATH = 'ffmpeg';
// External binary paths
OPENSSL_PATH: 'openssl',
SSHADD_PATH: 'ssh-add',
SSHKEYGEN_PATH: 'ssh-keygen',
FFMPEG_PATH: 'ffmpeg',
};

View File

@ -1,12 +0,0 @@
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
import GLib from 'gi://GLib';
const [filename] = GLib.filename_from_uri(import.meta.url);
const dirname = GLib.path_get_dirname(filename);
imports.searchPath.unshift(dirname);
const Config = imports.config;
export default Config;

View File

@ -16,15 +16,15 @@ import {
ngettext
} from 'resource:///org/gnome/shell/extensions/extension.js';
import Config from './config.mjs';
import Config from './config.js';
import * as Clipboard from './shell/clipboard.js';
import * as Device from './shell/device.js';
import * as Keybindings from './shell/keybindings.js';
import * as Notification from './shell/notification.js';
import * as Input from './shell/input.js';
import * as Utils from './shell/utils.js';
import Remote from './utils/remote.mjs';
import setup from './utils/setup.mjs';
import * as Remote from './utils/remote.js';
import setup from './utils/setup.js';
const QuickSettingsMenu = Main.panel.statusArea.quickSettings;

View File

@ -1,4 +1,4 @@
#!/usr/bin/env gjs
#!/usr/bin/env -S gjs -m
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
@ -6,43 +6,20 @@
// -*- mode: js; -*-
'use strict';
import Gdk from 'gi://Gdk?version=3.0';
import 'gi://GdkPixbuf?version=2.0';
import Gio from 'gi://Gio?version=2.0';
import GLib from 'gi://GLib?version=2.0';
import GObject from 'gi://GObject?version=2.0';
import Gtk from 'gi://Gtk?version=3.0';
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.GdkPixbuf = '2.0';
imports.gi.versions.Gio = '2.0';
imports.gi.versions.GLib = '2.0';
imports.gi.versions.GObject = '2.0';
imports.gi.versions.Gtk = '3.0';
import system from 'system';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import './preferences/init.js';
import {Window} from './preferences/service.js';
import Config from './config.js';
// Bootstrap
function get_datadir() {
let [, path] = /@([^:]+):\d+/.exec(new Error().stack.split('\n')[1]);
const info = Gio.File.new_for_path(path)
.query_info('standard::*', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
path = info.get_is_symlink() ? info.get_symlink_target() : path;
return Gio.File.new_for_path(path).get_parent().get_path();
}
imports.searchPath.unshift(get_datadir());
imports.config.PACKAGE_DATADIR = imports.searchPath[0];
// Bootstrap
const {setup, setupGettext} = imports.utils.setup;
setup(imports.config.PACKAGE_DATADIR);
setupGettext();
// Local Imports
const Config = imports.config;
const Settings = imports.preferences.service;
import('gi://GioUnix?version=2.0').catch(() => {}); // Set version for optional dependency
/**
@ -65,7 +42,7 @@ const Preferences = GObject.registerClass({
vfunc_activate() {
if (this._window === undefined) {
this._window = new Settings.Window({
this._window = new Window({
application: this,
});
}
@ -77,7 +54,7 @@ const Preferences = GObject.registerClass({
super.vfunc_startup();
// Init some resources
let provider = new Gtk.CssProvider();
const provider = new Gtk.CssProvider();
provider.load_from_resource(`${Config.APP_PATH}/application.css`);
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(),
@ -85,13 +62,13 @@ const Preferences = GObject.registerClass({
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
let actions = [
const actions = [
['refresh', null],
['connect', GLib.VariantType.new('s')],
];
for (let [name, type] of actions) {
let action = new Gio.SimpleAction({
for (const [name, type] of actions) {
const action = new Gio.SimpleAction({
name: name,
parameter_type: type,
});
@ -101,7 +78,7 @@ const Preferences = GObject.registerClass({
vfunc_activate_action(action_name, parameter) {
try {
let paramArray = [];
const paramArray = [];
if (parameter instanceof GLib.Variant)
paramArray[0] = parameter;
@ -124,4 +101,4 @@ const Preferences = GObject.registerClass({
}
});
(new Preferences()).run([imports.system.programInvocationName].concat(ARGV));
await (new Preferences()).runAsync([system.programInvocationName].concat(ARGV));

View File

@ -1,8 +1,12 @@
{
"uuid": "gsconnect@andyholmes.github.io",
"name": "GSConnect",
"description": "GSConnect is a complete implementation of KDE Connect especially for GNOME Shell with Nautilus, Chrome and Firefox integration. It does not rely on the KDE Connect desktop application and will not work with it installed.\n\nKDE Connect allows devices to securely share content like notifications or files and other features like SMS messaging and remote control. The KDE Connect team has applications for Linux, BSD, Android, Sailfish, iOS, macOS and Windows.\n\nPlease report issues on Github!",
"version": 56,
"shell-version": [ "46" ],
"url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki"
}
"_generated": "Generated by SweetTooth, do not edit",
"description": "GSConnect is a complete implementation of KDE Connect especially for GNOME Shell with Nautilus, Chrome and Firefox integration. It does not rely on the KDE Connect desktop application and will not work with it installed.\n\nKDE Connect allows devices to securely share content like notifications or files and other features like SMS messaging and remote control. The KDE Connect team has applications for Linux, BSD, Android, Sailfish, iOS, macOS and Windows.\n\nPlease report issues on Github!",
"name": "GSConnect",
"shell-version": [
"46",
"47"
],
"url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki",
"uuid": "gsconnect@andyholmes.github.io",
"version": 58
}

View File

@ -2,24 +2,23 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import Pango from 'gi://Pango';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Config = imports.config;
const Keybindings = imports.preferences.keybindings;
import Config from '../config.js';
import plugins from '../service/plugins/index.js';
import * as Keybindings from './keybindings.js';
// Build a list of plugins and shortcuts for devices
const DEVICE_PLUGINS = [];
const DEVICE_SHORTCUTS = {};
for (const name in imports.service.plugins) {
const module = imports.service.plugins[name];
for (const name in plugins) {
const module = plugins[name];
if (module.Metadata === undefined)
continue;
@ -41,7 +40,7 @@ for (const name in imports.service.plugins) {
* @param {Gtk.ListBoxRow} row - The current row
* @param {Gtk.ListBoxRow} before - The previous row
*/
function rowSeparators(row, before) {
export function rowSeparators(row, before) {
const header = row.get_header();
if (before === null) {
@ -63,7 +62,7 @@ function rowSeparators(row, before) {
* @param {Gtk.ListBoxRow} row2 - The second row
* @return {number} -1, 0 or 1
*/
function titleSortFunc(row1, row2) {
export function titleSortFunc(row1, row2) {
if (!row1.title || !row2.title)
return 0;
@ -249,7 +248,7 @@ const CommandEditor = GObject.registerClass({
/**
* A widget for configuring a remote device.
*/
var Panel = GObject.registerClass({
export const Panel = GObject.registerClass({
GTypeName: 'GSConnectPreferencesDevicePanel',
Properties: {
'device': GObject.ParamSpec.object(
@ -424,7 +423,7 @@ var Panel = GObject.registerClass({
this._pluginSettings = {};
if (!this._pluginSettings.hasOwnProperty(name)) {
const meta = imports.service.plugins[name].Metadata;
const meta = plugins[name].Metadata;
this._pluginSettings[name] = new Gio.Settings({
settings_schema: Config.GSCHEMA.lookup(meta.id, -1),
@ -1058,7 +1057,7 @@ var Panel = GObject.registerClass({
}
_addPlugin(name) {
const plugin = imports.service.plugins[name];
const plugin = plugins[name];
const row = new SectionRow({
height_request: 48,

View File

@ -2,13 +2,11 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import Gdk from 'gi://Gdk';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
/*
@ -32,7 +30,7 @@ const _MODIFIERS = [
/**
* Response enum for ShortcutChooserDialog
*/
var ResponseType = {
export const ResponseType = {
CANCEL: Gtk.ResponseType.CANCEL,
SET: Gtk.ResponseType.APPLY,
UNSET: 2,
@ -42,7 +40,7 @@ var ResponseType = {
/**
* A simplified version of the shortcut editor from GNOME Control Center
*/
var ShortcutChooserDialog = GObject.registerClass({
export const ShortcutChooserDialog = GObject.registerClass({
GTypeName: 'GSConnectPreferencesShortcutEditor',
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-shortcut-editor.ui',
Children: [
@ -209,7 +207,7 @@ var ShortcutChooserDialog = GObject.registerClass({
* @param {number} [grabFlags] - Grab Flags
* @param {boolean} %true if available, %false on error or unavailable
*/
async function checkAccelerator(accelerator, modeFlags = 0, grabFlags = 0) {
export async function checkAccelerator(accelerator, modeFlags = 0, grabFlags = 0) {
try {
let result = false;
@ -276,7 +274,7 @@ async function checkAccelerator(accelerator, modeFlags = 0, grabFlags = 0) {
* @param {string} accelerator - An accelerator as taken by Gtk.ShortcutLabel
* @return {string} An accelerator or %null if it should be unset.
*/
async function getAccelerator(summary, accelerator = null) {
export async function getAccelerator(summary, accelerator = null) {
try {
const dialog = new ShortcutChooserDialog({
summary: summary,

View File

@ -2,18 +2,18 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import GdkPixbuf from 'gi://GdkPixbuf';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const Gdk = imports.gi.Gdk;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import system from 'system';
const Config = imports.config;
const Device = imports.preferences.device;
const Remote = imports.utils.remote;
import Config from '../config.js';
import {Panel, rowSeparators} from './device.js';
import {Service} from '../utils/remote.js';
/*
@ -21,7 +21,7 @@ const Remote = imports.utils.remote;
*/
const LOG_HEADER = new GLib.Bytes(`
GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'})
GJS: ${imports.system.version}
GJS: ${system.version}
Session: ${GLib.getenv('XDG_SESSION_TYPE')}
OS: ${GLib.get_os_info('PRETTY_NAME')}
--------------------------------------------------------------------------------
@ -91,7 +91,7 @@ async function generateSupportLog(time) {
/**
* "Connect to..." Dialog
*/
var ConnectDialog = GObject.registerClass({
const ConnectDialog = GObject.registerClass({
GTypeName: 'GSConnectConnectDialog',
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/connect-dialog.ui',
Children: [
@ -132,7 +132,7 @@ var ConnectDialog = GObject.registerClass({
});
var Window = GObject.registerClass({
export const Window = GObject.registerClass({
GTypeName: 'GSConnectPreferencesWindow',
Properties: {
'display-mode': GObject.ParamSpec.string(
@ -173,7 +173,7 @@ var Window = GObject.registerClass({
});
// Service Proxy
this.service = new Remote.Service();
this.service = new Service();
this._deviceAddedId = this.service.connect(
'device-added',
@ -198,7 +198,7 @@ var Window = GObject.registerClass({
this.service_box.set_focus_vadjustment(this.service_window.vadjustment);
// Device List
this.device_list.set_header_func(Device.rowSeparators);
this.device_list.set_header_func(rowSeparators);
// Discoverable InfoBar
this.settings.bind(
@ -580,7 +580,7 @@ var Window = GObject.registerClass({
try {
if (!this.stack.get_child_by_name(device.id)) {
// Add the device preferences
const prefs = new Device.Panel(device);
const prefs = new Panel(device);
this.stack.add_titled(prefs, device.id, device.name);
// Add a row to the device list

View File

@ -8,7 +8,7 @@ import Adw from 'gi://Adw';
// Bootstrap
import * as Utils from './shell/utils.js';
import setup from './utils/setup.mjs';
import setup from './utils/setup.js';
import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
export default class GSConnectExtensionPreferences extends ExtensionPreferences {

View File

@ -2,15 +2,23 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Config = imports.config;
const Core = imports.service.core;
import Config from '../../config.js';
import * as Core from '../core.js';
// Retain compatibility with GLib < 2.80, which lacks GioUnix
let GioUnix;
try {
GioUnix = (await import('gi://GioUnix')).default;
} catch (e) {
GioUnix = {
InputStream: Gio.UnixInputStream,
OutputStream: Gio.UnixOutputStream,
};
}
/**
* TCP Port Constants
@ -25,7 +33,7 @@ const TRANSFER_MAX = 1764;
/*
* One-time check for Linux/FreeBSD socket options
*/
var _LINUX_SOCKETS = true;
export let _LINUX_SOCKETS = true;
try {
// This should throw on FreeBSD
@ -44,7 +52,7 @@ try {
*
* @param {Gio.SocketConnection} connection - The connection to configure
*/
function _configureSocket(connection) {
export function _configureSocket(connection) {
try {
if (_LINUX_SOCKETS) {
connection.socket.set_option(6, 4, 10); // TCP_KEEPIDLE
@ -78,7 +86,7 @@ function _configureSocket(connection) {
* include the TCP port, while the IP address is taken from the UDP packet
* itself. We respond by opening a TCP connection to that address.
*/
var ChannelService = GObject.registerClass({
export const ChannelService = GObject.registerClass({
GTypeName: 'GSConnectLanChannelService',
Properties: {
'certificate': GObject.ParamSpec.object(
@ -264,7 +272,7 @@ var ChannelService = GObject.registerClass({
// Input stream
this._udp6_stream = new Gio.DataInputStream({
base_stream: new Gio.UnixInputStream({
base_stream: new GioUnix.InputStream({
fd: this._udp6.fd,
close_fd: false,
}),
@ -296,7 +304,7 @@ var ChannelService = GObject.registerClass({
// Input stream
this._udp4_stream = new Gio.DataInputStream({
base_stream: new Gio.UnixInputStream({
base_stream: new GioUnix.InputStream({
fd: this._udp4.fd,
close_fd: false,
}),
@ -527,7 +535,7 @@ var ChannelService = GObject.registerClass({
* This class essentially just extends Core.Channel to set TCP socket options
* and negotiate TLS encrypted connections.
*/
var Channel = GObject.registerClass({
export const Channel = GObject.registerClass({
GTypeName: 'GSConnectLanChannel',
}, class LanChannel extends Core.Channel {

View File

@ -1,71 +0,0 @@
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
/*
* Singleton Tracker
*/
const Default = new Map();
/**
* Acquire a reference to a component. Calls to this function should always be
* followed by a call to `release()`.
*
* @param {string} name - The module name
* @return {*} The default instance of a component
*/
function acquire(name) {
let component;
try {
let info = Default.get(name);
if (info === undefined) {
const module = imports.service.components[name];
info = {
instance: new module.Component(),
refcount: 0,
};
Default.set(name, info);
}
info.refcount++;
component = info.instance;
} catch (e) {
debug(e, name);
}
return component;
}
/**
* Release a reference on a component. If the caller was the last reference
* holder, the component will be freed.
*
* @param {string} name - The module name
* @return {null} A %null value, useful for overriding a traced variable
*/
function release(name) {
try {
const info = Default.get(name);
if (info.refcount === 1) {
info.instance.destroy();
Default.delete(name);
}
info.refcount--;
} catch (e) {
debug(e, name);
}
return null;
}

View File

@ -2,12 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
imports.gi.versions.Atspi = '2.0';
const Atspi = imports.gi.Atspi;
const Gdk = imports.gi.Gdk;
import Atspi from 'gi://Atspi?version=2.0';
import Gdk from 'gi://Gdk';
/**
@ -30,7 +26,7 @@ const XKeycode = {
/**
* A thin wrapper around Atspi for X11 sessions without Pipewire support.
*/
var Controller = class {
export default class Controller {
constructor() {
// Atspi.init() return 2 on fail, but still marks itself as inited. We
// uninit before throwing an error otherwise any future call to init()
@ -312,5 +308,5 @@ var Controller = class {
// Silence errors
}
}
};
}

View File

@ -2,20 +2,21 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gdk = imports.gi.Gdk;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
import Gdk from 'gi://Gdk';
import GLib from 'gi://GLib';
import Gtk from 'gi://Gtk';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard';
const DBUS_PATH = '/org/gnome/Shell/Extensions/GSConnect/Clipboard';
var Clipboard = GObject.registerClass({
/**
* The service class for this component
*/
const Clipboard = GObject.registerClass({
GTypeName: 'GSConnectClipboard',
Properties: {
'text': GObject.ParamSpec.string(
@ -98,7 +99,7 @@ var Clipboard = GObject.registerClass({
if (!globalThis.HAVE_GNOME) {
// Directly subscrible signal
this.signalHandler = Gio.DBus.session.signal_subscribe(
DBUS_NAME,
null,
DBUS_NAME,
'OwnerChange',
DBUS_PATH,
@ -219,10 +220,6 @@ var Clipboard = GObject.registerClass({
}
});
/**
* The service class for this component
*/
var Component = Clipboard;
export default Clipboard;
// vim:tabstop=2:shiftwidth=2:expandtab

View File

@ -2,23 +2,21 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Config from '../../config.js';
const Config = imports.config;
var HAVE_EDS = true;
var EBook = null;
var EBookContacts = null;
var EDataServer = null;
let HAVE_EDS = true;
let EBook = null;
let EBookContacts = null;
let EDataServer = null;
try {
EBook = imports.gi.EBook;
EBookContacts = imports.gi.EBookContacts;
EDataServer = imports.gi.EDataServer;
EBook = (await import('gi://EBook')).default;
EBookContacts = (await import('gi://EBookContacts')).default;
EDataServer = (await import('gi://EDataServer')).default;
} catch (e) {
HAVE_EDS = false;
}
@ -27,7 +25,7 @@ try {
/**
* A store for contacts
*/
var Store = GObject.registerClass({
const Store = GObject.registerClass({
GTypeName: 'GSConnectContactsStore',
Properties: {
'context': GObject.ParamSpec.string(
@ -611,9 +609,5 @@ var Store = GObject.registerClass({
}
});
/**
* The service class for this component
*/
var Component = Store;
export default Store;

View File

@ -2,15 +2,15 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import AtspiController from './atspi.js';
const SESSION_TIMEOUT = 15;
const SESSION_TIMEOUT = 300;
const RemoteSession = GObject.registerClass({
@ -229,7 +229,7 @@ const RemoteSession = GObject.registerClass({
});
class Controller {
export default class Controller {
constructor() {
this._nameAppearedId = 0;
this._session = null;
@ -339,8 +339,7 @@ class Controller {
if (this.connection === null) {
debug('Falling back to Atspi');
const fallback = imports.service.components.atspi;
this._session = new fallback.Controller();
this._session = new AtspiController();
// Mutter is available and there isn't another session starting
} else if (this._sessionStarting === false) {
@ -513,9 +512,3 @@ class Controller {
}
}
}
/**
* The service class for this component
*/
var Component = Controller;

View File

@ -2,14 +2,12 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
var Player = GObject.registerClass({
export const Player = GObject.registerClass({
GTypeName: 'GSConnectMediaPlayerInterface',
Properties: {
// Application Properties
@ -790,7 +788,7 @@ const PlayerProxy = GObject.registerClass({
/**
* A manager for media players
*/
var Manager = GObject.registerClass({
const Manager = GObject.registerClass({
GTypeName: 'GSConnectMPRISManager',
Signals: {
'player-added': {
@ -1001,5 +999,5 @@ var Manager = GObject.registerClass({
/**
* The service class for this component
*/
var Component = Manager;
export default Manager;

View File

@ -2,14 +2,12 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GjsPrivate from 'gi://GjsPrivate';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GjsPrivate = imports.gi.GjsPrivate;
const GObject = imports.gi.GObject;
const DBus = imports.service.utils.dbus;
import * as DBus from '../utils/dbus.js';
const _nodeInfo = Gio.DBusNodeInfo.new_for_xml(`
@ -408,4 +406,4 @@ const Listener = GObject.registerClass({
/**
* The service class for this component
*/
var Component = Listener;
export default Listener;

View File

@ -2,40 +2,43 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GIRepository from 'gi://GIRepository';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Config from '../../config.js';
const Tweener = imports.tweener.tweener;
const GIRepository = imports.gi.GIRepository;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Config = imports.config;
let Gvc = null;
try {
// Add gnome-shell's typelib dir to the search path
const typelibDir = GLib.build_filenamev([Config.GNOME_SHELL_LIBDIR, 'gnome-shell']);
GIRepository.Repository.prepend_search_path(typelibDir);
GIRepository.Repository.prepend_library_path(typelibDir);
// Add gnome-shell's typelib dir to the search path
const typelibDir = GLib.build_filenamev([Config.GNOME_SHELL_LIBDIR, 'gnome-shell']);
GIRepository.Repository.prepend_search_path(typelibDir);
GIRepository.Repository.prepend_library_path(typelibDir);
const Gvc = imports.gi.Gvc;
Gvc = (await import('gi://Gvc')).default;
} catch (e) {}
/**
* Extend Gvc.MixerStream with a property for returning a user-visible name
*/
Object.defineProperty(Gvc.MixerStream.prototype, 'display_name', {
get: function () {
try {
if (!this.get_ports().length)
return this.description;
if (Gvc) {
Object.defineProperty(Gvc.MixerStream.prototype, 'display_name', {
get: function () {
try {
if (!this.get_ports().length)
return this.description;
return `${this.get_port().human_port} (${this.description})`;
} catch (e) {
return this.description;
}
},
});
return `${this.get_port().human_port} (${this.description})`;
} catch (e) {
return this.description;
}
},
});
}
/**
@ -110,7 +113,7 @@ class Stream {
* The Mixer class uses GNOME Shell's Gvc library to control the system volume
* and offers a few convenience functions.
*/
const Mixer = GObject.registerClass({
const Mixer = !Gvc ? null : GObject.registerClass({
GTypeName: 'GSConnectAudioMixer',
}, class Mixer extends Gvc.MixerControl {
_init(params) {
@ -265,4 +268,4 @@ const Mixer = GObject.registerClass({
/**
* The service class for this component
*/
var Component = Mixer;
export default Mixer;

View File

@ -2,10 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
const Session = class {
@ -82,5 +80,5 @@ const Session = class {
/**
* The service class for this component
*/
var Component = Session;
export default Session;

View File

@ -2,23 +2,17 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
let GSound = null;
try {
GSound = (await import('gi://GSound')).default;
} catch (e) {}
/*
* Used to ensure 'audible-bell' is enabled for fallback
*/
const WM_SETTINGS = new Gio.Settings({
schema_id: 'org.gnome.desktop.wm.preferences',
path: '/org/gnome/desktop/wm/preferences/',
});
var Player = class Player {
const Player = class Player {
constructor() {
this._playing = new Set();
@ -27,22 +21,20 @@ var Player = class Player {
get backend() {
if (this._backend === undefined) {
// Prefer GSound
try {
this._gsound = new imports.gi.GSound.Context();
if (GSound !== null) {
this._gsound = new GSound.Context();
this._gsound.init(null);
this._backend = 'gsound';
// Try falling back to libcanberra, otherwise just re-run the test
// in case one or the other is installed later
} catch (e) {
if (GLib.find_program_in_path('canberra-gtk-play') !== null) {
this._canberra = new Gio.SubprocessLauncher({
flags: Gio.SubprocessFlags.NONE,
});
this._backend = 'libcanberra';
} else {
return null;
}
} else if (GLib.find_program_in_path('canberra-gtk-play') !== null) {
this._canberra = new Gio.SubprocessLauncher({
flags: Gio.SubprocessFlags.NONE,
});
this._backend = 'libcanberra';
} else {
return null;
}
}
@ -176,5 +168,5 @@ var Player = class Player {
/**
* The service class for this component
*/
var Component = Player;
export default Player;

View File

@ -2,11 +2,9 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
/**
@ -49,7 +47,7 @@ const DeviceState = {
/**
* A class representing the system battery.
*/
var Battery = GObject.registerClass({
const Battery = GObject.registerClass({
GTypeName: 'GSConnectSystemBattery',
Signals: {
'changed': {
@ -213,5 +211,5 @@ var Battery = GObject.registerClass({
/**
* The service class for this component
*/
var Component = Battery;
export default Battery;

View File

@ -2,10 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const Gdk = imports.gi.Gdk;
import Gio from 'gi://Gio';
import Gdk from 'gi://Gdk';
const keyCodes = new Map([
['1', 2],
@ -55,7 +53,7 @@ const keyCodes = new Map([
['/', 53],
['\\', 43],
]);
class Controller {
export default class Controller {
constructor() {
// laucher for wl-clipboard
this._launcher = new Gio.SubprocessLauncher({
@ -137,7 +135,7 @@ class Controller {
modifiers_codes.push(input);
} else if (typeof input === 'string') {
input = input.toUpperCase();
for (var i = 0; i < input.length; i++) {
for (let i = 0; i < input.length; i++) {
if (keyCodes.get(input[i])) {
modifiers_codes.push(keyCodes.get(input[i]));
} else {
@ -160,8 +158,3 @@ class Controller {
this._args = [];
}
}
/**
* The service class for this component
*/
var Component = Controller;

View File

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import plugins from './plugins/index.js';
/**
@ -14,13 +14,16 @@ const GObject = imports.gi.GObject;
*
* @return {string} A device type string
*/
function _getDeviceType() {
export function _getDeviceType() {
try {
let type = GLib.file_get_contents('/sys/class/dmi/id/chassis_type')[1];
type = Number(new TextDecoder().decode(type));
if ([8, 9, 10, 14].includes(type))
if ([30, 32].includes(type))
return 'tablet';
if ([8, 9, 10, 14, 31].includes(type))
return 'laptop';
return 'desktop';
@ -34,7 +37,7 @@ function _getDeviceType() {
* The packet class is a simple Object-derived class, offering some conveniences
* for working with KDE Connect packets.
*/
var Packet = class Packet {
export class Packet {
constructor(data = null) {
this.id = 0;
@ -114,7 +117,7 @@ var Packet = class Packet {
return (Object.keys(this.payloadTransferInfo).length > 0);
}
};
}
/**
@ -122,7 +125,7 @@ var Packet = class Packet {
* devices. The implementation is responsible for all negotiation of the
* underlying protocol.
*/
var Channel = GObject.registerClass({
export const Channel = GObject.registerClass({
GTypeName: 'GSConnectChannel',
Properties: {
'closed': GObject.ParamSpec.boolean(
@ -297,7 +300,7 @@ var Channel = GObject.registerClass({
* ChannelService implementations provide Channel objects, emitting the
* ChannelService::channel signal when a new connection has been accepted.
*/
var ChannelService = GObject.registerClass({
export const ChannelService = GObject.registerClass({
GTypeName: 'GSConnectChannelService',
Properties: {
'active': GObject.ParamSpec.boolean(
@ -409,8 +412,8 @@ var ChannelService = GObject.registerClass({
},
});
for (const name in imports.service.plugins) {
const meta = imports.service.plugins[name].Metadata;
for (const name in plugins) {
const meta = plugins[name].Metadata;
if (meta === undefined)
continue;
@ -460,7 +463,7 @@ var ChannelService = GObject.registerClass({
/**
* A class representing a file transfer.
*/
var Transfer = GObject.registerClass({
export const Transfer = GObject.registerClass({
GTypeName: 'GSConnectTransfer',
Properties: {
'channel': GObject.ParamSpec.object(
@ -691,4 +694,3 @@ var Transfer = GObject.registerClass({
this._cancellable.cancel();
}
});

View File

@ -1,46 +1,27 @@
#!/usr/bin/env gjs
#!/usr/bin/env -S gjs -m
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk?version=3.0';
import 'gi://GdkPixbuf?version=2.0';
import Gio from 'gi://Gio?version=2.0';
import 'gi://GIRepository?version=2.0';
import GLib from 'gi://GLib?version=2.0';
import GObject from 'gi://GObject?version=2.0';
import Gtk from 'gi://Gtk?version=3.0';
import 'gi://Pango?version=1.0';
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.GdkPixbuf = '2.0';
imports.gi.versions.Gio = '2.0';
imports.gi.versions.GIRepository = '2.0';
imports.gi.versions.GLib = '2.0';
imports.gi.versions.GObject = '2.0';
imports.gi.versions.Gtk = '3.0';
imports.gi.versions.Pango = '1.0';
import system from 'system';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import './init.js';
// Bootstrap
function get_datadir() {
let [, path] = /@([^:]+):\d+/.exec(new Error().stack.split('\n')[1]);
const info = Gio.File.new_for_path(path)
.query_info('standard::*', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
path = info.get_is_symlink() ? info.get_symlink_target() : path;
import Config from '../config.js';
import Manager from './manager.js';
import * as ServiceUI from './ui/service.js';
return Gio.File.new_for_path(path).get_parent().get_parent().get_path();
}
imports.searchPath.unshift(get_datadir());
imports.config.PACKAGE_DATADIR = imports.searchPath[0];
const _setup = imports.service.utils.setup;
// Local Imports
const Config = imports.config;
const Manager = imports.service.manager;
const ServiceUI = imports.service.ui.service;
import('gi://GioUnix?version=2.0').catch(() => {}); // Set version for optional dependency
/**
@ -267,7 +248,7 @@ const Service = GObject.registerClass({
if (!super.vfunc_dbus_register(connection, object_path))
return false;
this.manager = new Manager.Manager({
this.manager = new Manager({
connection: connection,
object_path: object_path,
});
@ -337,7 +318,7 @@ const Service = GObject.registerClass({
continue;
// Force a GC to prevent any more calls back into JS, then chain-up
imports.system.gc();
system.gc();
super.vfunc_shutdown();
}
@ -717,5 +698,5 @@ const Service = GObject.registerClass({
}
});
(new Service()).run([imports.system.programInvocationName].concat(ARGV));
await (new Service()).runAsync([system.programInvocationName].concat(ARGV));

View File

@ -2,16 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Config = imports.config;
const Components = imports.service.components;
const Core = imports.service.core;
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Config from '../config.js';
import * as Components from './components/index.js';
import * as Core from './core.js';
import plugins from './plugins/index.js';
/**
* An object representing a remote device.
@ -20,7 +18,7 @@ const Core = imports.service.core;
* GActionGroup and GActionMap interfaces, like Gio.Application.
*
*/
var Device = GObject.registerClass({
const Device = GObject.registerClass({
GTypeName: 'GSConnectDevice',
Properties: {
'connected': GObject.ParamSpec.boolean(
@ -297,8 +295,8 @@ var Device = GObject.registerClass({
// Determine supported plugins by matching incoming to outgoing types
const supported = [];
for (const name in imports.service.plugins) {
const meta = imports.service.plugins[name].Metadata;
for (const name in plugins) {
const meta = plugins[name].Metadata;
if (meta === undefined)
continue;
@ -1011,8 +1009,8 @@ var Device = GObject.registerClass({
try {
if (this.paired && !this._plugins.has(name)) {
// Instantiate the handler
handler = imports.service.plugins[name];
plugin = new handler.Plugin(this);
handler = plugins[name];
plugin = new handler.default(this);
// Register packet handlers
for (const packetType of handler.Metadata.incomingCapabilities)
@ -1053,7 +1051,7 @@ var Device = GObject.registerClass({
try {
if (this._plugins.has(name)) {
// Unregister packet handlers
handler = imports.service.plugins[name];
handler = plugins[name];
for (const type of handler.Metadata.incomingCapabilities)
this._handlers.delete(type);
@ -1104,3 +1102,4 @@ var Device = GObject.registerClass({
}
});
export default Device;

View File

@ -138,20 +138,17 @@ const _debugFunc = function (error, prefix = null) {
});
};
// Swap the function out for a no-op anonymous function for speed
globalThis._debugFunc = _debugFunc;
const settings = new Gio.Settings({
settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true),
});
settings.connect('changed::debug', (settings, key) => {
globalThis.debug = settings.get_boolean(key) ? _debugFunc : () => {};
});
if (settings.get_boolean('debug'))
globalThis.debug = _debugFunc;
else
if (settings.get_boolean('debug')) {
globalThis.debug = globalThis._debugFunc;
} else {
// Swap the function out for a no-op anonymous function for speed
globalThis.debug = () => {};
}
/**
* Start wl_clipboard if not under Gnome

View File

@ -2,25 +2,30 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Config from '../config.js';
import * as DBus from './utils/dbus.js';
import Device from './device.js';
const Config = imports.config;
const DBus = imports.service.utils.dbus;
const Device = imports.service.device;
import * as LanBackend from './backends/lan.js';
const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device';
const DEVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect/Device';
const DEVICE_IFACE = Config.DBUS.lookup_interface(DEVICE_NAME);
const backends = {
lan: LanBackend,
};
/**
* A manager for devices.
*/
var Manager = GObject.registerClass({
const Manager = GObject.registerClass({
GTypeName: 'GSConnectManager',
Properties: {
'active': GObject.ParamSpec.boolean(
@ -30,6 +35,13 @@ var Manager = GObject.registerClass({
GObject.ParamFlags.READABLE,
false
),
'debug': GObject.ParamSpec.boolean(
'debug',
'Debug',
'Whether debug logging is enabled in GSConnect',
GObject.ParamFlags.READWRITE,
false
),
'discoverable': GObject.ParamSpec.boolean(
'discoverable',
'Discoverable',
@ -80,6 +92,21 @@ var Manager = GObject.registerClass({
return this._backends;
}
get debug() {
if (this._debug === undefined)
this._debug = this.settings.get_boolean('debug');
return this._debug;
}
set debug(value) {
if (this._debug === value)
return;
this._debug = value;
this._onDebugChanged(this._debug);
}
get devices() {
if (this._devices === undefined)
this._devices = new Map();
@ -198,11 +225,20 @@ var Manager = GObject.registerClass({
this.settings.set_string('name', GLib.get_host_name());
// Bound Properties
this.settings.bind('debug', this, 'debug', 0);
this.settings.bind('discoverable', this, 'discoverable', 0);
this.settings.bind('id', this, 'id', 0);
this.settings.bind('name', this, 'name', 0);
}
_onDebugChanged(debug = false) {
// If debugging is disabled, install a no-op for speed
if (debug && globalThis._debugFunc !== undefined)
globalThis.debug = globalThis._debugFunc;
else
globalThis.debug = () => {};
}
/*
* Backends
*/
@ -235,9 +271,9 @@ var Manager = GObject.registerClass({
}
_loadBackends() {
for (const name in imports.service.backends) {
for (const name in backends) {
try {
const module = imports.service.backends[name];
const module = backends[name];
if (module.ChannelService === undefined)
continue;
@ -270,7 +306,7 @@ var Manager = GObject.registerClass({
_loadDevices() {
// Load cached devices
for (const id of this.settings.get_strv('devices')) {
const device = new Device.Device({body: {deviceId: id}});
const device = new Device({body: {deviceId: id}});
this._exportDevice(device);
this.devices.set(id, device);
}
@ -346,7 +382,7 @@ var Manager = GObject.registerClass({
* of known devices if it doesn't exist.
*
* @param {Core.Packet} packet - An identity packet for the device
* @return {Device.Device} A device object
* @return {Device} A device object
*/
_ensureDevice(packet) {
let device = this.devices.get(packet.body.deviceId);
@ -365,7 +401,7 @@ var Manager = GObject.registerClass({
if (unpaired.length === 3)
this.discoverable = false;
device = new Device.Device(packet);
device = new Device(packet);
this._exportDevice(device);
this.devices.set(device.id, device);
@ -506,3 +542,4 @@ var Manager = GObject.registerClass({
}
});
export default Manager;

View File

@ -1,19 +1,25 @@
#!/usr/bin/env gjs
#!/usr/bin/env -S gjs -m
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio?version=2.0';
import GLib from 'gi://GLib?version=2.0';
import GObject from 'gi://GObject?version=2.0';
imports.gi.versions.Gio = '2.0';
imports.gi.versions.GLib = '2.0';
imports.gi.versions.GObject = '2.0';
import system from 'system';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const System = imports.system;
// Retain compatibility with GLib < 2.80, which lacks GioUnix
let GioUnix;
try {
GioUnix = (await import('gi://GioUnix?version=2.0')).default;
} catch (e) {
GioUnix = {
InputStream: Gio.UnixInputStream,
OutputStream: Gio.UnixOutputStream,
};
}
const NativeMessagingHost = GObject.registerClass({
@ -44,12 +50,12 @@ const NativeMessagingHost = GObject.registerClass({
// IO Channels
this._stdin = new Gio.DataInputStream({
base_stream: new Gio.UnixInputStream({fd: 0}),
base_stream: new GioUnix.InputStream({fd: 0}),
byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN,
});
this._stdout = new Gio.DataOutputStream({
base_stream: new Gio.UnixOutputStream({fd: 1}),
base_stream: new GioUnix.OutputStream({fd: 1}),
byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN,
});
@ -215,5 +221,5 @@ const NativeMessagingHost = GObject.registerClass({
});
// NOTE: must not pass ARGV
(new NativeMessagingHost()).run([System.programInvocationName]);
await (new NativeMessagingHost()).runAsync([system.programInvocationName]);

View File

@ -2,19 +2,18 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Config = imports.config;
import Config from '../config.js';
import plugins from './plugins/index.js';
/**
* Base class for device plugins.
*/
var Plugin = GObject.registerClass({
const Plugin = GObject.registerClass({
GTypeName: 'GSConnectPlugin',
Properties: {
'device': GObject.ParamSpec.object(
@ -42,7 +41,7 @@ var Plugin = GObject.registerClass({
this._meta = meta;
if (this._meta === null)
this._meta = imports.service.plugins[name].Metadata;
this._meta = plugins[name].Metadata;
// GSettings
const schema = Config.GSCHEMA.lookup(this._meta.id, false);
@ -248,3 +247,5 @@ var Plugin = GObject.registerClass({
}
});
export default Plugin;

View File

@ -2,17 +2,15 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Battery'),
description: _('Exchange battery information'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Battery',
@ -32,9 +30,9 @@ var Metadata = {
* Battery Plugin
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/battery
*/
var Plugin = GObject.registerClass({
const BatteryPlugin = GObject.registerClass({
GTypeName: 'GSConnectBatteryPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class BatteryPlugin extends Plugin {
_init(device) {
super._init(device, 'battery');
@ -431,3 +429,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default BatteryPlugin;

View File

@ -2,15 +2,13 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GObject from 'gi://GObject';
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Clipboard'),
description: _('Share the clipboard content'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Clipboard',
@ -47,9 +45,9 @@ var Metadata = {
* Clipboard Plugin
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/clipboard
*/
var Plugin = GObject.registerClass({
const ClipboardPlugin = GObject.registerClass({
GTypeName: 'GSConnectClipboardPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class ClipboardPlugin extends Plugin {
_init(device) {
super._init(device, 'clipboard');
@ -180,3 +178,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default ClipboardPlugin;

View File

@ -2,17 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const PluginBase = imports.service.plugin;
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Connectivity Report'),
description: _('Display connectivity status'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.ConnectivityReport',
@ -30,9 +27,9 @@ var Metadata = {
* Connectivity Report Plugin
* https://invent.kde.org/network/kdeconnect-kde/-/tree/master/plugins/connectivity_report
*/
var Plugin = GObject.registerClass({
const ConnectivityReportPlugin = GObject.registerClass({
GTypeName: 'GSConnectConnectivityReportPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class ConnectivityReportPlugin extends Plugin {
_init(device) {
super._init(device, 'connectivity_report');
@ -162,3 +159,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default ConnectivityReportPlugin;

View File

@ -2,27 +2,28 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const PluginBase = imports.service.plugin;
const Contacts = imports.service.components.contacts;
import Plugin from '../plugin.js';
import Contacts from '../components/contacts.js';
/*
* We prefer libebook's vCard parser if it's available
*/
var EBookContacts;
let EBookContacts;
export const setEBookContacts = (ebook) => { // This function is only for tests to call!
EBookContacts = ebook;
};
try {
EBookContacts = imports.gi.EBookContacts;
EBookContacts = (await import('gi://EBookContacts')).default;
} catch (e) {
EBookContacts = null;
}
var Metadata = {
export const Metadata = {
label: _('Contacts'),
description: _('Access contacts of the paired device'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Contacts',
@ -53,14 +54,14 @@ const VCARD_TYPED_META = /([a-z]+)=(.*)/i;
* Contacts Plugin
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/contacts
*/
var Plugin = GObject.registerClass({
const ContactsPlugin = GObject.registerClass({
GTypeName: 'GSConnectContactsPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class ContactsPlugin extends Plugin {
_init(device) {
super._init(device, 'contacts');
this._store = new Contacts.Store(device.id);
this._store = new Contacts(device.id);
this._store.fetch = this._requestUids.bind(this);
// Notify when the store is ready
@ -458,3 +459,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default ContactsPlugin;

View File

@ -2,18 +2,16 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Components = imports.service.components;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Find My Phone'),
description: _('Ring your paired device'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.FindMyPhone',
@ -36,9 +34,9 @@ var Metadata = {
* FindMyPhone Plugin
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/findmyphone
*/
var Plugin = GObject.registerClass({
const FindMyPhonePlugin = GObject.registerClass({
GTypeName: 'GSConnectFindMyPhonePlugin',
}, class Plugin extends PluginBase.Plugin {
}, class FindMyPhonePlugin extends Plugin {
_init(device) {
super._init(device, 'findmyphone');
@ -247,3 +245,5 @@ const Dialog = GObject.registerClass({
this._plugin = plugin;
}
});
export default FindMyPhonePlugin;

View File

@ -2,17 +2,15 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import GObject from 'gi://GObject';
const Gdk = imports.gi.Gdk;
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const {InputDialog} = imports.service.ui.mousepad;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import {InputDialog} from '../ui/mousepad.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Mousepad'),
description: _('Enables the paired device to act as a remote mouse and keyboard'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Mousepad',
@ -120,7 +118,7 @@ const KeyMapCodes = new Map([
*
* TODO: support outgoing mouse events?
*/
var Plugin = GObject.registerClass({
const MousepadPlugin = GObject.registerClass({
GTypeName: 'GSConnectMousepadPlugin',
Properties: {
'state': GObject.ParamSpec.boolean(
@ -131,7 +129,7 @@ var Plugin = GObject.registerClass({
false
),
},
}, class Plugin extends PluginBase.Plugin {
}, class MousepadPlugin extends Plugin {
_init(device) {
super._init(device, 'mousepad');
@ -379,3 +377,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default MousepadPlugin;

View File

@ -2,20 +2,18 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const Config = imports.config;
const DBus = imports.service.utils.dbus;
const MPRIS = imports.service.components.mpris;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Config from '../../config.js';
import * as DBus from '../utils/dbus.js';
import {Player} from '../components/mpris.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('MPRIS'),
description: _('Bidirectional remote media playback control'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.MPRIS',
@ -33,9 +31,9 @@ var Metadata = {
* https://specifications.freedesktop.org/mpris-spec/latest/
* https://github.com/GNOME/gnome-shell/blob/master/js/ui/mpris.js
*/
var Plugin = GObject.registerClass({
const MPRISPlugin = GObject.registerClass({
GTypeName: 'GSConnectMPRISPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class MPRISPlugin extends Plugin {
_init(device) {
super._init(device, 'mpris');
@ -242,11 +240,22 @@ var Plugin = GObject.registerClass({
player.Volume = packet.body.setVolume / 100;
if (packet.body.hasOwnProperty('Seek'))
await player.Seek(packet.body.Seek * 1000);
await player.Seek(packet.body.Seek);
if (packet.body.hasOwnProperty('SetPosition')) {
const offset = (packet.body.SetPosition * 1000) - player.Position;
await player.Seek(offset);
// We want to avoid implementing this as a seek operation,
// because some players seek a fixed amount for every
// seek request, only respecting the sign of the parameter.
// (Chrome, for example, will only seek ±5 seconds, regardless
// what value is passed to Seek().)
const position = packet.body.SetPosition;
const metadata = player.Metadata;
if (metadata.hasOwnProperty('mpris:trackid')) {
const trackId = metadata['mpris:trackid'];
await player.SetPosition(trackId, position * 1000);
} else {
await player.Seek(position * 1000 - player.Position);
}
}
// Information Request
@ -448,7 +457,7 @@ var Plugin = GObject.registerClass({
*/
const PlayerRemote = GObject.registerClass({
GTypeName: 'GSConnectMPRISPlayerRemote',
}, class PlayerRemote extends MPRIS.Player {
}, class PlayerRemote extends Player {
_init(device, identity) {
super._init();
@ -904,3 +913,5 @@ const PlayerRemote = GObject.registerClass({
}
}
});
export default MPRISPlugin;

View File

@ -2,20 +2,18 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Components = imports.service.components;
const Config = imports.config;
const PluginBase = imports.service.plugin;
const NotificationUI = imports.service.ui.notification;
import * as Components from '../components/index.js';
import Config from '../../config.js';
import Plugin from '../plugin.js';
import ReplyDialog from '../ui/notification.js';
var Metadata = {
export const Metadata = {
label: _('Notifications'),
description: _('Share notifications with the paired device'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Notification',
@ -162,9 +160,9 @@ function _removeNotification(id, application = null) {
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/notifications
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sendnotifications
*/
var Plugin = GObject.registerClass({
const NotificationPlugin = GObject.registerClass({
GTypeName: 'GSConnectNotificationPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class NotificationPlugin extends Plugin {
_init(device) {
super._init(device, 'notification');
@ -642,7 +640,7 @@ var Plugin = GObject.registerClass({
// If the message has no content, open a dialog for the user to add one
if (!message) {
const dialog = new NotificationUI.ReplyDialog({
const dialog = new ReplyDialog({
device: this.device,
uuid: uuid,
notification: notification,
@ -692,3 +690,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default NotificationPlugin;

View File

@ -2,16 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const PluginBase = imports.service.plugin;
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Ping'),
description: _('Send and receive pings'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Ping',
@ -34,9 +32,9 @@ var Metadata = {
* Ping Plugin
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/ping
*/
var Plugin = GObject.registerClass({
const PingPlugin = GObject.registerClass({
GTypeName: 'GSConnectPingPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class PingPlugin extends Plugin {
_init(device) {
super._init(device, 'ping');
@ -71,3 +69,5 @@ var Plugin = GObject.registerClass({
this.device.sendPacket(packet);
}
});
export default PingPlugin;

View File

@ -2,15 +2,13 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GObject from 'gi://GObject';
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Presentation'),
description: _('Use the paired device as a presenter'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Presenter',
@ -25,9 +23,9 @@ var Metadata = {
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/presenter
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/PresenterPlugin/
*/
var Plugin = GObject.registerClass({
const PresenterPlugin = GObject.registerClass({
GTypeName: 'GSConnectPresenterPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class PresenterPlugin extends Plugin {
_init(device) {
super._init(device, 'presenter');
@ -61,3 +59,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default PresenterPlugin;

View File

@ -2,16 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const PluginBase = imports.service.plugin;
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Run Commands'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.RunCommand',
description: _('Run commands on your paired device or let the device run predefined commands on this PC'),
@ -49,7 +47,7 @@ var Metadata = {
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/remotecommands
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/runcommand
*/
var Plugin = GObject.registerClass({
const RunCommandPlugin = GObject.registerClass({
GTypeName: 'GSConnectRunCommandPlugin',
Properties: {
'remote-commands': GObject.param_spec_variant(
@ -61,7 +59,7 @@ var Plugin = GObject.registerClass({
GObject.ParamFlags.READABLE
),
},
}, class Plugin extends PluginBase.Plugin {
}, class RunCommandPlugin extends Plugin {
_init(device) {
super._init(device, 'runcommand');
@ -252,3 +250,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default RunCommandPlugin;

View File

@ -2,18 +2,15 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Config = imports.config;
const Lan = imports.service.backends.lan;
const PluginBase = imports.service.plugin;
import Config from '../../config.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('SFTP'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SFTP',
description: _('Browse the paired device filesystem'),
@ -48,9 +45,9 @@ const MAX_MOUNT_DIRS = 12;
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sftp
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SftpPlugin
*/
var Plugin = GObject.registerClass({
const SFTPPlugin = GObject.registerClass({
GTypeName: 'GSConnectSFTPPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class SFTPPlugin extends Plugin {
_init(device) {
super._init(device, 'sftp');
@ -106,7 +103,7 @@ var Plugin = GObject.registerClass({
super.connected();
// Only enable for Lan connections
if (this.device.channel instanceof Lan.Channel) {
if (this.device.channel.constructor.name === 'LanChannel') { // FIXME: Circular import workaround
if (this.settings.get_boolean('automount'))
this.mount();
} else {
@ -486,3 +483,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default SFTPPlugin;

View File

@ -2,19 +2,17 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GdkPixbuf from 'gi://GdkPixbuf';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const PluginBase = imports.service.plugin;
const URI = imports.service.utils.uri;
import Plugin from '../plugin.js';
import * as URI from '../utils/uri.js';
var Metadata = {
export const Metadata = {
label: _('Share'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Share',
description: _('Share files and URLs between devices'),
@ -64,9 +62,9 @@ var Metadata = {
* TODO: receiving 'text' TODO: Window with textview & 'Copy to Clipboard..
* https://github.com/KDE/kdeconnect-kde/commit/28f11bd5c9a717fb9fbb3f02ddd6cea62021d055
*/
var Plugin = GObject.registerClass({
const SharePlugin = GObject.registerClass({
GTypeName: 'GSConnectSharePlugin',
}, class Plugin extends PluginBase.Plugin {
}, class SharePlugin extends Plugin {
_init(device) {
super._init(device, 'share');
@ -198,6 +196,9 @@ var Plugin = GObject.registerClass({
];
iconName = 'document-save-symbolic';
const gtk_recent_manager = Gtk.RecentManager.get_default();
gtk_recent_manager.add_item(file.get_uri());
if (packet.body.open) {
const uri = file.get_uri();
Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null);
@ -369,7 +370,7 @@ var Plugin = GObject.registerClass({
/** A simple FileChooserDialog for sharing files */
var FileChooserDialog = GObject.registerClass({
const FileChooserDialog = GObject.registerClass({
GTypeName: 'GSConnectShareFileChooserDialog',
}, class FileChooserDialog extends Gtk.FileChooserDialog {
@ -451,10 +452,11 @@ var FileChooserDialog = GObject.registerClass({
_onUriButtonToggled(button) {
const header = this.get_header_bar();
// Show the URL entry
// Show and focus the URL entry
if (button.active) {
this.extra_widget.sensitive = false;
header.set_custom_title(this._uriEntry);
this._uriEntry.grab_focus();
this.set_response_sensitive(Gtk.ResponseType.OK, true);
// Hide the URL entry
@ -490,3 +492,5 @@ var FileChooserDialog = GObject.registerClass({
this.destroy();
}
});
export default SharePlugin;

View File

@ -2,19 +2,17 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const PluginBase = imports.service.plugin;
const LegacyMessaging = imports.service.ui.legacyMessaging;
const Messaging = imports.service.ui.messaging;
const URI = imports.service.utils.uri;
import Plugin from '../plugin.js';
import LegacyMessagingDialog from '../ui/legacyMessaging.js';
import * as Messaging from '../ui/messaging.js';
import SmsURI from '../utils/uri.js';
var Metadata = {
export const Metadata = {
label: _('SMS'),
description: _('Send and read SMS of the paired device and be notified of new SMS'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SMS',
@ -85,7 +83,7 @@ var Metadata = {
*
* TEXT_MESSAGE: Has a "body" field which contains pure, human-readable text
*/
var MessageEventType = {
export const MessageEventType = {
TEXT_MESSAGE: 0x1,
};
@ -97,7 +95,7 @@ var MessageEventType = {
* UNREAD: A message not marked as read
* READ: A message marked as read
*/
var MessageStatus = {
export const MessageStatus = {
UNREAD: 0,
READ: 1,
};
@ -117,7 +115,7 @@ var MessageStatus = {
* FAILED: Failed outgoing messages
* QUEUED: Messages queued to send later
*/
var MessageBox = {
export const MessageBox = {
ALL: 0,
INBOX: 1,
SENT: 2,
@ -133,7 +131,7 @@ var MessageBox = {
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sms
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SMSPlugin/
*/
var Plugin = GObject.registerClass({
const SMSPlugin = GObject.registerClass({
GTypeName: 'GSConnectSMSPlugin',
Properties: {
'threads': GObject.param_spec_variant(
@ -145,7 +143,7 @@ var Plugin = GObject.registerClass({
GObject.ParamFlags.READABLE
),
},
}, class Plugin extends PluginBase.Plugin {
}, class SMSPlugin extends Plugin {
_init(device) {
super._init(device, 'sms');
@ -162,7 +160,7 @@ var Plugin = GObject.registerClass({
get window() {
if (this.settings.get_boolean('legacy-sms')) {
return new LegacyMessaging.Dialog({
return new LegacyMessagingDialog({
device: this.device,
plugin: this,
});
@ -473,7 +471,7 @@ var Plugin = GObject.registerClass({
*/
uriSms(uri) {
try {
uri = new URI.SmsURI(uri);
uri = new SmsURI(uri);
// Lookup contacts
const addresses = uri.recipients.map(number => {
@ -534,3 +532,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default SMSPlugin;

View File

@ -2,16 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GObject from 'gi://GObject';
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const Config = imports.config;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Config from '../../config.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('System Volume'),
description: _('Enable the paired device to control the system volume'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SystemVolume',
@ -26,9 +24,9 @@ var Metadata = {
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/systemvolume
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SystemvolumePlugin/
*/
var Plugin = GObject.registerClass({
const SystemVolumePlugin = GObject.registerClass({
GTypeName: 'GSConnectSystemVolumePlugin',
}, class Plugin extends PluginBase.Plugin {
}, class SystemVolumePlugin extends Plugin {
_init(device) {
super._init(device, 'systemvolume');
@ -202,3 +200,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default SystemVolumePlugin;

View File

@ -2,18 +2,16 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GdkPixbuf from 'gi://GdkPixbuf';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Components = imports.service.components;
const PluginBase = imports.service.plugin;
import * as Components from '../components/index.js';
import Plugin from '../plugin.js';
var Metadata = {
export const Metadata = {
label: _('Telephony'),
description: _('Be notified about calls and adjust system volume during ringing/ongoing calls'),
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Telephony',
@ -43,9 +41,9 @@ var Metadata = {
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/telephony
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/TelephonyPlugin
*/
var Plugin = GObject.registerClass({
const TelephonyPlugin = GObject.registerClass({
GTypeName: 'GSConnectTelephonyPlugin',
}, class Plugin extends PluginBase.Plugin {
}, class TelephonyPlugin extends Plugin {
_init(device) {
super._init(device, 'telephony');
@ -243,3 +241,5 @@ var Plugin = GObject.registerClass({
super.destroy();
}
});
export default TelephonyPlugin;

View File

@ -2,13 +2,13 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import GdkPixbuf from 'gi://GdkPixbuf';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const Gdk = imports.gi.Gdk;
const GdkPixbuf = imports.gi.GdkPixbuf;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import system from 'system';
/**
@ -156,7 +156,7 @@ function getNumberTypeLabel(type) {
* @param {string} address - A phone number
* @return {string} A (possibly) better display number for the address
*/
function getDisplayNumber(contact, address) {
export function getDisplayNumber(contact, address) {
const number = address.toPhoneNumber();
for (const contactNumber of contact.numbers) {
@ -175,7 +175,7 @@ function getDisplayNumber(contact, address) {
*/
const AvatarCache = new WeakMap();
var Avatar = GObject.registerClass({
export const Avatar = GObject.registerClass({
GTypeName: 'GSConnectContactAvatar',
}, class ContactAvatar extends Gtk.DrawingArea {
@ -363,7 +363,7 @@ const AddressRow = GObject.registerClass({
/**
* A widget for selecting contact addresses (usually phone numbers)
*/
var ContactChooser = GObject.registerClass({
export const ContactChooser = GObject.registerClass({
GTypeName: 'GSConnectContactChooser',
Properties: {
'device': GObject.ParamSpec.object(
@ -435,7 +435,7 @@ var ContactChooser = GObject.registerClass({
for (let i = 0, len = rows.length; i < len; i++) {
rows[i].destroy();
// HACK: temporary mitigator for mysterious GtkListBox leak
imports.system.gc();
system.gc();
}
}
@ -482,7 +482,7 @@ var ContactChooser = GObject.registerClass({
if (row.contact.id === id) {
row.destroy();
// HACK: temporary mitigator for mysterious GtkListBox leak
imports.system.gc();
system.gc();
}
}
}

View File

@ -2,19 +2,17 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Contacts = imports.service.ui.contacts;
const Messaging = imports.service.ui.messaging;
const URI = imports.service.utils.uri;
const _ui = imports.service.utils.ui;
import * as Contacts from '../ui/contacts.js';
import * as Messaging from '../ui/messaging.js';
import * as URI from '../utils/uri.js';
import '../utils/ui.js';
var Dialog = GObject.registerClass({
const Dialog = GObject.registerClass({
GTypeName: 'GSConnectLegacyMessagingDialog',
Properties: {
'device': GObject.ParamSpec.object(
@ -226,3 +224,4 @@ var Dialog = GObject.registerClass({
}
});
export default Dialog;

View File

@ -2,21 +2,21 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import Pango from 'gi://Pango';
import system from 'system';
import * as Contacts from './contacts.js';
import * as Sms from '../plugins/sms.js';
import * as URI from '../utils/uri.js';
import '../utils/ui.js';
const Tweener = imports.tweener.tweener;
const Gdk = imports.gi.Gdk;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Contacts = imports.service.ui.contacts;
const Sms = imports.service.plugins.sms;
const URI = imports.service.utils.uri;
const _ui = imports.service.utils.ui;
/*
* Useful time constants
@ -460,7 +460,7 @@ const Conversation = GObject.registerClass({
conversation.list.foreach(message => {
// HACK: temporary mitigator for mysterious GtkListBox leak
message.destroy();
imports.system.gc();
system.gc();
});
}
@ -800,7 +800,7 @@ const ConversationSummary = GObject.registerClass({
/**
* A Gtk.ApplicationWindow for SMS conversations
*/
var Window = GObject.registerClass({
export const Window = GObject.registerClass({
GTypeName: 'GSConnectMessagingWindow',
Properties: {
'device': GObject.ParamSpec.object(
@ -1025,13 +1025,13 @@ var Window = GObject.registerClass({
if (conversation) {
conversation.destroy();
imports.system.gc();
system.gc();
}
// Then the summary widget
row.destroy();
// HACK: temporary mitigator for mysterious GtkListBox leak
imports.system.gc();
system.gc();
}
}
@ -1219,7 +1219,7 @@ var Window = GObject.registerClass({
/**
* A Gtk.ApplicationWindow for selecting from open conversations
*/
var ConversationChooser = GObject.registerClass({
export const ConversationChooser = GObject.registerClass({
GTypeName: 'GSConnectConversationChooser',
Properties: {
'device': GObject.ParamSpec.object(

View File

@ -2,12 +2,10 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const GLib = imports.gi.GLib;
const Gdk = imports.gi.Gdk;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import GLib from 'gi://GLib';
import Gdk from 'gi://Gdk';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
/**
@ -73,7 +71,7 @@ const isShift = (key) => [Gdk.KEY_Shift_L, Gdk.KEY_Shift_R].includes(key);
const isSuper = (key) => [Gdk.KEY_Super_L, Gdk.KEY_Super_R].includes(key);
var InputDialog = GObject.registerClass({
export const InputDialog = GObject.registerClass({
GTypeName: 'GSConnectMousepadInputDialog',
Properties: {
'device': GObject.ParamSpec.object(
@ -390,7 +388,7 @@ var InputDialog = GObject.registerClass({
(Math.abs(this.touchpad_motion_y) < 4);
if (is_click) {
var click_body = {};
const click_body = {};
switch (gesture_button) {
case 1:
click_body.singleclick = true;
@ -444,8 +442,8 @@ var InputDialog = GObject.registerClass({
}
_onTouchpadMotionTimeout() {
var diff_x = this.touchpad_motion_x - this.touchpad_motion_prev_x;
var diff_y = this.touchpad_motion_y - this.touchpad_motion_prev_y;
const diff_x = this.touchpad_motion_x - this.touchpad_motion_prev_x;
const diff_y = this.touchpad_motion_y - this.touchpad_motion_prev_y;
this.device.sendPacket({
type: 'kdeconnect.mousepad.request',

View File

@ -2,20 +2,18 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const URI = imports.service.utils.uri;
const _ui = imports.service.utils.ui;
import * as URI from '../utils/uri.js';
import '../utils/ui.js';
/**
* A dialog for repliable notifications.
*/
var ReplyDialog = GObject.registerClass({
const ReplyDialog = GObject.registerClass({
GTypeName: 'GSConnectNotificationReplyDialog',
Properties: {
'device': GObject.ParamSpec.object(
@ -177,3 +175,4 @@ var ReplyDialog = GObject.registerClass({
}
});
export default ReplyDialog;

View File

@ -2,14 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import GLib from 'gi://GLib';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
import system from 'system';
const Config = imports.config;
import Config from '../../config.js';
/*
@ -17,7 +17,7 @@ const Config = imports.config;
*/
const ISSUE_HEADER = `
GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'})
GJS: ${imports.system.version}
GJS: ${system.version}
Session: ${GLib.getenv('XDG_SESSION_TYPE')}
OS: ${GLib.get_os_info('PRETTY_NAME')}
`;
@ -26,7 +26,7 @@ OS: ${GLib.get_os_info('PRETTY_NAME')}
/**
* A dialog for selecting a device
*/
var DeviceChooser = GObject.registerClass({
export const DeviceChooser = GObject.registerClass({
GTypeName: 'GSConnectServiceDeviceChooser',
Properties: {
'action-name': GObject.ParamSpec.string(
@ -192,7 +192,7 @@ var DeviceChooser = GObject.registerClass({
/**
* A dialog for reporting an error.
*/
var ErrorDialog = GObject.registerClass({
export const ErrorDialog = GObject.registerClass({
GTypeName: 'GSConnectServiceErrorDialog',
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/service-error-dialog.ui',
Children: [

View File

@ -2,12 +2,10 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GjsPrivate = imports.gi.GjsPrivate;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Gio from 'gi://Gio';
import GjsPrivate from 'gi://GjsPrivate';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
/*
@ -19,12 +17,6 @@ function toDBusCase(string) {
}).replace(/[\s_-]+/g, '');
}
function toHyphenCase(string) {
return string.replace(/(?:[A-Z])/g, (ltr, offset) => {
return (offset > 0) ? `-${ltr.toLowerCase()}` : ltr.toLowerCase();
}).replace(/[\s_]+/g, '');
}
function toUnderscoreCase(string) {
return string.replace(/(?:^\w|[A-Z]|_|\b\w)/g, (ltr, offset) => {
if (ltr === '_')
@ -39,7 +31,7 @@ function toUnderscoreCase(string) {
* DBus.Interface represents a DBus interface bound to an object instance, meant
* to be exported over DBus.
*/
var Interface = GObject.registerClass({
export const Interface = GObject.registerClass({
GTypeName: 'GSConnectDBusInterface',
Implements: [Gio.DBusInterface],
Properties: {
@ -241,7 +233,7 @@ var Interface = GObject.registerClass({
* @param {Gio.Cancellable} [cancellable] - an optional Gio.Cancellable
* @return {Promise<Gio.DBusConnection>} A new DBus connection
*/
function newConnection(busType = Gio.BusType.SESSION, cancellable = null) {
export function newConnection(busType = Gio.BusType.SESSION, cancellable = null) {
return new Promise((resolve, reject) => {
Gio.DBusConnection.new_for_address(
Gio.dbus_address_get_for_bus_sync(busType, cancellable),

View File

@ -1,427 +0,0 @@
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GIRepository = imports.gi.GIRepository;
const GLib = imports.gi.GLib;
const Config = imports.config;
const {setup, setupGettext} = imports.utils.setup;
// Promise Wrappers
try {
const {EBook, EDataServer} = imports.gi;
Gio._promisify(EBook.BookClient, 'connect');
Gio._promisify(EBook.BookClient.prototype, 'get_view');
Gio._promisify(EBook.BookClient.prototype, 'get_contacts');
Gio._promisify(EDataServer.SourceRegistry, 'new');
} catch (e) {
// Silence import errors
}
Gio._promisify(Gio.AsyncInitable.prototype, 'init_async');
Gio._promisify(Gio.DBusConnection.prototype, 'call');
Gio._promisify(Gio.DBusProxy.prototype, 'call');
Gio._promisify(Gio.DataInputStream.prototype, 'read_line_async',
'read_line_finish_utf8');
Gio._promisify(Gio.File.prototype, 'delete_async');
Gio._promisify(Gio.File.prototype, 'enumerate_children_async');
Gio._promisify(Gio.File.prototype, 'load_contents_async');
Gio._promisify(Gio.File.prototype, 'mount_enclosing_volume');
Gio._promisify(Gio.File.prototype, 'query_info_async');
Gio._promisify(Gio.File.prototype, 'read_async');
Gio._promisify(Gio.File.prototype, 'replace_async');
Gio._promisify(Gio.File.prototype, 'replace_contents_bytes_async',
'replace_contents_finish');
Gio._promisify(Gio.FileEnumerator.prototype, 'next_files_async');
Gio._promisify(Gio.Mount.prototype, 'unmount_with_operation');
Gio._promisify(Gio.InputStream.prototype, 'close_async');
Gio._promisify(Gio.OutputStream.prototype, 'close_async');
Gio._promisify(Gio.OutputStream.prototype, 'splice_async');
Gio._promisify(Gio.OutputStream.prototype, 'write_all_async');
Gio._promisify(Gio.SocketClient.prototype, 'connect_async');
Gio._promisify(Gio.SocketListener.prototype, 'accept_async');
Gio._promisify(Gio.Subprocess.prototype, 'communicate_utf8_async');
Gio._promisify(Gio.Subprocess.prototype, 'wait_check_async');
Gio._promisify(Gio.TlsConnection.prototype, 'handshake_async');
Gio._promisify(Gio.DtlsConnection.prototype, 'handshake_async');
// User Directories
Config.CACHEDIR = GLib.build_filenamev([GLib.get_user_cache_dir(), 'gsconnect']);
Config.CONFIGDIR = GLib.build_filenamev([GLib.get_user_config_dir(), 'gsconnect']);
Config.RUNTIMEDIR = GLib.build_filenamev([GLib.get_user_runtime_dir(), 'gsconnect']);
// Bootstrap
setup(Config.PACKAGE_DATADIR);
setupGettext();
if (Config.IS_USER) {
// Infer libdir by assuming gnome-shell shares a common prefix with gjs;
// assume the parent directory if it's not there
let libdir = GIRepository.Repository.get_search_path().find(path => {
return path.endsWith('/gjs/girepository-1.0');
}).replace('/gjs/girepository-1.0', '');
const gsdir = GLib.build_filenamev([libdir, 'gnome-shell']);
if (!GLib.file_test(gsdir, GLib.FileTest.IS_DIR)) {
const currentDir = `/${GLib.path_get_basename(libdir)}`;
libdir = libdir.replace(currentDir, '');
}
Config.GNOME_SHELL_LIBDIR = libdir;
}
// Load DBus interfaces
Config.DBUS = (() => {
const bytes = Gio.resources_lookup_data(
GLib.build_filenamev([Config.APP_PATH, `${Config.APP_ID}.xml`]),
Gio.ResourceLookupFlags.NONE
);
const xml = new TextDecoder().decode(bytes.toArray());
const dbus = Gio.DBusNodeInfo.new_for_xml(xml);
dbus.nodes.forEach(info => info.cache_build());
return dbus;
})();
// Init User Directories
for (const path of [Config.CACHEDIR, Config.CONFIGDIR, Config.RUNTIMEDIR])
GLib.mkdir_with_parents(path, 0o755);
globalThis.HAVE_GNOME = GLib.getenv('GSCONNECT_MODE')?.toLowerCase() !== 'cli' && (GLib.getenv('GNOME_SETUP_DISPLAY') !== null || GLib.getenv('XDG_CURRENT_DESKTOP')?.toUpperCase()?.includes('GNOME') || GLib.getenv('XDG_SESSION_DESKTOP')?.toLowerCase() === 'gnome');
/**
* A custom debug function that logs at LEVEL_MESSAGE to avoid the need for env
* variables to be set.
*
* @param {Error|string} message - A string or Error to log
* @param {string} [prefix] - An optional prefix for the warning
*/
const _debugCallerMatch = new RegExp(/([^@]*)@([^:]*):([^:]*)/);
// eslint-disable-next-line func-style
const _debugFunc = function (error, prefix = null) {
let caller, message;
if (error.stack) {
caller = error.stack.split('\n')[0];
message = `${error.message}\n${error.stack}`;
} else {
caller = (new Error()).stack.split('\n')[1];
message = JSON.stringify(error, null, 2);
}
if (prefix)
message = `${prefix}: ${message}`;
const [, func, file, line] = _debugCallerMatch.exec(caller);
const script = file.replace(Config.PACKAGE_DATADIR, '');
GLib.log_structured('GSConnect', GLib.LogLevelFlags.LEVEL_MESSAGE, {
'MESSAGE': `[${script}:${func}:${line}]: ${message}`,
'SYSLOG_IDENTIFIER': 'org.gnome.Shell.Extensions.GSConnect',
'CODE_FILE': file,
'CODE_FUNC': func,
'CODE_LINE': line,
});
};
// Swap the function out for a no-op anonymous function for speed
const settings = new Gio.Settings({
settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true),
});
settings.connect('changed::debug', (settings, key) => {
globalThis.debug = settings.get_boolean(key) ? _debugFunc : () => {};
});
if (settings.get_boolean('debug'))
globalThis.debug = _debugFunc;
else
globalThis.debug = () => {};
/**
* Start wl_clipboard if not under Gnome
*/
if (!globalThis.HAVE_GNOME) {
debug('Not running as a Gnome extension');
imports.wl_clipboard.watchService();
}
/**
* A simple (for now) pre-comparison sanitizer for phone numbers
* See: https://github.com/KDE/kdeconnect-kde/blob/master/smsapp/conversationlistmodel.cpp#L200-L210
*
* @return {string} Return the string stripped of leading 0, and ' ()-+'
*/
String.prototype.toPhoneNumber = function () {
const strippedNumber = this.replace(/^0*|[ ()+-]/g, '');
if (strippedNumber.length)
return strippedNumber;
return this;
};
/**
* A simple equality check for phone numbers based on `toPhoneNumber()`
*
* @param {string} number - A phone number string to compare
* @return {boolean} If `this` and @number are equivalent phone numbers
*/
String.prototype.equalsPhoneNumber = function (number) {
const a = this.toPhoneNumber();
const b = number.toPhoneNumber();
return (a.length && b.length && (a.endsWith(b) || b.endsWith(a)));
};
/**
* An implementation of `rm -rf` in Gio
*
* @param {Gio.File|string} file - a GFile or filepath
*/
Gio.File.rm_rf = function (file) {
try {
if (typeof file === 'string')
file = Gio.File.new_for_path(file);
try {
const iter = file.enumerate_children(
'standard::name',
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
null
);
let info;
while ((info = iter.next_file(null)))
Gio.File.rm_rf(iter.get_child(info));
iter.close(null);
} catch (e) {
// Silence errors
}
file.delete(null);
} catch (e) {
// Silence errors
}
};
/**
* Extend GLib.Variant with a static method to recursively pack a variant
*
* @param {*} [obj] - May be a GLib.Variant, Array, standard Object or literal.
* @return {GLib.Variant} The resulting GVariant
*/
function _full_pack(obj) {
let packed;
const type = typeof obj;
switch (true) {
case (obj instanceof GLib.Variant):
return obj;
case (type === 'string'):
return GLib.Variant.new('s', obj);
case (type === 'number'):
return GLib.Variant.new('d', obj);
case (type === 'boolean'):
return GLib.Variant.new('b', obj);
case (obj instanceof Uint8Array):
return GLib.Variant.new('ay', obj);
case (obj === null):
return GLib.Variant.new('mv', null);
case (typeof obj.map === 'function'):
return GLib.Variant.new(
'av',
obj.filter(e => e !== undefined).map(e => _full_pack(e))
);
case (obj instanceof Gio.Icon):
return obj.serialize();
case (type === 'object'):
packed = {};
for (const [key, val] of Object.entries(obj)) {
if (val !== undefined)
packed[key] = _full_pack(val);
}
return GLib.Variant.new('a{sv}', packed);
default:
throw Error(`Unsupported type '${type}': ${obj}`);
}
}
GLib.Variant.full_pack = _full_pack;
/**
* Extend GLib.Variant with a method to recursively deepUnpack() a variant
*
* @param {*} [obj] - May be a GLib.Variant, Array, standard Object or literal.
* @return {*} The resulting object
*/
function _full_unpack(obj) {
obj = (obj === undefined) ? this : obj;
const unpacked = {};
switch (true) {
case (obj === null):
return obj;
case (obj instanceof GLib.Variant):
return _full_unpack(obj.deepUnpack());
case (obj instanceof Uint8Array):
return obj;
case (typeof obj.map === 'function'):
return obj.map(e => _full_unpack(e));
case (typeof obj === 'object'):
for (const [key, value] of Object.entries(obj)) {
// Try to detect and deserialize GIcons
try {
if (key === 'icon' && value.get_type_string() === '(sv)')
unpacked[key] = Gio.Icon.deserialize(value);
else
unpacked[key] = _full_unpack(value);
} catch (e) {
unpacked[key] = _full_unpack(value);
}
}
return unpacked;
default:
return obj;
}
}
GLib.Variant.prototype.full_unpack = _full_unpack;
/**
* Creates a GTlsCertificate from the PEM-encoded data in @cert_path and
* @key_path. If either are missing a new pair will be generated.
*
* Additionally, the private key will be added using ssh-add to allow sftp
* connections using Gio.
*
* See: https://github.com/KDE/kdeconnect-kde/blob/master/core/kdeconnectconfig.cpp#L119
*
* @param {string} certPath - Absolute path to a x509 certificate in PEM format
* @param {string} keyPath - Absolute path to a private key in PEM format
* @param {string} commonName - A unique common name for the certificate
* @return {Gio.TlsCertificate} A TLS certificate
*/
Gio.TlsCertificate.new_for_paths = function (certPath, keyPath, commonName = null) {
// Check if the certificate/key pair already exists
const certExists = GLib.file_test(certPath, GLib.FileTest.EXISTS);
const keyExists = GLib.file_test(keyPath, GLib.FileTest.EXISTS);
// Create a new certificate and private key if necessary
if (!certExists || !keyExists) {
// If we weren't passed a common name, generate a random one
if (!commonName)
commonName = GLib.uuid_string_random();
const proc = new Gio.Subprocess({
argv: [
Config.OPENSSL_PATH, 'req',
'-new', '-x509', '-sha256',
'-out', certPath,
'-newkey', 'rsa:4096', '-nodes',
'-keyout', keyPath,
'-days', '3650',
'-subj', `/O=andyholmes.github.io/OU=GSConnect/CN=${commonName}`,
],
flags: (Gio.SubprocessFlags.STDOUT_SILENCE |
Gio.SubprocessFlags.STDERR_SILENCE),
});
proc.init(null);
proc.wait_check(null);
}
return Gio.TlsCertificate.new_from_files(certPath, keyPath);
};
Object.defineProperties(Gio.TlsCertificate.prototype, {
/**
* The common name of the certificate.
*/
'common_name': {
get: function () {
if (!this.__common_name) {
const proc = new Gio.Subprocess({
argv: [Config.OPENSSL_PATH, 'x509', '-noout', '-subject', '-inform', 'pem'],
flags: Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE,
});
proc.init(null);
const stdout = proc.communicate_utf8(this.certificate_pem, null)[1];
this.__common_name = /(?:cn|CN) ?= ?([^,\n]*)/.exec(stdout)[1];
}
return this.__common_name;
},
configurable: true,
enumerable: true,
},
/**
* Get just the pubkey as a DER ByteArray of a certificate.
*
* @return {GLib.Bytes} The pubkey as DER of the certificate.
*/
'pubkey_der': {
value: function () {
if (!this.__pubkey_der) {
let proc = new Gio.Subprocess({
argv: [Config.OPENSSL_PATH, 'x509', '-noout', '-pubkey', '-inform', 'pem'],
flags: Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE,
});
proc.init(null);
const pubkey = proc.communicate_utf8(this.certificate_pem, null)[1];
proc = new Gio.Subprocess({
argv: [Config.OPENSSL_PATH, 'pkey', '-pubin', '-inform', 'pem', '-outform', 'der'],
flags: Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE,
});
proc.init(null);
this.__pubkey_der = proc.communicate(new TextEncoder().encode(pubkey), null)[1];
}
return this.__pubkey_der;
},
configurable: true,
enumerable: false,
},
});

View File

@ -2,14 +2,12 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
import Gdk from 'gi://Gdk';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import Gtk from 'gi://Gtk';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Config = imports.config;
import Config from '../../config.js';
/*

View File

@ -2,9 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const GLib = imports.gi.GLib;
import GLib from 'gi://GLib';
/**
@ -83,7 +81,7 @@ const _numberRegex = new RegExp(
* @param {string} str - the string to search
* @return {Object[]} the list of match objects, as described above
*/
function findUrls(str) {
export function findUrls(str) {
_urlRegexp.lastIndex = 0;
const res = [];
@ -107,7 +105,7 @@ function findUrls(str) {
* @param {string} [title] - An optional title (eg. alt text, tooltip)
* @return {string} the modified text
*/
function linkify(str, title = null) {
export function linkify(str, title = null) {
const text = GLib.markup_escape_text(str, -1);
_urlRegexp.lastIndex = 0;
@ -126,7 +124,7 @@ function linkify(str, title = null) {
/**
* A simple parsing class for sms: URI's (https://tools.ietf.org/html/rfc5724)
*/
var SmsURI = class URI {
export default class URI {
constructor(uri) {
_smsRegex.lastIndex = 0;
const [, recipients, query] = _smsRegex.exec(uri);
@ -167,5 +165,5 @@ var SmsURI = class URI {
return this.body ? `${uri}?body=${escape(this.body)}` : uri;
}
};
}

View File

@ -4,7 +4,7 @@
import Gio from 'gi://Gio';
import Config from '../config.mjs';
import Config from '../config.js';
export class LockscreenRemoteAccess {

View File

@ -239,19 +239,20 @@ const Source = GObject.registerClass({
if (cachedNotification) {
cachedNotification.requestReplyId = requestReplyId;
// Bail early If @notificationParams represents an exact repeat
const title = notification.title;
const body = notification.body
? notification.body
: null;
// Bail early If @notification represents an exact repeat
if (cachedNotification.title === title &&
cachedNotification.body === body)
return cachedNotification;
// If the details have changed, flag as an update
cachedNotification.title = title;
cachedNotification.body = body;
cachedNotification.acknowledged = false;
return cachedNotification;
}
@ -304,10 +305,8 @@ const Source = GObject.registerClass({
* notification limit (3)
*/
_addNotificationToMessageTray(notification) {
if (this.notifications.includes(notification)) {
notification.acknowledged = false;
if (this.notifications.includes(notification))
return;
}
while (this.notifications.length >= 10) {
const [oldest] = this.notifications;

View File

@ -170,8 +170,7 @@ export default class Tooltip {
this._bin.child.add_child(this.label);
}
Main.layoutManager.uiGroup.add_child(this._bin);
Main.layoutManager.uiGroup.set_child_above_sibling(this._bin, null);
Main.layoutManager.addTopChrome(this._bin);
} else if (this.custom) {
this._bin.child = this.custom;
} else {
@ -234,7 +233,7 @@ export default class Tooltip {
time: 0.10,
transition: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
Main.layoutManager.uiGroup.remove_actor(this._bin);
Main.layoutManager.removeChrome(this._bin);
if (this.custom)
this._bin.remove_child(this.custom);
@ -291,7 +290,7 @@ export default class Tooltip {
this.custom.destroy();
if (this._bin) {
Main.layoutManager.uiGroup.remove_actor(this._bin);
Main.layoutManager.removeChrome(this._bin);
this._bin.destroy();
}
@ -306,4 +305,3 @@ export default class Tooltip {
}
}
}

View File

@ -6,7 +6,7 @@ import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import Gtk from 'gi://Gtk';
import Config from '../config.mjs';
import Config from '../config.js';
let St = null; // St is not available for prefs.js importing this file.
try {

View File

@ -2,16 +2,13 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
const SERVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect';
const SERVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect';
const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device';
const DEVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect/Device';
const _PROPERTIES = {
@ -51,7 +48,7 @@ function _proxyInit(proxy, cancellable = null) {
/**
* A simple proxy wrapper for devices exported over DBus.
*/
var Device = GObject.registerClass({
export const Device = GObject.registerClass({
GTypeName: 'GSConnectRemoteDevice',
Implements: [Gio.DBusInterface],
Properties: {
@ -222,7 +219,7 @@ var Device = GObject.registerClass({
/**
* A simple proxy wrapper for the GSConnect service.
*/
var Service = GObject.registerClass({
export const Service = GObject.registerClass({
GTypeName: 'GSConnectRemoteService',
Implements: [Gio.DBusInterface],
Properties: {

View File

@ -1,12 +0,0 @@
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
import GLib from 'gi://GLib';
const [filename] = GLib.filename_from_uri(import.meta.url);
const dirname = GLib.path_get_dirname(filename);
imports.searchPath.unshift(dirname);
const Remote = imports.remote;
export default Remote;

View File

@ -2,18 +2,18 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
const Gettext = imports.gettext;
import Gettext from 'gettext';
const Config = imports.config;
import Config from '../config.js';
/**
* Initialise and setup Gettext.
*/
function setupGettext() {
export function setupGettext() {
// Init Gettext
String.prototype.format = imports.format.format;
Gettext.bindtextdomain(Config.APP_ID, Config.PACKAGE_LOCALEDIR);
@ -25,7 +25,7 @@ function setupGettext() {
* Initialise and setup Config, GResources and GSchema.
* @param {string} extensionPath - The absolute path to the extension directory
*/
function setup(extensionPath) {
export default function setup(extensionPath) {
// Ensure config.js is setup properly
Config.PACKAGE_DATADIR = extensionPath;
const userDir = GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']);

View File

@ -1,12 +0,0 @@
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
//
// SPDX-License-Identifier: GPL-2.0-or-later
import GLib from 'gi://GLib';
const [filename] = GLib.filename_from_uri(import.meta.url);
const dirname = GLib.path_get_dirname(filename);
imports.searchPath.unshift(dirname);
export const {setup, setupGettext} = imports.setup;
export default setup;

View File

@ -2,12 +2,10 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
'use strict';
const Gio = imports.gi.Gio;
const GjsPrivate = imports.gi.GjsPrivate;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
import Gio from 'gi://Gio';
import GjsPrivate from 'gi://GjsPrivate';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
// laucher for wl-clipboard
const launcher = new Gio.SubprocessLauncher({
@ -55,7 +53,7 @@ const TEXT_MIMETYPES = [
* A simple clipboard portal, especially useful on Wayland where GtkClipboard
* doesn't work in the background.
*/
var Clipboard = GObject.registerClass(
export const Clipboard = GObject.registerClass(
{
GTypeName: 'GSConnectShellClipboard',
},
@ -258,13 +256,13 @@ var Clipboard = GObject.registerClass(
}
);
var _portal = null;
var _portalId = 0;
let _portal = null;
let _portalId = 0;
/**
* Watch for the service to start and export the clipboard portal when it does.
*/
function watchService() {
export function watchService() {
if (_portalId > 0)
return;
@ -288,7 +286,7 @@ function watchService() {
/**
* Stop watching the service and export the portal if currently running.
*/
function unwatchService() {
export function unwatchService() {
if (_portalId > 0) {
Gio.bus_unwatch_name(_portalId);
_portalId = 0;

View File

@ -0,0 +1,52 @@
import St from 'gi://St';
const DEFAULT_SPEED = 0.75;
import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
import * as Settings from './settings.js';
function LOG(m){
console.log("[impatience] " + m);
};
var noop = function() {};
export default class Impatience extends Extension {
constructor(metadata) {
super(metadata);
this.enabled = false;
this.original_speed = St.Settings.get().slow_down_factor;
this.modified_speed = DEFAULT_SPEED;
this.unbind = noop;
};
enable() {
this.enabled = true;
var pref = (new Settings.Prefs(this)).SPEED;
LOG("enabled");
var binding = pref.changed(() => {
this.set_speed(pref.get());
});
this.unbind = () => {
pref.disconnect(binding);
this.unbind = noop;
};
this.set_speed(pref.get());
};
disable() {
this.enabled = false;
this.unbind();
St.Settings.get().slow_down_factor = this.original_speed;
};
set_speed(new_speed) {
if(!this.enabled) {
LOG("NOT setting new speed, since the extension is disabled.");
return;
}
if(new_speed !== undefined) {
this.modified_speed = new_speed;
}
LOG("setting new speed: " + this.modified_speed);
St.Settings.get().slow_down_factor = this.modified_speed;
};
}

View File

@ -0,0 +1,14 @@
{
"_generated": "Generated by SweetTooth, do not edit",
"description": "Speed up the gnome-shell animation speed",
"name": "Impatience",
"settings-schema": "org.gnome.shell.extensions.net.gfxmonk.impatience",
"shell-version": [
"45",
"46",
"47"
],
"url": "http://gfxmonk.net/dist/0install/gnome-shell-impatience.xml",
"uuid": "impatience@gfxmonk.net",
"version": 27
}

View File

@ -0,0 +1,61 @@
import Gtk from 'gi://Gtk';
import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import * as Settings from './settings.js';
export default class ImpatiencePrefs extends ExtensionPreferences {
getPreferencesWidget() {
let config = new Settings.Prefs(this);
let frame = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
'margin-top': 20,
'margin-bottom': 20,
'margin-start': 20,
'margin-end': 20
});
(function() {
let hbox = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 20
});
let label = new Gtk.Label({
label: "Speed scaling\n<small>(1 = normal, 0.5 = twice as fast)</small>",
use_markup: true,
});
let adjustment = new Gtk.Adjustment({
lower: 0,
upper: 2,
step_increment: 0.05
});
let scale = new Gtk.Scale({
orientation: Gtk.Orientation.HORIZONTAL,
digits:2,
adjustment: adjustment,
hexpand: true,
value_pos: Gtk.PositionType.RIGHT
});
hbox.append(label);
hbox.append(scale);
frame.append(hbox);
var pref = config.SPEED;
scale.set_value(pref.get());
[0.25, 0.5, 1.0, 2.0].forEach(
mark => scale.add_mark(mark, Gtk.PositionType.TOP, "<small>" + mark + "</small>")
);
scale.connect('value-changed', function(sw) {
var oldval = pref.get();
var newval = sw.get_value();
if (newval != pref.get()) {
pref.set(newval);
}
});
})();
frame.show();
return frame;
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id="org.gnome.shell.extensions.net.gfxmonk.impatience" path="/org/gnome/shell/extensions/net/gfxmonk/impatience/">
<key type="d" name="speed-factor">
<default>0.75</default>
<summary>speed factor</summary>
<description/>
</key>
</schema>
</schemalist>

View File

@ -0,0 +1,10 @@
export function Prefs(extension) {
var settings = this.settings = extension.getSettings();
this.SPEED = {
key: 'speed-factor',
get: function() { return settings.get_double(this.key); },
set: function(v) { settings.set_double(this.key, v); },
changed: function(cb) { return settings.connect('changed::' + this.key, cb); },
disconnect: function() { return settings.disconnect.apply(settings, arguments); },
};
};