diff --git a/src/lib/components/decorators.ts b/src/lib/components/decorators.ts index daa48b6f..7e858a08 100644 --- a/src/lib/components/decorators.ts +++ b/src/lib/components/decorators.ts @@ -10,9 +10,7 @@ export enum ConflictingMode { CONTINUOUS, // Continuously check and hide conflicting elements } -type CSSProperties = JQuery.PlainObject< - string | number | ((this: HTMLElement, index: number, value: string) => string | number | void | undefined) ->; +type CSSProperties = Record; /** * Decorator that applies CSS to DOM elements from conflicting extensions @@ -31,23 +29,18 @@ export function StyleConflictingElement( return; } - const styleElements = () => { - $J(selector).each(function () { - $J(this).css(cssProps); - }); - }; - - const checkAndStyle = async () => { - const found = $J(selector).length > 0; - if (found) { - styleElements(); + const checkAndStyle = () => { + const elements = document.querySelectorAll(selector); + for (const el of elements) { + for (const [prop, value] of Object.entries(cssProps)) { + el.style.setProperty(prop, String(value)); + } } - return found; + return elements.length > 0; }; - const interval = setInterval(async () => { - const result = await checkAndStyle(); - if (result && mode === ConflictingMode.ONCE) { + const interval = setInterval(() => { + if (checkAndStyle() && mode === ConflictingMode.ONCE) { clearInterval(interval); } }, 250); diff --git a/src/lib/components/injectors.ts b/src/lib/components/injectors.ts index ab6cc03b..80f16320 100644 --- a/src/lib/components/injectors.ts +++ b/src/lib/components/injectors.ts @@ -19,25 +19,39 @@ enum InjectionType { } interface InjectionConfig { - exists: (ctx: JQuery, selector: string) => boolean; - op: (ctx: JQuery, target: typeof FloatElement) => void; + exists: (ctx: HTMLElement, selector: string) => boolean; + op: (ctx: HTMLElement, target: typeof FloatElement) => void; } +type InjectionGuard = () => boolean; + const InjectionConfigs: {[key in InjectionType]: InjectionConfig} = { [InjectionType.Append]: { - exists: (ctx, selector) => !!ctx.children(selector).length, - op: (ctx, target) => ctx.append(target.elem()), + exists: (anchor, selector) => Array.from(anchor.children).some((child) => child.matches(selector)), + op: (anchor, target) => anchor.appendChild(target.elem()), }, [InjectionType.Before]: { - exists: (ctx, selector) => !!ctx.parent().children(selector).length, - op: (ctx, target) => ctx.before(target.elem()), + exists: (anchor, selector) => hasSiblingMatching(anchor, 'previousElementSibling', selector), + op: (anchor, target) => anchor.before(target.elem()), }, [InjectionType.After]: { - exists: (ctx, selector) => !!ctx.parent().children(selector).length, - op: (ctx, target) => ctx.after(target.elem()), + exists: (anchor, selector) => hasSiblingMatching(anchor, 'nextElementSibling', selector), + op: (anchor, target) => anchor.after(target.elem()), }, }; +/** Checks if any sibling of `anchor` in the given direction matches the selector. */ +function hasSiblingMatching( + anchor: HTMLElement, + direction: keyof Pick, + selector: string +): boolean { + for (let el = anchor[direction]; el; el = el[direction]) { + if (el.matches(selector)) return true; + } + return false; +} + export function CustomElement(): any { return function (target: typeof FloatElement, propertyKey: string, descriptor: PropertyDescriptor) { if (!inPageContext()) { @@ -53,24 +67,34 @@ export function CustomElement(): any { }; } -function Inject(selector: string, mode: InjectionMode, type: InjectionType): any { +const canInject = (guard?: InjectionGuard) => (guard ? guard() : true); + +function Inject(selector: string, mode: InjectionMode, type: InjectionType, guard?: InjectionGuard): any { return function (target: typeof FloatElement, propertyKey: string, descriptor: PropertyDescriptor) { if (!inPageContext()) { return; } + if (!canInject(guard)) { + return; + } + switch (mode) { case InjectionMode.ONCE: - $J(selector).each(function () { - InjectionConfigs[type].op($J(this), target); + document.querySelectorAll(selector).forEach((el) => { + InjectionConfigs[type].op(el, target); }); break; case InjectionMode.CONTINUOUS: setInterval(() => { - $J(selector).each(function () { + if (!canInject(guard)) { + return; + } + + document.querySelectorAll(selector).forEach((el) => { // Don't add the item again if we already have - if (InjectionConfigs[type].exists($J(this), target.tag())) return; + if (InjectionConfigs[type].exists(el, target.tag())) return; - InjectionConfigs[type].op($J(this), target); + InjectionConfigs[type].op(el, target); }); }, 250); break; @@ -78,14 +102,14 @@ function Inject(selector: string, mode: InjectionMode, type: InjectionType): any }; } -export function InjectAppend(selector: string, mode: InjectionMode = InjectionMode.ONCE): any { - return Inject(selector, mode, InjectionType.Append); +export function InjectAppend(selector: string, mode: InjectionMode = InjectionMode.ONCE, guard?: InjectionGuard): any { + return Inject(selector, mode, InjectionType.Append, guard); } -export function InjectBefore(selector: string, mode: InjectionMode = InjectionMode.ONCE): any { - return Inject(selector, mode, InjectionType.Before); +export function InjectBefore(selector: string, mode: InjectionMode = InjectionMode.ONCE, guard?: InjectionGuard): any { + return Inject(selector, mode, InjectionType.Before, guard); } -export function InjectAfter(selector: string, mode: InjectionMode = InjectionMode.ONCE): any { - return Inject(selector, mode, InjectionType.After); +export function InjectAfter(selector: string, mode: InjectionMode = InjectionMode.ONCE, guard?: InjectionGuard): any { + return Inject(selector, mode, InjectionType.After, guard); } diff --git a/src/lib/components/inventory/list_item_modal_styles.ts b/src/lib/components/inventory/list_item_modal_styles.ts index 7d804835..2bdfe7ed 100644 --- a/src/lib/components/inventory/list_item_modal_styles.ts +++ b/src/lib/components/inventory/list_item_modal_styles.ts @@ -96,7 +96,6 @@ export const listItemModalStyles = [ padding: 20px; width: 500px; max-width: 90%; - font-family: Roboto, 'Helvetica Neue', sans-serif; border-width: 2px; border-style: solid; border-color: rgba(193, 206, 255, 0.07); diff --git a/src/lib/components/market/item_row_wrapper.ts b/src/lib/components/market/item_row_wrapper.ts index da8f6bef..c78a87aa 100644 --- a/src/lib/components/market/item_row_wrapper.ts +++ b/src/lib/components/market/item_row_wrapper.ts @@ -28,9 +28,14 @@ import './sticker_display'; import {FetchBluegem, FetchBluegemResponse} from '../../bridge/handlers/fetch_bluegem'; import {ClientSend} from '../../bridge/client'; import {ConflictingExtension, ConflictingMode, HideConflictingElement, StyleConflictingElement} from '../decorators'; +import {isLegacySteamMarket} from './mode'; @CustomElement() -@InjectAppend('#searchResultsRows .market_listing_row .market_listing_item_name_block', InjectionMode.CONTINUOUS) +@InjectAppend( + '#searchResultsRows .market_listing_row .market_listing_item_name_block', + InjectionMode.CONTINUOUS, + isLegacySteamMarket +) @HideConflictingElement( ConflictingExtension.CS2_TRADER, '#searchResultsRows .market_listing_row .stickerHolderMarket, #searchResultsRows .market_listing_row .stickersTotal, #searchResultsRows .market_listing_row .floatBarMarket', diff --git a/src/lib/components/market/mode.ts b/src/lib/components/market/mode.ts new file mode 100644 index 00000000..02775183 --- /dev/null +++ b/src/lib/components/market/mode.ts @@ -0,0 +1,14 @@ +export function isLegacySteamMarket(): boolean { + return ( + typeof $J === 'function' && + typeof g_rgListingInfo === 'object' && + g_rgListingInfo !== null && + typeof g_rgAssets === 'object' && + g_rgAssets !== null + ); +} + +/** True only if current page is part of the Steam Market AND the beta is being used */ +export function isReactSteamMarket(): boolean { + return (window as any).SSR?.reactRoot !== undefined; +} diff --git a/src/lib/components/market/utility_belt.ts b/src/lib/components/market/utility_belt.ts index 4fe38b83..e316709f 100644 --- a/src/lib/components/market/utility_belt.ts +++ b/src/lib/components/market/utility_belt.ts @@ -9,9 +9,10 @@ import '../filter/filter_container'; import {Observe} from '../../utils/observers'; import {isBuggedSkin} from '../../utils/skin'; import {AppId, ContextId} from '../../types/steam_constants'; +import {isLegacySteamMarket} from './mode'; @CustomElement() -@InjectBefore('#searchResultsRows', InjectionMode.ONCE) +@InjectBefore('#searchResultsRows', InjectionMode.ONCE, isLegacySteamMarket) export class UtilityBelt extends FloatElement { @state() private buggedSkinCount = 0; diff --git a/src/lib/page_scripts/utils.ts b/src/lib/page_scripts/utils.ts index 7c9b7630..1c1a1280 100644 --- a/src/lib/page_scripts/utils.ts +++ b/src/lib/page_scripts/utils.ts @@ -63,12 +63,6 @@ export async function init(scriptPath: string, ifPage: () => any) { // @ts-ignore Deprecated name window.csgofloat = true; - // Add Roboto font in the page context - const fontLink = document.createElement('link'); - fontLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@500;700&display=swap'; - fontLink.rel = 'stylesheet'; - document.head.appendChild(fontLink); - ifPage(); return; }