mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-02 16:23:48 +03:00
feat: parse xml
This commit is contained in:
parent
119af47d77
commit
fd80b85786
@ -65,7 +65,6 @@
|
|||||||
"lottie-react": "^2.4.0",
|
"lottie-react": "^2.4.0",
|
||||||
"parse-torrent": "^11.0.17",
|
"parse-torrent": "^11.0.17",
|
||||||
"piscina": "^4.7.0",
|
"piscina": "^4.7.0",
|
||||||
"powertoast": "^3.0.0",
|
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-i18next": "^14.1.0",
|
"react-i18next": "^14.1.0",
|
||||||
"react-loading-skeleton": "^3.4.0",
|
"react-loading-skeleton": "^3.4.0",
|
||||||
|
@ -4,13 +4,13 @@ import { parseICO } from "icojs";
|
|||||||
import trayIcon from "@resources/tray-icon.png?asset";
|
import trayIcon from "@resources/tray-icon.png?asset";
|
||||||
import { Game } from "@main/entity";
|
import { Game } from "@main/entity";
|
||||||
import { gameRepository, userPreferencesRepository } from "@main/repository";
|
import { gameRepository, userPreferencesRepository } from "@main/repository";
|
||||||
import { toXmlString } from "powertoast";
|
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import sound from "sound-play";
|
import sound from "sound-play";
|
||||||
import { achievementSoundPath } from "@main/constants";
|
import { achievementSoundPath } from "@main/constants";
|
||||||
import icon from "@resources/icon.png?asset";
|
import icon from "@resources/icon.png?asset";
|
||||||
|
import { NotificationOptions, toXmlString } from "./xml";
|
||||||
|
|
||||||
const getGameIconNativeImage = async (gameId: number) => {
|
const getGameIconNativeImage = async (gameId: number) => {
|
||||||
try {
|
try {
|
||||||
@ -101,7 +101,7 @@ export const publishCombinedNewAchievementNotification = async (
|
|||||||
? await downloadImage(achievementIcon)
|
? await downloadImage(achievementIcon)
|
||||||
: icon;
|
: icon;
|
||||||
|
|
||||||
new Notification({
|
const options: NotificationOptions = {
|
||||||
title: "New achievement unlocked",
|
title: "New achievement unlocked",
|
||||||
body: t("new_achievements_unlocked", {
|
body: t("new_achievements_unlocked", {
|
||||||
ns: "achievement",
|
ns: "achievement",
|
||||||
@ -110,16 +110,11 @@ export const publishCombinedNewAchievementNotification = async (
|
|||||||
}),
|
}),
|
||||||
icon: iconPath,
|
icon: iconPath,
|
||||||
silent: true,
|
silent: true,
|
||||||
toastXml: toXmlString({
|
};
|
||||||
title: "New achievement unlocked",
|
|
||||||
message: t("new_achievements_unlocked", {
|
new Notification({
|
||||||
ns: "achievement",
|
...options,
|
||||||
gameCount,
|
toastXml: toXmlString(options),
|
||||||
achievementCount,
|
|
||||||
}),
|
|
||||||
icon: iconPath,
|
|
||||||
silent: true,
|
|
||||||
}),
|
|
||||||
}).show();
|
}).show();
|
||||||
|
|
||||||
sound.play(achievementSoundPath);
|
sound.play(achievementSoundPath);
|
||||||
@ -133,24 +128,22 @@ export const publishNewAchievementNotification = async (achievement: {
|
|||||||
}) => {
|
}) => {
|
||||||
const iconPath = await downloadImage(achievement.achievementIcon);
|
const iconPath = await downloadImage(achievement.achievementIcon);
|
||||||
|
|
||||||
new Notification({
|
const options: NotificationOptions = {
|
||||||
title: "New achievement unlocked",
|
title: "New achievement unlocked",
|
||||||
body: achievement.displayName,
|
body: achievement.displayName,
|
||||||
icon: iconPath,
|
icon: iconPath,
|
||||||
silent: true,
|
silent: true,
|
||||||
toastXml: toXmlString({
|
|
||||||
title: "New achievement unlocked",
|
|
||||||
message: achievement.displayName,
|
|
||||||
icon: iconPath,
|
|
||||||
silent: true,
|
|
||||||
progress: {
|
progress: {
|
||||||
value: Math.round(
|
value:
|
||||||
(achievement.unlockedAchievementCount * 100) /
|
achievement.unlockedAchievementCount /
|
||||||
achievement.totalAchievementCount
|
achievement.totalAchievementCount,
|
||||||
),
|
|
||||||
valueOverride: `${achievement.unlockedAchievementCount}/${achievement.totalAchievementCount} achievements`,
|
valueOverride: `${achievement.unlockedAchievementCount}/${achievement.totalAchievementCount} achievements`,
|
||||||
},
|
},
|
||||||
}),
|
};
|
||||||
|
|
||||||
|
new Notification({
|
||||||
|
...options,
|
||||||
|
toastXml: toXmlString(options),
|
||||||
}).show();
|
}).show();
|
||||||
|
|
||||||
sound.play(achievementSoundPath);
|
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;
|
||||||
|
}
|
29
yarn.lock
29
yarn.lock
@ -2824,26 +2824,6 @@
|
|||||||
"@types/babel__core" "^7.20.5"
|
"@types/babel__core" "^7.20.5"
|
||||||
react-refresh "^0.14.0"
|
react-refresh "^0.14.0"
|
||||||
|
|
||||||
"@xan105/error@^1.6.2", "@xan105/error@^1.7.0":
|
|
||||||
version "1.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@xan105/error/-/error-1.7.1.tgz#d417e839cef7d79df4594943553d3d5b14f26bfa"
|
|
||||||
integrity sha512-FYIUYijbmg62L9QQ5BsR14DuZatAJJvwo10yzuEDEsu8L0FAa4DZivWFAf66nYjEiSz50SFGtMxWSyG+y/ZGGw==
|
|
||||||
|
|
||||||
"@xan105/fs@^2.2.1":
|
|
||||||
version "2.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@xan105/fs/-/fs-2.2.1.tgz#46ca0f943443f5fa5daebd0af6bee289637be098"
|
|
||||||
integrity sha512-jYvheYkJ1F6XfUYSfCIgdfgx/yWiW5uitXhydEceirICNMRubboNQM1LUB5+ZDmKq4hCNyjqxv4TPeARMcOepQ==
|
|
||||||
dependencies:
|
|
||||||
"@xan105/error" "^1.6.2"
|
|
||||||
"@xan105/is" "^2.9.3"
|
|
||||||
|
|
||||||
"@xan105/is@^2.9.3":
|
|
||||||
version "2.9.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/@xan105/is/-/is-2.9.3.tgz#81c2152202e450c0aad8927fdc6eea30649f30d6"
|
|
||||||
integrity sha512-1Ivr52VENqksdcvhar+rv+kTSsDWFBPyScpMIJibZJMzSOyiGmu25bJOwiSVl0x2hFJcQW2FFUURUqYyxe9X1g==
|
|
||||||
dependencies:
|
|
||||||
"@xan105/error" "^1.6.2"
|
|
||||||
|
|
||||||
"@xmldom/xmldom@^0.8.8":
|
"@xmldom/xmldom@^0.8.8":
|
||||||
version "0.8.10"
|
version "0.8.10"
|
||||||
resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz"
|
resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz"
|
||||||
@ -7031,15 +7011,6 @@ postgres-range@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863"
|
resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863"
|
||||||
integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==
|
integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==
|
||||||
|
|
||||||
powertoast@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/powertoast/-/powertoast-3.0.0.tgz#38cbcfde8cb15867ef14d89d0c890c76a445f828"
|
|
||||||
integrity sha512-nlGnBkMchJS6P4uQgjROpzHs72WqgB6cYP7hDFACXOZUSu2lXgDqJ5fKt2B/53jO+UynVlbhAQHHQvSOLUAUmQ==
|
|
||||||
dependencies:
|
|
||||||
"@xan105/error" "^1.7.0"
|
|
||||||
"@xan105/fs" "^2.2.1"
|
|
||||||
"@xan105/is" "^2.9.3"
|
|
||||||
|
|
||||||
prebuild-install@^7.1.1:
|
prebuild-install@^7.1.1:
|
||||||
version "7.1.2"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.2.tgz#a5fd9986f5a6251fbc47e1e5c65de71e68c0a056"
|
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.2.tgz#a5fd9986f5a6251fbc47e1e5c65de71e68c0a056"
|
||||||
|
Loading…
Reference in New Issue
Block a user