Skip to content

Commit

Permalink
Add autodisable time indicator to popup menu
Browse files Browse the repository at this point in the history
When a keepawake with autodisable timeeout is active,
show the message "Automatically disable at HH:MM" in
the popup
  • Loading branch information
nielm committed May 30, 2024
1 parent 445e8ff commit 3eaf590
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@
"message": " until: ",
"description": "Suffix to append to above Titles to append an end time"
},
"autoDisableText": {
"autoDisableAfterText": {
"message": "Automatically disable after:",
"description": "Text labelling a slider allowing setting a timeout for disabling the power saving state."
},
"autoDisableAtText": {
"message": "Automatically disable at: ",
"description": "Prefix Text indicating the time when the state will automatically switch to disabled."
},
"autoDisableHoursSuffix": {
"message": "h",
"description": "Text to append after a number indicating a quantity of hours"
Expand Down
16 changes: 12 additions & 4 deletions api-samples/power/keepAwake Advanced/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ function updateState(mode) {
chrome.action.setBadgeText({ text: `${hoursLeft}h` });
const endDate = new Date(mode.endMillis);
chrome.action.setTitle({
title: `${title}${chrome.i18n.getMessage('untilText')} ${endDate.toLocaleTimeString('short')}`
title: `${title}${chrome.i18n.getMessage('untilText')} ${endDate.toLocaleTimeString(undefined, { timeStyle: 'short' })}`
});
log(
`mode = ${mode.state} for the next ${hoursLeft}hrs until ${endDate.toLocaleTimeString('short')}`
`mode = ${mode.state} for the next ${hoursLeft}hrs until ${endDate.toLocaleTimeString()}`
);
} else {
// No timeout.
Expand All @@ -86,9 +86,11 @@ function updateState(mode) {
}

/**
*
* Apply a new KeepAwake mode.
*
* @param {KeepAwakeMode} newMode
* @return {Promise<KeepAwakeMode>}
*/
async function setNewMode(newMode) {
// Clear any old alarms
Expand All @@ -110,6 +112,7 @@ async function setNewMode(newMode) {
// Store the new mode.
chrome.storage.local.set(newMode);
updateState(newMode);
return newMode;
}

/**
Expand Down Expand Up @@ -197,15 +200,20 @@ chrome.runtime.onMessage.addListener(function (request, _, sendResponse) {
request.state,
request.duration
);
sendResponse({});

setNewMode(
verifyMode({
state: request.state,
defaultDurationHrs: request.duration,
endMillis: null
})
);
)
.then((newMode) => sendResponse(newMode))
.catch((e) => {
log(`failed to set new mode: ${e}`, e);
sendResponse(null);
});
return true; // sendResponse() called asynchronously
});

// Handle action clicks - rotates the mode to the next mode.
Expand Down
18 changes: 9 additions & 9 deletions api-samples/power/keepAwake Advanced/popup.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
<!doctype html>
<html>
<head>
<title>Keep Awake</title>
<title>#extensionName</title>
<script type="module" src="./popup.js"></script>
<link rel="stylesheet" href="./popup.css" />
</head>

<body>
<div id="popup">
<h3 id="title">Keep Awake</h3>
<h3 id="title">#extensionName</h3>
<div id="buttons">
<button id="disabled" title="Disable keep awake">
<button id="disabled" title="#disabledTitle">
<img src="images/night-38.png" alt="Moon" />
<br />
<span class="buttonLabel">Disabled</span>
<span class="buttonLabel">#disabledLabel</span>
</button>
<button id="display" title="Keep systam and display on">
<button id="display" title="#displayTitle">
<img src="images/day-38.png" alt="Sun" />
<br />
<span class="buttonLabel">Display On</span>
<span class="buttonLabel">#displayLabel</span>
</button>
<button id="system" title="Keep system on, allow display sleep">
<button id="system" title="#systemTitle">
<img src="images/sunset-38.png" alt="Sunset" />
<br />
<span class="buttonLabel">System On</span>
<span class="buttonLabel">#systemLabel</span>
</button>
</div>
<div id="autodisable-text">Automatically disable after:</div>
<div id="autodisable-text">#autoDisableAfterText</div>
<div>
<input
type="range"
Expand Down
47 changes: 35 additions & 12 deletions api-samples/power/keepAwake Advanced/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import { DURATION_FOR_EVER, getSavedMode, StateEnum } from './common.js';

/** @typedef {import('./common.js').KeepAwakeMode} KeepAwakeMode */

/** @type {HTMLLabelElement} */
let durationLabel;
/** @type {HTMLInputElement} */
Expand Down Expand Up @@ -55,17 +57,20 @@ function updateDurationLabel() {
async function durationSliderChanged() {
updateDurationLabel();

await sendMessageToBackground(
const newState = await sendMessageToBackground(
(await getSavedMode()).state,
Number(durationSlider.value)
);
updateState(newState);
}

/**
* Sends a message to the background service worker to set the new state and
* duration.
*
* @param {string} state
* @param {number} duration
* @return {Promise<KeepAwakeMode>} Updated mode
*/
async function sendMessageToBackground(state, duration) {
if (!Object.values(StateEnum).includes(state)) {
Expand All @@ -79,8 +84,7 @@ async function sendMessageToBackground(state, duration) {
} else {
message.duration = duration;
}

chrome.runtime.sendMessage(message);
return await chrome.runtime.sendMessage(message);
}

/**
Expand All @@ -93,14 +97,37 @@ async function sendMessageToBackground(state, duration) {
*/
async function buttonClicked(e) {
const button = /** @type {HTMLElement} */ (e.currentTarget);
await sendMessageToBackground(
const newState = await sendMessageToBackground(
// Button id is named after state.
button.id,
Number(durationSlider.value)
);
updateState(newState);
}

/**
* @param {KeepAwakeMode} newMode
*/

function updateState(newMode) {
console.log('new state: %o', newMode);
if (!newMode) {
throw new Error('invalid null state');
}
// Re-set active button state.
document.querySelector(`#buttons .active`)?.classList?.remove('active');
button.classList.add('active');
querySelectorAndAssert(`#buttons #${newMode.state}`).classList?.add('active');
if (newMode.state === StateEnum.DISABLED || !newMode.endMillis) {
querySelectorAndAssert('#autodisable-text').textContent =
chrome.i18n.getMessage('autoDisableAfterText');
} else {
querySelectorAndAssert('#autodisable-text').textContent =
chrome.i18n.getMessage('autoDisableAtText') +
new Date(newMode.endMillis).toLocaleTimeString(undefined, {
timeStyle: 'short'
});
}
updateDurationLabel();
}

/**
Expand All @@ -118,8 +145,8 @@ async function onload() {

querySelectorAndAssert('#title').textContent =
chrome.i18n.getMessage('extensionName');
querySelectorAndAssert('#autodisable-text').title =
chrome.i18n.getMessage('autoDisableText');

const mode = await getSavedMode();

// set button titles and listeners
for (const id of Object.values(StateEnum)) {
Expand All @@ -130,16 +157,12 @@ async function onload() {
chrome.i18n.getMessage(button.id + 'Label');
}

// set active button state. Assumes buttons have same IDs as state names.
const mode = await getSavedMode();
querySelectorAndAssert(`#buttons #${mode.state}`).classList?.add('active');

durationSlider.max = DURATION_FOR_EVER.toString();
durationSlider.value = (
mode.defaultDurationHrs ? mode.defaultDurationHrs : DURATION_FOR_EVER
).toString();
updateDurationLabel();
durationSlider.addEventListener('input', durationSliderChanged);
updateState(mode);
}

document.addEventListener('DOMContentLoaded', onload);

0 comments on commit 3eaf590

Please sign in to comment.