194 lines
4.8 KiB
JavaScript
194 lines
4.8 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const Gdk = imports.gi.Gdk;
|
||
|
const Gio = imports.gi.Gio;
|
||
|
const GLib = imports.gi.GLib;
|
||
|
const GObject = imports.gi.GObject;
|
||
|
const Gtk = imports.gi.Gtk;
|
||
|
|
||
|
const PluginsBase = imports.service.plugins.base;
|
||
|
|
||
|
|
||
|
var Metadata = {
|
||
|
label: _('Find My Phone'),
|
||
|
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.FindMyPhone',
|
||
|
incomingCapabilities: ['kdeconnect.findmyphone.request'],
|
||
|
outgoingCapabilities: ['kdeconnect.findmyphone.request'],
|
||
|
actions: {
|
||
|
ring: {
|
||
|
label: _('Ring'),
|
||
|
icon_name: 'phonelink-ring-symbolic',
|
||
|
|
||
|
parameter_type: null,
|
||
|
incoming: [],
|
||
|
outgoing: ['kdeconnect.findmyphone.request']
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* FindMyPhone Plugin
|
||
|
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/findmyphone
|
||
|
*
|
||
|
* TODO: cancel incoming requests on disconnect?
|
||
|
*/
|
||
|
var Plugin = GObject.registerClass({
|
||
|
GTypeName: 'GSConnectFindMyPhonePlugin',
|
||
|
}, class Plugin extends PluginsBase.Plugin {
|
||
|
|
||
|
_init(device) {
|
||
|
super._init(device, 'findmyphone');
|
||
|
}
|
||
|
|
||
|
handlePacket(packet) {
|
||
|
if (packet.type === 'kdeconnect.findmyphone.request') {
|
||
|
this._handleRequest();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handle an incoming location request.
|
||
|
*/
|
||
|
_handleRequest() {
|
||
|
try {
|
||
|
// If this is a second request, stop announcing and return
|
||
|
if (this._dialog) {
|
||
|
this._dialog.response(Gtk.ResponseType.DELETE_EVENT);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this._dialog = new Dialog(this.device.name);
|
||
|
this._dialog.connect('response', () => this._dialog = null);
|
||
|
} catch (e) {
|
||
|
this._cancelRequest();
|
||
|
logError(e, this.device.name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_cancelRequest() {
|
||
|
if (this._dialog) {
|
||
|
this._dialog.response(Gtk.ResponseType.DELETE_EVENT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Request the remote device announce it's location
|
||
|
*/
|
||
|
ring() {
|
||
|
this.device.sendPacket({
|
||
|
type: 'kdeconnect.findmyphone.request',
|
||
|
body: {}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
destroy() {
|
||
|
this._cancelRequest();
|
||
|
super.destroy();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 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/'
|
||
|
});
|
||
|
|
||
|
|
||
|
/**
|
||
|
* A custom GtkMessageDialog for alerting of incoming requests
|
||
|
*/
|
||
|
const Dialog = GObject.registerClass({
|
||
|
GTypeName: 'GSConnectFindMyPhoneDialog'
|
||
|
}, class Dialog extends Gtk.MessageDialog {
|
||
|
_init(name) {
|
||
|
super._init({
|
||
|
buttons: Gtk.ButtonsType.CLOSE,
|
||
|
image: new Gtk.Image({
|
||
|
icon_name: 'phonelink-ring-symbolic',
|
||
|
pixel_size: 512,
|
||
|
halign: Gtk.Align.CENTER,
|
||
|
hexpand: true,
|
||
|
valign: Gtk.Align.CENTER,
|
||
|
vexpand: true,
|
||
|
visible: true
|
||
|
}),
|
||
|
urgency_hint: true
|
||
|
});
|
||
|
|
||
|
this.set_keep_above(true);
|
||
|
this.maximize();
|
||
|
this.message_area.destroy();
|
||
|
|
||
|
// If the mixer is available start fading the volume up
|
||
|
let service = Gio.Application.get_default();
|
||
|
let mixer = service.components.get('pulseaudio');
|
||
|
|
||
|
if (mixer) {
|
||
|
this._stream = mixer.output;
|
||
|
|
||
|
this._previousMuted = this._stream.muted;
|
||
|
this._previousVolume = this._stream.volume;
|
||
|
|
||
|
this._stream.muted = false;
|
||
|
this._stream.fade(0.85, 15);
|
||
|
|
||
|
// Otherwise ensure audible-bell is enabled
|
||
|
} else {
|
||
|
this._previousBell = WM_SETTINGS.get_boolean('audible-bell');
|
||
|
WM_SETTINGS.set_boolean('audible-bell', true);
|
||
|
}
|
||
|
|
||
|
// Start the alarm
|
||
|
let sound = service.components.get('sound');
|
||
|
|
||
|
if (sound !== undefined) {
|
||
|
sound.loopSound('phone-incoming-call', this.cancellable);
|
||
|
}
|
||
|
|
||
|
// Show the dialog
|
||
|
this.show_all();
|
||
|
}
|
||
|
|
||
|
vfunc_key_press_event(event) {
|
||
|
this.response(Gtk.ResponseType.DELETE_EVENT);
|
||
|
|
||
|
return Gdk.EVENT_STOP;
|
||
|
}
|
||
|
|
||
|
vfunc_motion_notify_event(event) {
|
||
|
this.response(Gtk.ResponseType.DELETE_EVENT);
|
||
|
|
||
|
return Gdk.EVENT_STOP;
|
||
|
}
|
||
|
|
||
|
vfunc_response(response_id) {
|
||
|
// Stop the alarm
|
||
|
this.cancellable.cancel();
|
||
|
|
||
|
// Restore the mixer level
|
||
|
if (this._stream) {
|
||
|
this._stream.muted = this._previousMuted;
|
||
|
this._stream.fade(this._previousVolume);
|
||
|
|
||
|
// Restore the audible-bell
|
||
|
} else {
|
||
|
WM_SETTINGS.set_boolean('audible-bell', this._previousBell);
|
||
|
}
|
||
|
|
||
|
this.destroy();
|
||
|
}
|
||
|
|
||
|
get cancellable() {
|
||
|
if (this._cancellable === undefined) {
|
||
|
this._cancellable = new Gio.Cancellable();
|
||
|
}
|
||
|
|
||
|
return this._cancellable;
|
||
|
}
|
||
|
});
|
||
|
|