[gnome] Update extensions

This commit is contained in:
2024-10-31 10:19:02 -04:00
parent 851ec4a772
commit 6d1e6d1132
238 changed files with 8705 additions and 4185 deletions

View File

@ -29,7 +29,7 @@ other: Other
## [v3] - 2022-02-05
### Added
- Add alernatives thresholds paths.
- Add alternatives thresholds paths.
- Add available flag and the _init code is restructured according to this addition... Now the submenu is shown even if the thresholds are not available.
### Fixed
- Fix _available function. The test whether the files exist points to the start file twice!
@ -240,7 +240,7 @@ other: Other
## [v36] - 2023-10-10
### Fixed
- Remove "this" in prefs.js (Thanks Just Perfection)
- Remove "run_dispose()" in driver.js and inicator.js (Thanks Just Perfection)
- Remove "run_dispose()" in driver.js and indicator.js (Thanks Just Perfection)
## [v37] - 2023-10-13
### Performance
@ -275,4 +275,28 @@ other: Other
## [v44] - 2024-03-20
### Added
- Gnome 46 support
- Gnome 46 support
## [v45] - 2024-05-18
### Fixed
- Issue [#20](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/20): On some models the start threshold 0 is not allowed, instead 95 is used (Ex: P14s Gen 2a)
## [v46] - 2024-08-02
### Added
- Automatic detection of start threshold value disabled
- Show a notification and different indicator if the current thresholds are not set (suggestion #21)
- Gnome 47 support
## [v47] - 2024-08-03
### Fixed
- Issue [#23](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/23): Indicator mode NEVER does not work
## [v48] - 2024-08-07
### Other
- Update translations
## [v49] - 2024-08-08
### Fixed
- Issue [#24](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/24): The "NEVER" indicator mode does not work properly
### Changed
- "Automatic threshold detection disabled" is not convenient (no way to know the status before it is disabled for the first time), we returns to "model detection mode" and keeps "manual mode" (user settings)

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16px"
viewBox="0 0 16 16"
width="16px"
version="1.1"
id="svg4"
sodipodi:docname="threshold-active-warning-symbolic.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="21.152521"
inkscape:cx="8.7460024"
inkscape:cy="6.1222017"
inkscape:window-width="1366"
inkscape:window-height="699"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"
inkscape:showpageshadow="0"
inkscape:deskcolor="#505050" />
<path
d="M 7,0 C 6,0 6,1 6,1 V 2 H 5 C 5,2 4.292969,1.984375 3.550781,2.355469 2.8125,2.726562 2,3.667969 2,5 v 8 C 2,13 1.984375,13.707031 2.355469,14.445312 2.726562,15.1875 3.667969,16 5,16 h 6 c 0,0 0.707031,0.01563 1.449219,-0.355469 C 13.1875,15.273438 14,14.332031 14,13 V 5 C 14,3.667969 13.1875,2.726562 12.449219,2.355469 11.707031,1.984375 11,2 11,2 H 10 V 1 C 10,0 9,0 9,0 Z m 4,4 c 0.554688,0 1,0.445312 1,1 v 8 c 0,0.554688 -0.445312,1 -1,1 H 5 C 4.445312,14 4,13.554688 4,13 V 5 C 4,4.445312 4.445312,4 5,4 Z"
fill="#2e3434"
id="path2"
style="fill:#2e3436;fill-opacity:1"
sodipodi:nodetypes="sccccsccsccsscccscssssssssss" />
<path
d="M 11.5,7.6665023 A 1.8814995,1.8814995 0 0 0 9.6150005,5.7880035 c -0.6849999,0 -1.2850011,0.3649993 -1.6150015,0.910999 A 1.8849995,1.8849995 0 0 0 6.384997,5.7880035 1.8814995,1.8814995 0 0 0 4.5000003,7.6665023 1.8699996,1.8699996 0 0 0 5.095,9.0355003 H 5.0944993 L 7.9570006,11.783506 10.906,9.0355003 h -0.0012 a 1.8695001,1.8695001 0 0 0 0.595,-1.368998"
fill="#474747"
id="path2-6"
style="fill:#2e3436;fill-opacity:1;stroke-width:0.499998" />
<path
d="m 11.9913,8.5468749 c -0.263672,-0.013672 -0.519531,0.140625 -0.71875,0.484375 L 8.1475498,14.828125 C 7.8799718,15.310547 8.1709868,16 8.6944248,16 H 15.27255 c 0.490234,0 0.951172,-0.580078 0.609375,-1.171875 L 12.725675,9.0624999 C 12.526456,8.7402344 12.254972,8.5605469 11.9913,8.5468749 Z M 12.538175,10.5 V 13 c 0.0039,0.263672 -0.236328,0.5 -0.5,0.5 -0.263672,0 -0.503906,-0.236328 -0.5,-0.5 v -2.5 z m -0.5,3.5 c 0.27539,0 0.5,0.224609 0.5,0.5 0,0.27539 -0.22461,0.5 -0.5,0.5 -0.275391,0 -0.5,-0.22461 -0.5,-0.5 0,-0.275391 0.224609,-0.5 0.5,-0.5 z m 0,0"
fill="#2e3436"
id="path1"
class="warning"
style="fill:#ff7800;fill-opacity:1;stroke-width:0.5" />
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16px"
viewBox="0 0 16 16"
width="16px"
version="1.1"
id="svg4"
sodipodi:docname="threshold-active-warning.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="21.152521"
inkscape:cx="8.7460024"
inkscape:cy="6.1222017"
inkscape:window-width="1366"
inkscape:window-height="699"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"
inkscape:showpageshadow="0"
inkscape:deskcolor="#505050" />
<path
d="M 7,0 C 6,0 6,1 6,1 V 2 H 5 C 5,2 4.292969,1.984375 3.550781,2.355469 2.8125,2.726562 2,3.667969 2,5 v 8 C 2,13 1.984375,13.707031 2.355469,14.445312 2.726562,15.1875 3.667969,16 5,16 h 6 c 0,0 0.707031,0.01563 1.449219,-0.355469 C 13.1875,15.273438 14,14.332031 14,13 V 5 C 14,3.667969 13.1875,2.726562 12.449219,2.355469 11.707031,1.984375 11,2 11,2 H 10 V 1 C 10,0 9,0 9,0 Z m 4,4 c 0.554688,0 1,0.445312 1,1 v 8 c 0,0.554688 -0.445312,1 -1,1 H 5 C 4.445312,14 4,13.554688 4,13 V 5 C 4,4.445312 4.445312,4 5,4 Z"
fill="#2e3434"
id="path2"
style="fill:#33d17a;fill-opacity:1"
sodipodi:nodetypes="sccccsccsccsscccscssssssssss" />
<path
d="M 11.5,7.6665023 A 1.8814995,1.8814995 0 0 0 9.6150005,5.7880035 c -0.6849999,0 -1.2850011,0.3649993 -1.6150015,0.910999 A 1.8849995,1.8849995 0 0 0 6.384997,5.7880035 1.8814995,1.8814995 0 0 0 4.5000003,7.6665023 1.8699996,1.8699996 0 0 0 5.095,9.0355003 H 5.0944993 L 7.9570006,11.783506 10.906,9.0355003 h -0.0012 a 1.8695001,1.8695001 0 0 0 0.595,-1.368998"
fill="#474747"
id="path2-6"
style="fill:#33d17a;fill-opacity:1;stroke-width:0.499998" />
<path
d="m 11.9913,8.5468749 c -0.263672,-0.013672 -0.519531,0.140625 -0.71875,0.484375 L 8.1475498,14.828125 C 7.8799718,15.310547 8.1709868,16 8.6944248,16 H 15.27255 c 0.490234,0 0.951172,-0.580078 0.609375,-1.171875 L 12.725675,9.0624999 C 12.526456,8.7402344 12.254972,8.5605469 11.9913,8.5468749 Z M 12.538175,10.5 V 13 c 0.0039,0.263672 -0.236328,0.5 -0.5,0.5 -0.263672,0 -0.503906,-0.236328 -0.5,-0.5 v -2.5 z m -0.5,3.5 c 0.27539,0 0.5,0.224609 0.5,0.5 0,0.27539 -0.22461,0.5 -0.5,0.5 -0.275391,0 -0.5,-0.22461 -0.5,-0.5 0,-0.275391 0.224609,-0.5 0.5,-0.5 z m 0,0"
fill="#2e3436"
id="path1"
style="fill:#ff7800;fill-opacity:1;stroke-width:0.5" />
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -11,6 +11,14 @@ import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gio from 'gi://Gio';
/*
* On some models the start threshold 0 is not allowed, instead 95 is used (Ex: E14 Gen 3)
* See issues:
* #8: https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/8
* #20: https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/20
*/
const ALTERNATIVE_DISABLED_START = /(Think[pP]ad) (E14 Gen 3|P14s Gen 2a)/;
// Driver constants
const BASE_PATH = '/sys/class/power_supply';
const START_FILE_OLD = 'charge_start_threshold'; // kernel 4.17 and newer
@ -24,7 +32,7 @@ const END_FILE_NEW = 'charge_control_end_threshold'; // kernel 5.9 and newer
* @param {string} path Path of file
* @returns {string} File contents
*/
const readFile = function(path) {
const readFile = function (path) {
try {
const f = Gio.File.new_for_path(path);
const [, contents,] = f.load_contents(null);
@ -41,7 +49,7 @@ const readFile = function(path) {
* @param {string} path Path of file
* @returns {number|null} Return a integer or null
*/
const readFileInt = function(path) {
const readFileInt = function (path) {
try {
const v = readFile(path);
if (v) {
@ -52,15 +60,15 @@ const readFileInt = function(path) {
} catch (e) {
return null;
}
}
}
/**
* Test file/direcory exists
* Test file/directory exists
*
* @param {string} path File/directory path
* @returns {boolean}
*/
const fileExists = function(path) {
const fileExists = function (path) {
try {
const f = Gio.File.new_for_path(path);
return f.query_exists(null);
@ -79,7 +87,7 @@ const Environment = GObject.registerClass({
get productVersion() {
if (this._productVersion === undefined) {
const tmp = readFile('/sys/class/dmi/id/product_version');
if (tmp) {
if (tmp) {
// Remove non-alphanumeric characters
const sanitize = /([^ A-Za-z0-9])+/g;
this._productVersion = tmp.replace(sanitize, '');
@ -109,23 +117,23 @@ const Environment = GObject.registerClass({
get kernelMajorVersion() {
if (this._kernelMajorVersion === undefined) {
[this._kernelMajorVersion , this._kernelMinorVersion] = this.kernelRelease.split('.', 2);
[this._kernelMajorVersion, this._kernelMinorVersion] = this.kernelRelease.split('.', 2);
}
return this._kernelMajorVersion;
}
get kernelMinorVersion() {
if (this._kernelMinorVersion === undefined) {
[this._kernelMajorVersion , this._kernelMinorVersion] = this.kernelRelease.split('.', 2);
[this._kernelMajorVersion, this._kernelMinorVersion] = this.kernelRelease.split('.', 2);
}
return this._kernelMinorVersion;
}
checkMinKernelVersion(major, minor) {
return (
this.kernelMajorVersion > major ||
(this,this.kernelMajorVersion === major && this.kernelMinorVersion >= minor)
);
this.kernelMajorVersion > major ||
(this.kernelMajorVersion === major && this.kernelMinorVersion >= minor)
);
}
});
@ -140,7 +148,7 @@ const Runnable = GObject.registerClass({
GTypeName: 'Runnable',
Signals: {
'command-completed': {
param_types: [GObject.TYPE_JSOBJECT /* erro */]
param_types: [GObject.TYPE_JSOBJECT /* error */]
}
}
}, class Runnable extends GObject.Object {
@ -167,8 +175,8 @@ const Runnable = GObject.registerClass({
try {
GLib.spawn_check_exit_status(status);
this.emit('command-completed', null);
} catch(e) {
if (e.code == 126) {
} catch (e) {
if (e.code == 126) {
// Cancelled
} else {
logError(e);
@ -272,13 +280,6 @@ export const ThinkPadBattery = GObject.registerClass({
throw Error('Battery name not defined');
}
// Signals handlers IDs
this._monitorId = null;
this._settingStartId = null;
this._settingEndId = null;
this._startId = null;
this._endId = null;
// Battery directory
this._baseDirectoryPath = `${BASE_PATH}/${this.name}`;
this._baseDirectory = Gio.File.new_for_path(this._baseDirectoryPath);
@ -334,28 +335,29 @@ export const ThinkPadBattery = GObject.registerClass({
// Update flags on changes in threshold values
this._startId = this.connect(
'notify::start-value', () => {
this.isActive = this._checkActive();
this.isAvailable = this.startValue !== null || this.endValue !== null;
this.pendingChanges = this._checkPendingChanges();
this._updateStatuses();
}
);
this._endId = this.connect(
'notify::end-value', () => {
this.isActive = this._checkActive();
this.isAvailable = this.startValue !== null || this.endValue !== null;
this.pendingChanges = this._checkPendingChanges();
this._updateStatuses();
}
);
// Update pending changes flag on changes to setting values
this._settingStartId = this.settings.connect(
`changed::start-${this.name.toLowerCase()}`, () => {
this.pendingChanges = this._checkPendingChanges();
this._updateStatuses();
}
);
this._settingEndId = this.settings.connect(
`changed::end-${this.name.toLowerCase()}`, () => {
this.pendingChanges = this._checkPendingChanges();
this._updateStatuses();
}
);
this._settingDisabledValueId = this.settings.connect(
`changed::disabled-start-${this.name.toLowerCase()}-value`, () => {
this._updateStatuses();
}
);
@ -366,33 +368,34 @@ export const ThinkPadBattery = GObject.registerClass({
}
/**
* Check if thresholds is active
*
* @returns {boolean} Returns true if the battery has active thresholds
* Update the statuses
*/
_checkActive() {
// RegExs
/* On some models the start threshold 0 is not allowed, instead 95 is used (Ex: E14 Gen 3)
* See issue #8: https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/8
*/
const disableStart95 = /(Think[pP]ad) (E14 Gen 3)/;
_updateStatuses() {
// Check if is available
this.isAvailable = this.startValue !== null || this.endValue !== null;
if (this.environment.productVersion.search(disableStart95) >= 0) {
return (this.startValue !== 95 && this.startValue !== null) || (this.endValue !== 100 && this.endValue !== null);
// Check if thresholds is active
const disabledStartValue = this.settings.get_int(`disabled-start-${this.name.toLowerCase()}-value`);
if (disabledStartValue === -1) {
// Use model detection
if (this.environment.productVersion.search(ALTERNATIVE_DISABLED_START) >= 0) {
this.isActive = (this.startValue !== null && this.startValue !== 95) || (this.endValue !== null && this.endValue !== 100);
} else {
this.isActive = (this.startValue !== null && this.startValue !== 0) || (this.endValue !== null && this.endValue !== 100);
}
} else {
return (this.startValue !== 0 && this.startValue !== null) || (this.endValue !== 100 && this.endValue !== null);
// Use user settings
this.isActive = (this.startValue !== null && this.startValue !== disabledStartValue) || (this.endValue !== null && this.endValue !== 100);
}
}
/**
* Check if there are changes to the settings that need to be applied
*
* @returns {boolean} Returns true if there are changes to the settings that need to be applied
*/
_checkPendingChanges() {
const startSetting = this.settings.get_int(`start-${this.name.toLowerCase()}`);
const endSetting = this.settings.get_int(`end-${this.name.toLowerCase()}`);
return ((this.startValue != null && this.startValue !== startSetting) || (this.endValue != null && this.endValue !== endSetting));
if (this.isActive) {
this.pendingChanges = (this.startValue !== null && this.startValue !== startSetting) || (this.endValue !== null && this.endValue !== endSetting);
} else {
this.pendingChanges = false;
}
}
/**
@ -419,7 +422,7 @@ export const ThinkPadBattery = GObject.registerClass({
}
} catch (e) {
// Ignored
}
}
return false;
}
@ -446,12 +449,12 @@ export const ThinkPadBattery = GObject.registerClass({
}
get isAvailable() {
return this._isAvaialble;
return this._isAvailable;
}
set isAvailable(value) {
if (this.isAvailable !== value) {
this._isAvaialble = value;
this._isAvailable = value;
this.notify('is-available');
}
}
@ -627,6 +630,9 @@ export const ThinkPadBattery = GObject.registerClass({
if (this._settingEndId) {
this.settings.disconnect(this._settingEndId);
}
if (this._settingDisabledValueId) {
this.settings.disconnect(this._settingDisabledValueId);
}
if (this._monitorId) {
this._baseMonitor.disconnect(this._monitorId);
}
@ -660,6 +666,13 @@ export const ThinkPad = GObject.registerClass({
GObject.ParamFlags.READABLE,
false
),
'pending-changes': GObject.ParamSpec.boolean(
'pending-changes',
'Pending changes',
'Indicates if the current values do not match the configured values',
GObject.ParamFlags.READABLE,
false
),
'batteries': GObject.ParamSpec.jsobject(
'batteries',
'Batteries',
@ -706,12 +719,12 @@ export const ThinkPad = GObject.registerClass({
this.batteries = [
new ThinkPadBattery({
'environment': this.environment,
'name': 'BAT0',
'name': 'BAT0',
'settings': this.settings
}),
new ThinkPadBattery({
'environment': this.environment,
'name': 'BAT1',
'name': 'BAT1',
'settings': this.settings
}),
];
@ -728,6 +741,11 @@ export const ThinkPad = GObject.registerClass({
this.isActive = this._checkActive();
}
);
const pendingChangesId = battery.connect(
'notify::pending-changes', (bat) => {
this.pendingChanges = this._checkPendingChanges();
}
);
const enableCompletedId = battery.connect(
'enable-completed', (bat, error) => {
this.emit('enable-battery-completed', bat, error);
@ -744,6 +762,7 @@ export const ThinkPad = GObject.registerClass({
// Load initial values
this.isAvailable = this._checkAvailable();
this.isActive = this._checkActive();
this.pendingChanges = this._checkPendingChanges();
}
get environment() {
@ -754,12 +773,12 @@ export const ThinkPad = GObject.registerClass({
}
get isAvailable() {
return this._isAvaialble;
return this._isAvailable;
}
set isAvailable(value) {
if (this.isAvailable !== value) {
this._isAvaialble = value;
this._isAvailable = value;
this.notify('is-available');
}
}
@ -775,6 +794,28 @@ export const ThinkPad = GObject.registerClass({
}
}
get pendingChanges() {
return this._pendingChanges;
}
set pendingChanges(value) {
if (this.pendingChanges !== value) {
this._pendingChanges = value;
this.notify('pending-changes');
}
}
/**
* Check if there are changes to the settings that need to be applied
*
* @returns {boolean} Returns true if there are changes to the settings that need to be applied
*/
_checkPendingChanges() {
return this.batteries.some(bat => {
return bat.pendingChanges;
});
}
/**
* Check if at least one battery has the thresholds active
*
@ -817,7 +858,7 @@ export const ThinkPad = GObject.registerClass({
runnable.connect('command-completed', (obj, error) => {
this.emit('enable-all-completed', error);
})
runnable.run();
runnable.run();
}
/**
@ -840,7 +881,7 @@ export const ThinkPad = GObject.registerClass({
runnable.connect('command-completed', (obj, error) => {
this.emit('disable-all-completed', error);
})
runnable.run();
runnable.run();
}
destroy() {

View File

@ -37,9 +37,6 @@ const BatteryItem = GObject.registerClass({
this._settings = settings;
this._battery = battery;
// Flag to prevent the PopupImageMenuItem from being activated when the reload icon is clicked
this._reloading = false;
const box = new St.BoxLayout({
'opacity': 128,
@ -58,9 +55,8 @@ const BatteryItem = GObject.registerClass({
});
this._reload.connectObject(
'button-press-event', () => {
this._reloading = true;
this._battery.enable();
return true; // Does not prevent event propagation???
return true;
},
this
);
@ -91,10 +87,7 @@ const BatteryItem = GObject.registerClass({
// Menu item action
this.connectObject(
'activate', () => {
if (!this._reloading) {
this._battery.toggle();
}
this._reloading = false;
this._battery.toggle();
},
'destroy', () => {
this._settings.disconnectObject(this);
@ -123,7 +116,11 @@ const BatteryItem = GObject.registerClass({
if (this._battery.isActive) {
// TRANSLATORS: %s is the name of the battery.
this.label.text = _('Disable thresholds (%s)').format(this._battery.name);
this.setIcon(getIcon('threshold-active', colorMode));
if (this._battery.pendingChanges) {
this.setIcon(getIcon('threshold-active-warning', colorMode));
} else {
this.setIcon(getIcon('threshold-active', colorMode));
}
// Status text
const showCurrentValues = this._settings.get_boolean('show-current-values');
if (showCurrentValues) {
@ -249,6 +246,9 @@ export const ThresholdIndicator = GObject.registerClass({
'notify::is-active', () => {
this._updateIndicator();
},
'notify::pending-changes', () => {
this._updateIndicator();
},
'enable-battery-completed', (driver, battery, error) => {
if (!error) {
this._notifyEnabled(
@ -330,6 +330,15 @@ export const ThresholdIndicator = GObject.registerClass({
this._driver = null;
this._extension = null;
});
// Pending changes alert
this._driver.batteries.every(battery => {
if (battery.pendingChanges && battery.isActive) {
this._notify(_('Battery Threshold'), _('The currently set thresholds do not match the configured ones'), 'threshold-active-warning', false);
return false;
}
return true;
});
}
/**
@ -339,7 +348,11 @@ export const ThresholdIndicator = GObject.registerClass({
const colorMode = this._settings.get_boolean('color-mode');
if (this._driver.isAvailable) {
if (this._driver.isActive) {
this._indicator.gicon = getIcon('threshold-active', colorMode);
if (this._driver.pendingChanges) {
this._indicator.gicon = getIcon('threshold-active-warning', colorMode);
} else {
this._indicator.gicon = getIcon('threshold-active', colorMode);
}
} else {
this._indicator.gicon = getIcon('threshold-inactive', colorMode);
}
@ -352,14 +365,14 @@ export const ThresholdIndicator = GObject.registerClass({
case 0: // Active
this._indicator.visible = this._driver.isActive;
break;
case 1: // Inactive
this._indicator.visible = !this._driver.isActive;
case 1: // Inactive (or pending changes)
this._indicator.visible = !this._driver.isActive || this._driver.pendingChanges;
break;
case 2: // Always
this._indicator.visible = true;
break;
case 3: // Never
this._indicator.visible = false;
case 3: // Never (or pending changes)
this._indicator.visible = this._driver.pendingChanges;
break;
default:
this._indicator.visible = true;
@ -368,15 +381,15 @@ export const ThresholdIndicator = GObject.registerClass({
}
/**
* Show notificaion.
* Show notification.
*
* @param {string} msg Title
* @param {string} details Message
* @param {string} iconName Icon name
* @param {boolean} [transient=true] Transient notification
*/
_notify(msg, details, iconName) {
_notify(msg, details, iconName, transient=true) {
if (!this._settings.get_boolean('show-notifications')) return;
const colorMode = this._settings.get_boolean('color-mode');
if (SHELL_VERSION === 45) {
const source = new MessageTray.Source(this._name);
Main.messageTray.add(source);
@ -384,9 +397,9 @@ export const ThresholdIndicator = GObject.registerClass({
source,
msg,
details,
{gicon: getIcon(iconName, colorMode)}
{gicon: getIcon(iconName, true)}
);
notification.setTransient(true);
notification.setTransient(transient);
source.showNotification(notification);
} else {
const source = new MessageTray.Source({'title': this._name});
@ -395,8 +408,8 @@ export const ThresholdIndicator = GObject.registerClass({
source: source,
title: msg,
body: details,
isTransient: true,
gicon: getIcon(iconName, colorMode)
isTransient: transient,
gicon: getIcon(iconName, true)
});
source.addNotification(notification);
}
@ -408,7 +421,7 @@ export const ThresholdIndicator = GObject.registerClass({
* @param {string} message Message
*/
_notifyError(message) {
this._notify(_('Battery Threshold'), message, 'threshold-error');
this._notify(_('Battery Threshold'), message, 'threshold-error', false);
}
/**

View File

@ -6,9 +6,10 @@
"settings-schema": "org.gnome.shell.extensions.thinkpad-battery-threshold",
"shell-version": [
"45",
"46"
"46",
"47"
],
"url": "https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension",
"uuid": "thinkpad-battery-threshold@marcosdalvarez.org",
"version": 44
"version": 49
}

View File

@ -7,6 +7,14 @@ import Gio from 'gi://Gio';
import Gtk from 'gi://Gtk';
import Gdk from 'gi://Gdk';
// Links
const URLS = {
readme: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/',
bug_report: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues',
license: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/blob/main/LICENSE',
translate: 'https://hosted.weblate.org/engage/thinkpad-battery-threshold/',
};
export const About = GObject.registerClass({
GTypeName: 'AboutPrefs',
Template: GLib.Uri.resolve_relative(import.meta.url, '../ui/about.ui',GLib.UriFlags.NONE),
@ -14,6 +22,10 @@ export const About = GObject.registerClass({
'app_icon_image',
'app_name_label',
'version_label',
'open_readme',
'open_bug_report',
'open_license',
'open_translate',
]
}, class About extends Adw.PreferencesPage {
constructor(window) {
@ -21,25 +33,29 @@ export const About = GObject.registerClass({
this._app_icon_image.gicon = Gio.icon_new_for_string(`${GLib.Uri.resolve_relative(import.meta.url, '../icons/threshold-active.svg',GLib.UriFlags.NONE)}`);
this._app_name_label.label = window._metadata.name;
this._version_label.label = window._metadata.version.toString();
this._version_label.label = window._metadata.version ? window._metadata.version.toString() : "0";
// setup menu actions
// Setup actions
const actionGroup = new Gio.SimpleActionGroup();
window.insert_action_group('prefs', actionGroup);
// a list of actions with their associated link
// A list of actions with their associated link
const actions = [
{
name: 'open-bug-report',
link: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues'
link: URLS.bug_report
},
{
name: 'open-readme',
link: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/'
link: URLS.readme
},
{
name: 'open-license',
link: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/blob/main/LICENSE'
link: URLS.license
},
{
name: 'open-translate',
link: URLS.translate
},
];
@ -51,5 +67,11 @@ export const About = GObject.registerClass({
);
actionGroup.add_action(act);
});
// Set tooltips
this._open_readme.tooltip_text = URLS.readme;
this._open_license.tooltip_text = URLS.license;
this._open_bug_report.tooltip_text = URLS.bug_report;
this._open_translate.tooltip_text = URLS.translate;
}
});

View File

@ -16,7 +16,11 @@ export const Thinkpad = GObject.registerClass({
'reset',
'apply_bat0',
'apply_bat1',
'reset_thresholds_dialog'
'reset_thresholds_dialog',
'disabled_start_bat0',
'disabled_start_bat1',
'warn_bat0',
'warn_bat1'
],
}, class Thinkpad extends Adw.PreferencesPage {
constructor(window) {
@ -46,26 +50,48 @@ export const Thinkpad = GObject.registerClass({
'value',
Gio.SettingsBindFlags.DEFAULT
);
window._settings.bind(
'disabled-start-bat0-value',
this._disabled_start_bat0,
'value',
Gio.SettingsBindFlags.DEFAULT
);
window._settings.bind(
'disabled-start-bat1-value',
this._disabled_start_bat1,
'value',
Gio.SettingsBindFlags.DEFAULT
);
window._settings.connect('changed::start-bat0', () => {
if (this._start_bat0.value >= this._end_bat0.value) {
this._end_bat0.value = this._start_bat0.value + 1;
}
this._updateWarnings();
});
window._settings.connect('changed::end-bat0', () => {
if (this._start_bat0.value >= this._end_bat0.value) {
this._start_bat0.value = this._end_bat0.value - 1;
}
this._updateWarnings();
});
window._settings.connect('changed::start-bat1', () => {
if (this._start_bat1.value >= this._end_bat1.value) {
this._end_bat1.value = this._start_bat1.value + 1;
}
this._updateWarnings();
});
window._settings.connect('changed::end-bat1', () => {
if (this._start_bat1.value >= this._end_bat1.value) {
this._start_bat1.value = this._end_bat1.value - 1;
}
this._updateWarnings();
});
window._settings.connect('changed::disabled-start-bat0-value', () => {
this._updateWarnings();
});
window._settings.connect('changed::disabled-start-bat1-value', () => {
this._updateWarnings();
});
const bat0 = window._driver.batteries.find(battery => battery.name === 'BAT0');
@ -96,13 +122,17 @@ export const Thinkpad = GObject.registerClass({
this._apply_bat1.sensitive = bat1.pendingChanges;
});
this._updateWarnings();
this._reset_thresholds_dialog.connect('response', (obj, response, data) => {
if (response === 'reset') {
const keys = [
'start-bat0',
'end-bat0',
'start-bat1',
'end-bat1'
'end-bat1',
'disabled-start-bat0-value',
'disabled-start-bat1-value',
];
keys.forEach(key => {
window._settings.reset(key);
@ -116,4 +146,9 @@ export const Thinkpad = GObject.registerClass({
this._reset_thresholds_dialog.present();
});
}
_updateWarnings() {
this._warn_bat0.reveal_child = this._start_bat0.value === this._disabled_start_bat0.value && this._end_bat0.value === 100;
this._warn_bat1.reveal_child = this._start_bat1.value === this._disabled_start_bat1.value && this._end_bat1.value === 100;
}
});

View File

@ -13,7 +13,7 @@
<!-- UI settings -->
<key name="indicator-mode" enum="org.gnome.shell.extensions.thinkpad-battery-threshold.indicator-mode">
<default>"ACTIVE"</default>
<default>"ALWAYS"</default>
<summary>Set when the Icon tray should appear in Gnome tray</summary>
</key>
<key name="show-current-values" type="b">
@ -39,12 +39,28 @@
<summary>Stop charging when the level is above this value</summary>
</key>
<key name="start-bat1" type="i">
<default>0</default>
<default>75</default>
<summary>Start charging when the level is below this value</summary>
</key>
<key name="end-bat1" type="i">
<default>100</default>
<default>80</default>
<summary>Stop charging when the level is above this value</summary>
</key>
<key name="auto-disabled-start-bat0-value" type="b">
<default>true</default>
<summary>Use autodetected disabled start value</summary>
</key>
<key name="disabled-start-bat0-value" type="i">
<default>-1</default>
<summary>Disabled start value instead of default value</summary>
</key>
<key name="auto-disabled-start-bat1-value" type="b">
<default>true</default>
<summary>Use autodetected disabled start value</summary>
</key>
<key name="disabled-start-bat1-value" type="i">
<default>-1</default>
<summary>Disabled start value instead of default value</summary>
</key>
</schema>
</schemalist>

View File

@ -53,8 +53,6 @@
<child>
<object class="AdwActionRow" id="open_readme">
<property name="title" translatable="yes">Project site</property>
<!-- <property name="subtitle" translatable="yes">Activate colored icons</property> -->
<property name="tooltip-text">https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/</property>
<property name="action-name">prefs.open-readme</property>
<property name="activatable">true</property>
<child>
@ -68,8 +66,6 @@
<child>
<object class="AdwActionRow" id="open_bug_report">
<property name="title" translatable="yes">Bug report</property>
<!-- <property name="subtitle" translatable="yes">Activate colored icons</property> -->
<property name="tooltip-text">https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues</property>
<property name="action-name">prefs.open-bug-report</property>
<property name="activatable">true</property>
<child>
@ -83,8 +79,6 @@
<child>
<object class="AdwActionRow" id="open_license">
<property name="title" translatable="yes">License</property>
<!-- <property name="subtitle" translatable="yes">Activate colored icons</property> -->
<property name="tooltip-text">https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/blob/main/LICENSE</property>
<property name="action-name">prefs.open-license</property>
<property name="activatable">true</property>
<child>
@ -95,6 +89,19 @@
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="open_translate">
<property name="title" translatable="yes">Translate</property>
<property name="action-name">prefs.open-translate</property>
<property name="activatable">true</property>
<child>
<object class="GtkImage">
<property name="valign">center</property>
<property name="icon-name">adw-external-link-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>

View File

@ -29,16 +29,100 @@
<object class="AdwSpinRow" id="start_bat0">
<property name="title" translatable="yes">Charging start value</property>
<property name="subtitle" translatable="yes">Start charging when the level is below this value</property>
<property name="adjustment">bat0_start_adjustment</property>
<property name="snap-to-ticks">true</property>
<property name="update-policy">if-valid</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">99.0</property>
<property name="lower">0.0</property>
<property name="value">75.0</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwSpinRow" id="end_bat0">
<property name="title" translatable="yes">Charging stop value</property>
<property name="subtitle" translatable="yes">Stop charging when the level is above this value</property>
<property name="adjustment">bat0_end_adjustment</property>
<property name="snap-to-ticks">true</property>
<property name="update-policy">if-valid</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">100.0</property>
<property name="lower">1.0</property>
<property name="value">80.0</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwSpinRow" id="disabled_start_bat0">
<property name="title" translatable="yes">Start value considered disabled</property>
<property name="subtitle" translatable="yes">The start threshold value that is considered disabled is not the same on all laptops (usually 0 or 95). We will try to automatically detect this value, but if you can't turn off the thresholds, try changing it manually (use -1 to automatically detect it)</property>
<property name="snap-to-ticks">true</property>
<property name="update-policy">if-valid</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">99.0</property>
<property name="lower">-1.0</property>
<property name="value">-1.0</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkRevealer" id="warn_bat0">
<property name="reveal-child">true</property>
<child>
<object class="GtkBox">
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="spacing">12</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<child>
<object class="GtkImage">
<property name="icon-name">dialog-warning</property>
<property name="css-classes">warning</property>
<property name="icon-size">GTK_ICON_SIZE_LARGE</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">WARNING</property>
<property name="css-classes">warning</property>
<property name="wrap">true</property>
<property name="hexpand">true</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<attributes>
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="wrap">true</property>
<property name="hexpand">true</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<property name="label" translatable="yes">The configured threshold values are equal to the values considered "disabled"</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
@ -66,16 +150,100 @@
<object class="AdwSpinRow" id="start_bat1">
<property name="title" translatable="yes">Charging start value</property>
<property name="subtitle" translatable="yes">Start charging when the level is below this value</property>
<property name="adjustment">bat1_start_adjustment</property>
<property name="snap-to-ticks">true</property>
<property name="update-policy">if-valid</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">99.0</property>
<property name="lower">0.0</property>
<property name="value">75.0</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwSpinRow" id="end_bat1">
<property name="title" translatable="yes">Charging stop value</property>
<property name="subtitle" translatable="yes">Stop charging when the level is above this value</property>
<property name="adjustment">bat1_end_adjustment</property>
<property name="snap-to-ticks">true</property>
<property name="update-policy">if-valid</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">100.0</property>
<property name="lower">1.0</property>
<property name="value">80.0</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwSpinRow" id="disabled_start_bat1">
<property name="title" translatable="yes">Start value considered disabled</property>
<property name="subtitle" translatable="yes">The start threshold value that is considered disabled is not the same on all laptops (usually 0 or 95). We will try to automatically detect this value, but if you can't turn off the thresholds, try changing it manually (use -1 to automatically detect it)</property>
<property name="snap-to-ticks">true</property>
<property name="update-policy">if-valid</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">99.0</property>
<property name="lower">-1.0</property>
<property name="value">-1.0</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkRevealer" id="warn_bat1">
<property name="reveal-child">true</property>
<child>
<object class="GtkBox">
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="spacing">12</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<child>
<object class="GtkImage">
<property name="icon-name">dialog-warning</property>
<property name="css-classes">warning</property>
<property name="icon-size">GTK_ICON_SIZE_LARGE</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">WARNING</property>
<property name="css-classes">warning</property>
<property name="wrap">true</property>
<property name="hexpand">true</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<attributes>
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="wrap">true</property>
<property name="hexpand">true</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
<property name="label" translatable="yes">The configured threshold values are equal to the values considered "disabled"</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
@ -116,33 +284,4 @@
<response id="reset" translatable="yes" appearance="destructive">Reset</response>
</responses>
</object>
<object class="GtkAdjustment" id="bat0_start_adjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">99.0</property>
<property name="lower">0.0</property>
<property name="value">75.0</property>
</object>
<object class="GtkAdjustment" id="bat0_end_adjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">100.0</property>
<property name="lower">1.0</property>
<property name="value">80.0</property>
</object>
<object class="GtkAdjustment" id="bat1_start_adjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">99.0</property>
<property name="lower">0.0</property>
<property name="value">75.0</property>
</object>
<object class="GtkAdjustment" id="bat1_end_adjustment">
<property name="page-increment">5.0</property>
<property name="step-increment">1.0</property>
<property name="upper">100.0</property>
<property name="lower">1.0</property>
<property name="value">80.0</property>
</object>
</interface>