Update TrueAchievements button in Guide Menu

This commit is contained in:
redphx 2024-09-04 19:44:41 +07:00
parent 29f6413306
commit 6a792548fa
5 changed files with 77 additions and 54 deletions

View File

@ -326,36 +326,18 @@ function observeRootDialog($root: HTMLElement) {
continue;
}
console.log('added', mutation.addedNodes);
BX_FLAGS.Debug && BxLogger.warning('RootDialog', 'added', mutation.addedNodes);
if (mutation.addedNodes.length === 1) {
const $addedElm = mutation.addedNodes[0];
if ($addedElm instanceof HTMLElement && $addedElm.className) {
if ($addedElm.className.startsWith('NavigationAnimation') || $addedElm.className.startsWith('DialogRoutes') || $addedElm.className.startsWith('Dialog-module__container')) {
// Make sure it's Guide dialog
if (document.querySelector('#gamepass-dialog-root div[class*=GuideDialog]')) {
// Achievement Details page
const $achievDetailPage = $addedElm.querySelector('div[class*=AchievementDetailPage]');
if ($achievDetailPage) {
TrueAchievements.injectAchievementDetailPage($achievDetailPage as HTMLElement);
} else {
// Find navigation bar
const $selectedTab = $addedElm.querySelector('div[class^=NavigationMenu] button[aria-selected=true');
if ($selectedTab) {
let $elm: Element | null = $selectedTab;
let index;
for (index = 0; ($elm = $elm?.previousElementSibling); index++);
if (index === 0) {
BxEvent.dispatch(window, BxEvent.XCLOUD_GUIDE_MENU_SHOWN, {where: GuideMenuTab.HOME});
}
}
}
}
// Make sure it's Guide dialog
if ($root.querySelector('div[class*=GuideDialog]')) {
GuideMenu.observe($addedElm);
}
}
}
const shown = ($root.firstElementChild && $root.firstElementChild.childElementCount > 0) || false;
const shown = !!($root.firstElementChild && $root.firstElementChild.childElementCount > 0);
if (shown !== beingShown) {
beingShown = shown;
BxEvent.dispatch(window, shown ? BxEvent.XCLOUD_DIALOG_SHOWN : BxEvent.XCLOUD_DIALOG_DISMISSED);
@ -416,7 +398,7 @@ function main() {
(getPref(PrefKey.GAME_BAR_POSITION) !== 'off') && GameBar.getInstance();
Screenshot.setup();
GuideMenu.observe();
GuideMenu.addEventListeners();
StreamBadges.setupEvents();
StreamStats.setupEvents();
EmulatedMkbHandler.setupEvents();

View File

@ -42,7 +42,7 @@ export class GuideMenu {
reloadPage: createButton({
icon: BxIcon.REFRESH,
title: t('reload-page'),
style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE | ButtonStyle.GHOST,
style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE,
onClick: e => {
if (STATES.isPlaying) {
confirm(t('confirm-reload-stream')) && window.location.reload();
@ -58,7 +58,7 @@ export class GuideMenu {
backToHome: createButton({
icon: BxIcon.HOME,
title: t('back-to-home'),
style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE | ButtonStyle.GHOST,
style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE,
onClick: e => {
confirm(t('back-to-home-confirm')) && (window.location.href = window.location.href.substring(0, 31));
@ -69,17 +69,6 @@ export class GuideMenu {
'data-state': 'playing',
},
}),
trueAchievements: createButton({
label: t('true-achievements'),
style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE,
onClick: e => {
TrueAchievements.open(false);
// Close all xCloud's dialogs
window.BX_EXPOSED.dialogRoutes.closeAll();
},
}),
}
static #$renderedButtons: HTMLElement;
@ -95,8 +84,8 @@ export class GuideMenu {
const buttons = [
GuideMenu.#BUTTONS.scriptSettings,
GuideMenu.#BUTTONS.trueAchievements,
[
TrueAchievements.$button,
GuideMenu.#BUTTONS.backToHome,
GuideMenu.#BUTTONS.reloadPage,
GuideMenu.#BUTTONS.closeApp,
@ -159,7 +148,35 @@ export class GuideMenu {
}
}
static observe() {
static addEventListeners() {
window.addEventListener(BxEvent.XCLOUD_GUIDE_MENU_SHOWN, GuideMenu.#onShown);
}
static observe($addedElm: HTMLElement) {
const className = $addedElm.className;
if (!className.startsWith('NavigationAnimation') &&
!className.startsWith('DialogRoutes') &&
!className.startsWith('Dialog-module__container')) {
return;
}
// Achievement Details page
const $achievDetailPage = $addedElm.querySelector('div[class*=AchievementDetailPage]');
if ($achievDetailPage) {
TrueAchievements.injectAchievementDetailPage($achievDetailPage as HTMLElement);
return;
}
// Find navigation bar
const $selectedTab = $addedElm.querySelector('div[class^=NavigationMenu] button[aria-selected=true');
if ($selectedTab) {
let $elm: Element | null = $selectedTab;
let index;
for (index = 0; ($elm = $elm?.previousElementSibling); index++);
if (index === 0) {
BxEvent.dispatch(window, BxEvent.XCLOUD_GUIDE_MENU_SHOWN, {where: GuideMenuTab.HOME});
}
}
}
}

View File

@ -1,4 +1,6 @@
import { AppInterface } from "@utils/global";
import { BxLogger } from "./bx-logger";
import { BX_FLAGS } from "./bx-flags";
export namespace BxEvent {
@ -75,6 +77,8 @@ export namespace BxEvent {
target.dispatchEvent(event);
AppInterface && AppInterface.onEvent(eventName);
BX_FLAGS.Debug && BxLogger.warning('BxEvent', 'dispatch', eventName, data)
}
}

View File

@ -1,6 +1,8 @@
import { BxLogger } from "./bx-logger";
type BxFlags = {
Debug: boolean;
CheckForUpdate: boolean;
EnableXcloudLogging: boolean;
SafariWorkaround: boolean;
@ -20,6 +22,8 @@ type BxFlags = {
// Setup flags
const DEFAULT_FLAGS: BxFlags = {
Debug: false,
CheckForUpdate: true,
EnableXcloudLogging: false,
SafariWorkaround: true,

View File

@ -1,24 +1,43 @@
import { BxIcon } from "./bx-icon";
import { AppInterface, STATES } from "./global";
import { ButtonStyle, CE, createButton, getReactProps } from "./html";
import { t } from "./translation";
export class TrueAchievements {
private static $taLink = createButton({
private static $link = createButton({
label: t('true-achievements'),
url: 'https://www.trueachievements.com',
url: '#',
icon: BxIcon.TRUE_ACHIEVEMENTS,
style: ButtonStyle.FOCUSABLE | ButtonStyle.GHOST | ButtonStyle.FULL_WIDTH | ButtonStyle.NORMAL_LINK,
onClick: e => {
e.preventDefault();
const dataset = TrueAchievements.$taLink.dataset;
TrueAchievements.open(true, dataset.xboxTitleId, dataset.id);
},
onClick: TrueAchievements.onClick,
}) as HTMLAnchorElement;
static $button = createButton({
title: t('true-achievements'),
icon: BxIcon.TRUE_ACHIEVEMENTS,
style: ButtonStyle.FOCUSABLE | ButtonStyle.FULL_WIDTH,
onClick: TrueAchievements.onClick,
}) as HTMLAnchorElement;
private static onClick(e: Event) {
e.preventDefault();
const dataset = TrueAchievements.$link.dataset;
TrueAchievements.open(true, dataset.xboxTitleId, dataset.id);
}
private static $hiddenLink = CE<HTMLAnchorElement>('a', {
target: '_blank',
});
private static updateLinks(xboxTitleId?: string, id?: string) {
TrueAchievements.$link.dataset.xboxTitleId = xboxTitleId;
TrueAchievements.$link.dataset.id = id;
TrueAchievements.$button.dataset.xboxTitleId = xboxTitleId;
TrueAchievements.$button.dataset.id = id;
}
static injectAchievementDetailPage($parent: HTMLElement) {
const props = getReactProps($parent);
if (!props) {
@ -46,17 +65,14 @@ export class TrueAchievements {
// Found achievement -> add TrueAchievements button
if (id) {
TrueAchievements.$taLink.dataset.xboxTitleId = xboxTitleId;
TrueAchievements.$taLink.dataset.id = id;
TrueAchievements.$taLink.href = `https://www.trueachievements.com/deeplink/${xboxTitleId}/${id}`;
$parent.appendChild(TrueAchievements.$taLink);
TrueAchievements.updateLinks(xboxTitleId, id);
$parent.appendChild(TrueAchievements.$link);
}
} catch (e) {};
}
static open(override: boolean, xboxTitleId?: number | string, id?: number | string) {
if (!xboxTitleId) {
if (!xboxTitleId || xboxTitleId === 'undefined') {
xboxTitleId = STATES.currentStream.xboxTitleId || STATES.currentStream.titleInfo?.details.xboxTitleId;
}
@ -67,7 +83,7 @@ export class TrueAchievements {
let url = 'https://www.trueachievements.com';
if (xboxTitleId) {
if (id) {
if (id && id !== 'undefined') {
url += `/deeplink/${xboxTitleId}/${id}`;
} else {
url += `/deeplink/${xboxTitleId}`;