/* GsConnect Proxy * * Copyright (C) 2021, 2025 Sundeep Mediratta (smedius@gmail.com) * Translation to javascript of python file with tweaks for DING * * Based on nautilus-gsconnect.py - * A Nautilus extension for sending files via GSConnect by Andy Holmes *fg * A great deal of credit and appreciation is owed to the indicator-kdeconnect * developers for the sister Python script 'kdeconnect-send-nautilus.py': * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import {Gio, GLib} from '../../dependencies/gi.js'; export {GsConnectSendFileOperationsManager}; var GsConnectSendFileOperationsManager = class { constructor(GsConnectManager, mainApp) { this._mainApp = mainApp; this.gsConnectDevices = {}; this.devices = {}; this.gsConnectServiceName = 'org.gnome.Shell.Extensions.GSConnect'; this.gsConnectServicePath = '/org/gnome/Shell/Extensions/GSConnect'; this.GsConnectManager = GsConnectManager; this.GsConnectManager.connect('changed-status', () => { GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => { this._startGsConnectService(); return false; }); }); this._startGsConnectService(); this._createSendAction(); } _startGsConnectService() { if (this.GsConnectManager.isAvailable) { this.gsConnectProxy = this.GsConnectManager.proxy; if (!this.gsConnectProxy) { this._stopService(); return; } this.signalID = this.gsConnectProxy.connect( 'g-signal', this._on_g_signal.bind(this) ); this._on_name_owner_changed(); } else { this._stopService(); } } _stopService() { this.gsConnectDevices = {}; this.devices = {}; if (this.signalID) { this.gsConnectProxy.disconnect(this.signalID); this.signalID = null; } } _on_g_signal(proxy, senderName, signalName, parameters) { // Wait until the service is ready if (!this.gsConnectProxy.get_name_owner()) return; let objects = parameters.recursiveUnpack(); if (signalName === 'InterfacesAdded') { for (let [objectPath, props] of Object.entries(objects)) { props = props['org.gnome.Shell.Extensions.GSConnect.Device']; if (!props) continue; let action = Gio.DBusActionGroup.get( this.gsConnectProxy.get_connection(), this.gsConnectServiceName, objectPath ); this.gsConnectDevices[objectPath] = [props['Name'], action]; } } else if (signalName === 'InterfacesRemoved') { for (const objectPath of Object.keys(objects)) { try { delete this.gsConnectDevices[objectPath]; } catch (e) {} } } this._update_devices(); } _on_name_owner_changed() { // Wait until the service is ready if (!this.gsConnectProxy.get_name_owner()) { this.gsConnectDevices = {}; } else { this.gsConnectProxy.call( 'GetManagedObjects', null, Gio.DBusCallFlags.NO_AUTO_START, -1, null, this._get_managed_objects.bind(this) ); } } _get_managed_objects(proxy, res) { let objects = this.gsConnectProxy.call_finish(res).recursiveUnpack()[0]; if (objects) { for (let [objectPath, props] of Object.entries(objects)) { props = props['org.gnome.Shell.Extensions.GSConnect.Device']; if (!Object.keys(props).length > 0) continue; let action = Gio.DBusActionGroup.get( this.gsConnectProxy.get_connection(), this.gsConnectServiceName, objectPath ); this.gsConnectDevices[objectPath] = [props['Name'], action]; } this._update_devices(); } } _createSendAction() { let sendfiles = new Gio.SimpleAction({ name: 'sendfiles', parameter_type: new GLib.VariantType('s'), }); sendfiles.connect('activate', (action, parameter) => { let device = parameter.recursiveUnpack(); this._send_files(device); }); this._mainApp.add_action(sendfiles); } _send_files(device) { // send files to shareFile action in actiongroup // for the devices actiongroup let actionGroup = this.devices[device]; for (let file of this.sendablefiles) { let variant = GLib.Variant.new('(sb)', [file.get_uri(), false]); actionGroup.activate_action('shareFile', variant); } } _update_devices() { this.devices = {}; for (let [name, actionGroup] of Object.values(this.gsConnectDevices)) { if (actionGroup.get_action_enabled('shareFile')) this.devices[name] = actionGroup; } } _get_devices() { // No capable devices if (!Object.keys(this.devices).length > 0) return null; else return true; } _sendable_file_items(files) { // Return a list of select files to be sent // Only accept regular files for (let f of files) { if (f.get_uri_scheme() !== 'file') return null; } return true; } create_gsconnect_menu(files) { this.sendablefiles = files.map(f => f.file); this._update_devices(); if ( this._sendable_file_items(this.sendablefiles) && this._get_devices() ) { this._menu = new Gio.Menu(); for (let device of Object.keys(this.devices)) { let menuitem = Gio.MenuItem.new(`${device}`, null); menuitem.set_action_and_target_value( 'app.sendfiles', GLib.Variant.new('s', `${device}`) ); this._menu.append_item(menuitem); } return this._menu; } else { return null; } } };