mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: parse xml
This commit is contained in:
parent
119af47d77
commit
fd80b85786
4 changed files with 117 additions and 56 deletions
|
@ -4,13 +4,13 @@ import { parseICO } from "icojs";
|
|||
import trayIcon from "@resources/tray-icon.png?asset";
|
||||
import { Game } from "@main/entity";
|
||||
import { gameRepository, userPreferencesRepository } from "@main/repository";
|
||||
import { toXmlString } from "powertoast";
|
||||
import fs from "node:fs";
|
||||
import axios from "axios";
|
||||
import path from "node:path";
|
||||
import sound from "sound-play";
|
||||
import { achievementSoundPath } from "@main/constants";
|
||||
import icon from "@resources/icon.png?asset";
|
||||
import { NotificationOptions, toXmlString } from "./xml";
|
||||
|
||||
const getGameIconNativeImage = async (gameId: number) => {
|
||||
try {
|
||||
|
@ -101,7 +101,7 @@ export const publishCombinedNewAchievementNotification = async (
|
|||
? await downloadImage(achievementIcon)
|
||||
: icon;
|
||||
|
||||
new Notification({
|
||||
const options: NotificationOptions = {
|
||||
title: "New achievement unlocked",
|
||||
body: t("new_achievements_unlocked", {
|
||||
ns: "achievement",
|
||||
|
@ -110,16 +110,11 @@ export const publishCombinedNewAchievementNotification = async (
|
|||
}),
|
||||
icon: iconPath,
|
||||
silent: true,
|
||||
toastXml: toXmlString({
|
||||
title: "New achievement unlocked",
|
||||
message: t("new_achievements_unlocked", {
|
||||
ns: "achievement",
|
||||
gameCount,
|
||||
achievementCount,
|
||||
}),
|
||||
icon: iconPath,
|
||||
silent: true,
|
||||
}),
|
||||
};
|
||||
|
||||
new Notification({
|
||||
...options,
|
||||
toastXml: toXmlString(options),
|
||||
}).show();
|
||||
|
||||
sound.play(achievementSoundPath);
|
||||
|
@ -133,24 +128,22 @@ export const publishNewAchievementNotification = async (achievement: {
|
|||
}) => {
|
||||
const iconPath = await downloadImage(achievement.achievementIcon);
|
||||
|
||||
new Notification({
|
||||
const options: NotificationOptions = {
|
||||
title: "New achievement unlocked",
|
||||
body: achievement.displayName,
|
||||
icon: iconPath,
|
||||
silent: true,
|
||||
toastXml: toXmlString({
|
||||
title: "New achievement unlocked",
|
||||
message: achievement.displayName,
|
||||
icon: iconPath,
|
||||
silent: true,
|
||||
progress: {
|
||||
value: Math.round(
|
||||
(achievement.unlockedAchievementCount * 100) /
|
||||
achievement.totalAchievementCount
|
||||
),
|
||||
valueOverride: `${achievement.unlockedAchievementCount}/${achievement.totalAchievementCount} achievements`,
|
||||
},
|
||||
}),
|
||||
progress: {
|
||||
value:
|
||||
achievement.unlockedAchievementCount /
|
||||
achievement.totalAchievementCount,
|
||||
valueOverride: `${achievement.unlockedAchievementCount}/${achievement.totalAchievementCount} achievements`,
|
||||
},
|
||||
};
|
||||
|
||||
new Notification({
|
||||
...options,
|
||||
toastXml: toXmlString(options),
|
||||
}).show();
|
||||
|
||||
sound.play(achievementSoundPath);
|
98
src/main/services/notifications/xml.ts
Normal file
98
src/main/services/notifications/xml.ts
Normal file
|
@ -0,0 +1,98 @@
|
|||
export interface NotificationOptions {
|
||||
title: string;
|
||||
body?: string;
|
||||
icon: string;
|
||||
duration?: "short" | "long";
|
||||
silent?: boolean;
|
||||
progress?: {
|
||||
title?: string;
|
||||
status?: string;
|
||||
value: number;
|
||||
valueOverride: string;
|
||||
};
|
||||
}
|
||||
function escape(string: string) {
|
||||
return string.replace(/[<>&'"]/g, (match) => {
|
||||
switch (match) {
|
||||
case "<":
|
||||
return "<";
|
||||
case ">":
|
||||
return ">";
|
||||
case "&":
|
||||
return "&";
|
||||
case "'":
|
||||
return "'";
|
||||
case '"':
|
||||
return """;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addAttributeOrTrim(name, value) {
|
||||
return value ? `${name}="${value}" ` : "";
|
||||
}
|
||||
|
||||
const Activation = {
|
||||
types: [
|
||||
"protocol",
|
||||
"background",
|
||||
"foreground",
|
||||
"system", //system call such as alarm (snooze/dismiss), also used by Notification Visualizer
|
||||
],
|
||||
behavior: ["default", "pendingUpdate"],
|
||||
};
|
||||
|
||||
const Scenarios = [
|
||||
"default",
|
||||
"alarm",
|
||||
"reminder",
|
||||
"incomingCall",
|
||||
"urgent", //win10/11 22h2
|
||||
];
|
||||
|
||||
export function toXmlString(options: NotificationOptions) {
|
||||
let template =
|
||||
"<toast " +
|
||||
`displayTimestamp="${new Date().toISOString()}" ` +
|
||||
`scenario="${Scenarios[0]}" ` +
|
||||
`duration="${options.duration ?? "short"}" ` +
|
||||
`activationType="${Activation.types[0]}" ` +
|
||||
">";
|
||||
|
||||
//Visual
|
||||
template += `<visual><binding template="ToastGeneric">`;
|
||||
if (options.icon)
|
||||
template += `<image placement="appLogoOverride" src="${options.icon}" hint-crop="none"/>`;
|
||||
template +=
|
||||
`<text><![CDATA[${options.title}]]></text>` +
|
||||
`<text><![CDATA[${options.body}]]></text>`;
|
||||
|
||||
//Progress bar
|
||||
if (options.progress) {
|
||||
template +=
|
||||
"<progress " +
|
||||
`value="${options.progress.value}" ` +
|
||||
`status="" ` +
|
||||
addAttributeOrTrim("title", escape(options.progress.title || "")) +
|
||||
addAttributeOrTrim(
|
||||
"valueStringOverride",
|
||||
escape(options.progress.valueOverride)
|
||||
) +
|
||||
"/>";
|
||||
}
|
||||
template += "</binding></visual>";
|
||||
|
||||
//Actions
|
||||
template += "<actions>";
|
||||
template += "</actions>";
|
||||
|
||||
//Audio
|
||||
template += "<audio " + `silent="true" ` + `loop="false" ` + "/>";
|
||||
|
||||
//EOF
|
||||
template += "</toast>";
|
||||
|
||||
return template;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue