Show local co-op icon in details page

This commit is contained in:
redphx 2025-01-03 19:49:40 +07:00
parent 68b29ecb50
commit 6448a00271
8 changed files with 73 additions and 18 deletions

View File

@ -106,7 +106,6 @@
&.bx-frosted {
--button-alpha: 0.2;
background-color: unquote('rgba(var(--button-rgb), var(--button-alpha))');
backdrop-filter: blur(4px) brightness(1.5);
&:not([disabled]):not(:active) {
&:hover, &.bx-focusable:focus {

View File

@ -1,3 +1,12 @@
.bx-product-details-icons {
padding: 8px;
border-radius: 4px;
svg {
margin-right: 8px;
}
}
.bx-product-details-buttons {
display: flex;
gap: 10px;

View File

@ -149,6 +149,10 @@ div[class^=HUDButton-module__hiddenContainer] ~ div:not([class^=HUDButton-module
font-family: var(--bx-normal-font) !important;
}
.bx-frosted {
backdrop-filter: blur(4px) brightness(1.5);
}
select[multiple], select[multiple]:focus {
overflow: auto;
border: none;

View File

@ -1054,6 +1054,33 @@ ${subsVar} = subs;
str = PatcherUtils.insertAt(str, returnIndex, newCode);
return str;
},
/*
// 27.0.6-hotfix.1, 28444.js
gameCardPassTitle(str: string) {
// Pass gameTitle info to gameCardCustomIcons()
let index = str.indexOf('=["productId","showInputBadges","ownershipBadgeType"');
index > -1 && (index = PatcherUtils.indexOf(str, ',gameTitle:', index, 500, true));
if (index < 0) {
return false;
}
const gameTitleVar = PatcherUtils.getVariableNameAfter(str, index);
if (!gameTitleVar) {
return false;
}
index = PatcherUtils.indexOf(str, 'return', index);
index = PatcherUtils.indexOf(str, 'productId:', index);
if (index < 0) {
return false;
}
const newCode = `gameTitle: ${gameTitleVar},`;
str = PatcherUtils.insertAt(str, index, newCode);
return str;
},
*/
};
let PATCH_ORDERS = PatcherUtils.filterPatches([
@ -1065,6 +1092,7 @@ let PATCH_ORDERS = PatcherUtils.filterPatches([
'exposeReactCreateComponent',
'gameCardCustomIcons',
// 'gameCardPassTitle',
'modifyPreloadedState',
@ -1185,7 +1213,7 @@ let STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
]);
let PRODUCT_DETAIL_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
AppInterface && 'detectProductDetailPage',
'detectProductDetailPage',
]);
const ALL_PATCHES = [...PATCH_ORDERS, ...HOME_PAGE_PATCH_ORDERS, ...STREAM_PAGE_PATCH_ORDERS, ...PRODUCT_DETAIL_PAGE_PATCH_ORDERS];

View File

@ -5,5 +5,5 @@ const supportedInputIcons = $supportedInputIcons$;
const { productId } = $param$;
if (window.BX_EXPOSED.localCoOpManager.isSupported(productId)) {
supportedInputIcons.push(() => window.BX_EXPOSED.createReactLocalCoOpIcon());
supportedInputIcons.push(window.BX_EXPOSED.createReactLocalCoOpIcon);
}

View File

@ -1,7 +1,8 @@
import { BX_FLAGS } from "@/utils/bx-flags";
import { BxIcon } from "@/utils/bx-icon";
import { AppInterface } from "@/utils/global";
import { ButtonStyle, CE, createButton } from "@/utils/html";
import { ButtonStyle, CE, createButton, createSvgIcon } from "@/utils/html";
import { LocalCoOpManager } from "@/utils/local-co-op-manager";
import { t } from "@/utils/translation";
import { parseDetailsPath } from "@/utils/utils";
@ -28,21 +29,33 @@ export class ProductDetailsPage {
private static injectTimeoutId: number | null = null;
static injectButtons() {
if (!AppInterface) {
return;
}
ProductDetailsPage.injectTimeoutId && clearTimeout(ProductDetailsPage.injectTimeoutId);
ProductDetailsPage.injectTimeoutId = window.setTimeout(() => {
// Find action buttons container
const $container = document.querySelector('div[class*=ActionButtons-module__container]');
if ($container && $container.parentElement) {
$container.parentElement.appendChild(CE('div', {
class: 'bx-product-details-buttons',
},
['android-handheld', 'android'].includes(BX_FLAGS.DeviceInfo.deviceType) && ProductDetailsPage.$btnShortcut,
ProductDetailsPage.$btnWallpaper,
));
// Inputs
const $inputsContainer = document.querySelector<HTMLElement>('div[class*="Header-module__gamePassAndInputsContainer"]');
if ($inputsContainer && !$inputsContainer.dataset.bxInjected) {
$inputsContainer.dataset.bxInjected = 'true';
const { productId } = parseDetailsPath(window.location.pathname);
if (LocalCoOpManager.getInstance().isSupported(productId || '')) {
$inputsContainer.insertAdjacentElement('afterend', CE('div', {
class: 'bx-product-details-icons bx-frosted',
}, createSvgIcon(BxIcon.LOCAL_CO_OP), t('local-co-op')));
}
}
// Inject buttons for Android app
if (AppInterface) {
// Find action buttons container
const $container = document.querySelector('div[class*=ActionButtons-module__container]');
if ($container && $container.parentElement) {
$container.parentElement.appendChild(CE('div', {
class: 'bx-product-details-buttons',
},
['android-handheld', 'android'].includes(BX_FLAGS.DeviceInfo.deviceType) && ProductDetailsPage.$btnShortcut,
ProductDetailsPage.$btnWallpaper,
));
}
}
}, 500);
}

View File

@ -10,6 +10,7 @@ import iconDisplay from "@assets/svg/display.svg" with { type: "text" };
import iconEye from "@assets/svg/eye.svg" with { type: "text" };
import iconEyeSlash from "@assets/svg/eye-slash.svg" with { type: "text" };
import iconHome from "@assets/svg/home.svg" with { type: "text" };
import iconLocalCoOp from "@assets/svg/local-co-op.svg" with { type: "text" };
import iconNativeMkb from "@assets/svg/native-mkb.svg" with { type: "text" };
import iconNew from "@assets/svg/new.svg" with { type: "text" };
import iconPencil from "@assets/svg/pencil-simple-line.svg" with { type: "text" };
@ -52,6 +53,7 @@ export const BxIcon = {
EYE: iconEye,
EYE_SLASH: iconEyeSlash,
HOME: iconHome,
LOCAL_CO_OP: iconLocalCoOp,
NATIVE_MKB: iconNativeMkb,
NEW: iconNew,
MANAGE: iconPencil,

View File

@ -123,7 +123,7 @@ export function productTitleToSlug(title: string): string {
export function parseDetailsPath(path: string) {
const matches = /\/games\/(?<titleSlug>[^\/]+)\/(?<productId>\w+)/.exec(path);
if (!matches?.groups) {
return;
return {};
}
const titleSlug = matches.groups.titleSlug!.replaceAll('\%' + '7C', '-');