[gnome] Fix version for gjsosk and gsconnect, add impatience
This commit is contained in:
@ -5,9 +5,11 @@
|
|||||||
"name": "GJS OSK",
|
"name": "GJS OSK",
|
||||||
"settings-schema": "org.gnome.shell.extensions.gjsosk",
|
"settings-schema": "org.gnome.shell.extensions.gjsosk",
|
||||||
"shell-version": [
|
"shell-version": [
|
||||||
"45"
|
"45",
|
||||||
|
"46",
|
||||||
|
"47"
|
||||||
],
|
],
|
||||||
"url": "https://github.com/Vishram1123/gjs-osk",
|
"url": "https://github.com/Vishram1123/gjs-osk",
|
||||||
"uuid": "gjsosk@vishram1123.com",
|
"uuid": "gjsosk@vishram1123.com",
|
||||||
"version": 10
|
"version": 10
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,21 +2,23 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
var PACKAGE_VERSION = 56;
|
export default {
|
||||||
var PACKAGE_URL = 'https://github.com/GSConnect/gnome-shell-extension-gsconnect';
|
PACKAGE_VERSION: 58,
|
||||||
var PACKAGE_BUGREPORT = 'https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/new';
|
PACKAGE_URL: 'https://github.com/GSConnect/gnome-shell-extension-gsconnect',
|
||||||
var PACKAGE_DATADIR = '/usr/share/gnome-shell/extensions/gsconnect@andyholmes.github.io';
|
PACKAGE_BUGREPORT: 'https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/new',
|
||||||
var PACKAGE_LOCALEDIR = '/usr/share/locale';
|
PACKAGE_DATADIR: '/usr/local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io',
|
||||||
var GSETTINGS_SCHEMA_DIR = '/usr/share/glib-2.0/schemas';
|
PACKAGE_LOCALEDIR: '/usr/local/share/locale',
|
||||||
var GNOME_SHELL_LIBDIR = '/usr/lib64/';
|
GSETTINGS_SCHEMA_DIR: '/usr/local/share/glib-2.0/schemas',
|
||||||
|
GNOME_SHELL_LIBDIR: '/usr/local/lib64',
|
||||||
|
|
||||||
var APP_ID = 'org.gnome.Shell.Extensions.GSConnect';
|
APP_ID: 'org.gnome.Shell.Extensions.GSConnect',
|
||||||
var APP_PATH = '/org/gnome/Shell/Extensions/GSConnect';
|
APP_PATH: '/org/gnome/Shell/Extensions/GSConnect',
|
||||||
|
|
||||||
var IS_USER = false;
|
IS_USER: false,
|
||||||
|
|
||||||
// External binary paths
|
// External binary paths
|
||||||
var OPENSSL_PATH = 'openssl';
|
OPENSSL_PATH: 'openssl',
|
||||||
var SSHADD_PATH = 'ssh-add';
|
SSHADD_PATH: 'ssh-add',
|
||||||
var SSHKEYGEN_PATH = 'ssh-keygen';
|
SSHKEYGEN_PATH: 'ssh-keygen',
|
||||||
var FFMPEG_PATH = 'ffmpeg';
|
FFMPEG_PATH: 'ffmpeg',
|
||||||
|
};
|
||||||
|
|||||||
@ -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;
|
|
||||||
@ -16,15 +16,15 @@ import {
|
|||||||
ngettext
|
ngettext
|
||||||
} from 'resource:///org/gnome/shell/extensions/extension.js';
|
} 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 Clipboard from './shell/clipboard.js';
|
||||||
import * as Device from './shell/device.js';
|
import * as Device from './shell/device.js';
|
||||||
import * as Keybindings from './shell/keybindings.js';
|
import * as Keybindings from './shell/keybindings.js';
|
||||||
import * as Notification from './shell/notification.js';
|
import * as Notification from './shell/notification.js';
|
||||||
import * as Input from './shell/input.js';
|
import * as Input from './shell/input.js';
|
||||||
import * as Utils from './shell/utils.js';
|
import * as Utils from './shell/utils.js';
|
||||||
import Remote from './utils/remote.mjs';
|
import * as Remote from './utils/remote.js';
|
||||||
import setup from './utils/setup.mjs';
|
import setup from './utils/setup.js';
|
||||||
|
|
||||||
const QuickSettingsMenu = Main.panel.statusArea.quickSettings;
|
const QuickSettingsMenu = Main.panel.statusArea.quickSettings;
|
||||||
|
|
||||||
|
|||||||
61
gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences
Normal file → Executable file
61
gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences
Normal file → Executable file
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env gjs
|
#!/usr/bin/env -S gjs -m
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
|
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
|
||||||
//
|
//
|
||||||
@ -6,43 +6,20 @@
|
|||||||
|
|
||||||
// -*- mode: js; -*-
|
// -*- 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';
|
import system from 'system';
|
||||||
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';
|
|
||||||
|
|
||||||
const Gdk = imports.gi.Gdk;
|
import './preferences/init.js';
|
||||||
const Gio = imports.gi.Gio;
|
import {Window} from './preferences/service.js';
|
||||||
const GLib = imports.gi.GLib;
|
import Config from './config.js';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
|
import('gi://GioUnix?version=2.0').catch(() => {}); // Set version for optional dependency
|
||||||
// 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;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +42,7 @@ const Preferences = GObject.registerClass({
|
|||||||
|
|
||||||
vfunc_activate() {
|
vfunc_activate() {
|
||||||
if (this._window === undefined) {
|
if (this._window === undefined) {
|
||||||
this._window = new Settings.Window({
|
this._window = new Window({
|
||||||
application: this,
|
application: this,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -77,7 +54,7 @@ const Preferences = GObject.registerClass({
|
|||||||
super.vfunc_startup();
|
super.vfunc_startup();
|
||||||
|
|
||||||
// Init some resources
|
// Init some resources
|
||||||
let provider = new Gtk.CssProvider();
|
const provider = new Gtk.CssProvider();
|
||||||
provider.load_from_resource(`${Config.APP_PATH}/application.css`);
|
provider.load_from_resource(`${Config.APP_PATH}/application.css`);
|
||||||
Gtk.StyleContext.add_provider_for_screen(
|
Gtk.StyleContext.add_provider_for_screen(
|
||||||
Gdk.Screen.get_default(),
|
Gdk.Screen.get_default(),
|
||||||
@ -85,13 +62,13 @@ const Preferences = GObject.registerClass({
|
|||||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
);
|
);
|
||||||
|
|
||||||
let actions = [
|
const actions = [
|
||||||
['refresh', null],
|
['refresh', null],
|
||||||
['connect', GLib.VariantType.new('s')],
|
['connect', GLib.VariantType.new('s')],
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let [name, type] of actions) {
|
for (const [name, type] of actions) {
|
||||||
let action = new Gio.SimpleAction({
|
const action = new Gio.SimpleAction({
|
||||||
name: name,
|
name: name,
|
||||||
parameter_type: type,
|
parameter_type: type,
|
||||||
});
|
});
|
||||||
@ -101,7 +78,7 @@ const Preferences = GObject.registerClass({
|
|||||||
|
|
||||||
vfunc_activate_action(action_name, parameter) {
|
vfunc_activate_action(action_name, parameter) {
|
||||||
try {
|
try {
|
||||||
let paramArray = [];
|
const paramArray = [];
|
||||||
|
|
||||||
if (parameter instanceof GLib.Variant)
|
if (parameter instanceof GLib.Variant)
|
||||||
paramArray[0] = parameter;
|
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));
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,8 +1,12 @@
|
|||||||
{
|
{
|
||||||
"uuid": "gsconnect@andyholmes.github.io",
|
"_generated": "Generated by SweetTooth, do not edit",
|
||||||
"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!",
|
||||||
"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",
|
||||||
"version": 56,
|
"shell-version": [
|
||||||
"shell-version": [ "46" ],
|
"46",
|
||||||
"url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki"
|
"47"
|
||||||
}
|
],
|
||||||
|
"url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki",
|
||||||
|
"uuid": "gsconnect@andyholmes.github.io",
|
||||||
|
"version": 58
|
||||||
|
}
|
||||||
Binary file not shown.
@ -2,24 +2,23 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../config.js';
|
||||||
const GLib = imports.gi.GLib;
|
import plugins from '../service/plugins/index.js';
|
||||||
const GObject = imports.gi.GObject;
|
import * as Keybindings from './keybindings.js';
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
|
||||||
const Keybindings = imports.preferences.keybindings;
|
|
||||||
|
|
||||||
|
|
||||||
// Build a list of plugins and shortcuts for devices
|
// Build a list of plugins and shortcuts for devices
|
||||||
const DEVICE_PLUGINS = [];
|
const DEVICE_PLUGINS = [];
|
||||||
const DEVICE_SHORTCUTS = {};
|
const DEVICE_SHORTCUTS = {};
|
||||||
|
|
||||||
for (const name in imports.service.plugins) {
|
for (const name in plugins) {
|
||||||
const module = imports.service.plugins[name];
|
const module = plugins[name];
|
||||||
|
|
||||||
if (module.Metadata === undefined)
|
if (module.Metadata === undefined)
|
||||||
continue;
|
continue;
|
||||||
@ -41,7 +40,7 @@ for (const name in imports.service.plugins) {
|
|||||||
* @param {Gtk.ListBoxRow} row - The current row
|
* @param {Gtk.ListBoxRow} row - The current row
|
||||||
* @param {Gtk.ListBoxRow} before - The previous row
|
* @param {Gtk.ListBoxRow} before - The previous row
|
||||||
*/
|
*/
|
||||||
function rowSeparators(row, before) {
|
export function rowSeparators(row, before) {
|
||||||
const header = row.get_header();
|
const header = row.get_header();
|
||||||
|
|
||||||
if (before === null) {
|
if (before === null) {
|
||||||
@ -63,7 +62,7 @@ function rowSeparators(row, before) {
|
|||||||
* @param {Gtk.ListBoxRow} row2 - The second row
|
* @param {Gtk.ListBoxRow} row2 - The second row
|
||||||
* @return {number} -1, 0 or 1
|
* @return {number} -1, 0 or 1
|
||||||
*/
|
*/
|
||||||
function titleSortFunc(row1, row2) {
|
export function titleSortFunc(row1, row2) {
|
||||||
if (!row1.title || !row2.title)
|
if (!row1.title || !row2.title)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -249,7 +248,7 @@ const CommandEditor = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A widget for configuring a remote device.
|
* A widget for configuring a remote device.
|
||||||
*/
|
*/
|
||||||
var Panel = GObject.registerClass({
|
export const Panel = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectPreferencesDevicePanel',
|
GTypeName: 'GSConnectPreferencesDevicePanel',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -424,7 +423,7 @@ var Panel = GObject.registerClass({
|
|||||||
this._pluginSettings = {};
|
this._pluginSettings = {};
|
||||||
|
|
||||||
if (!this._pluginSettings.hasOwnProperty(name)) {
|
if (!this._pluginSettings.hasOwnProperty(name)) {
|
||||||
const meta = imports.service.plugins[name].Metadata;
|
const meta = plugins[name].Metadata;
|
||||||
|
|
||||||
this._pluginSettings[name] = new Gio.Settings({
|
this._pluginSettings[name] = new Gio.Settings({
|
||||||
settings_schema: Config.GSCHEMA.lookup(meta.id, -1),
|
settings_schema: Config.GSCHEMA.lookup(meta.id, -1),
|
||||||
@ -1058,7 +1057,7 @@ var Panel = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_addPlugin(name) {
|
_addPlugin(name) {
|
||||||
const plugin = imports.service.plugins[name];
|
const plugin = plugins[name];
|
||||||
|
|
||||||
const row = new SectionRow({
|
const row = new SectionRow({
|
||||||
height_request: 48,
|
height_request: 48,
|
||||||
|
|||||||
@ -2,13 +2,11 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gdk from 'gi://Gdk';
|
||||||
|
import Gio from 'gi://Gio';
|
||||||
const Gdk = imports.gi.Gdk;
|
import GLib from 'gi://GLib';
|
||||||
const Gio = imports.gi.Gio;
|
import GObject from 'gi://GObject';
|
||||||
const GLib = imports.gi.GLib;
|
import Gtk from 'gi://Gtk';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -32,7 +30,7 @@ const _MODIFIERS = [
|
|||||||
/**
|
/**
|
||||||
* Response enum for ShortcutChooserDialog
|
* Response enum for ShortcutChooserDialog
|
||||||
*/
|
*/
|
||||||
var ResponseType = {
|
export const ResponseType = {
|
||||||
CANCEL: Gtk.ResponseType.CANCEL,
|
CANCEL: Gtk.ResponseType.CANCEL,
|
||||||
SET: Gtk.ResponseType.APPLY,
|
SET: Gtk.ResponseType.APPLY,
|
||||||
UNSET: 2,
|
UNSET: 2,
|
||||||
@ -42,7 +40,7 @@ var ResponseType = {
|
|||||||
/**
|
/**
|
||||||
* A simplified version of the shortcut editor from GNOME Control Center
|
* A simplified version of the shortcut editor from GNOME Control Center
|
||||||
*/
|
*/
|
||||||
var ShortcutChooserDialog = GObject.registerClass({
|
export const ShortcutChooserDialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectPreferencesShortcutEditor',
|
GTypeName: 'GSConnectPreferencesShortcutEditor',
|
||||||
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-shortcut-editor.ui',
|
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-shortcut-editor.ui',
|
||||||
Children: [
|
Children: [
|
||||||
@ -209,7 +207,7 @@ var ShortcutChooserDialog = GObject.registerClass({
|
|||||||
* @param {number} [grabFlags] - Grab Flags
|
* @param {number} [grabFlags] - Grab Flags
|
||||||
* @param {boolean} %true if available, %false on error or unavailable
|
* @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 {
|
try {
|
||||||
let result = false;
|
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
|
* @param {string} accelerator - An accelerator as taken by Gtk.ShortcutLabel
|
||||||
* @return {string} An accelerator or %null if it should be unset.
|
* @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 {
|
try {
|
||||||
const dialog = new ShortcutChooserDialog({
|
const dialog = new ShortcutChooserDialog({
|
||||||
summary: summary,
|
summary: summary,
|
||||||
|
|||||||
@ -2,18 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import system from 'system';
|
||||||
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 Config = imports.config;
|
import Config from '../config.js';
|
||||||
const Device = imports.preferences.device;
|
import {Panel, rowSeparators} from './device.js';
|
||||||
const Remote = imports.utils.remote;
|
import {Service} from '../utils/remote.js';
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -21,7 +21,7 @@ const Remote = imports.utils.remote;
|
|||||||
*/
|
*/
|
||||||
const LOG_HEADER = new GLib.Bytes(`
|
const LOG_HEADER = new GLib.Bytes(`
|
||||||
GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'})
|
GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'})
|
||||||
GJS: ${imports.system.version}
|
GJS: ${system.version}
|
||||||
Session: ${GLib.getenv('XDG_SESSION_TYPE')}
|
Session: ${GLib.getenv('XDG_SESSION_TYPE')}
|
||||||
OS: ${GLib.get_os_info('PRETTY_NAME')}
|
OS: ${GLib.get_os_info('PRETTY_NAME')}
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -91,7 +91,7 @@ async function generateSupportLog(time) {
|
|||||||
/**
|
/**
|
||||||
* "Connect to..." Dialog
|
* "Connect to..." Dialog
|
||||||
*/
|
*/
|
||||||
var ConnectDialog = GObject.registerClass({
|
const ConnectDialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectConnectDialog',
|
GTypeName: 'GSConnectConnectDialog',
|
||||||
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/connect-dialog.ui',
|
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/connect-dialog.ui',
|
||||||
Children: [
|
Children: [
|
||||||
@ -132,7 +132,7 @@ var ConnectDialog = GObject.registerClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var Window = GObject.registerClass({
|
export const Window = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectPreferencesWindow',
|
GTypeName: 'GSConnectPreferencesWindow',
|
||||||
Properties: {
|
Properties: {
|
||||||
'display-mode': GObject.ParamSpec.string(
|
'display-mode': GObject.ParamSpec.string(
|
||||||
@ -173,7 +173,7 @@ var Window = GObject.registerClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Service Proxy
|
// Service Proxy
|
||||||
this.service = new Remote.Service();
|
this.service = new Service();
|
||||||
|
|
||||||
this._deviceAddedId = this.service.connect(
|
this._deviceAddedId = this.service.connect(
|
||||||
'device-added',
|
'device-added',
|
||||||
@ -198,7 +198,7 @@ var Window = GObject.registerClass({
|
|||||||
this.service_box.set_focus_vadjustment(this.service_window.vadjustment);
|
this.service_box.set_focus_vadjustment(this.service_window.vadjustment);
|
||||||
|
|
||||||
// Device List
|
// Device List
|
||||||
this.device_list.set_header_func(Device.rowSeparators);
|
this.device_list.set_header_func(rowSeparators);
|
||||||
|
|
||||||
// Discoverable InfoBar
|
// Discoverable InfoBar
|
||||||
this.settings.bind(
|
this.settings.bind(
|
||||||
@ -580,7 +580,7 @@ var Window = GObject.registerClass({
|
|||||||
try {
|
try {
|
||||||
if (!this.stack.get_child_by_name(device.id)) {
|
if (!this.stack.get_child_by_name(device.id)) {
|
||||||
// Add the device preferences
|
// Add the device preferences
|
||||||
const prefs = new Device.Panel(device);
|
const prefs = new Panel(device);
|
||||||
this.stack.add_titled(prefs, device.id, device.name);
|
this.stack.add_titled(prefs, device.id, device.name);
|
||||||
|
|
||||||
// Add a row to the device list
|
// Add a row to the device list
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import Adw from 'gi://Adw';
|
|||||||
|
|
||||||
// Bootstrap
|
// Bootstrap
|
||||||
import * as Utils from './shell/utils.js';
|
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';
|
import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||||
|
|
||||||
export default class GSConnectExtensionPreferences extends ExtensionPreferences {
|
export default class GSConnectExtensionPreferences extends ExtensionPreferences {
|
||||||
|
|||||||
@ -2,15 +2,23 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../../config.js';
|
||||||
const GLib = imports.gi.GLib;
|
import * as Core from '../core.js';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
|
||||||
const Core = imports.service.core;
|
|
||||||
|
|
||||||
|
// 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
|
* TCP Port Constants
|
||||||
@ -25,7 +33,7 @@ const TRANSFER_MAX = 1764;
|
|||||||
/*
|
/*
|
||||||
* One-time check for Linux/FreeBSD socket options
|
* One-time check for Linux/FreeBSD socket options
|
||||||
*/
|
*/
|
||||||
var _LINUX_SOCKETS = true;
|
export let _LINUX_SOCKETS = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// This should throw on FreeBSD
|
// This should throw on FreeBSD
|
||||||
@ -44,7 +52,7 @@ try {
|
|||||||
*
|
*
|
||||||
* @param {Gio.SocketConnection} connection - The connection to configure
|
* @param {Gio.SocketConnection} connection - The connection to configure
|
||||||
*/
|
*/
|
||||||
function _configureSocket(connection) {
|
export function _configureSocket(connection) {
|
||||||
try {
|
try {
|
||||||
if (_LINUX_SOCKETS) {
|
if (_LINUX_SOCKETS) {
|
||||||
connection.socket.set_option(6, 4, 10); // TCP_KEEPIDLE
|
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
|
* 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.
|
* itself. We respond by opening a TCP connection to that address.
|
||||||
*/
|
*/
|
||||||
var ChannelService = GObject.registerClass({
|
export const ChannelService = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectLanChannelService',
|
GTypeName: 'GSConnectLanChannelService',
|
||||||
Properties: {
|
Properties: {
|
||||||
'certificate': GObject.ParamSpec.object(
|
'certificate': GObject.ParamSpec.object(
|
||||||
@ -264,7 +272,7 @@ var ChannelService = GObject.registerClass({
|
|||||||
|
|
||||||
// Input stream
|
// Input stream
|
||||||
this._udp6_stream = new Gio.DataInputStream({
|
this._udp6_stream = new Gio.DataInputStream({
|
||||||
base_stream: new Gio.UnixInputStream({
|
base_stream: new GioUnix.InputStream({
|
||||||
fd: this._udp6.fd,
|
fd: this._udp6.fd,
|
||||||
close_fd: false,
|
close_fd: false,
|
||||||
}),
|
}),
|
||||||
@ -296,7 +304,7 @@ var ChannelService = GObject.registerClass({
|
|||||||
|
|
||||||
// Input stream
|
// Input stream
|
||||||
this._udp4_stream = new Gio.DataInputStream({
|
this._udp4_stream = new Gio.DataInputStream({
|
||||||
base_stream: new Gio.UnixInputStream({
|
base_stream: new GioUnix.InputStream({
|
||||||
fd: this._udp4.fd,
|
fd: this._udp4.fd,
|
||||||
close_fd: false,
|
close_fd: false,
|
||||||
}),
|
}),
|
||||||
@ -527,7 +535,7 @@ var ChannelService = GObject.registerClass({
|
|||||||
* This class essentially just extends Core.Channel to set TCP socket options
|
* This class essentially just extends Core.Channel to set TCP socket options
|
||||||
* and negotiate TLS encrypted connections.
|
* and negotiate TLS encrypted connections.
|
||||||
*/
|
*/
|
||||||
var Channel = GObject.registerClass({
|
export const Channel = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectLanChannel',
|
GTypeName: 'GSConnectLanChannel',
|
||||||
}, class LanChannel extends Core.Channel {
|
}, class LanChannel extends Core.Channel {
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -2,12 +2,8 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Atspi from 'gi://Atspi?version=2.0';
|
||||||
|
import Gdk from 'gi://Gdk';
|
||||||
imports.gi.versions.Atspi = '2.0';
|
|
||||||
|
|
||||||
const Atspi = imports.gi.Atspi;
|
|
||||||
const Gdk = imports.gi.Gdk;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,7 +26,7 @@ const XKeycode = {
|
|||||||
/**
|
/**
|
||||||
* A thin wrapper around Atspi for X11 sessions without Pipewire support.
|
* A thin wrapper around Atspi for X11 sessions without Pipewire support.
|
||||||
*/
|
*/
|
||||||
var Controller = class {
|
export default class Controller {
|
||||||
constructor() {
|
constructor() {
|
||||||
// Atspi.init() return 2 on fail, but still marks itself as inited. We
|
// Atspi.init() return 2 on fail, but still marks itself as inited. We
|
||||||
// uninit before throwing an error otherwise any future call to init()
|
// uninit before throwing an error otherwise any future call to init()
|
||||||
@ -312,5 +308,5 @@ var Controller = class {
|
|||||||
// Silence errors
|
// Silence errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,20 +2,21 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gdk from 'gi://Gdk';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
const Gdk = imports.gi.Gdk;
|
import Gtk from 'gi://Gtk';
|
||||||
const GLib = imports.gi.GLib;
|
import Gio from 'gi://Gio';
|
||||||
const Gtk = imports.gi.Gtk;
|
import GObject from 'gi://GObject';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
|
|
||||||
const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard';
|
const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard';
|
||||||
const DBUS_PATH = '/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',
|
GTypeName: 'GSConnectClipboard',
|
||||||
Properties: {
|
Properties: {
|
||||||
'text': GObject.ParamSpec.string(
|
'text': GObject.ParamSpec.string(
|
||||||
@ -98,7 +99,7 @@ var Clipboard = GObject.registerClass({
|
|||||||
if (!globalThis.HAVE_GNOME) {
|
if (!globalThis.HAVE_GNOME) {
|
||||||
// Directly subscrible signal
|
// Directly subscrible signal
|
||||||
this.signalHandler = Gio.DBus.session.signal_subscribe(
|
this.signalHandler = Gio.DBus.session.signal_subscribe(
|
||||||
DBUS_NAME,
|
null,
|
||||||
DBUS_NAME,
|
DBUS_NAME,
|
||||||
'OwnerChange',
|
'OwnerChange',
|
||||||
DBUS_PATH,
|
DBUS_PATH,
|
||||||
@ -219,10 +220,6 @@ var Clipboard = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default Clipboard;
|
||||||
/**
|
|
||||||
* The service class for this component
|
|
||||||
*/
|
|
||||||
var Component = Clipboard;
|
|
||||||
|
|
||||||
// vim:tabstop=2:shiftwidth=2:expandtab
|
// vim:tabstop=2:shiftwidth=2:expandtab
|
||||||
|
|||||||
@ -2,23 +2,21 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../../config.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
let HAVE_EDS = true;
|
||||||
|
let EBook = null;
|
||||||
var HAVE_EDS = true;
|
let EBookContacts = null;
|
||||||
var EBook = null;
|
let EDataServer = null;
|
||||||
var EBookContacts = null;
|
|
||||||
var EDataServer = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
EBook = imports.gi.EBook;
|
EBook = (await import('gi://EBook')).default;
|
||||||
EBookContacts = imports.gi.EBookContacts;
|
EBookContacts = (await import('gi://EBookContacts')).default;
|
||||||
EDataServer = imports.gi.EDataServer;
|
EDataServer = (await import('gi://EDataServer')).default;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
HAVE_EDS = false;
|
HAVE_EDS = false;
|
||||||
}
|
}
|
||||||
@ -27,7 +25,7 @@ try {
|
|||||||
/**
|
/**
|
||||||
* A store for contacts
|
* A store for contacts
|
||||||
*/
|
*/
|
||||||
var Store = GObject.registerClass({
|
const Store = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectContactsStore',
|
GTypeName: 'GSConnectContactsStore',
|
||||||
Properties: {
|
Properties: {
|
||||||
'context': GObject.ParamSpec.string(
|
'context': GObject.ParamSpec.string(
|
||||||
@ -611,9 +609,5 @@ var Store = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default Store;
|
||||||
/**
|
|
||||||
* The service class for this component
|
|
||||||
*/
|
|
||||||
var Component = Store;
|
|
||||||
|
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import AtspiController from './atspi.js';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
|
|
||||||
const SESSION_TIMEOUT = 15;
|
const SESSION_TIMEOUT = 300;
|
||||||
|
|
||||||
|
|
||||||
const RemoteSession = GObject.registerClass({
|
const RemoteSession = GObject.registerClass({
|
||||||
@ -229,7 +229,7 @@ const RemoteSession = GObject.registerClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
class Controller {
|
export default class Controller {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._nameAppearedId = 0;
|
this._nameAppearedId = 0;
|
||||||
this._session = null;
|
this._session = null;
|
||||||
@ -339,8 +339,7 @@ class Controller {
|
|||||||
if (this.connection === null) {
|
if (this.connection === null) {
|
||||||
debug('Falling back to Atspi');
|
debug('Falling back to Atspi');
|
||||||
|
|
||||||
const fallback = imports.service.components.atspi;
|
this._session = new AtspiController();
|
||||||
this._session = new fallback.Controller();
|
|
||||||
|
|
||||||
// Mutter is available and there isn't another session starting
|
// Mutter is available and there isn't another session starting
|
||||||
} else if (this._sessionStarting === false) {
|
} else if (this._sessionStarting === false) {
|
||||||
@ -513,9 +512,3 @@ class Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The service class for this component
|
|
||||||
*/
|
|
||||||
var Component = Controller;
|
|
||||||
|
|||||||
@ -2,14 +2,12 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
const Gio = imports.gi.Gio;
|
import GObject from 'gi://GObject';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
|
|
||||||
var Player = GObject.registerClass({
|
export const Player = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMediaPlayerInterface',
|
GTypeName: 'GSConnectMediaPlayerInterface',
|
||||||
Properties: {
|
Properties: {
|
||||||
// Application Properties
|
// Application Properties
|
||||||
@ -790,7 +788,7 @@ const PlayerProxy = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A manager for media players
|
* A manager for media players
|
||||||
*/
|
*/
|
||||||
var Manager = GObject.registerClass({
|
const Manager = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMPRISManager',
|
GTypeName: 'GSConnectMPRISManager',
|
||||||
Signals: {
|
Signals: {
|
||||||
'player-added': {
|
'player-added': {
|
||||||
@ -1001,5 +999,5 @@ var Manager = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* The service class for this component
|
* The service class for this component
|
||||||
*/
|
*/
|
||||||
var Component = Manager;
|
export default Manager;
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,12 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as DBus from '../utils/dbus.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GjsPrivate = imports.gi.GjsPrivate;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const DBus = imports.service.utils.dbus;
|
|
||||||
|
|
||||||
|
|
||||||
const _nodeInfo = Gio.DBusNodeInfo.new_for_xml(`
|
const _nodeInfo = Gio.DBusNodeInfo.new_for_xml(`
|
||||||
@ -408,4 +406,4 @@ const Listener = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* The service class for this component
|
* The service class for this component
|
||||||
*/
|
*/
|
||||||
var Component = Listener;
|
export default Listener;
|
||||||
|
|||||||
@ -2,40 +2,43 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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 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);
|
||||||
|
|
||||||
|
Gvc = (await import('gi://Gvc')).default;
|
||||||
// Add gnome-shell's typelib dir to the search path
|
} catch (e) {}
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend Gvc.MixerStream with a property for returning a user-visible name
|
* Extend Gvc.MixerStream with a property for returning a user-visible name
|
||||||
*/
|
*/
|
||||||
Object.defineProperty(Gvc.MixerStream.prototype, 'display_name', {
|
if (Gvc) {
|
||||||
get: function () {
|
Object.defineProperty(Gvc.MixerStream.prototype, 'display_name', {
|
||||||
try {
|
get: function () {
|
||||||
if (!this.get_ports().length)
|
try {
|
||||||
return this.description;
|
if (!this.get_ports().length)
|
||||||
|
return this.description;
|
||||||
|
|
||||||
return `${this.get_port().human_port} (${this.description})`;
|
return `${this.get_port().human_port} (${this.description})`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,7 +113,7 @@ class Stream {
|
|||||||
* The Mixer class uses GNOME Shell's Gvc library to control the system volume
|
* The Mixer class uses GNOME Shell's Gvc library to control the system volume
|
||||||
* and offers a few convenience functions.
|
* and offers a few convenience functions.
|
||||||
*/
|
*/
|
||||||
const Mixer = GObject.registerClass({
|
const Mixer = !Gvc ? null : GObject.registerClass({
|
||||||
GTypeName: 'GSConnectAudioMixer',
|
GTypeName: 'GSConnectAudioMixer',
|
||||||
}, class Mixer extends Gvc.MixerControl {
|
}, class Mixer extends Gvc.MixerControl {
|
||||||
_init(params) {
|
_init(params) {
|
||||||
@ -265,4 +268,4 @@ const Mixer = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* The service class for this component
|
* The service class for this component
|
||||||
*/
|
*/
|
||||||
var Component = Mixer;
|
export default Mixer;
|
||||||
|
|||||||
@ -2,10 +2,8 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
|
|
||||||
|
|
||||||
const Session = class {
|
const Session = class {
|
||||||
@ -82,5 +80,5 @@ const Session = class {
|
|||||||
/**
|
/**
|
||||||
* The service class for this component
|
* The service class for this component
|
||||||
*/
|
*/
|
||||||
var Component = Session;
|
export default Session;
|
||||||
|
|
||||||
|
|||||||
@ -2,23 +2,17 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
let GSound = null;
|
||||||
const Gio = imports.gi.Gio;
|
try {
|
||||||
const GLib = imports.gi.GLib;
|
GSound = (await import('gi://GSound')).default;
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
|
||||||
/*
|
const Player = class Player {
|
||||||
* 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 {
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._playing = new Set();
|
this._playing = new Set();
|
||||||
@ -27,22 +21,20 @@ var Player = class Player {
|
|||||||
get backend() {
|
get backend() {
|
||||||
if (this._backend === undefined) {
|
if (this._backend === undefined) {
|
||||||
// Prefer GSound
|
// Prefer GSound
|
||||||
try {
|
if (GSound !== null) {
|
||||||
this._gsound = new imports.gi.GSound.Context();
|
this._gsound = new GSound.Context();
|
||||||
this._gsound.init(null);
|
this._gsound.init(null);
|
||||||
this._backend = 'gsound';
|
this._backend = 'gsound';
|
||||||
|
|
||||||
// Try falling back to libcanberra, otherwise just re-run the test
|
// Try falling back to libcanberra, otherwise just re-run the test
|
||||||
// in case one or the other is installed later
|
// in case one or the other is installed later
|
||||||
} catch (e) {
|
} else if (GLib.find_program_in_path('canberra-gtk-play') !== null) {
|
||||||
if (GLib.find_program_in_path('canberra-gtk-play') !== null) {
|
this._canberra = new Gio.SubprocessLauncher({
|
||||||
this._canberra = new Gio.SubprocessLauncher({
|
flags: Gio.SubprocessFlags.NONE,
|
||||||
flags: Gio.SubprocessFlags.NONE,
|
});
|
||||||
});
|
this._backend = 'libcanberra';
|
||||||
this._backend = 'libcanberra';
|
} else {
|
||||||
} else {
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,5 +168,5 @@ var Player = class Player {
|
|||||||
/**
|
/**
|
||||||
* The service class for this component
|
* The service class for this component
|
||||||
*/
|
*/
|
||||||
var Component = Player;
|
export default Player;
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,9 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
const Gio = imports.gi.Gio;
|
import GObject from 'gi://GObject';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +47,7 @@ const DeviceState = {
|
|||||||
/**
|
/**
|
||||||
* A class representing the system battery.
|
* A class representing the system battery.
|
||||||
*/
|
*/
|
||||||
var Battery = GObject.registerClass({
|
const Battery = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectSystemBattery',
|
GTypeName: 'GSConnectSystemBattery',
|
||||||
Signals: {
|
Signals: {
|
||||||
'changed': {
|
'changed': {
|
||||||
@ -213,5 +211,5 @@ var Battery = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* The service class for this component
|
* The service class for this component
|
||||||
*/
|
*/
|
||||||
var Component = Battery;
|
export default Battery;
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,8 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import Gdk from 'gi://Gdk';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Gdk = imports.gi.Gdk;
|
|
||||||
|
|
||||||
const keyCodes = new Map([
|
const keyCodes = new Map([
|
||||||
['1', 2],
|
['1', 2],
|
||||||
@ -55,7 +53,7 @@ const keyCodes = new Map([
|
|||||||
['/', 53],
|
['/', 53],
|
||||||
['\\', 43],
|
['\\', 43],
|
||||||
]);
|
]);
|
||||||
class Controller {
|
export default class Controller {
|
||||||
constructor() {
|
constructor() {
|
||||||
// laucher for wl-clipboard
|
// laucher for wl-clipboard
|
||||||
this._launcher = new Gio.SubprocessLauncher({
|
this._launcher = new Gio.SubprocessLauncher({
|
||||||
@ -137,7 +135,7 @@ class Controller {
|
|||||||
modifiers_codes.push(input);
|
modifiers_codes.push(input);
|
||||||
} else if (typeof input === 'string') {
|
} else if (typeof input === 'string') {
|
||||||
input = input.toUpperCase();
|
input = input.toUpperCase();
|
||||||
for (var i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
if (keyCodes.get(input[i])) {
|
if (keyCodes.get(input[i])) {
|
||||||
modifiers_codes.push(keyCodes.get(input[i]));
|
modifiers_codes.push(keyCodes.get(input[i]));
|
||||||
} else {
|
} else {
|
||||||
@ -160,8 +158,3 @@ class Controller {
|
|||||||
this._args = [];
|
this._args = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The service class for this component
|
|
||||||
*/
|
|
||||||
var Component = Controller;
|
|
||||||
|
|||||||
@ -2,11 +2,11 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import plugins from './plugins/index.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,13 +14,16 @@ const GObject = imports.gi.GObject;
|
|||||||
*
|
*
|
||||||
* @return {string} A device type string
|
* @return {string} A device type string
|
||||||
*/
|
*/
|
||||||
function _getDeviceType() {
|
export function _getDeviceType() {
|
||||||
try {
|
try {
|
||||||
let type = GLib.file_get_contents('/sys/class/dmi/id/chassis_type')[1];
|
let type = GLib.file_get_contents('/sys/class/dmi/id/chassis_type')[1];
|
||||||
|
|
||||||
type = Number(new TextDecoder().decode(type));
|
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 'laptop';
|
||||||
|
|
||||||
return 'desktop';
|
return 'desktop';
|
||||||
@ -34,7 +37,7 @@ function _getDeviceType() {
|
|||||||
* The packet class is a simple Object-derived class, offering some conveniences
|
* The packet class is a simple Object-derived class, offering some conveniences
|
||||||
* for working with KDE Connect packets.
|
* for working with KDE Connect packets.
|
||||||
*/
|
*/
|
||||||
var Packet = class Packet {
|
export class Packet {
|
||||||
|
|
||||||
constructor(data = null) {
|
constructor(data = null) {
|
||||||
this.id = 0;
|
this.id = 0;
|
||||||
@ -114,7 +117,7 @@ var Packet = class Packet {
|
|||||||
|
|
||||||
return (Object.keys(this.payloadTransferInfo).length > 0);
|
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
|
* devices. The implementation is responsible for all negotiation of the
|
||||||
* underlying protocol.
|
* underlying protocol.
|
||||||
*/
|
*/
|
||||||
var Channel = GObject.registerClass({
|
export const Channel = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectChannel',
|
GTypeName: 'GSConnectChannel',
|
||||||
Properties: {
|
Properties: {
|
||||||
'closed': GObject.ParamSpec.boolean(
|
'closed': GObject.ParamSpec.boolean(
|
||||||
@ -297,7 +300,7 @@ var Channel = GObject.registerClass({
|
|||||||
* ChannelService implementations provide Channel objects, emitting the
|
* ChannelService implementations provide Channel objects, emitting the
|
||||||
* ChannelService::channel signal when a new connection has been accepted.
|
* ChannelService::channel signal when a new connection has been accepted.
|
||||||
*/
|
*/
|
||||||
var ChannelService = GObject.registerClass({
|
export const ChannelService = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectChannelService',
|
GTypeName: 'GSConnectChannelService',
|
||||||
Properties: {
|
Properties: {
|
||||||
'active': GObject.ParamSpec.boolean(
|
'active': GObject.ParamSpec.boolean(
|
||||||
@ -409,8 +412,8 @@ var ChannelService = GObject.registerClass({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const name in imports.service.plugins) {
|
for (const name in plugins) {
|
||||||
const meta = imports.service.plugins[name].Metadata;
|
const meta = plugins[name].Metadata;
|
||||||
|
|
||||||
if (meta === undefined)
|
if (meta === undefined)
|
||||||
continue;
|
continue;
|
||||||
@ -460,7 +463,7 @@ var ChannelService = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A class representing a file transfer.
|
* A class representing a file transfer.
|
||||||
*/
|
*/
|
||||||
var Transfer = GObject.registerClass({
|
export const Transfer = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectTransfer',
|
GTypeName: 'GSConnectTransfer',
|
||||||
Properties: {
|
Properties: {
|
||||||
'channel': GObject.ParamSpec.object(
|
'channel': GObject.ParamSpec.object(
|
||||||
@ -691,4 +694,3 @@ var Transfer = GObject.registerClass({
|
|||||||
this._cancellable.cancel();
|
this._cancellable.cancel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
55
gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/daemon.js
Normal file → Executable file
55
gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/daemon.js
Normal file → Executable file
@ -1,46 +1,27 @@
|
|||||||
#!/usr/bin/env gjs
|
#!/usr/bin/env -S gjs -m
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
|
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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';
|
import system from 'system';
|
||||||
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';
|
|
||||||
|
|
||||||
const Gdk = imports.gi.Gdk;
|
import './init.js';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
// Bootstrap
|
import Config from '../config.js';
|
||||||
function get_datadir() {
|
import Manager from './manager.js';
|
||||||
let [, path] = /@([^:]+):\d+/.exec(new Error().stack.split('\n')[1]);
|
import * as ServiceUI from './ui/service.js';
|
||||||
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_parent().get_path();
|
import('gi://GioUnix?version=2.0').catch(() => {}); // Set version for optional dependency
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -267,7 +248,7 @@ const Service = GObject.registerClass({
|
|||||||
if (!super.vfunc_dbus_register(connection, object_path))
|
if (!super.vfunc_dbus_register(connection, object_path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.manager = new Manager.Manager({
|
this.manager = new Manager({
|
||||||
connection: connection,
|
connection: connection,
|
||||||
object_path: object_path,
|
object_path: object_path,
|
||||||
});
|
});
|
||||||
@ -337,7 +318,7 @@ const Service = GObject.registerClass({
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Force a GC to prevent any more calls back into JS, then chain-up
|
// Force a GC to prevent any more calls back into JS, then chain-up
|
||||||
imports.system.gc();
|
system.gc();
|
||||||
super.vfunc_shutdown();
|
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));
|
||||||
|
|
||||||
|
|||||||
@ -2,16 +2,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
const Gio = imports.gi.Gio;
|
import GObject from 'gi://GObject';
|
||||||
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 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.
|
* An object representing a remote device.
|
||||||
@ -20,7 +18,7 @@ const Core = imports.service.core;
|
|||||||
* GActionGroup and GActionMap interfaces, like Gio.Application.
|
* GActionGroup and GActionMap interfaces, like Gio.Application.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
var Device = GObject.registerClass({
|
const Device = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectDevice',
|
GTypeName: 'GSConnectDevice',
|
||||||
Properties: {
|
Properties: {
|
||||||
'connected': GObject.ParamSpec.boolean(
|
'connected': GObject.ParamSpec.boolean(
|
||||||
@ -297,8 +295,8 @@ var Device = GObject.registerClass({
|
|||||||
// Determine supported plugins by matching incoming to outgoing types
|
// Determine supported plugins by matching incoming to outgoing types
|
||||||
const supported = [];
|
const supported = [];
|
||||||
|
|
||||||
for (const name in imports.service.plugins) {
|
for (const name in plugins) {
|
||||||
const meta = imports.service.plugins[name].Metadata;
|
const meta = plugins[name].Metadata;
|
||||||
|
|
||||||
if (meta === undefined)
|
if (meta === undefined)
|
||||||
continue;
|
continue;
|
||||||
@ -1011,8 +1009,8 @@ var Device = GObject.registerClass({
|
|||||||
try {
|
try {
|
||||||
if (this.paired && !this._plugins.has(name)) {
|
if (this.paired && !this._plugins.has(name)) {
|
||||||
// Instantiate the handler
|
// Instantiate the handler
|
||||||
handler = imports.service.plugins[name];
|
handler = plugins[name];
|
||||||
plugin = new handler.Plugin(this);
|
plugin = new handler.default(this);
|
||||||
|
|
||||||
// Register packet handlers
|
// Register packet handlers
|
||||||
for (const packetType of handler.Metadata.incomingCapabilities)
|
for (const packetType of handler.Metadata.incomingCapabilities)
|
||||||
@ -1053,7 +1051,7 @@ var Device = GObject.registerClass({
|
|||||||
try {
|
try {
|
||||||
if (this._plugins.has(name)) {
|
if (this._plugins.has(name)) {
|
||||||
// Unregister packet handlers
|
// Unregister packet handlers
|
||||||
handler = imports.service.plugins[name];
|
handler = plugins[name];
|
||||||
|
|
||||||
for (const type of handler.Metadata.incomingCapabilities)
|
for (const type of handler.Metadata.incomingCapabilities)
|
||||||
this._handlers.delete(type);
|
this._handlers.delete(type);
|
||||||
@ -1104,3 +1102,4 @@ var Device = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default Device;
|
||||||
|
|||||||
@ -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({
|
const settings = new Gio.Settings({
|
||||||
settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true),
|
settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true),
|
||||||
});
|
});
|
||||||
|
if (settings.get_boolean('debug')) {
|
||||||
settings.connect('changed::debug', (settings, key) => {
|
globalThis.debug = globalThis._debugFunc;
|
||||||
globalThis.debug = settings.get_boolean(key) ? _debugFunc : () => {};
|
} else {
|
||||||
});
|
// Swap the function out for a no-op anonymous function for speed
|
||||||
|
|
||||||
if (settings.get_boolean('debug'))
|
|
||||||
globalThis.debug = _debugFunc;
|
|
||||||
else
|
|
||||||
globalThis.debug = () => {};
|
globalThis.debug = () => {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start wl_clipboard if not under Gnome
|
* Start wl_clipboard if not under Gnome
|
||||||
|
|||||||
@ -2,25 +2,30 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../config.js';
|
||||||
const GLib = imports.gi.GLib;
|
import * as DBus from './utils/dbus.js';
|
||||||
const GObject = imports.gi.GObject;
|
import Device from './device.js';
|
||||||
|
|
||||||
const Config = imports.config;
|
import * as LanBackend from './backends/lan.js';
|
||||||
const DBus = imports.service.utils.dbus;
|
|
||||||
const Device = imports.service.device;
|
|
||||||
|
|
||||||
const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device';
|
const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device';
|
||||||
const DEVICE_PATH = '/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 DEVICE_IFACE = Config.DBUS.lookup_interface(DEVICE_NAME);
|
||||||
|
|
||||||
|
|
||||||
|
const backends = {
|
||||||
|
lan: LanBackend,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A manager for devices.
|
* A manager for devices.
|
||||||
*/
|
*/
|
||||||
var Manager = GObject.registerClass({
|
const Manager = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectManager',
|
GTypeName: 'GSConnectManager',
|
||||||
Properties: {
|
Properties: {
|
||||||
'active': GObject.ParamSpec.boolean(
|
'active': GObject.ParamSpec.boolean(
|
||||||
@ -30,6 +35,13 @@ var Manager = GObject.registerClass({
|
|||||||
GObject.ParamFlags.READABLE,
|
GObject.ParamFlags.READABLE,
|
||||||
false
|
false
|
||||||
),
|
),
|
||||||
|
'debug': GObject.ParamSpec.boolean(
|
||||||
|
'debug',
|
||||||
|
'Debug',
|
||||||
|
'Whether debug logging is enabled in GSConnect',
|
||||||
|
GObject.ParamFlags.READWRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
'discoverable': GObject.ParamSpec.boolean(
|
'discoverable': GObject.ParamSpec.boolean(
|
||||||
'discoverable',
|
'discoverable',
|
||||||
'Discoverable',
|
'Discoverable',
|
||||||
@ -80,6 +92,21 @@ var Manager = GObject.registerClass({
|
|||||||
return this._backends;
|
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() {
|
get devices() {
|
||||||
if (this._devices === undefined)
|
if (this._devices === undefined)
|
||||||
this._devices = new Map();
|
this._devices = new Map();
|
||||||
@ -198,11 +225,20 @@ var Manager = GObject.registerClass({
|
|||||||
this.settings.set_string('name', GLib.get_host_name());
|
this.settings.set_string('name', GLib.get_host_name());
|
||||||
|
|
||||||
// Bound Properties
|
// Bound Properties
|
||||||
|
this.settings.bind('debug', this, 'debug', 0);
|
||||||
this.settings.bind('discoverable', this, 'discoverable', 0);
|
this.settings.bind('discoverable', this, 'discoverable', 0);
|
||||||
this.settings.bind('id', this, 'id', 0);
|
this.settings.bind('id', this, 'id', 0);
|
||||||
this.settings.bind('name', this, 'name', 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
|
* Backends
|
||||||
*/
|
*/
|
||||||
@ -235,9 +271,9 @@ var Manager = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_loadBackends() {
|
_loadBackends() {
|
||||||
for (const name in imports.service.backends) {
|
for (const name in backends) {
|
||||||
try {
|
try {
|
||||||
const module = imports.service.backends[name];
|
const module = backends[name];
|
||||||
|
|
||||||
if (module.ChannelService === undefined)
|
if (module.ChannelService === undefined)
|
||||||
continue;
|
continue;
|
||||||
@ -270,7 +306,7 @@ var Manager = GObject.registerClass({
|
|||||||
_loadDevices() {
|
_loadDevices() {
|
||||||
// Load cached devices
|
// Load cached devices
|
||||||
for (const id of this.settings.get_strv('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._exportDevice(device);
|
||||||
this.devices.set(id, device);
|
this.devices.set(id, device);
|
||||||
}
|
}
|
||||||
@ -346,7 +382,7 @@ var Manager = GObject.registerClass({
|
|||||||
* of known devices if it doesn't exist.
|
* of known devices if it doesn't exist.
|
||||||
*
|
*
|
||||||
* @param {Core.Packet} packet - An identity packet for the device
|
* @param {Core.Packet} packet - An identity packet for the device
|
||||||
* @return {Device.Device} A device object
|
* @return {Device} A device object
|
||||||
*/
|
*/
|
||||||
_ensureDevice(packet) {
|
_ensureDevice(packet) {
|
||||||
let device = this.devices.get(packet.body.deviceId);
|
let device = this.devices.get(packet.body.deviceId);
|
||||||
@ -365,7 +401,7 @@ var Manager = GObject.registerClass({
|
|||||||
if (unpaired.length === 3)
|
if (unpaired.length === 3)
|
||||||
this.discoverable = false;
|
this.discoverable = false;
|
||||||
|
|
||||||
device = new Device.Device(packet);
|
device = new Device(packet);
|
||||||
this._exportDevice(device);
|
this._exportDevice(device);
|
||||||
this.devices.set(device.id, device);
|
this.devices.set(device.id, device);
|
||||||
|
|
||||||
@ -506,3 +542,4 @@ var Manager = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default Manager;
|
||||||
|
|||||||
30
gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js
Normal file → Executable file
30
gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js
Normal file → Executable file
@ -1,19 +1,25 @@
|
|||||||
#!/usr/bin/env gjs
|
#!/usr/bin/env -S gjs -m
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
|
// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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';
|
import system from 'system';
|
||||||
imports.gi.versions.GLib = '2.0';
|
|
||||||
imports.gi.versions.GObject = '2.0';
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
// Retain compatibility with GLib < 2.80, which lacks GioUnix
|
||||||
const GLib = imports.gi.GLib;
|
let GioUnix;
|
||||||
const GObject = imports.gi.GObject;
|
try {
|
||||||
const System = imports.system;
|
GioUnix = (await import('gi://GioUnix?version=2.0')).default;
|
||||||
|
} catch (e) {
|
||||||
|
GioUnix = {
|
||||||
|
InputStream: Gio.UnixInputStream,
|
||||||
|
OutputStream: Gio.UnixOutputStream,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const NativeMessagingHost = GObject.registerClass({
|
const NativeMessagingHost = GObject.registerClass({
|
||||||
@ -44,12 +50,12 @@ const NativeMessagingHost = GObject.registerClass({
|
|||||||
|
|
||||||
// IO Channels
|
// IO Channels
|
||||||
this._stdin = new Gio.DataInputStream({
|
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,
|
byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._stdout = new Gio.DataOutputStream({
|
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,
|
byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -215,5 +221,5 @@ const NativeMessagingHost = GObject.registerClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// NOTE: must not pass ARGV
|
// NOTE: must not pass ARGV
|
||||||
(new NativeMessagingHost()).run([System.programInvocationName]);
|
await (new NativeMessagingHost()).runAsync([system.programInvocationName]);
|
||||||
|
|
||||||
|
|||||||
@ -2,19 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../config.js';
|
||||||
const GLib = imports.gi.GLib;
|
import plugins from './plugins/index.js';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for device plugins.
|
* Base class for device plugins.
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const Plugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectPlugin',
|
GTypeName: 'GSConnectPlugin',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -42,7 +41,7 @@ var Plugin = GObject.registerClass({
|
|||||||
this._meta = meta;
|
this._meta = meta;
|
||||||
|
|
||||||
if (this._meta === null)
|
if (this._meta === null)
|
||||||
this._meta = imports.service.plugins[name].Metadata;
|
this._meta = plugins[name].Metadata;
|
||||||
|
|
||||||
// GSettings
|
// GSettings
|
||||||
const schema = Config.GSCHEMA.lookup(this._meta.id, false);
|
const schema = Config.GSCHEMA.lookup(this._meta.id, false);
|
||||||
@ -248,3 +247,5 @@ var Plugin = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default Plugin;
|
||||||
|
|
||||||
|
|||||||
@ -2,17 +2,15 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Components from '../components/index.js';
|
||||||
const GLib = imports.gi.GLib;
|
import Plugin from '../plugin.js';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Components = imports.service.components;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Battery'),
|
label: _('Battery'),
|
||||||
description: _('Exchange battery information'),
|
description: _('Exchange battery information'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Battery',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Battery',
|
||||||
@ -32,9 +30,9 @@ var Metadata = {
|
|||||||
* Battery Plugin
|
* Battery Plugin
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/battery
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/battery
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const BatteryPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectBatteryPlugin',
|
GTypeName: 'GSConnectBatteryPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class BatteryPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'battery');
|
super._init(device, 'battery');
|
||||||
@ -431,3 +429,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default BatteryPlugin;
|
||||||
|
|||||||
@ -2,15 +2,13 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import GObject from 'gi://GObject';
|
||||||
|
|
||||||
const GObject = imports.gi.GObject;
|
import * as Components from '../components/index.js';
|
||||||
|
import Plugin from '../plugin.js';
|
||||||
const Components = imports.service.components;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Clipboard'),
|
label: _('Clipboard'),
|
||||||
description: _('Share the clipboard content'),
|
description: _('Share the clipboard content'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Clipboard',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Clipboard',
|
||||||
@ -47,9 +45,9 @@ var Metadata = {
|
|||||||
* Clipboard Plugin
|
* Clipboard Plugin
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/clipboard
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/clipboard
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const ClipboardPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectClipboardPlugin',
|
GTypeName: 'GSConnectClipboardPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class ClipboardPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'clipboard');
|
super._init(device, 'clipboard');
|
||||||
@ -180,3 +178,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default ClipboardPlugin;
|
||||||
|
|||||||
@ -2,17 +2,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Plugin from '../plugin.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Components = imports.service.components;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Connectivity Report'),
|
label: _('Connectivity Report'),
|
||||||
description: _('Display connectivity status'),
|
description: _('Display connectivity status'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.ConnectivityReport',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.ConnectivityReport',
|
||||||
@ -30,9 +27,9 @@ var Metadata = {
|
|||||||
* Connectivity Report Plugin
|
* Connectivity Report Plugin
|
||||||
* https://invent.kde.org/network/kdeconnect-kde/-/tree/master/plugins/connectivity_report
|
* https://invent.kde.org/network/kdeconnect-kde/-/tree/master/plugins/connectivity_report
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const ConnectivityReportPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectConnectivityReportPlugin',
|
GTypeName: 'GSConnectConnectivityReportPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class ConnectivityReportPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'connectivity_report');
|
super._init(device, 'connectivity_report');
|
||||||
@ -162,3 +159,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default ConnectivityReportPlugin;
|
||||||
|
|||||||
@ -2,27 +2,28 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Plugin from '../plugin.js';
|
||||||
const GObject = imports.gi.GObject;
|
import Contacts from '../components/contacts.js';
|
||||||
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
const Contacts = imports.service.components.contacts;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We prefer libebook's vCard parser if it's available
|
* 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 {
|
try {
|
||||||
EBookContacts = imports.gi.EBookContacts;
|
EBookContacts = (await import('gi://EBookContacts')).default;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
EBookContacts = null;
|
EBookContacts = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Contacts'),
|
label: _('Contacts'),
|
||||||
description: _('Access contacts of the paired device'),
|
description: _('Access contacts of the paired device'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Contacts',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Contacts',
|
||||||
@ -53,14 +54,14 @@ const VCARD_TYPED_META = /([a-z]+)=(.*)/i;
|
|||||||
* Contacts Plugin
|
* Contacts Plugin
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/contacts
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/contacts
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const ContactsPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectContactsPlugin',
|
GTypeName: 'GSConnectContactsPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class ContactsPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'contacts');
|
super._init(device, 'contacts');
|
||||||
|
|
||||||
this._store = new Contacts.Store(device.id);
|
this._store = new Contacts(device.id);
|
||||||
this._store.fetch = this._requestUids.bind(this);
|
this._store.fetch = this._requestUids.bind(this);
|
||||||
|
|
||||||
// Notify when the store is ready
|
// Notify when the store is ready
|
||||||
@ -458,3 +459,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default ContactsPlugin;
|
||||||
|
|||||||
@ -2,18 +2,16 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Components from '../components/index.js';
|
||||||
const Gio = imports.gi.Gio;
|
import Plugin from '../plugin.js';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
const Components = imports.service.components;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Find My Phone'),
|
label: _('Find My Phone'),
|
||||||
description: _('Ring your paired device'),
|
description: _('Ring your paired device'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.FindMyPhone',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.FindMyPhone',
|
||||||
@ -36,9 +34,9 @@ var Metadata = {
|
|||||||
* FindMyPhone Plugin
|
* FindMyPhone Plugin
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/findmyphone
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/findmyphone
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const FindMyPhonePlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectFindMyPhonePlugin',
|
GTypeName: 'GSConnectFindMyPhonePlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class FindMyPhonePlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'findmyphone');
|
super._init(device, 'findmyphone');
|
||||||
@ -247,3 +245,5 @@ const Dialog = GObject.registerClass({
|
|||||||
this._plugin = plugin;
|
this._plugin = plugin;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default FindMyPhonePlugin;
|
||||||
|
|||||||
@ -2,17 +2,15 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Components from '../components/index.js';
|
||||||
const GObject = imports.gi.GObject;
|
import {InputDialog} from '../ui/mousepad.js';
|
||||||
|
import Plugin from '../plugin.js';
|
||||||
const Components = imports.service.components;
|
|
||||||
const {InputDialog} = imports.service.ui.mousepad;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Mousepad'),
|
label: _('Mousepad'),
|
||||||
description: _('Enables the paired device to act as a remote mouse and keyboard'),
|
description: _('Enables the paired device to act as a remote mouse and keyboard'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Mousepad',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Mousepad',
|
||||||
@ -120,7 +118,7 @@ const KeyMapCodes = new Map([
|
|||||||
*
|
*
|
||||||
* TODO: support outgoing mouse events?
|
* TODO: support outgoing mouse events?
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const MousepadPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMousepadPlugin',
|
GTypeName: 'GSConnectMousepadPlugin',
|
||||||
Properties: {
|
Properties: {
|
||||||
'state': GObject.ParamSpec.boolean(
|
'state': GObject.ParamSpec.boolean(
|
||||||
@ -131,7 +129,7 @@ var Plugin = GObject.registerClass({
|
|||||||
false
|
false
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class MousepadPlugin extends Plugin {
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'mousepad');
|
super._init(device, 'mousepad');
|
||||||
|
|
||||||
@ -379,3 +377,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default MousepadPlugin;
|
||||||
|
|||||||
@ -2,20 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Components from '../components/index.js';
|
||||||
const GLib = imports.gi.GLib;
|
import Config from '../../config.js';
|
||||||
const GObject = imports.gi.GObject;
|
import * as DBus from '../utils/dbus.js';
|
||||||
|
import {Player} from '../components/mpris.js';
|
||||||
const Components = imports.service.components;
|
import Plugin from '../plugin.js';
|
||||||
const Config = imports.config;
|
|
||||||
const DBus = imports.service.utils.dbus;
|
|
||||||
const MPRIS = imports.service.components.mpris;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('MPRIS'),
|
label: _('MPRIS'),
|
||||||
description: _('Bidirectional remote media playback control'),
|
description: _('Bidirectional remote media playback control'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.MPRIS',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.MPRIS',
|
||||||
@ -33,9 +31,9 @@ var Metadata = {
|
|||||||
* https://specifications.freedesktop.org/mpris-spec/latest/
|
* https://specifications.freedesktop.org/mpris-spec/latest/
|
||||||
* https://github.com/GNOME/gnome-shell/blob/master/js/ui/mpris.js
|
* https://github.com/GNOME/gnome-shell/blob/master/js/ui/mpris.js
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const MPRISPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMPRISPlugin',
|
GTypeName: 'GSConnectMPRISPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class MPRISPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'mpris');
|
super._init(device, 'mpris');
|
||||||
@ -242,11 +240,22 @@ var Plugin = GObject.registerClass({
|
|||||||
player.Volume = packet.body.setVolume / 100;
|
player.Volume = packet.body.setVolume / 100;
|
||||||
|
|
||||||
if (packet.body.hasOwnProperty('Seek'))
|
if (packet.body.hasOwnProperty('Seek'))
|
||||||
await player.Seek(packet.body.Seek * 1000);
|
await player.Seek(packet.body.Seek);
|
||||||
|
|
||||||
if (packet.body.hasOwnProperty('SetPosition')) {
|
if (packet.body.hasOwnProperty('SetPosition')) {
|
||||||
const offset = (packet.body.SetPosition * 1000) - player.Position;
|
// We want to avoid implementing this as a seek operation,
|
||||||
await player.Seek(offset);
|
// 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
|
// Information Request
|
||||||
@ -448,7 +457,7 @@ var Plugin = GObject.registerClass({
|
|||||||
*/
|
*/
|
||||||
const PlayerRemote = GObject.registerClass({
|
const PlayerRemote = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMPRISPlayerRemote',
|
GTypeName: 'GSConnectMPRISPlayerRemote',
|
||||||
}, class PlayerRemote extends MPRIS.Player {
|
}, class PlayerRemote extends Player {
|
||||||
|
|
||||||
_init(device, identity) {
|
_init(device, identity) {
|
||||||
super._init();
|
super._init();
|
||||||
@ -904,3 +913,5 @@ const PlayerRemote = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default MPRISPlugin;
|
||||||
|
|||||||
@ -2,20 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Components from '../components/index.js';
|
||||||
const GLib = imports.gi.GLib;
|
import Config from '../../config.js';
|
||||||
const GObject = imports.gi.GObject;
|
import Plugin from '../plugin.js';
|
||||||
const Gtk = imports.gi.Gtk;
|
import ReplyDialog from '../ui/notification.js';
|
||||||
|
|
||||||
const Components = imports.service.components;
|
|
||||||
const Config = imports.config;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
const NotificationUI = imports.service.ui.notification;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Notifications'),
|
label: _('Notifications'),
|
||||||
description: _('Share notifications with the paired device'),
|
description: _('Share notifications with the paired device'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Notification',
|
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/notifications
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sendnotifications
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sendnotifications
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const NotificationPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectNotificationPlugin',
|
GTypeName: 'GSConnectNotificationPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class NotificationPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'notification');
|
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 the message has no content, open a dialog for the user to add one
|
||||||
if (!message) {
|
if (!message) {
|
||||||
const dialog = new NotificationUI.ReplyDialog({
|
const dialog = new ReplyDialog({
|
||||||
device: this.device,
|
device: this.device,
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
notification: notification,
|
notification: notification,
|
||||||
@ -692,3 +690,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default NotificationPlugin;
|
||||||
|
|||||||
@ -2,16 +2,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Plugin from '../plugin.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Ping'),
|
label: _('Ping'),
|
||||||
description: _('Send and receive pings'),
|
description: _('Send and receive pings'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Ping',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Ping',
|
||||||
@ -34,9 +32,9 @@ var Metadata = {
|
|||||||
* Ping Plugin
|
* Ping Plugin
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/ping
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/ping
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const PingPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectPingPlugin',
|
GTypeName: 'GSConnectPingPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class PingPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'ping');
|
super._init(device, 'ping');
|
||||||
@ -71,3 +69,5 @@ var Plugin = GObject.registerClass({
|
|||||||
this.device.sendPacket(packet);
|
this.device.sendPacket(packet);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default PingPlugin;
|
||||||
|
|||||||
@ -2,15 +2,13 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import GObject from 'gi://GObject';
|
||||||
|
|
||||||
const GObject = imports.gi.GObject;
|
import * as Components from '../components/index.js';
|
||||||
|
import Plugin from '../plugin.js';
|
||||||
const Components = imports.service.components;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Presentation'),
|
label: _('Presentation'),
|
||||||
description: _('Use the paired device as a presenter'),
|
description: _('Use the paired device as a presenter'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.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-kde/tree/master/plugins/presenter
|
||||||
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/PresenterPlugin/
|
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/PresenterPlugin/
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const PresenterPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectPresenterPlugin',
|
GTypeName: 'GSConnectPresenterPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class PresenterPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'presenter');
|
super._init(device, 'presenter');
|
||||||
@ -61,3 +59,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default PresenterPlugin;
|
||||||
|
|||||||
@ -2,16 +2,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Plugin from '../plugin.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Run Commands'),
|
label: _('Run Commands'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.RunCommand',
|
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'),
|
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/remotecommands
|
||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/runcommand
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/runcommand
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const RunCommandPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectRunCommandPlugin',
|
GTypeName: 'GSConnectRunCommandPlugin',
|
||||||
Properties: {
|
Properties: {
|
||||||
'remote-commands': GObject.param_spec_variant(
|
'remote-commands': GObject.param_spec_variant(
|
||||||
@ -61,7 +59,7 @@ var Plugin = GObject.registerClass({
|
|||||||
GObject.ParamFlags.READABLE
|
GObject.ParamFlags.READABLE
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class RunCommandPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'runcommand');
|
super._init(device, 'runcommand');
|
||||||
@ -252,3 +250,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default RunCommandPlugin;
|
||||||
|
|||||||
@ -2,18 +2,15 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../../config.js';
|
||||||
const GLib = imports.gi.GLib;
|
import Plugin from '../plugin.js';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
|
||||||
const Lan = imports.service.backends.lan;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('SFTP'),
|
label: _('SFTP'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SFTP',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SFTP',
|
||||||
description: _('Browse the paired device filesystem'),
|
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-kde/tree/master/plugins/sftp
|
||||||
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SftpPlugin
|
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SftpPlugin
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const SFTPPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectSFTPPlugin',
|
GTypeName: 'GSConnectSFTPPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class SFTPPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'sftp');
|
super._init(device, 'sftp');
|
||||||
@ -106,7 +103,7 @@ var Plugin = GObject.registerClass({
|
|||||||
super.connected();
|
super.connected();
|
||||||
|
|
||||||
// Only enable for Lan connections
|
// 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'))
|
if (this.settings.get_boolean('automount'))
|
||||||
this.mount();
|
this.mount();
|
||||||
} else {
|
} else {
|
||||||
@ -486,3 +483,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default SFTPPlugin;
|
||||||
|
|||||||
@ -2,19 +2,17 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Plugin from '../plugin.js';
|
||||||
const Gio = imports.gi.Gio;
|
import * as URI from '../utils/uri.js';
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Share'),
|
label: _('Share'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Share',
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Share',
|
||||||
description: _('Share files and URLs between devices'),
|
description: _('Share files and URLs between devices'),
|
||||||
@ -64,9 +62,9 @@ var Metadata = {
|
|||||||
* TODO: receiving 'text' TODO: Window with textview & 'Copy to Clipboard..
|
* TODO: receiving 'text' TODO: Window with textview & 'Copy to Clipboard..
|
||||||
* https://github.com/KDE/kdeconnect-kde/commit/28f11bd5c9a717fb9fbb3f02ddd6cea62021d055
|
* https://github.com/KDE/kdeconnect-kde/commit/28f11bd5c9a717fb9fbb3f02ddd6cea62021d055
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const SharePlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectSharePlugin',
|
GTypeName: 'GSConnectSharePlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class SharePlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'share');
|
super._init(device, 'share');
|
||||||
@ -198,6 +196,9 @@ var Plugin = GObject.registerClass({
|
|||||||
];
|
];
|
||||||
iconName = 'document-save-symbolic';
|
iconName = 'document-save-symbolic';
|
||||||
|
|
||||||
|
const gtk_recent_manager = Gtk.RecentManager.get_default();
|
||||||
|
gtk_recent_manager.add_item(file.get_uri());
|
||||||
|
|
||||||
if (packet.body.open) {
|
if (packet.body.open) {
|
||||||
const uri = file.get_uri();
|
const uri = file.get_uri();
|
||||||
Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null);
|
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 */
|
/** A simple FileChooserDialog for sharing files */
|
||||||
var FileChooserDialog = GObject.registerClass({
|
const FileChooserDialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectShareFileChooserDialog',
|
GTypeName: 'GSConnectShareFileChooserDialog',
|
||||||
}, class FileChooserDialog extends Gtk.FileChooserDialog {
|
}, class FileChooserDialog extends Gtk.FileChooserDialog {
|
||||||
|
|
||||||
@ -451,10 +452,11 @@ var FileChooserDialog = GObject.registerClass({
|
|||||||
_onUriButtonToggled(button) {
|
_onUriButtonToggled(button) {
|
||||||
const header = this.get_header_bar();
|
const header = this.get_header_bar();
|
||||||
|
|
||||||
// Show the URL entry
|
// Show and focus the URL entry
|
||||||
if (button.active) {
|
if (button.active) {
|
||||||
this.extra_widget.sensitive = false;
|
this.extra_widget.sensitive = false;
|
||||||
header.set_custom_title(this._uriEntry);
|
header.set_custom_title(this._uriEntry);
|
||||||
|
this._uriEntry.grab_focus();
|
||||||
this.set_response_sensitive(Gtk.ResponseType.OK, true);
|
this.set_response_sensitive(Gtk.ResponseType.OK, true);
|
||||||
|
|
||||||
// Hide the URL entry
|
// Hide the URL entry
|
||||||
@ -490,3 +492,5 @@ var FileChooserDialog = GObject.registerClass({
|
|||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default SharePlugin;
|
||||||
|
|||||||
@ -2,19 +2,17 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Plugin from '../plugin.js';
|
||||||
const GLib = imports.gi.GLib;
|
import LegacyMessagingDialog from '../ui/legacyMessaging.js';
|
||||||
const GObject = imports.gi.GObject;
|
import * as Messaging from '../ui/messaging.js';
|
||||||
|
import SmsURI from '../utils/uri.js';
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
const LegacyMessaging = imports.service.ui.legacyMessaging;
|
|
||||||
const Messaging = imports.service.ui.messaging;
|
|
||||||
const URI = imports.service.utils.uri;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('SMS'),
|
label: _('SMS'),
|
||||||
description: _('Send and read SMS of the paired device and be notified of new SMS'),
|
description: _('Send and read SMS of the paired device and be notified of new SMS'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.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
|
* TEXT_MESSAGE: Has a "body" field which contains pure, human-readable text
|
||||||
*/
|
*/
|
||||||
var MessageEventType = {
|
export const MessageEventType = {
|
||||||
TEXT_MESSAGE: 0x1,
|
TEXT_MESSAGE: 0x1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -97,7 +95,7 @@ var MessageEventType = {
|
|||||||
* UNREAD: A message not marked as read
|
* UNREAD: A message not marked as read
|
||||||
* READ: A message marked as read
|
* READ: A message marked as read
|
||||||
*/
|
*/
|
||||||
var MessageStatus = {
|
export const MessageStatus = {
|
||||||
UNREAD: 0,
|
UNREAD: 0,
|
||||||
READ: 1,
|
READ: 1,
|
||||||
};
|
};
|
||||||
@ -117,7 +115,7 @@ var MessageStatus = {
|
|||||||
* FAILED: Failed outgoing messages
|
* FAILED: Failed outgoing messages
|
||||||
* QUEUED: Messages queued to send later
|
* QUEUED: Messages queued to send later
|
||||||
*/
|
*/
|
||||||
var MessageBox = {
|
export const MessageBox = {
|
||||||
ALL: 0,
|
ALL: 0,
|
||||||
INBOX: 1,
|
INBOX: 1,
|
||||||
SENT: 2,
|
SENT: 2,
|
||||||
@ -133,7 +131,7 @@ var MessageBox = {
|
|||||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sms
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sms
|
||||||
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SMSPlugin/
|
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SMSPlugin/
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const SMSPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectSMSPlugin',
|
GTypeName: 'GSConnectSMSPlugin',
|
||||||
Properties: {
|
Properties: {
|
||||||
'threads': GObject.param_spec_variant(
|
'threads': GObject.param_spec_variant(
|
||||||
@ -145,7 +143,7 @@ var Plugin = GObject.registerClass({
|
|||||||
GObject.ParamFlags.READABLE
|
GObject.ParamFlags.READABLE
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class SMSPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'sms');
|
super._init(device, 'sms');
|
||||||
@ -162,7 +160,7 @@ var Plugin = GObject.registerClass({
|
|||||||
|
|
||||||
get window() {
|
get window() {
|
||||||
if (this.settings.get_boolean('legacy-sms')) {
|
if (this.settings.get_boolean('legacy-sms')) {
|
||||||
return new LegacyMessaging.Dialog({
|
return new LegacyMessagingDialog({
|
||||||
device: this.device,
|
device: this.device,
|
||||||
plugin: this,
|
plugin: this,
|
||||||
});
|
});
|
||||||
@ -473,7 +471,7 @@ var Plugin = GObject.registerClass({
|
|||||||
*/
|
*/
|
||||||
uriSms(uri) {
|
uriSms(uri) {
|
||||||
try {
|
try {
|
||||||
uri = new URI.SmsURI(uri);
|
uri = new SmsURI(uri);
|
||||||
|
|
||||||
// Lookup contacts
|
// Lookup contacts
|
||||||
const addresses = uri.recipients.map(number => {
|
const addresses = uri.recipients.map(number => {
|
||||||
@ -534,3 +532,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default SMSPlugin;
|
||||||
|
|||||||
@ -2,16 +2,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import GObject from 'gi://GObject';
|
||||||
|
|
||||||
const GObject = imports.gi.GObject;
|
import * as Components from '../components/index.js';
|
||||||
|
import Config from '../../config.js';
|
||||||
const Components = imports.service.components;
|
import Plugin from '../plugin.js';
|
||||||
const Config = imports.config;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('System Volume'),
|
label: _('System Volume'),
|
||||||
description: _('Enable the paired device to control the system volume'),
|
description: _('Enable the paired device to control the system volume'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SystemVolume',
|
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-kde/tree/master/plugins/systemvolume
|
||||||
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SystemvolumePlugin/
|
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SystemvolumePlugin/
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const SystemVolumePlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectSystemVolumePlugin',
|
GTypeName: 'GSConnectSystemVolumePlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class SystemVolumePlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'systemvolume');
|
super._init(device, 'systemvolume');
|
||||||
@ -202,3 +200,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default SystemVolumePlugin;
|
||||||
|
|||||||
@ -2,18 +2,16 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Components from '../components/index.js';
|
||||||
const Gio = imports.gi.Gio;
|
import Plugin from '../plugin.js';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const Components = imports.service.components;
|
|
||||||
const PluginBase = imports.service.plugin;
|
|
||||||
|
|
||||||
|
|
||||||
var Metadata = {
|
export const Metadata = {
|
||||||
label: _('Telephony'),
|
label: _('Telephony'),
|
||||||
description: _('Be notified about calls and adjust system volume during ringing/ongoing calls'),
|
description: _('Be notified about calls and adjust system volume during ringing/ongoing calls'),
|
||||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Telephony',
|
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-kde/tree/master/plugins/telephony
|
||||||
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/TelephonyPlugin
|
* https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/TelephonyPlugin
|
||||||
*/
|
*/
|
||||||
var Plugin = GObject.registerClass({
|
const TelephonyPlugin = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectTelephonyPlugin',
|
GTypeName: 'GSConnectTelephonyPlugin',
|
||||||
}, class Plugin extends PluginBase.Plugin {
|
}, class TelephonyPlugin extends Plugin {
|
||||||
|
|
||||||
_init(device) {
|
_init(device) {
|
||||||
super._init(device, 'telephony');
|
super._init(device, 'telephony');
|
||||||
@ -243,3 +241,5 @@ var Plugin = GObject.registerClass({
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default TelephonyPlugin;
|
||||||
|
|||||||
@ -2,13 +2,13 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import system from 'system';
|
||||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,7 +156,7 @@ function getNumberTypeLabel(type) {
|
|||||||
* @param {string} address - A phone number
|
* @param {string} address - A phone number
|
||||||
* @return {string} A (possibly) better display number for the address
|
* @return {string} A (possibly) better display number for the address
|
||||||
*/
|
*/
|
||||||
function getDisplayNumber(contact, address) {
|
export function getDisplayNumber(contact, address) {
|
||||||
const number = address.toPhoneNumber();
|
const number = address.toPhoneNumber();
|
||||||
|
|
||||||
for (const contactNumber of contact.numbers) {
|
for (const contactNumber of contact.numbers) {
|
||||||
@ -175,7 +175,7 @@ function getDisplayNumber(contact, address) {
|
|||||||
*/
|
*/
|
||||||
const AvatarCache = new WeakMap();
|
const AvatarCache = new WeakMap();
|
||||||
|
|
||||||
var Avatar = GObject.registerClass({
|
export const Avatar = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectContactAvatar',
|
GTypeName: 'GSConnectContactAvatar',
|
||||||
}, class ContactAvatar extends Gtk.DrawingArea {
|
}, class ContactAvatar extends Gtk.DrawingArea {
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ const AddressRow = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A widget for selecting contact addresses (usually phone numbers)
|
* A widget for selecting contact addresses (usually phone numbers)
|
||||||
*/
|
*/
|
||||||
var ContactChooser = GObject.registerClass({
|
export const ContactChooser = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectContactChooser',
|
GTypeName: 'GSConnectContactChooser',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -435,7 +435,7 @@ var ContactChooser = GObject.registerClass({
|
|||||||
for (let i = 0, len = rows.length; i < len; i++) {
|
for (let i = 0, len = rows.length; i < len; i++) {
|
||||||
rows[i].destroy();
|
rows[i].destroy();
|
||||||
// HACK: temporary mitigator for mysterious GtkListBox leak
|
// 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) {
|
if (row.contact.id === id) {
|
||||||
row.destroy();
|
row.destroy();
|
||||||
// HACK: temporary mitigator for mysterious GtkListBox leak
|
// HACK: temporary mitigator for mysterious GtkListBox leak
|
||||||
imports.system.gc();
|
system.gc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,19 +2,17 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as Contacts from '../ui/contacts.js';
|
||||||
const GObject = imports.gi.GObject;
|
import * as Messaging from '../ui/messaging.js';
|
||||||
const Gtk = imports.gi.Gtk;
|
import * as URI from '../utils/uri.js';
|
||||||
|
import '../utils/ui.js';
|
||||||
const Contacts = imports.service.ui.contacts;
|
|
||||||
const Messaging = imports.service.ui.messaging;
|
|
||||||
const URI = imports.service.utils.uri;
|
|
||||||
const _ui = imports.service.utils.ui;
|
|
||||||
|
|
||||||
|
|
||||||
var Dialog = GObject.registerClass({
|
const Dialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectLegacyMessagingDialog',
|
GTypeName: 'GSConnectLegacyMessagingDialog',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -226,3 +224,4 @@ var Dialog = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default Dialog;
|
||||||
|
|||||||
@ -2,21 +2,21 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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 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
|
* Useful time constants
|
||||||
@ -460,7 +460,7 @@ const Conversation = GObject.registerClass({
|
|||||||
conversation.list.foreach(message => {
|
conversation.list.foreach(message => {
|
||||||
// HACK: temporary mitigator for mysterious GtkListBox leak
|
// HACK: temporary mitigator for mysterious GtkListBox leak
|
||||||
message.destroy();
|
message.destroy();
|
||||||
imports.system.gc();
|
system.gc();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -800,7 +800,7 @@ const ConversationSummary = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A Gtk.ApplicationWindow for SMS conversations
|
* A Gtk.ApplicationWindow for SMS conversations
|
||||||
*/
|
*/
|
||||||
var Window = GObject.registerClass({
|
export const Window = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMessagingWindow',
|
GTypeName: 'GSConnectMessagingWindow',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -1025,13 +1025,13 @@ var Window = GObject.registerClass({
|
|||||||
|
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
conversation.destroy();
|
conversation.destroy();
|
||||||
imports.system.gc();
|
system.gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then the summary widget
|
// Then the summary widget
|
||||||
row.destroy();
|
row.destroy();
|
||||||
// HACK: temporary mitigator for mysterious GtkListBox leak
|
// 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
|
* A Gtk.ApplicationWindow for selecting from open conversations
|
||||||
*/
|
*/
|
||||||
var ConversationChooser = GObject.registerClass({
|
export const ConversationChooser = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectConversationChooser',
|
GTypeName: 'GSConnectConversationChooser',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
|
|||||||
@ -2,12 +2,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import GLib from 'gi://GLib';
|
||||||
|
import Gdk from 'gi://Gdk';
|
||||||
const GLib = imports.gi.GLib;
|
import GObject from 'gi://GObject';
|
||||||
const Gdk = imports.gi.Gdk;
|
import Gtk from 'gi://Gtk';
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.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);
|
const isSuper = (key) => [Gdk.KEY_Super_L, Gdk.KEY_Super_R].includes(key);
|
||||||
|
|
||||||
|
|
||||||
var InputDialog = GObject.registerClass({
|
export const InputDialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectMousepadInputDialog',
|
GTypeName: 'GSConnectMousepadInputDialog',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -390,7 +388,7 @@ var InputDialog = GObject.registerClass({
|
|||||||
(Math.abs(this.touchpad_motion_y) < 4);
|
(Math.abs(this.touchpad_motion_y) < 4);
|
||||||
|
|
||||||
if (is_click) {
|
if (is_click) {
|
||||||
var click_body = {};
|
const click_body = {};
|
||||||
switch (gesture_button) {
|
switch (gesture_button) {
|
||||||
case 1:
|
case 1:
|
||||||
click_body.singleclick = true;
|
click_body.singleclick = true;
|
||||||
@ -444,8 +442,8 @@ var InputDialog = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onTouchpadMotionTimeout() {
|
_onTouchpadMotionTimeout() {
|
||||||
var diff_x = this.touchpad_motion_x - this.touchpad_motion_prev_x;
|
const 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_y = this.touchpad_motion_y - this.touchpad_motion_prev_y;
|
||||||
|
|
||||||
this.device.sendPacket({
|
this.device.sendPacket({
|
||||||
type: 'kdeconnect.mousepad.request',
|
type: 'kdeconnect.mousepad.request',
|
||||||
|
|||||||
@ -2,20 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import * as URI from '../utils/uri.js';
|
||||||
const GObject = imports.gi.GObject;
|
import '../utils/ui.js';
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
const URI = imports.service.utils.uri;
|
|
||||||
const _ui = imports.service.utils.ui;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dialog for repliable notifications.
|
* A dialog for repliable notifications.
|
||||||
*/
|
*/
|
||||||
var ReplyDialog = GObject.registerClass({
|
const ReplyDialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectNotificationReplyDialog',
|
GTypeName: 'GSConnectNotificationReplyDialog',
|
||||||
Properties: {
|
Properties: {
|
||||||
'device': GObject.ParamSpec.object(
|
'device': GObject.ParamSpec.object(
|
||||||
@ -177,3 +175,4 @@ var ReplyDialog = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default ReplyDialog;
|
||||||
|
|||||||
@ -2,14 +2,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import system from 'system';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
import Config from '../../config.js';
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -17,7 +17,7 @@ const Config = imports.config;
|
|||||||
*/
|
*/
|
||||||
const ISSUE_HEADER = `
|
const ISSUE_HEADER = `
|
||||||
GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'})
|
GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'})
|
||||||
GJS: ${imports.system.version}
|
GJS: ${system.version}
|
||||||
Session: ${GLib.getenv('XDG_SESSION_TYPE')}
|
Session: ${GLib.getenv('XDG_SESSION_TYPE')}
|
||||||
OS: ${GLib.get_os_info('PRETTY_NAME')}
|
OS: ${GLib.get_os_info('PRETTY_NAME')}
|
||||||
`;
|
`;
|
||||||
@ -26,7 +26,7 @@ OS: ${GLib.get_os_info('PRETTY_NAME')}
|
|||||||
/**
|
/**
|
||||||
* A dialog for selecting a device
|
* A dialog for selecting a device
|
||||||
*/
|
*/
|
||||||
var DeviceChooser = GObject.registerClass({
|
export const DeviceChooser = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectServiceDeviceChooser',
|
GTypeName: 'GSConnectServiceDeviceChooser',
|
||||||
Properties: {
|
Properties: {
|
||||||
'action-name': GObject.ParamSpec.string(
|
'action-name': GObject.ParamSpec.string(
|
||||||
@ -192,7 +192,7 @@ var DeviceChooser = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A dialog for reporting an error.
|
* A dialog for reporting an error.
|
||||||
*/
|
*/
|
||||||
var ErrorDialog = GObject.registerClass({
|
export const ErrorDialog = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectServiceErrorDialog',
|
GTypeName: 'GSConnectServiceErrorDialog',
|
||||||
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/service-error-dialog.ui',
|
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/service-error-dialog.ui',
|
||||||
Children: [
|
Children: [
|
||||||
|
|||||||
@ -2,12 +2,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GjsPrivate from 'gi://GjsPrivate';
|
||||||
const Gio = imports.gi.Gio;
|
import GLib from 'gi://GLib';
|
||||||
const GjsPrivate = imports.gi.GjsPrivate;
|
import GObject from 'gi://GObject';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -19,12 +17,6 @@ function toDBusCase(string) {
|
|||||||
}).replace(/[\s_-]+/g, '');
|
}).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) {
|
function toUnderscoreCase(string) {
|
||||||
return string.replace(/(?:^\w|[A-Z]|_|\b\w)/g, (ltr, offset) => {
|
return string.replace(/(?:^\w|[A-Z]|_|\b\w)/g, (ltr, offset) => {
|
||||||
if (ltr === '_')
|
if (ltr === '_')
|
||||||
@ -39,7 +31,7 @@ function toUnderscoreCase(string) {
|
|||||||
* DBus.Interface represents a DBus interface bound to an object instance, meant
|
* DBus.Interface represents a DBus interface bound to an object instance, meant
|
||||||
* to be exported over DBus.
|
* to be exported over DBus.
|
||||||
*/
|
*/
|
||||||
var Interface = GObject.registerClass({
|
export const Interface = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectDBusInterface',
|
GTypeName: 'GSConnectDBusInterface',
|
||||||
Implements: [Gio.DBusInterface],
|
Implements: [Gio.DBusInterface],
|
||||||
Properties: {
|
Properties: {
|
||||||
@ -241,7 +233,7 @@ var Interface = GObject.registerClass({
|
|||||||
* @param {Gio.Cancellable} [cancellable] - an optional Gio.Cancellable
|
* @param {Gio.Cancellable} [cancellable] - an optional Gio.Cancellable
|
||||||
* @return {Promise<Gio.DBusConnection>} A new DBus connection
|
* @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) => {
|
return new Promise((resolve, reject) => {
|
||||||
Gio.DBusConnection.new_for_address(
|
Gio.DBusConnection.new_for_address(
|
||||||
Gio.dbus_address_get_for_bus_sync(busType, cancellable),
|
Gio.dbus_address_get_for_bus_sync(busType, cancellable),
|
||||||
|
|||||||
@ -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,
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
|
||||||
@ -2,14 +2,12 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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;
|
import Config from '../../config.js';
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
|
|
||||||
const Config = imports.config;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import GLib from 'gi://GLib';
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +81,7 @@ const _numberRegex = new RegExp(
|
|||||||
* @param {string} str - the string to search
|
* @param {string} str - the string to search
|
||||||
* @return {Object[]} the list of match objects, as described above
|
* @return {Object[]} the list of match objects, as described above
|
||||||
*/
|
*/
|
||||||
function findUrls(str) {
|
export function findUrls(str) {
|
||||||
_urlRegexp.lastIndex = 0;
|
_urlRegexp.lastIndex = 0;
|
||||||
|
|
||||||
const res = [];
|
const res = [];
|
||||||
@ -107,7 +105,7 @@ function findUrls(str) {
|
|||||||
* @param {string} [title] - An optional title (eg. alt text, tooltip)
|
* @param {string} [title] - An optional title (eg. alt text, tooltip)
|
||||||
* @return {string} the modified text
|
* @return {string} the modified text
|
||||||
*/
|
*/
|
||||||
function linkify(str, title = null) {
|
export function linkify(str, title = null) {
|
||||||
const text = GLib.markup_escape_text(str, -1);
|
const text = GLib.markup_escape_text(str, -1);
|
||||||
|
|
||||||
_urlRegexp.lastIndex = 0;
|
_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)
|
* A simple parsing class for sms: URI's (https://tools.ietf.org/html/rfc5724)
|
||||||
*/
|
*/
|
||||||
var SmsURI = class URI {
|
export default class URI {
|
||||||
constructor(uri) {
|
constructor(uri) {
|
||||||
_smsRegex.lastIndex = 0;
|
_smsRegex.lastIndex = 0;
|
||||||
const [, recipients, query] = _smsRegex.exec(uri);
|
const [, recipients, query] = _smsRegex.exec(uri);
|
||||||
@ -167,5 +165,5 @@ var SmsURI = class URI {
|
|||||||
|
|
||||||
return this.body ? `${uri}?body=${escape(this.body)}` : uri;
|
return this.body ? `${uri}?body=${escape(this.body)}` : uri;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import Gio from 'gi://Gio';
|
import Gio from 'gi://Gio';
|
||||||
|
|
||||||
import Config from '../config.mjs';
|
import Config from '../config.js';
|
||||||
|
|
||||||
export class LockscreenRemoteAccess {
|
export class LockscreenRemoteAccess {
|
||||||
|
|
||||||
|
|||||||
@ -239,19 +239,20 @@ const Source = GObject.registerClass({
|
|||||||
if (cachedNotification) {
|
if (cachedNotification) {
|
||||||
cachedNotification.requestReplyId = requestReplyId;
|
cachedNotification.requestReplyId = requestReplyId;
|
||||||
|
|
||||||
// Bail early If @notificationParams represents an exact repeat
|
|
||||||
const title = notification.title;
|
const title = notification.title;
|
||||||
const body = notification.body
|
const body = notification.body
|
||||||
? notification.body
|
? notification.body
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
// Bail early If @notification represents an exact repeat
|
||||||
if (cachedNotification.title === title &&
|
if (cachedNotification.title === title &&
|
||||||
cachedNotification.body === body)
|
cachedNotification.body === body)
|
||||||
return cachedNotification;
|
return cachedNotification;
|
||||||
|
|
||||||
|
// If the details have changed, flag as an update
|
||||||
cachedNotification.title = title;
|
cachedNotification.title = title;
|
||||||
cachedNotification.body = body;
|
cachedNotification.body = body;
|
||||||
|
cachedNotification.acknowledged = false;
|
||||||
return cachedNotification;
|
return cachedNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,10 +305,8 @@ const Source = GObject.registerClass({
|
|||||||
* notification limit (3)
|
* notification limit (3)
|
||||||
*/
|
*/
|
||||||
_addNotificationToMessageTray(notification) {
|
_addNotificationToMessageTray(notification) {
|
||||||
if (this.notifications.includes(notification)) {
|
if (this.notifications.includes(notification))
|
||||||
notification.acknowledged = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
while (this.notifications.length >= 10) {
|
while (this.notifications.length >= 10) {
|
||||||
const [oldest] = this.notifications;
|
const [oldest] = this.notifications;
|
||||||
|
|||||||
@ -170,8 +170,7 @@ export default class Tooltip {
|
|||||||
this._bin.child.add_child(this.label);
|
this._bin.child.add_child(this.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
Main.layoutManager.uiGroup.add_child(this._bin);
|
Main.layoutManager.addTopChrome(this._bin);
|
||||||
Main.layoutManager.uiGroup.set_child_above_sibling(this._bin, null);
|
|
||||||
} else if (this.custom) {
|
} else if (this.custom) {
|
||||||
this._bin.child = this.custom;
|
this._bin.child = this.custom;
|
||||||
} else {
|
} else {
|
||||||
@ -234,7 +233,7 @@ export default class Tooltip {
|
|||||||
time: 0.10,
|
time: 0.10,
|
||||||
transition: Clutter.AnimationMode.EASE_OUT_QUAD,
|
transition: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
Main.layoutManager.uiGroup.remove_actor(this._bin);
|
Main.layoutManager.removeChrome(this._bin);
|
||||||
|
|
||||||
if (this.custom)
|
if (this.custom)
|
||||||
this._bin.remove_child(this.custom);
|
this._bin.remove_child(this.custom);
|
||||||
@ -291,7 +290,7 @@ export default class Tooltip {
|
|||||||
this.custom.destroy();
|
this.custom.destroy();
|
||||||
|
|
||||||
if (this._bin) {
|
if (this._bin) {
|
||||||
Main.layoutManager.uiGroup.remove_actor(this._bin);
|
Main.layoutManager.removeChrome(this._bin);
|
||||||
this._bin.destroy();
|
this._bin.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,4 +305,3 @@ export default class Tooltip {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import Gio from 'gi://Gio';
|
|||||||
import GLib from 'gi://GLib';
|
import GLib from 'gi://GLib';
|
||||||
import Gtk from 'gi://Gtk';
|
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.
|
let St = null; // St is not available for prefs.js importing this file.
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -2,16 +2,13 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GLib from 'gi://GLib';
|
||||||
const Gio = imports.gi.Gio;
|
import GObject from 'gi://GObject';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
const SERVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect';
|
const SERVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect';
|
||||||
const SERVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect';
|
const SERVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect';
|
||||||
const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device';
|
const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device';
|
||||||
const DEVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect/Device';
|
|
||||||
|
|
||||||
|
|
||||||
const _PROPERTIES = {
|
const _PROPERTIES = {
|
||||||
@ -51,7 +48,7 @@ function _proxyInit(proxy, cancellable = null) {
|
|||||||
/**
|
/**
|
||||||
* A simple proxy wrapper for devices exported over DBus.
|
* A simple proxy wrapper for devices exported over DBus.
|
||||||
*/
|
*/
|
||||||
var Device = GObject.registerClass({
|
export const Device = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectRemoteDevice',
|
GTypeName: 'GSConnectRemoteDevice',
|
||||||
Implements: [Gio.DBusInterface],
|
Implements: [Gio.DBusInterface],
|
||||||
Properties: {
|
Properties: {
|
||||||
@ -222,7 +219,7 @@ var Device = GObject.registerClass({
|
|||||||
/**
|
/**
|
||||||
* A simple proxy wrapper for the GSConnect service.
|
* A simple proxy wrapper for the GSConnect service.
|
||||||
*/
|
*/
|
||||||
var Service = GObject.registerClass({
|
export const Service = GObject.registerClass({
|
||||||
GTypeName: 'GSConnectRemoteService',
|
GTypeName: 'GSConnectRemoteService',
|
||||||
Implements: [Gio.DBusInterface],
|
Implements: [Gio.DBusInterface],
|
||||||
Properties: {
|
Properties: {
|
||||||
|
|||||||
@ -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;
|
|
||||||
@ -2,18 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
import Gio from 'gi://Gio';
|
||||||
const GLib = imports.gi.GLib;
|
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.
|
* Initialise and setup Gettext.
|
||||||
*/
|
*/
|
||||||
function setupGettext() {
|
export function setupGettext() {
|
||||||
// Init Gettext
|
// Init Gettext
|
||||||
String.prototype.format = imports.format.format;
|
String.prototype.format = imports.format.format;
|
||||||
Gettext.bindtextdomain(Config.APP_ID, Config.PACKAGE_LOCALEDIR);
|
Gettext.bindtextdomain(Config.APP_ID, Config.PACKAGE_LOCALEDIR);
|
||||||
@ -25,7 +25,7 @@ function setupGettext() {
|
|||||||
* Initialise and setup Config, GResources and GSchema.
|
* Initialise and setup Config, GResources and GSchema.
|
||||||
* @param {string} extensionPath - The absolute path to the extension directory
|
* @param {string} extensionPath - The absolute path to the extension directory
|
||||||
*/
|
*/
|
||||||
function setup(extensionPath) {
|
export default function setup(extensionPath) {
|
||||||
// Ensure config.js is setup properly
|
// Ensure config.js is setup properly
|
||||||
Config.PACKAGE_DATADIR = extensionPath;
|
Config.PACKAGE_DATADIR = extensionPath;
|
||||||
const userDir = GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']);
|
const userDir = GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']);
|
||||||
|
|||||||
@ -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;
|
|
||||||
@ -2,12 +2,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
'use strict';
|
import Gio from 'gi://Gio';
|
||||||
|
import GjsPrivate from 'gi://GjsPrivate';
|
||||||
const Gio = imports.gi.Gio;
|
import GLib from 'gi://GLib';
|
||||||
const GjsPrivate = imports.gi.GjsPrivate;
|
import GObject from 'gi://GObject';
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
|
|
||||||
// laucher for wl-clipboard
|
// laucher for wl-clipboard
|
||||||
const launcher = new Gio.SubprocessLauncher({
|
const launcher = new Gio.SubprocessLauncher({
|
||||||
@ -55,7 +53,7 @@ const TEXT_MIMETYPES = [
|
|||||||
* A simple clipboard portal, especially useful on Wayland where GtkClipboard
|
* A simple clipboard portal, especially useful on Wayland where GtkClipboard
|
||||||
* doesn't work in the background.
|
* doesn't work in the background.
|
||||||
*/
|
*/
|
||||||
var Clipboard = GObject.registerClass(
|
export const Clipboard = GObject.registerClass(
|
||||||
{
|
{
|
||||||
GTypeName: 'GSConnectShellClipboard',
|
GTypeName: 'GSConnectShellClipboard',
|
||||||
},
|
},
|
||||||
@ -258,13 +256,13 @@ var Clipboard = GObject.registerClass(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
var _portal = null;
|
let _portal = null;
|
||||||
var _portalId = 0;
|
let _portalId = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watch for the service to start and export the clipboard portal when it does.
|
* Watch for the service to start and export the clipboard portal when it does.
|
||||||
*/
|
*/
|
||||||
function watchService() {
|
export function watchService() {
|
||||||
if (_portalId > 0)
|
if (_portalId > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -288,7 +286,7 @@ function watchService() {
|
|||||||
/**
|
/**
|
||||||
* Stop watching the service and export the portal if currently running.
|
* Stop watching the service and export the portal if currently running.
|
||||||
*/
|
*/
|
||||||
function unwatchService() {
|
export function unwatchService() {
|
||||||
if (_portalId > 0) {
|
if (_portalId > 0) {
|
||||||
Gio.bus_unwatch_name(_portalId);
|
Gio.bus_unwatch_name(_portalId);
|
||||||
_portalId = 0;
|
_portalId = 0;
|
||||||
|
|||||||
@ -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;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@ -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>
|
||||||
@ -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); },
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user