This commit is contained in:
davedatum
2019-10-26 23:53:38 +01:00
parent e7adc8779e
commit 2f34697860
417 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
<path style="fill:#bebebe" d="M 8 1 C 7.45 1 7 1.45 7 2 C 7 2.03 6.9998 2.0696 7.0098 2.0996 C 6.513 2.1994 6.0506 2.385 5.6191 2.6191 L 13 10 L 13 9 L 13 7 C 13 4.57 11.28 2.5596 8.9902 2.0996 C 9.0002 2.0696 9 2.03 9 2 C 9 1.45 8.55 1 8 1 z M 4.0078 4.0078 C 3.3813 4.8419 3 5.8717 3 7 L 3 11.5 L 1 13.5 L 1 14 L 3 14 L 13 14 L 14 14 L 4.0078 4.0078 z M 6.2695 15 C 6.6295 15.62 7.29 16 8 16 C 8.71 16 9.3705 15.62 9.7305 15 L 6.2695 15 z"/>
<path style="fill:#bebebe" d="M 2.5,1.5 15,14 13.5,15.5 1,3 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 596 B

View File

@@ -0,0 +1,84 @@
class Extension {
constructor(dnd, toggle, indicator, remote, audio){
this.dnd = dnd;
this.toggle = toggle;
this.indicator = indicator;
this.remote = remote;
this.audio = audio;
this.enabled = false;
this.toggle.setToggleState(this.dnd.isEnabled());
this.toggle.show();
this.toggle.onToggleStateChanged(() => {
if (this.toggle.getToggleState()){
this.enable();
} else {
this.disable();
}
});
// this.dndID = this.dnd.addStatusListener((dndEnabled) => this._setDND(dndEnabled));
this.remoteID = this.remote.addRemoteListener((dndEnabled) => this._setDND(dndEnabled));
this._setDND(this.remote.getRemote());
}
_setDND(enabled){
if (enabled){
this.enable();
} else {
this.disable();
}
}
/**
* Enable do not disturb mode
*/
enable(){
if (this.enabled){
return;
}
this.enabled = true;
this.dnd.enable();
this.toggle.setToggleState(true);
this.indicator.show();
this.remote.setRemote(true);
this.audio.mute();
}
/**
* Disable do not disturb mode
*/
disable(){
if (!this.enabled){
return;
}
this.enabled = false;
this.dnd.disable();
this.toggle.setToggleState(false);
this.indicator.hide();
this.remote.setRemote(false);
this.audio.unmute();
}
/**
* @return {Boolean} true if it is enabled, otherwise false
*/
isEnabled(){
return this.enabled;
}
/**
* Destroy the extension and its components
*/
destroy(){
this.enabled = false;
// this.dnd.removeStatusListener(this.dndID);
this.remote.removeRemoteListener(this.remoteID);
this.toggle.destroy();
this.indicator.destroy();
this.dnd.disable();
}
}

View File

@@ -0,0 +1,76 @@
const BUSY = 2;
const AVAILABLE = 0;
/**
* A class which can enable do not disturb mode
*/
class DoNotDisturb {
/**
* Constructor
* @param {Presence} presence the interface to the Gnome Presence API
*/
constructor(presence){
this.presence = presence;
this.listeners = [];
this.presenceListernerID = -1;
}
/**
* Enable do not disturb mode
*/
enable(){
this.presence.status = BUSY;
}
/**
* Disable do not disturb mode
*/
disable(){
this.presence.status = AVAILABLE;
}
/**
* @return {Boolean} true if do not disturb mode is on, otherwise false
*/
isEnabled(){
return this.presence.status == BUSY;
}
/**
* Add a status listener for when the do not disturb mode is toggled
* @param {[Boolean => ()]} listener the listener to add
* @return {Integer} the ID of the listener
*/
addStatusListener(listener){
if (listener == null){
return -1;
}
if (this.listeners.length == 0){
this.presenceListernerID = this.presence.addStatusListener((status) => {
this.listeners.forEach((fn) => {
fn(status == BUSY);
});
});
}
listener(this.isEnabled());
return this.listeners.push(listener) - 1;
}
/**
* Remove the status listener with the ID
* @param {Integer} id the ID of the status listener
*/
removeStatusListener(id){
if (id < 0 || id >= this.listeners.length){
return;
}
this.listeners.splice(id, 1);
if (this.listeners.length == 0) {
this.presence.removeStatusListener(this.presenceListernerID);
}
}
}

View File

@@ -0,0 +1,30 @@
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Settings = Me.imports.settings;
const System = Me.imports.system;
const Widget = Me.imports.widgets;
const DND = Me.imports.doNotDisturb;
const Extension = Me.imports.dndExtension.Extension;
/**
* Called when the extension is loaded.
*/
function init() {}
/**
* Enable the do not disturb extension. Adds all UI elements and monitors the settings object.
*/
function enable() {
var dnd = new DND.DoNotDisturb(new System.GnomePresence());
var toggle = new Widget.DoNotDisturbToggle();
var indicator = new Widget.DoNotDisturbIcon(new Settings.SettingsManager(), new System.NotificationManager());
var remote = new Settings.RemoteAPI();
var audio = new System.AudioManager(new Settings.SettingsManager());
this.extension = new Extension(dnd, toggle, indicator, remote, audio);
}
/**
* Disables the extension. Tears down all UI components.
*/
function disable() {
this.extension.destroy();
}

View File

@@ -0,0 +1,33 @@
/* From https://github.com/pop-os/gnome-shell-extension-pop-suspend-button */
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/**
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, either version 2 of the License, or
(at your option) any later version.
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 <http://www.gnu.org/licenses/>.
**/
const GLib = imports.gi.GLib;
const Gettext = imports.gettext;
const Config = imports.misc.config;
function initTranslations(extension) {
let localeDir = extension.dir.get_child('locale').get_path();
// Extension installed in .local
if (GLib.file_test(localeDir, GLib.FileTest.EXISTS)) {
Gettext.bindtextdomain('gnome-shell-extension-do-not-disturb', localeDir);
}
// Extension installed system-wide
else {
Gettext.bindtextdomain('gnome-shell-extension-do-not-disturb',
Config.LOCALEDIR);
}
}

View File

@@ -0,0 +1,46 @@
msgid ""
msgstr ""
"Project-Id-Version: Gnome-Shell-Extension Do Not Disturb\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-09 18:13+0200\n"
"PO-Revision-Date: 2018-10-14 07:30-0400\n"
"Last-Translator: \n"
"Language-Team: German <mike@barkmin.eu>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2\n"
#: prefs.js:31
msgid "Enabled Icon"
msgstr "Icon anzeigen"
#: prefs.js:31
msgid "Show an indicator icon when do not disturb is enabled."
msgstr "Zeige ein Icon, wenn nicht stören aktiviert ist."
#: prefs.js:38
msgid "Count"
msgstr "Anzahl"
#: prefs.js:39
msgid "Dot"
msgstr "Punkt"
#: prefs.js:40
msgid "Nothing"
msgstr "Nichts"
#: prefs.js:50
msgid "Mute Sounds"
msgstr "Audio stumm schalten"
#: prefs.js:50
msgid "Mutes all sound when do not disturb is enabled."
msgstr "Audio stumm schalten, wenn nicht stören aktiviert ist."
#: widgets.js:40
msgid "Do not disturb"
msgstr "Nicht stören"

View File

@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: Gnome-Shell-Extension Do Not Disturb\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-10-14 7:24+0200\n"
"PO-Revision-Date: 2018-10-14 07:30-0400\n"
"Language-Team: Spanish <kylecorry31@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2\n"
"Last-Translator: \n"
"Language: es\n"
#: widgets.js:39
msgid "Do not disturb"
msgstr "No interrumpir"

View File

@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: Gnome-Shell-Extension Do Not Disturb\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-10-14 7:24+0200\n"
"PO-Revision-Date: 2018-10-14 07:30-0400\n"
"Language-Team: French <kylecorry31@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2\n"
"Last-Translator: \n"
"Language: fr\n"
#: widgets.js:36
msgid "Do not disturb"
msgstr "Ne pas déranger"

View File

@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: Gnome-Shell-Extension Do Not Disturb\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-10-14 7:24+0200\n"
"PO-Revision-Date: 2018-10-14 07:30-0400\n"
"Language-Team: Portuguese <kylecorry31@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2\n"
"Last-Translator: \n"
"Language: pt\n"
#: widgets.js:39
msgid "Do not disturb"
msgstr "Não perturbe"

View File

@@ -0,0 +1,20 @@
{
"_generated": "Generated by SweetTooth, do not edit",
"description": "Activate or deactivate do not disturb mode",
"name": "Do Not Disturb",
"original-author": "kylecorry31@gmail.com",
"settings-schema": "org.gnome.shell.extensions.kylecorry31-do-not-disturb",
"shell-version": [
"3.18",
"3.20",
"3.22",
"3.24",
"3.26",
"3.28",
"3.30",
"3.32"
],
"url": "https://github.com/kylecorry31/gnome-shell-extension-do-not-disturb",
"uuid": "donotdisturb@kylecorry31.github.io",
"version": 12
}

View File

@@ -0,0 +1,109 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Adapted from lockkeys@vaina.lt and https://github.com/pop-os/gnome-shell-extension-pop-suspend-button
const Gtk = imports.gi.Gtk;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Gettext = imports.gettext.domain('gnome-shell-extension-do-not-disturb');
const _ = Gettext.gettext;
const Settings = Me.imports.settings;
const Lib = Me.imports.lib;
function init() {}
/**
* Builds the GTK widget which displays all of the application specific settings.
*
* @returns {Gtk.Box} - The frame to display.
*/
function buildPrefsWidget() {
let settings = new Settings.SettingsManager();
let frame = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
border_width: 10,
margin: 20,
spacing: 8
});
var box = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL
});
frame.add(createSwitch(settings.shouldShowIcon(), (b) => {settings.setShowIcon(b); if (b) { box.show(); } else { box.hide(); } }, _("Enabled Icon"), _("Show an indicator icon when do not disturb is enabled.")));
var indicatorLbl = new Gtk.Label({
label: "Notification Indicator",
xalign: 0
});
var showCountRadio = createRadioButton(settings.showCount, (b) => { settings.showCount = b }, _("Count"));
var showDotRadio = createRadioButton(settings.showDot, (b) => { settings.showDot = b }, _("Dot"), showCountRadio);
var showNothingRadio = createRadioButton(!(settings.showCount || settings.showDot), (b) => { }, _("Nothing"), showCountRadio);
box.pack_start(indicatorLbl, true, true, 0);
box.add(showCountRadio);
box.add(showDotRadio);
box.add(showNothingRadio);
frame.add(box);
frame.add(createSwitch(settings.shouldMuteSound(), (b) => settings.setShouldMuteSound(b), _("Mute Sounds"), _("Mutes all sound when do not disturb is enabled.")));
frame.show_all();
if (!settings.shouldShowIcon()){
box.hide();
}
return frame;
}
function createRadioButton(active, set, text, group){
var widget;
if (group){
widget = Gtk.RadioButton.new_with_label_from_widget(group, text);
widget.set_active(active);
} else {
widget = new Gtk.RadioButton({
active: active,
label: text
});
}
widget.connect('notify::active', function(switch_widget) {
set(switch_widget.active);
});
return widget;
}
/**
* Creates a switch setting.
*
* @param {boolean} active - The starting state of the switch.
* @param {(boolean) => ()} set - The setter function which is passed the value of the switch on state change.
* @param {string} text - The label of the widget.
* @param {string} tooltip - The description text to display on hover.
* @returns {Gtk.Box} - The widget containing the switch and label.
*/
function createSwitch(active, set, text, tooltip) {
let box = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL
});
let label = new Gtk.Label({
label: text,
xalign: 0,
tooltip_text: tooltip
});
let widget = new Gtk.Switch({
active: active
});
widget.connect('notify::active', function(switch_widget) {
set(switch_widget.active);
});
box.pack_start(label, true, true, 0);
box.add(widget);
return box;
}
Lib.initTranslations(Me);

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="org-gnome-shell-extensions-kylecorry31-do-not-disturb">
<schema path="/org/gnome/shell/extensions/kylecorry31-do-not-disturb/" id="org.gnome.shell.extensions.kylecorry31-do-not-disturb">
<key type="b" name="show-icon">
<default>true</default>
<summary>Show an indicator icon when do not disturb is enabled.</summary>
<description></description>
</key>
<key type="b" name="mute-sounds">
<default>false</default>
<summary>Mutes all sound when do not disturb is enabled.</summary>
<description></description>
</key>
<key type="b" name="show-dot">
<default>false</default>
<summary>Shows a dot next to the date when notifications arrive during do not disturb mode.</summary>
<description></description>
</key>
<key type="b" name="show-count">
<default>true</default>
<summary>Displays the number of notifications during do not disturb mode.</summary>
<description></description>
</key>
<key type="b" name="do-not-disturb">
<default>false</default>
<summary>Activate the do not disturb mode.</summary>
<description></description>
</key>
</schema>
</schemalist>

View File

@@ -0,0 +1,219 @@
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Me = imports.misc.extensionUtils.getCurrentExtension();
/**
* A class which handles all interactions with the settings.
*/
class SettingsManager {
/**
* Represents a settings repository, where settings can be modified and read.
* @constructor
*/
constructor() {
this.connections = [];
this._appSettings = _getSettings();
}
/**
* Enable or disable the icon in the system panel when do not disturb mode is enabled.
*
* @param {boolean} showIcon - True if the icon should be shown, false otherwise.
*/
setShowIcon(showIcon) {
this._appSettings.set_boolean('show-icon', showIcon);
}
/**
* Determines if the icon should be shown or not.
*
* @returns {boolean} - True if the icon should be shown when do not disturb is enabled, false otherwise.
*/
shouldShowIcon() {
return this._appSettings.get_boolean('show-icon');
}
/**
* Calls a function when the status of the show icon setting has changed.
*
* @param {() => ()} fn - The function to call when the show icon setting is changed.
*/
onShowIconChanged(fn) {
var id = this._appSettings.connect('changed::show-icon', fn);
this.connections.push(id);
}
/**
* Determines if the sound should be muted when do not disturb is enabled.
*
* @returns {boolean} - True if the sound should be muted when do not disturb is enabled, false otherwise.
*/
shouldMuteSound() {
return this._appSettings.get_boolean('mute-sounds');
}
/**
* Enable or disable the muting of sound when do not disturb mode is enabled.
*
* @param {boolean} muteSound - True if the sound should be muted when do not disturb is enabled, false otherwise.
*/
setShouldMuteSound(muteSound) {
this._appSettings.set_boolean('mute-sounds', muteSound);
}
/**
* Calls a function when the status of the mute sounds setting has changed.
*
* @param {() => ()} fn - The function to call when the mute sounds setting is changed.
*/
onMuteSoundChanged(fn) {
var id = this._appSettings.connect('changed::mute-sounds', fn);
this.connections.push(id);
}
/**
* Sets whether to show the count of notifications or not.
* @param {Boolean} newShowCount True if the notification count should be shown.
*/
set showCount(newShowCount){
this._appSettings.set_boolean('show-count', newShowCount);
}
/**
* Determines whether to show the notification count.
* @return {Boolean} True if the notification count should be shown.
*/
get showCount(){
return this._appSettings.get_boolean('show-count');
}
/**
* Calls a function when the status of the show count setting has changed.
*
* @param {() => ()} fn - The function to call when the show count setting is changed.
*/
onShowCountChanged(fn){
var id = this._appSettings.connect('changed::show-count', fn);
this.connections.push(id);
}
/**
* Sets whether to show an indicator of hidden notifications or not.
* @param {Boolean} newShowDot True if the notification dot should be shown.
*/
set showDot(newShowDot){
this._appSettings.set_boolean('show-dot', newShowDot);
}
/**
* Determines whether to show the notification dot.
* @return {Boolean} True if the notification dot should be shown.
*/
get showDot(){
return this._appSettings.get_boolean('show-dot');
}
/**
* Calls a function when the status of the show dot setting has changed.
*
* @param {() => ()} fn - The function to call when the show dot setting is changed.
*/
onShowDotChanged(fn){
var id = this._appSettings.connect('changed::show-dot', fn);
this.connections.push(id);
}
disconnectAll() {
this.connections.forEach((id) => {
this._appSettings.disconnect(id);
});
this.connections = [];
}
}
class RemoteAPI {
constructor() {
this._appSettings = _getSettings();
this.listeners = [];
this.id = this._appSettings.connect('changed::do-not-disturb', () => {
this.listeners.forEach((fn) => fn(this.getRemote()));
});
}
/**
* Calls a function when the status of the do not disturb setting has changed.
*
* @param {() => ()} listener - The function to call when the do not disturb setting is changed.
*/
addRemoteListener(listener) {
if (listener == null){
return -1;
}
if (this.listeners.length == 0){
this.id = this._appSettings.connect('changed::do-not-disturb', () => {
this.listeners.forEach((fn) => fn(this.getRemote()));
});
}
return this.listeners.push(listener) - 1;
}
removeRemoteListener(id) {
if (id < 0 || id >= this.listeners.length){
return;
}
this.listeners.splice(id, 1);
if (this.listeners.length == 0) {
this._appSettings.disconnect(this.id);
}
}
/**
* @return {Boolean} true if the external do not disturb is on, false otherwise
*/
getRemote() {
return this._appSettings.get_boolean('do-not-disturb');
}
/**
* @param {Boolean} dnd true if the external do not disturb should be on, false otherwise
*/
setRemote(dnd) {
this._appSettings.set_boolean('do-not-disturb', dnd);
}
}
/**
* A helper function to get the application specific settings. Adapted
* from the System76 Pop Suspend Button extension: https://github.com/pop-os/gnome-shell-extension-pop-suspend-button
*
* @returns {Gio.Settings} - The application specific settings object.
*/
function _getSettings() {
let schemaName = 'org.gnome.shell.extensions.kylecorry31-do-not-disturb';
let schemaDir = Me.dir.get_child('schemas').get_path();
// Extension installed in .local
if (GLib.file_test(schemaDir + '/gschemas.compiled', GLib.FileTest.EXISTS)) {
let schemaSource = Gio.SettingsSchemaSource.new_from_directory(schemaDir,
Gio.SettingsSchemaSource.get_default(),
false);
let schema = schemaSource.lookup(schemaName, false);
return new Gio.Settings({
settings_schema: schema
});
}
// Extension installed system-wide
else {
if (Gio.Settings.list_schemas().indexOf(schemaName) == -1)
throw "Schema \"%s\" not found.".format(schemaName);
return new Gio.Settings({
schema: schemaName
});
}
}

View File

@@ -0,0 +1,21 @@
.clear-button {
margin: 0 16px;
}
.do-not-disturb:active {
background-color: inherit !important;
}
.do-not-disturb-icon {
color: rgba(255, 255, 255, 0.6);
-st-icon-style: symbolic;
}
.hide-dot {
color: transparent;
width: 0;
}
.notification-count {
color: rgba(255, 255, 255, 0.6);
}

View File

@@ -0,0 +1,156 @@
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Main = imports.ui.main;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const GnomeSession = imports.misc.gnomeSession;
const Settings = Me.imports.settings;
/**
* A class for interacting with the Gnome Presence API.
*/
class GnomePresence {
/**
* Construct a new GnomePresence proxy.
*/
constructor() {
this._presence = new GnomeSession.Presence();
}
/**
* Set the status of GnomePresence.
* @param {number} newStatus A GnomeSession.PresenceStatus status constant to switch to.
*/
set status(newStatus) {
this._presence.SetStatusSync(newStatus);
}
/**
* Get the status of GnomePresence.
* @return {number} The current GnomeSession.PresenceStatus status.
*/
get status() {
return this._presence.status;
}
/**
* Add a listener to the GnomePresence status.
* @param {Function} fn The function to run when the status is changed (passed the current status).
* @return {number} The ID of the listener, used by removeStatusListener.
*/
addStatusListener(fn) {
return this._presence.connectSignal('StatusChanged', (proxy, _sender, [status]) => {
if (proxy.status != status) {
fn(status);
}
});
}
/**
* Remove a status listener to the GnomePresence status.
* @param {number} listenerID The ID of the listener to remove.
*/
removeStatusListener(listenerID) {
this._presence.disconnectSignal(listenerID);
}
}
/**
* A class for managing the audio on Gnome.
*/
class AudioManager {
constructor(settingsManager){
this._settings = settingsManager;
this.shouldMute = this._settings.shouldMuteSound();
this.muted = false;
this._settings.onMuteSoundChanged(() => {
var shouldMute = this._settings.shouldMuteSound();
if (this.muted && shouldMute){
this._internalMute();
} else if (this.muted && !shouldMute){
this._internalUnmute();
}
this.shouldMute = shouldMute;
});
}
_internalMute(){
_runCmd(["amixer", "-q", "-D", "pulse", "sset", "Master", "mute"]);
}
_internalUnmute(){
_runCmd(["amixer", "-q", "-D", "pulse", "sset", "Master", "unmute"]);
}
/**
* Mute the audio stream.
*/
mute() {
this.muted = true;
if (this.shouldMute){
this._internalMute();
}
}
/**
* Unmute the audio stream.
*/
unmute() {
this.muted = false;
if (this.shouldMute){
this._internalUnmute();
}
}
}
class NotificationManager {
constructor() {
}
/**
* Get the current number of notifications in the system tray.
* @return {number} The number of notifications.
*/
get notificationCount(){
var count = 0;
Main.messageTray.getSources().forEach(n => count += n.count);
return count;
}
/**
* Determines if there are any notifications.
* @return {Boolean} True if there are notifications, false otherwise
*/
get hasNotifications(){
return notificationCount() > 0;
}
/**
* Add a listener for when the notification count changes.
* @param {Function} fn The function to call when the notification count changes (passed the current notification count).
* @return {number array} The IDs of the listeners.
*/
addNotificationCountListener(fn){
var id1 = Main.messageTray.connect('source-added', () => fn(this.notificationCount));
var id2 = Main.messageTray.connect('source-removed', () => fn(this.notificationCount));
var id3 = Main.messageTray.connect('queue-changed', () => fn(this.notificationCount));
return [id1, id2, id3];
}
/**
* Remove a notification count listener.
* @param {number array} ids The ID of the listener to remove.
*/
removeNotificationCountListener(ids){
ids.forEach((id) => {
Main.messageTray.disconnect(id);
})
}
}
function _runCmd(cmd) {
GLib.spawn_sync(null, cmd, null, GLib.SpawnFlags.SEARCH_PATH, null);
}

View File

@@ -0,0 +1,236 @@
const Lang = imports.lang;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const St = imports.gi.St;
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extension-do-not-disturb');
const _ = Gettext.gettext;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Lib = Me.imports.lib;
/**
* A class which handles the UI of the do not disturb toggle.
*/
class DoNotDisturbToggle {
/**
* Represents a do not disturb toggle in the calendar/notification popup.
* @constructor
*/
constructor() {
this._connections = [];
}
/**
* Shows the do not disturb toggle in the calendar/notification popup.
*/
show() {
this._clearButton = Main.panel.statusArea.dateMenu._messageList._clearButton;
this._calendarBox = this._clearButton.get_parent();
this._clearBox = new St.BoxLayout({
vertical: false,
x_expand: true,
y_expand: false
});
this._disturbToggle = new PopupMenu.PopupSwitchMenuItem(_("Do not disturb"));
this._disturbToggle.actor.add_style_class_name('do-not-disturb');
this._disturbToggle.actor.set_x_expand(true);
this._disturbToggle.actor.track_hover = false;
this._disturbToggle.actor.set_x_align(Clutter.ActorAlign.START);
this._disturbToggle.actor.remove_child(this._disturbToggle.label);
this._disturbToggle.actor.add_child(this._disturbToggle.label);
this._disturbToggle.label.set_y_align(Clutter.ActorAlign.CENTER);
this._disturbToggle.actor.remove_child(this._disturbToggle._ornamentLabel);
this._clearBox.add_actor(this._disturbToggle.actor);
this._clearButton.reparent(this._clearBox);
this._clearButton.add_style_class_name('clear-button');
this._calendarBox.add_actor(this._clearBox);
}
/**
* Destroys all UI elements of the toggle and returns the clear button to its proper location.
*/
destroy() {
if (this._disturbToggle) {
this._connections.forEach((id) => {
this._disturbToggle.disconnect(id);
});
this._connections = [];
this._disturbToggle.destroy();
this._disturbToggle = 0;
}
if (this._clearButton) {
this._clearButton.reparent(this._calendarBox);
this._clearButton.remove_style_class_name('clear-button');
}
if (this._clearBox) {
this._clearBox.destroy();
this._clearBox = 0;
}
}
/**
* Sets the activation state of the toggle.
*
* @param {boolean} state - The state of the toggle: true for on, false for off.
*/
setToggleState(state) {
if (this._disturbToggle) {
this._disturbToggle.setToggleState(state);
}
}
/**
* Get the activation state of the toggle.
*
* @returns {boolean} - True if the toggle is on, false otherwise.
*/
getToggleState() {
if (this._disturbToggle) {
return this._disturbToggle._switch.state;
}
return false;
}
/**
* Calls a function when the toggle state changes.
*
* @param {() => ()} fn - The function to call when the toggle state changes.
*/
onToggleStateChanged(fn) {
if (this._disturbToggle) {
var id = this._disturbToggle.connect("toggled", (item, event) => fn());
this._connections.push(id);
}
}
}
/**
* A class which handles the UI of the do not disturb status icon.
*/
class DoNotDisturbIcon {
/**
* Represents a do not disturb icon in the system status area of the panel.
* @constructor
*/
constructor(settingsManager, notificationCounter) {
this._settings = settingsManager;
this.notificationCounter = notificationCounter;
this._indicatorArea = Main.panel._centerBox; //statusArea.aggregateMenu._indicators;
let icon = "notification-disabled-symbolic";
let fallback = "user-busy-symbolic";
this._enabledIcon = new St.Icon({
icon_name: icon,
fallback_icon_name: fallback,
style_class: 'popup-menu-icon do-not-disturb-icon'
});
this._countLbl = new St.Label();
this.updateCount(0);
this._countLbl.add_style_class_name("notification-count");
this._iconBox = new St.BoxLayout();
this._iconBox.add_actor(this._enabledIcon);
this._iconBox.add_actor(this._countLbl);
this.showDot = this._settings.showDot;
this.showCount = this._settings.showCount;
this.showIcon = this._settings.shouldShowIcon();
this.shown = false;
this.count = this.notificationCounter.notificationCount;
this.updateCount(this.count);
this._settings.onShowIconChanged(() => {
this.showIcon = this._settings.shouldShowIcon();
if (this.shown){
this.hide();
this.show();
}
});
this._settings.onShowCountChanged(() => {
this.showCount = this._settings.showCount;
this.updateCount(this.count);
});
this._settings.onShowDotChanged(() => {
this.showDot = this._settings.showDot;
this.updateCount(this.count);
});
this.notificationListenerID = this.notificationCounter.addNotificationCountListener((count) => {
this.updateCount(count);
});
}
updateCount(newCount){
this.count = newCount;
if (newCount == 0){
this._countLbl.add_style_class_name("hide-dot");
} else {
if (this.showCount){
this._countLbl.set_text("" + newCount);
this._countLbl.remove_style_class_name("hide-dot");
} else if(this.showDot){
this._countLbl.set_text("\u25CF");
this._countLbl.remove_style_class_name("hide-dot");
} else {
this._countLbl.add_style_class_name("hide-dot");
}
}
}
/**
* Shows the status icon.
*/
show() {
if (this.showIcon){
this._indicatorArea.add_child(this._iconBox);
Main.panel.statusArea.dateMenu._indicator.actor.add_style_class_name("hide-dot");
}
this.shown = true;
}
/**
* Hides the status icon.
*/
hide() {
Main.panel.statusArea.dateMenu._indicator.actor.remove_style_class_name("hide-dot");
if (this._iconBox.get_parent()) {
this._indicatorArea.remove_child(this._iconBox);
}
this.shown = false;
}
/**
* Destroys the status icon and removes it from the system status area.
*/
destroy() {
if (this._enabledIcon) {
if (this._iconBox.get_parent()) {
this._indicatorArea.remove_child(this._iconBox);
}
this._countLbl.destroy();
this._countLbl = 0;
this._enabledIcon.destroy();
this._enabledIcon = 0;
this._iconBox.destroy();
this._iconBox = 0;
}
this._settings.disconnectAll();
this.notificationCounter.removeNotificationCountListener(this.notificationListenerID);
}
}
Lib.initTranslations(Me);