diff --git a/data/org.gnome.Shell.Extensions.GSConnect.gschema.xml b/data/org.gnome.Shell.Extensions.GSConnect.gschema.xml index 6322910ef..4dfaddb3e 100644 --- a/data/org.gnome.Shell.Extensions.GSConnect.gschema.xml +++ b/data/org.gnome.Shell.Extensions.GSConnect.gschema.xml @@ -59,7 +59,7 @@ SPDX-License-Identifier: GPL-2.0-or-later {} - ["sms", "ring", "mount", "commands", "share", "photo", "keyboard"] + ["sms", "ring", "mount", "commands", "share", "keyboard"] "" @@ -141,14 +141,6 @@ SPDX-License-Identifier: GPL-2.0-or-later '{}' - - - true - - - "" - - diff --git a/data/ui/preferences-device-panel.ui b/data/ui/preferences-device-panel.ui index 8007a4bce..921eb7d01 100644 --- a/data/ui/preferences-device-panel.ui +++ b/data/ui/preferences-device-panel.ui @@ -78,63 +78,6 @@ SPDX-License-Identifier: GPL-2.0-or-later none - - - 56 - True - True - False - - - True - False - 12 - 12 - 12 - - - True - False - start - center - True - True - Camera - - - - - - - 0 - 0 - - - - - True - True - end - center - settings.share-camera - - - - - - - 1 - 0 - - - - - - - - - - 56 diff --git a/installed-tests/suites/plugins/meson.build b/installed-tests/suites/plugins/meson.build index 7cebe064d..fc47a5b82 100644 --- a/installed-tests/suites/plugins/meson.build +++ b/installed-tests/suites/plugins/meson.build @@ -14,7 +14,6 @@ plugin_tests = [ 'MousepadPlugin', 'MprisPlugin', 'NotificationPlugin', - 'PhotoPlugin', 'PingPlugin', 'PresenterPlugin', 'RuncommandPlugin', diff --git a/installed-tests/suites/plugins/testPhotoPlugin.js b/installed-tests/suites/plugins/testPhotoPlugin.js deleted file mode 100644 index fb0682651..000000000 --- a/installed-tests/suites/plugins/testPhotoPlugin.js +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -'use strict'; - -const Utils = imports.fixtures.utils; - - -describe('The photo plugin', function () { - let testRig; - let localPlugin, remotePlugin; - - beforeAll(async function () { - testRig = new Utils.TestRig(); - await testRig.prepare({ - localDevice: { - incomingCapabilities: [ - 'kdeconnect.photo', - 'kdeconnect.photo.request', - ], - outgoingCapabilities: [ - 'kdeconnect.photo', - 'kdeconnect.photo.request', - ], - }, - remoteDevice: { - incomingCapabilities: [ - 'kdeconnect.photo', - 'kdeconnect.photo.request', - ], - outgoingCapabilities: [ - 'kdeconnect.photo', - 'kdeconnect.photo.request', - ], - }, - }); - testRig.setPaired(true); - }); - - afterAll(function () { - testRig.destroy(); - }); - - beforeEach(function () { - if (localPlugin && remotePlugin) { - spyOn(localPlugin, 'handlePacket').and.callThrough(); - spyOn(remotePlugin, 'handlePacket').and.callThrough(); - } - }); - - it('can be loaded', async function () { - await testRig.loadPlugins(); - - localPlugin = testRig.localDevice._plugins.get('photo'); - remotePlugin = testRig.remoteDevice._plugins.get('photo'); - - expect(localPlugin).toBeDefined(); - expect(remotePlugin).toBeDefined(); - }); - - it('enables its GActions when connected', function () { - testRig.setConnected(true); - - expect(localPlugin.device.get_action_enabled('photo')).toBeTrue(); - expect(remotePlugin.device.get_action_enabled('photo')).toBeTrue(); - }); - - it('can request and receive photos', async function () { - spyOn(remotePlugin, '_sendPhoto'); - - localPlugin.photo(); - await remotePlugin.awaitPacket('kdeconnect.photo.request'); - - expect(remotePlugin._sendPhoto).toHaveBeenCalled(); - }); - - it('disables its GActions when disconnected', function () { - testRig.setConnected(false); - - expect(localPlugin.device.get_action_enabled('photo')).toBeFalse(); - expect(remotePlugin.device.get_action_enabled('photo')).toBeFalse(); - }); -}); - diff --git a/po/POTFILES b/po/POTFILES index dd040a208..1a12aa5bc 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -32,7 +32,6 @@ src/service/plugins/findmyphone.js src/service/plugins/mousepad.js src/service/plugins/mpris.js src/service/plugins/notification.js -src/service/plugins/photo.js src/service/plugins/ping.js src/service/plugins/presenter.js src/service/plugins/runcommand.js diff --git a/src/preferences/device.js b/src/preferences/device.js index 002eb5833..d51835305 100644 --- a/src/preferences/device.js +++ b/src/preferences/device.js @@ -463,9 +463,6 @@ var Panel = GObject.registerClass({ this.actions.add_action(settings.create_action('send-notifications')); this.actions.add_action(settings.create_action('send-active')); - settings = this.pluginSettings('photo'); - this.actions.add_action(settings.create_action('share-camera')); - settings = this.pluginSettings('sftp'); this.actions.add_action(settings.create_action('automount')); diff --git a/src/service/daemon.js b/src/service/daemon.js index 32e228651..86355d5a7 100755 --- a/src/service/daemon.js +++ b/src/service/daemon.js @@ -468,15 +468,6 @@ const Service = GObject.registerClass({ '' ); - this.add_main_option( - 'photo', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Photo'), - null - ); - this.add_main_option( 'ping', 0, @@ -706,9 +697,6 @@ const Service = GObject.registerClass({ if (options.contains('notification')) this._cliNotify(id, options); - if (options.contains('photo')) - this._cliAction(id, 'photo'); - if (options.contains('ping')) this._cliAction(id, 'ping', GLib.Variant.new_string('')); diff --git a/src/service/plugins/photo.js b/src/service/plugins/photo.js deleted file mode 100644 index 0f0cd2d22..000000000 --- a/src/service/plugins/photo.js +++ /dev/null @@ -1,236 +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 GLib = imports.gi.GLib; -const GObject = imports.gi.GObject; - -const Config = imports.config; -const PluginBase = imports.service.plugin; - - -var Metadata = { - label: _('Photo'), - description: _('Request the paired device to take a photo and transfer it to this PC'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Photo', - incomingCapabilities: [ - 'kdeconnect.photo', - 'kdeconnect.photo.request', - ], - outgoingCapabilities: [ - 'kdeconnect.photo', - 'kdeconnect.photo.request', - ], - actions: { - photo: { - label: _('Photo'), - icon_name: 'camera-photo-symbolic', - - parameter_type: null, - incoming: ['kdeconnect.photo'], - outgoing: ['kdeconnect.photo.request'], - }, - }, -}; - - -/** - * Photo Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/photo - * - * TODO: use Cheese? - * check for /dev/video* - */ -var Plugin = GObject.registerClass({ - GTypeName: 'GSConnectPhotoPlugin', -}, class Plugin extends PluginBase.Plugin { - - _init(device) { - super._init(device, 'photo'); - - // A reusable launcher for silence procs - this._launcher = new Gio.SubprocessLauncher({ - flags: (Gio.SubprocessFlags.STDOUT_SILENCE | - Gio.SubprocessFlags.STDERR_SILENCE), - }); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.photo': - this._receivePhoto(packet); - break; - - case 'kdeconnect.photo.request': - this._sendPhoto(packet); - break; - } - } - - /** - * Ensure we have a directory set for storing files that exists. - * - * @return {string} An absolute directory path - */ - _ensureReceiveDirectory() { - if (this._receiveDir !== undefined) - return this._receiveDir; - - // Ensure a directory is set - this._receiveDir = this.settings.get_string('receive-directory'); - - if (this._receiveDir === '') { - this._receiveDir = GLib.get_user_special_dir( - GLib.UserDirectory.DIRECTORY_PICTURES - ); - - // Fallback to ~/Pictures - const homeDir = GLib.get_home_dir(); - - if (!this._receiveDir || this._receiveDir === homeDir) { - this._receiveDir = GLib.build_filenamev([homeDir, 'Pictures']); - this.settings.set_string('receive-directory', this._receiveDir); - } - } - - // Ensure the directory exists - if (!GLib.file_test(this._receiveDir, GLib.FileTest.IS_DIR)) - GLib.mkdir_with_parents(this._receiveDir, 448); - - return this._receiveDir; - } - - /** - * Get a GFile for @filename, while ensuring the directory exists and the - * file is unique. - * - * @param {string} filename - A filename (eg. `image.jpg`) - * @return {Gio.File} a file object - */ - _getFile(filename) { - const dirpath = this._ensureReceiveDirectory(); - const basepath = GLib.build_filenamev([dirpath, filename]); - let filepath = basepath; - let copyNum = 0; - - while (GLib.file_test(filepath, GLib.FileTest.EXISTS)) - filepath = `${basepath} (${++copyNum})`; - - return Gio.File.new_for_path(filepath); - } - - /** - * Receive a photo taken by the remote device. - * - * @param {Core.Packet} packet - a `kdeconnect.photo` - */ - async _receivePhoto(packet) { - let file, transfer; - - try { - // Remote device cancelled the photo operation - if (packet.body.hasOwnProperty('cancel')) - return; - - // Open the target path and create a transfer - file = this._getFile(packet.body.filename); - - transfer = this.device.createTransfer(); - transfer.addFile(packet, file); - - // Open the photo if successful, delete on failure - await transfer.start(); - - const uri = file.get_uri(); - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } catch (e) { - debug(e, this.device.name); - - if (file) - file.delete_async(GLib.PRIORITY_DEFAULT, null, null); - } - } - - /** - * Take a photo using the Webcam and return the path. - * - * @param {Core.Packet} packet - A `kdeconnect.photo.request` - * @return {Promise} A file path - */ - _takePhoto(packet) { - const time = GLib.DateTime.new_now_local().format('%T'); - const path = GLib.build_filenamev([GLib.get_tmp_dir(), `${time}.jpg`]); - const proc = this._launcher.spawnv([ - Config.FFMPEG_PATH, - '-f', 'video4linux2', - '-ss', '0:0:2', - '-i', '/dev/video0', - '-frames', '1', - path, - ]); - - return proc.wait_check_async(null); - } - - /** - * Send a photo to the remote device. - * - * @param {Core.Packet} packet - A `kdeconnect.photo.request` - */ - async _sendPhoto(packet) { - if (this.settings.get_boolean('share-camera')) - return; - - let file, transfer; - - try { - // Take a photo - const path = await this._takePhoto(); - - if (path.startsWith('file://')) - file = Gio.File.new_for_uri(path); - else - file = Gio.File.new_for_path(path); - - // Create the transfer - transfer = this.device.createTransfer(); - - transfer.addFile({ - type: 'kdeconnect.photo', - body: { - filename: file.get_basename(), - }, - }, file); - - await transfer.start(); - } catch (e) { - debug(e, this.device.name); - - if (transfer) { - this.device.showNotification({ - id: transfer.uuid, - title: _('Transfer Failed'), - // TRANSLATORS: eg. Failed to send "photo.jpg" to Google Pixel - body: _('Failed to send ā€œ%sā€ to %s').format( - file.get_basename(), - this.device.name - ), - icon: new Gio.ThemedIcon({name: 'dialog-warning-symbolic'}), - }); - } - } - } - - /** - * Request the remote device begin a photo operation. - */ - photo() { - this.device.sendPacket({ - type: 'kdeconnect.photo.request', - body: {}, - }); - } -});