Update TA button's logic & layout in the Guide Menu

This commit is contained in:
redphx 2024-09-06 18:07:13 +07:00
parent 756d105f74
commit 421af05882
4 changed files with 116 additions and 16 deletions

View File

@ -1,10 +1,40 @@
.bx-guide-home-achievements-progress {
display: flex;
gap: 10px;
flex-direction: row;
.bx-button {
margin-bottom: 0 !important;
}
html[data-xds-platform=tv] & {
flex-direction: column;
}
html:not([data-xds-platform=tv]) & {
flex-direction: row;
> button:first-of-type {
flex: 1;
}
> button:last-of-type {
width: 40px;
span {
display: none;
}
}
}
}
.bx-guide-home-buttons { .bx-guide-home-buttons {
> div { > div {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 12px; gap: 12px;
body[data-media-type=tv] & { html[data-xds-platform=tv] & {
flex-direction: column; flex-direction: column;
button { button {
@ -12,7 +42,7 @@
} }
} }
body:not([data-media-type=tv]) & { html:not([data-xds-platform=tv]) & {
button { button {
span { span {
display: none; display: none;

View File

@ -88,7 +88,6 @@ export class GuideMenu {
const buttons = [ const buttons = [
GuideMenu.#BUTTONS.scriptSettings, GuideMenu.#BUTTONS.scriptSettings,
[ [
TrueAchievements.$button,
GuideMenu.#BUTTONS.backToHome, GuideMenu.#BUTTONS.backToHome,
GuideMenu.#BUTTONS.reloadPage, GuideMenu.#BUTTONS.reloadPage,
GuideMenu.#BUTTONS.closeApp, GuideMenu.#BUTTONS.closeApp,
@ -116,6 +115,11 @@ export class GuideMenu {
} }
static #injectHome($root: HTMLElement, isPlaying = false) { static #injectHome($root: HTMLElement, isPlaying = false) {
const $achievementsProgress = $root.querySelector('button[class*=AchievementsButton-module__progressBarContainer]');
if ($achievementsProgress) {
TrueAchievements.injectAchievementsProgress($achievementsProgress as HTMLElement);
}
// Find the element to add buttons to // Find the element to add buttons to
let $target: HTMLElement | null = null; let $target: HTMLElement | null = null;
if (isPlaying) { if (isPlaying) {
@ -157,6 +161,12 @@ export class GuideMenu {
static observe($addedElm: HTMLElement) { static observe($addedElm: HTMLElement) {
const className = $addedElm.className; const className = $addedElm.className;
if (className.includes('AchievementsButton-module__progressBarContainer')) {
TrueAchievements.injectAchievementsProgress($addedElm);
return;
}
if (!className.startsWith('NavigationAnimation') && if (!className.startsWith('NavigationAnimation') &&
!className.startsWith('DialogRoutes') && !className.startsWith('DialogRoutes') &&
!className.startsWith('Dialog-module__container')) { !className.startsWith('Dialog-module__container')) {

View File

@ -180,3 +180,10 @@ export function clearFocus() {
document.activeElement.blur(); document.activeElement.blur();
} }
} }
export function clearDataSet($elm: HTMLElement) {
Object.keys($elm.dataset).forEach(key => {
delete $elm.dataset[key];
});
}

View File

@ -1,6 +1,6 @@
import { BxIcon } from "./bx-icon"; import { BxIcon } from "./bx-icon";
import { AppInterface, STATES } from "./global"; import { AppInterface, STATES } from "./global";
import { ButtonStyle, CE, createButton, getReactProps } from "./html"; import { ButtonStyle, CE, clearDataSet, createButton, getReactProps } from "./html";
import { t } from "./translation"; import { t } from "./translation";
export class TrueAchievements { export class TrueAchievements {
@ -16,7 +16,7 @@ export class TrueAchievements {
label: t('true-achievements'), label: t('true-achievements'),
title: t('true-achievements'), title: t('true-achievements'),
icon: BxIcon.TRUE_ACHIEVEMENTS, icon: BxIcon.TRUE_ACHIEVEMENTS,
style: ButtonStyle.FOCUSABLE | ButtonStyle.FULL_WIDTH, style: ButtonStyle.FOCUSABLE,
onClick: TrueAchievements.onClick, onClick: TrueAchievements.onClick,
}) as HTMLAnchorElement; }) as HTMLAnchorElement;
@ -25,18 +25,67 @@ export class TrueAchievements {
const dataset = TrueAchievements.$link.dataset; const dataset = TrueAchievements.$link.dataset;
TrueAchievements.open(true, dataset.xboxTitleId, dataset.id); TrueAchievements.open(true, dataset.xboxTitleId, dataset.id);
// Close all xCloud's dialogs
window.BX_EXPOSED.dialogRoutes.closeAll();
} }
private static $hiddenLink = CE<HTMLAnchorElement>('a', { private static $hiddenLink = CE<HTMLAnchorElement>('a', {
target: '_blank', target: '_blank',
}); });
private static updateLinks(xboxTitleId?: string, id?: string) { private static updateIds(xboxTitleId?: string, id?: string) {
TrueAchievements.$link.dataset.xboxTitleId = xboxTitleId; const $link = TrueAchievements.$link;
TrueAchievements.$link.dataset.id = id; const $button = TrueAchievements.$button;
TrueAchievements.$button.dataset.xboxTitleId = xboxTitleId; clearDataSet($link);
TrueAchievements.$button.dataset.id = id; clearDataSet($button);
if (xboxTitleId) {
$link.dataset.xboxTitleId = xboxTitleId;
$button.dataset.xboxTitleId = xboxTitleId;
}
if (id) {
$link.dataset.id = id;
$button.dataset.id = id;
}
}
static injectAchievementsProgress($elm: HTMLElement) {
const $parent = $elm.parentElement!;
// Wrap xCloud's element with our own
const $div = CE('div', {
class: 'bx-guide-home-achievements-progress',
}, $elm);
// Get xboxTitleId of the game
let xboxTitleId: string | number | undefined;
try {
const $container = $parent.closest('div[class*=AchievementsPreview-module__container]') as HTMLElement;
if ($container) {
const props = getReactProps($container);
xboxTitleId = props.children.props.data.data.xboxTitleId;
}
} catch (e) {}
if (!xboxTitleId) {
xboxTitleId = TrueAchievements.getStreamXboxTitleId();
}
if (typeof xboxTitleId !== 'undefined') {
xboxTitleId = xboxTitleId.toString();
}
TrueAchievements.updateIds(xboxTitleId);
if (document.documentElement.dataset.xdsPlatform === 'tv') {
$div.appendChild(TrueAchievements.$link);
} else {
$div.appendChild(TrueAchievements.$button);
}
$parent.appendChild($div);
} }
static injectAchievementDetailPage($parent: HTMLElement) { static injectAchievementDetailPage($parent: HTMLElement) {
@ -66,15 +115,19 @@ export class TrueAchievements {
// Found achievement -> add TrueAchievements button // Found achievement -> add TrueAchievements button
if (id) { if (id) {
TrueAchievements.updateLinks(xboxTitleId, id); TrueAchievements.updateIds(xboxTitleId, id);
$parent.appendChild(TrueAchievements.$link); $parent.appendChild(TrueAchievements.$link);
} }
} catch (e) {}; } catch (e) {};
} }
private static getStreamXboxTitleId() : number | undefined {
return STATES.currentStream.xboxTitleId || STATES.currentStream.titleInfo?.details.xboxTitleId;
}
static open(override: boolean, xboxTitleId?: number | string, id?: number | string) { static open(override: boolean, xboxTitleId?: number | string, id?: number | string) {
if (!xboxTitleId || xboxTitleId === 'undefined') { if (!xboxTitleId || xboxTitleId === 'undefined') {
xboxTitleId = STATES.currentStream.xboxTitleId || STATES.currentStream.titleInfo?.details.xboxTitleId; xboxTitleId = TrueAchievements.getStreamXboxTitleId();
} }
if (AppInterface && AppInterface.openTrueAchievementsLink) { if (AppInterface && AppInterface.openTrueAchievementsLink) {
@ -84,10 +137,10 @@ export class TrueAchievements {
let url = 'https://www.trueachievements.com'; let url = 'https://www.trueachievements.com';
if (xboxTitleId) { if (xboxTitleId) {
if (id && id !== 'undefined') { url += `/deeplink/${xboxTitleId}`;
url += `/deeplink/${xboxTitleId}/${id}`;
} else { if (id) {
url += `/deeplink/${xboxTitleId}`; url += `/${id}`;
} }
} }