100 lines
4.2 KiB
JavaScript
100 lines
4.2 KiB
JavaScript
import GObject from 'gi://GObject';
|
|
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
|
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
|
|
import * as QuickSettings from 'resource:///org/gnome/shell/ui/quickSettings.js';
|
|
export const BleUnlockMenuToggle = GObject.registerClass(class BleUnlockMenuToggle extends QuickSettings.QuickMenuToggle {
|
|
_settings;
|
|
_monitor;
|
|
_deviceItems = new Map();
|
|
_rssiItem = null;
|
|
_rssiChangedId = 0;
|
|
_devicesChangedId = 0;
|
|
_settingsChangedId = 0;
|
|
constructor(settings, monitor, openPreferences, extensionUuid) {
|
|
super({
|
|
title: 'BLE Unlock',
|
|
iconName: 'bluetooth-symbolic',
|
|
toggleMode: true,
|
|
});
|
|
this._settings = settings;
|
|
this._monitor = monitor;
|
|
this.menu.setHeader('bluetooth-symbolic', 'BLE Unlock');
|
|
this._rssiItem = new PopupMenu.PopupMenuItem('RSSI: —', { reactive: false });
|
|
this.menu.addMenuItem(this._rssiItem);
|
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this._buildDeviceList();
|
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
const settingsItem = this.menu.addAction('Settings', openPreferences);
|
|
// Hide the settings item when the screen is locked
|
|
settingsItem.visible = Main.sessionMode.allowSettings;
|
|
// Register in _settingsActions so it is hidden on the lock screen
|
|
this.menu._settingsActions[extensionUuid] = settingsItem;
|
|
this._settingsChangedId = this._settings.connect('changed::enabled', () => {
|
|
this.checked = this._settings.get_boolean('enabled');
|
|
});
|
|
this.checked = this._settings.get_boolean('enabled');
|
|
this.connect('clicked', () => {
|
|
this._settings.set_boolean('enabled', !this._settings.get_boolean('enabled'));
|
|
});
|
|
this._rssiChangedId = this._monitor.connect('rssi-changed', (_obj, rssi) => {
|
|
this._onRssiChanged(rssi);
|
|
});
|
|
this._devicesChangedId = this._monitor.connect('devices-changed', () => {
|
|
this._buildDeviceList();
|
|
});
|
|
}
|
|
_buildDeviceList() {
|
|
for (const [, item] of this._deviceItems) {
|
|
item.destroy();
|
|
}
|
|
this._deviceItems.clear();
|
|
const selectedAddress = this._settings.get_string('device-address');
|
|
for (const [address, name] of this._monitor.devices) {
|
|
const label = name ? `${name} (${address})` : address;
|
|
const item = new PopupMenu.PopupMenuItem(label);
|
|
item.setOrnament(address === selectedAddress
|
|
? PopupMenu.Ornament.CHECK
|
|
: PopupMenu.Ornament.NONE);
|
|
item.connect('activate', () => {
|
|
this._settings.set_string('device-address', address);
|
|
this._buildDeviceList();
|
|
});
|
|
this._deviceItems.set(address, item);
|
|
// Insert before the last separator and settings item
|
|
this.menu.addMenuItem(item, 2);
|
|
}
|
|
}
|
|
_onRssiChanged(rssi) {
|
|
const selectedAddress = this._settings.get_string('device-address');
|
|
const subtitle = rssi !== 0 ? `${selectedAddress} · ${rssi} dBm` : selectedAddress;
|
|
this.subtitle = subtitle;
|
|
if (this._rssiItem) {
|
|
this._rssiItem.label.text = rssi !== 0 ? `RSSI: ${rssi} dBm` : 'RSSI: —';
|
|
}
|
|
}
|
|
destroy() {
|
|
if (this._rssiChangedId)
|
|
this._monitor.disconnect(this._rssiChangedId);
|
|
if (this._devicesChangedId)
|
|
this._monitor.disconnect(this._devicesChangedId);
|
|
if (this._settingsChangedId)
|
|
this._settings.disconnect(this._settingsChangedId);
|
|
super.destroy();
|
|
}
|
|
});
|
|
export const BleUnlockIndicator = GObject.registerClass(class BleUnlockIndicator extends QuickSettings.SystemIndicator {
|
|
_toggle = null;
|
|
constructor(settings, monitor, openPreferences, extensionUuid) {
|
|
super();
|
|
this._toggle = new BleUnlockMenuToggle(settings, monitor, openPreferences, extensionUuid);
|
|
this.quickSettingsItems.push(this._toggle);
|
|
}
|
|
destroy() {
|
|
if (this._toggle) {
|
|
this._toggle.destroy();
|
|
this._toggle = null;
|
|
}
|
|
super.destroy();
|
|
}
|
|
});
|