This commit is contained in:
Araxeus
2023-02-10 00:07:00 +02:00
parent 27d8bbdf85
commit 2f117117d8
7 changed files with 89 additions and 94 deletions

View File

@ -13,10 +13,10 @@ const migrations = {
setDefaultPluginOptions(store, "visualizer"); setDefaultPluginOptions(store, "visualizer");
if (store.get("plugins.notifications.toastStyle") === undefined) { if (store.get("plugins.notifications.toastStyle") === undefined) {
const pluginOptions = store.get("plugins.notifications") || {}; const pluginOptions = store.get("plugins.notifications") || {};
store.set("plugins.notifications", { store.set("plugins.notifications", {
...defaults.plugins.notifications, ...defaults.plugins.notifications,
...pluginOptions, ...pluginOptions,
}); });
} }
}, },

View File

@ -337,7 +337,7 @@ app.on("ready", () => {
// Clear cache after 20s // Clear cache after 20s
const clearCacheTimeout = setTimeout(() => { const clearCacheTimeout = setTimeout(() => {
if (is.dev()) { if (is.dev()) {
console.log("Clearing app cache."); console.log("Clearing app cache.");
} }
electron.session.defaultSession.clearCache(); electron.session.defaultSession.clearCache();
clearTimeout(clearCacheTimeout); clearTimeout(clearCacheTimeout);

View File

@ -19,7 +19,7 @@ module.exports = (win) => {
let currentSeconds = 0; let currentSeconds = 0;
ipcMain.on('apiLoaded', () => win.webContents.send('setupTimeChangedListener')); ipcMain.on('apiLoaded', () => win.webContents.send('setupTimeChangedListener'));
ipcMain.on('timeChanged', (_, t) => currentSeconds = t); ipcMain.on('timeChanged', (_, t) => currentSeconds = t);
if (app.isPackaged) save_temp_icons(); if (app.isPackaged) save_temp_icons();
@ -29,7 +29,7 @@ module.exports = (win) => {
// Register songInfoCallback // Register songInfoCallback
registerCallback(songInfo => { registerCallback(songInfo => {
savedSongInfo = { ...songInfo }; savedSongInfo = { ...songInfo };
if (!songInfo.isPaused && if (!songInfo.isPaused &&
(songInfo.url !== lastUrl || config.get("unpauseNotification")) (songInfo.url !== lastUrl || config.get("unpauseNotification"))
) { ) {
lastUrl = songInfo.url lastUrl = songInfo.url
@ -68,11 +68,11 @@ module.exports = (win) => {
if (Object.keys(songControls).includes(cmd)) { if (Object.keys(songControls).includes(cmd)) {
songControls[cmd](); songControls[cmd]();
if (config.get("refreshOnPlayPause") && ( if (config.get("refreshOnPlayPause") && (
cmd === 'pause' || cmd === 'pause' ||
(cmd === 'play' && !config.get("unpauseNotification")) (cmd === 'play' && !config.get("unpauseNotification"))
) )
) { ) {
setImmediate(() => setImmediate(() =>
sendNotification({ sendNotification({
...savedSongInfo, ...savedSongInfo,
isPaused: cmd === 'pause', isPaused: cmd === 'pause',
@ -91,16 +91,16 @@ function sendNotification(songInfo) {
savedNotification?.close(); savedNotification?.close();
savedNotification = new Notification({ savedNotification = new Notification({
title: songInfo.title || "Playing", title: songInfo.title || "Playing",
body: songInfo.artist, body: songInfo.artist,
icon: iconSrc, icon: iconSrc,
silent: true, silent: true,
// https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/schema-root // https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/schema-root
// https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/toast-schema // https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/toast-schema
// https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml // https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml
// https://learn.microsoft.com/en-us/uwp/api/windows.ui.notifications.toasttemplatetype // https://learn.microsoft.com/en-us/uwp/api/windows.ui.notifications.toasttemplatetype
toastXml: get_xml(songInfo, iconSrc), toastXml: get_xml(songInfo, iconSrc),
}); });
savedNotification.on("close", (_) => { savedNotification.on("close", (_) => {
savedNotification = undefined; savedNotification = undefined;
@ -112,7 +112,7 @@ function sendNotification(songInfo) {
const get_xml = (songInfo, iconSrc) => { const get_xml = (songInfo, iconSrc) => {
switch (config.get("toastStyle")) { switch (config.get("toastStyle")) {
default: default:
case ToastStyles.logo: case ToastStyles.logo:
case ToastStyles.legacy: case ToastStyles.legacy:
return xml_logo(songInfo, iconSrc); return xml_logo(songInfo, iconSrc);
case ToastStyles.banner_top_custom: case ToastStyles.banner_top_custom:
@ -133,7 +133,7 @@ const iconLocation = app.isPackaged ?
path.resolve(__dirname, '..', '..', 'assets/media-icons-black'); path.resolve(__dirname, '..', '..', 'assets/media-icons-black');
const display = (kind) => { const display = (kind) => {
if (config.get("toastStyle") === ToastStyles.legacy ) { if (config.get("toastStyle") === ToastStyles.legacy) {
return `content="${icons[kind]}"`; return `content="${icons[kind]}"`;
} else { } else {
return `\ return `\
@ -166,23 +166,18 @@ const toast = (content, isPaused) => `\
${getButtons(isPaused)} ${getButtons(isPaused)}
</toast>`; </toast>`;
const xml_logo = ({title, artist, isPaused}, imgSrc) => toast(`\ const xml_image = ({ title, artist, isPaused }, imgSrc, placement) => toast(`\
<image id="1" src="${imgSrc}" name="Image" placement="appLogoOverride"/> <image id="1" src="${imgSrc}" name="Image" ${placement}/>
<text id="1">${title}</text> <text id="1">${title}</text>
<text id="2">${artist}</text>\ <text id="2">${artist}</text>\
`, isPaused); `, isPaused);
const xml_hero = ({title, artist, isPaused}, imgSrc) => toast(`\
<image id="1" src="${imgSrc}" name="Image" placement="hero"/>
<text id="1">${title}</text>
<text id="2">${artist}</text>\
`, isPaused);
const xml_banner_bottom = ({title, artist, isPaused}, imgSrc) => toast(`\ const xml_logo = (songInfo, imgSrc) => xml_image(songInfo, imgSrc, 'placement="appLogoOverride"');
<image id="1" src="${imgSrc}" name="Image" />
<text id="1">${title}</text> const xml_hero = (songInfo, imgSrc) => xml_image(songInfo, imgSrc, 'placement="hero"');
<text id="2">${artist}</text>\
`, isPaused); const xml_banner_bottom = (songInfo, imgSrc) => xml_image(songInfo, imgSrc, '');
const xml_banner_top_custom = (songInfo, imgSrc) => toast(`\ const xml_banner_top_custom = (songInfo, imgSrc) => toast(`\
<image id="1" src="${imgSrc}" name="Image" /> <image id="1" src="${imgSrc}" name="Image" />
@ -196,15 +191,15 @@ const xml_banner_top_custom = (songInfo, imgSrc) => toast(`\
</group>\ </group>\
`, songInfo.isPaused); `, songInfo.isPaused);
const xml_more_data = ({ album, elapsedSeconds, songDuration })=> `\ const xml_more_data = ({ album, elapsedSeconds, songDuration }) => `\
<subgroup hint-textStacking="bottom"> <subgroup hint-textStacking="bottom">
${album ? ${album ?
`<text hint-style="captionSubtle" hint-wrap="true" hint-align="right">${album}</text>` : ''} `<text hint-style="captionSubtle" hint-wrap="true" hint-align="right">${album}</text>` : ''}
<text hint-style="captionSubtle" hint-wrap="true" hint-align="right">${secondsToMinutes(elapsedSeconds)} / ${secondsToMinutes(songDuration)}</text> <text hint-style="captionSubtle" hint-wrap="true" hint-align="right">${secondsToMinutes(elapsedSeconds)} / ${secondsToMinutes(songDuration)}</text>
</subgroup>\ </subgroup>\
`; `;
const xml_banner_centered_bottom = ({title, artist, isPaused}, imgSrc) => toast(`\ const xml_banner_centered_bottom = ({ title, artist, isPaused }, imgSrc) => toast(`\
<text></text> <text></text>
<group> <group>
<subgroup hint-weight="1" hint-textStacking="center"> <subgroup hint-weight="1" hint-textStacking="center">
@ -215,7 +210,7 @@ const xml_banner_centered_bottom = ({title, artist, isPaused}, imgSrc) => toast(
<image id="1" src="${imgSrc}" name="Image" hint-removeMargin="true" />\ <image id="1" src="${imgSrc}" name="Image" hint-removeMargin="true" />\
`, isPaused); `, isPaused);
const xml_banner_centered_top = ({title, artist, isPaused}, imgSrc) => toast(`\ const xml_banner_centered_top = ({ title, artist, isPaused }, imgSrc) => toast(`\
<image id="1" src="${imgSrc}" name="Image" /> <image id="1" src="${imgSrc}" name="Image" />
<text></text> <text></text>
<group> <group>

View File

@ -5,55 +5,55 @@ const config = require("./config");
module.exports = (_win, options) => [ module.exports = (_win, options) => [
...(is.linux() ...(is.linux()
? [ ? [
{ {
label: "Notification Priority", label: "Notification Priority",
submenu: urgencyLevels.map((level) => ({ submenu: urgencyLevels.map((level) => ({
label: level.name, label: level.name,
type: "radio", type: "radio",
checked: options.urgency === level.value, checked: options.urgency === level.value,
click: () => config.set("urgency", level.value), click: () => config.set("urgency", level.value),
})), })),
}, },
] ]
: []), : []),
...(is.windows() ...(is.windows()
? [ ? [
{ {
label: "Interactive Notifications", label: "Interactive Notifications",
type: "checkbox", type: "checkbox",
checked: options.interactive, checked: options.interactive,
// doesn't update until restart // doesn't update until restart
click: (item) => config.setAndMaybeRestart("interactive", item.checked), click: (item) => config.setAndMaybeRestart("interactive", item.checked),
}, },
{ {
// submenu with settings for interactive notifications (name shouldn't be too long) // submenu with settings for interactive notifications (name shouldn't be too long)
label: "Interactive Settings", label: "Interactive Settings",
submenu: [ submenu: [
{ {
label: "Open/Close on tray click", label: "Open/Close on tray click",
type: "checkbox", type: "checkbox",
checked: options.trayControls, checked: options.trayControls,
click: (item) => config.set("trayControls", item.checked), click: (item) => config.set("trayControls", item.checked),
}, },
{ {
label: "Hide Button Text", label: "Hide Button Text",
type: "checkbox", type: "checkbox",
checked: options.hideButtonText, checked: options.hideButtonText,
click: (item) => config.set("hideButtonText", item.checked), click: (item) => config.set("hideButtonText", item.checked),
}, },
{ {
label: "Refresh on Play/Pause", label: "Refresh on Play/Pause",
type: "checkbox", type: "checkbox",
checked: options.refreshOnPlayPause, checked: options.refreshOnPlayPause,
click: (item) => config.set("refreshOnPlayPause", item.checked), click: (item) => config.set("refreshOnPlayPause", item.checked),
} }
] ]
}, },
{ {
label: "Style", label: "Style",
submenu: getToastStyleMenuItems(options) submenu: getToastStyleMenuItems(options)
}, },
] ]
: []), : []),
{ {
label: "Show notification on unpause", label: "Show notification on unpause",

View File

@ -35,7 +35,7 @@ module.exports.notificationImage = (songInfo) => {
if (!songInfo.image) return icon; if (!songInfo.image) return icon;
if (!config.get("interactive")) return nativeImageToLogo(songInfo.image); if (!config.get("interactive")) return nativeImageToLogo(songInfo.image);
switch(config.get("toastStyle")) { switch (config.get("toastStyle")) {
case module.exports.ToastStyles.logo: case module.exports.ToastStyles.logo:
case module.exports.ToastStyles.legacy: case module.exports.ToastStyles.legacy:
return this.saveImage(nativeImageToLogo(songInfo.image), tempIcon); return this.saveImage(nativeImageToLogo(songInfo.image), tempIcon);
@ -67,13 +67,13 @@ function nativeImageToLogo(nativeImage) {
} }
module.exports.save_temp_icons = () => { module.exports.save_temp_icons = () => {
for (const kind of Object.keys(module.exports.icons)) { for (const kind of Object.keys(module.exports.icons)) {
const destinationPath = path.join(userData, 'icons', `${kind}.png`); const destinationPath = path.join(userData, 'icons', `${kind}.png`);
if (fs.existsSync(destinationPath)) continue; if (fs.existsSync(destinationPath)) continue;
const iconPath = path.resolve(__dirname, "../../assets/media-icons-black", `${kind}.png`); const iconPath = path.resolve(__dirname, "../../assets/media-icons-black", `${kind}.png`);
fs.mkdirSync(path.dirname(destinationPath), { recursive: true }); fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
fs.copyFile(iconPath, destinationPath, ()=>{}); fs.copyFile(iconPath, destinationPath, () => { });
} }
}; };
module.exports.snakeToCamel = (str) => { module.exports.snakeToCamel = (str) => {

View File

@ -1,5 +1,5 @@
const mpris = require("mpris-service"); const mpris = require("mpris-service");
const {ipcMain} = require("electron"); const { ipcMain } = require("electron");
const registerCallback = require("../../providers/song-info"); const registerCallback = require("../../providers/song-info");
const getSongControls = require("../../providers/song-controls"); const getSongControls = require("../../providers/song-controls");
const config = require("../../config"); const config = require("../../config");
@ -21,7 +21,7 @@ function setupMPRIS() {
/** @param {Electron.BrowserWindow} win */ /** @param {Electron.BrowserWindow} win */
function registerMPRIS(win) { function registerMPRIS(win) {
const songControls = getSongControls(win); const songControls = getSongControls(win);
const {playPause, next, previous, volumeMinus10, volumePlus10, shuffle} = songControls; const { playPause, next, previous, volumeMinus10, volumePlus10, shuffle } = songControls;
try { try {
const secToMicro = n => Math.round(Number(n) * 1e6); const secToMicro = n => Math.round(Number(n) * 1e6);
const microToSec = n => Math.round(Number(n) / 1e6); const microToSec = n => Math.round(Number(n) / 1e6);
@ -117,7 +117,7 @@ function registerMPRIS(win) {
// With precise volume we can set the volume to the exact value. // With precise volume we can set the volume to the exact value.
let newVol = parseInt(newVolume * 100); let newVol = parseInt(newVolume * 100);
if (parseInt(player.volume * 100) !== newVol) { if (parseInt(player.volume * 100) !== newVol) {
if (!autoUpdate){ if (!autoUpdate) {
mprisVolNewer = true; mprisVolNewer = true;
autoUpdate = false; autoUpdate = false;
win.webContents.send('setVolume', newVol); win.webContents.send('setVolume', newVol);

View File

@ -16,7 +16,7 @@ function setupProtocolHandler(win) {
} else { } else {
app.setAsDefaultProtocolClient(APP_PROTOCOL) app.setAsDefaultProtocolClient(APP_PROTOCOL)
} }
const songControls = getSongControls(win); const songControls = getSongControls(win);
protocolHandler = (cmd) => { protocolHandler = (cmd) => {