Skip to content

Commit

Permalink
CircDeps: Split out small screen event handling
Browse files Browse the repository at this point in the history
Move small screen event handling into its own class, reducing circular
dependencies from 41 to 12. Also adjust the handler so we only check the screen
size once per update instead of N times, where N is the number of listeners.
  • Loading branch information
danrahn committed Mar 10, 2024
1 parent 8e51de7 commit 5963af9
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 35 deletions.
8 changes: 4 additions & 4 deletions Client/Script/ButtonCreator.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { $, $$, appendChildren, buildNode } from './Common.js';
import { ContextualLog } from '../../Shared/ConsoleLog.js';

import { addWindowResizedListener, isSmallScreen } from './WindowResizeEventHandler.js';
import { getSvgIcon } from './SVGHelper.js';
import Icons from './Icons.js';
import { PlexUI } from './PlexUI.js';
import { ThemeColors } from './ThemeColors.js';
import Tooltip from './Tooltip.js';

Expand All @@ -22,8 +22,8 @@ class ButtonCreator {
* One-time setup that initializes the window resize event listener that determines whether to show
* text labels for dynamic buttons. */
static Setup() {
PlexUI.addResizeListener(() => {
const small = PlexUI.isSmallScreen();
addWindowResizedListener(() => {
const small = isSmallScreen();
$('.button.resizable').forEach((button) => {
const buttonText = $$('.buttonText', button);
buttonText.classList[small ? 'add' : 'remove']('hidden');
Expand Down Expand Up @@ -76,7 +76,7 @@ class ButtonCreator {
button.setAttribute('data-default-tooltip', 1);
}

if (PlexUI.isSmallScreen()) {
if (isSmallScreen()) {
$$('.buttonText', button).classList.add('hidden');
if (!attributes.tooltip) {
Tooltip.setTooltip(button, text);
Expand Down
6 changes: 3 additions & 3 deletions Client/Script/MarkerEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
timeToMs } from './Common.js';
import { ContextualLog } from '../../Shared/ConsoleLog.js';

import { addWindowResizedListener, isSmallScreen } from './WindowResizeEventHandler.js';
import { animateOpacity, slideDown, slideUp } from './AnimationHelpers.js';
import ButtonCreator from './ButtonCreator.js';
import { ClientSettings } from './ClientSettings.js';
Expand All @@ -19,7 +20,6 @@ import MarkerAddStickySettings from './StickySettings/MarkerAddStickySettings.js
import { MarkerData } from '../../Shared/PlexTypes.js';
import { MarkerType } from '../../Shared/MarkerType.js';
import Overlay from './Overlay.js';
import { PlexUI } from './PlexUI.js';
import { ServerCommands } from './Commands.js';
import { ThemeColors } from './ThemeColors.js';
import Tooltip from './Tooltip.js';
Expand Down Expand Up @@ -592,8 +592,8 @@ class ThumbnailMarkerEdit extends MarkerEdit {
/**
* One-time initialization to set up the window resize listener that adjusts the size of preview thumbnails. */
static Setup() {
PlexUI.addResizeListener(() => {
const width = PlexUI.isSmallScreen() ? 180 : 240;
addWindowResizedListener(() => {
const width = isSmallScreen() ? 180 : 240;
$('.inputThumb').forEach(thumb => {
thumb.width = width;
});
Expand Down
3 changes: 2 additions & 1 deletion Client/Script/PlexClientState.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { errorMessage, errorResponseOverlay } from './ErrorHandling.js';
import { FilterSettings, SortConditions, SortOrder } from './FilterDialog.js';
import { PurgedMovieSection, PurgedTVSection } from './PurgedMarkerCache.js';
import { SectionType, ShowData } from '../../Shared/PlexTypes.js';
import { addWindowResizedListener } from './WindowResizeEventHandler.js';
import { BulkActionType } from './BulkActionCommon.js';
import { ClientMovieData } from './ClientDataExtensions.js';
import { ClientSettings } from './ClientSettings.js';
Expand Down Expand Up @@ -71,7 +72,7 @@ class PlexClientStateManager {

// When the window resizes, let search results know so they can
// adjust their UI accordingly.
PlexUI.addResizeListener(() => {
addWindowResizedListener(() => {
if (Instance.#activeSeason) {
Instance.#activeSeason.notifyWindowResize();
}
Expand Down
23 changes: 0 additions & 23 deletions Client/Script/PlexUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ class PlexUIManager {
order : SortOrder.Ascending
};

/**
* Determines whether the window is classified as "small".
* Cached to avoid unnecessary queries if a resize event doesn't change our window size classification. */
#smallScreen = {};

/** Creates the singleton PlexUI for this session. */
static CreateInstance() {
if (Instance) {
Expand Down Expand Up @@ -557,24 +552,6 @@ class PlexUIManager {
// they both are UI-related.
PlexClientState.onFilterApplied();
}

/**
* Adds an listener to the window resize event.
* Ensures the event is only triggered when the small/large screen threshold is crossed.
* @param {(e: Event) => void} callback */
addResizeListener(callback) {
this.#smallScreen[callback] = document.body.clientWidth < 768;
window.addEventListener('resize', () => {
if (this.#smallScreen[callback] === document.body.clientWidth < 768) {
return;
}

this.#smallScreen[callback] = !this.#smallScreen[callback];
callback();
});
}

isSmallScreen() { return document.body.clientWidth < 768; }
}

export { PlexUIManager, UISection, Instance as PlexUI };
9 changes: 5 additions & 4 deletions Client/Script/ResultRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ButtonCreator from './ButtonCreator.js';
import { ClientSettings } from './ClientSettings.js';
import { getSvgIcon } from './SVGHelper.js';
import Icons from './Icons.js';
import { isSmallScreen } from './WindowResizeEventHandler.js';
import MarkerBreakdown from '../../Shared/MarkerBreakdown.js';
import Overlay from './Overlay.js';
import { PlexClientState } from './PlexClientState.js';
Expand Down Expand Up @@ -268,7 +269,7 @@ class ResultRow {
}

// TODO: Is it worth making toFixed dynamic? I don't think so.
const percent = (atLeastOne / mediaItem.episodeCount * 100).toFixed(PlexUI.isSmallScreen() ? 0 : 2);
const percent = (atLeastOne / mediaItem.episodeCount * 100).toFixed(isSmallScreen() ? 0 : 2);
const innerText = buildNode('span', {}, `${atLeastOne}/${mediaItem.episodeCount} (${percent}%)`);

if (this.hasPurgedMarkers()) {
Expand Down Expand Up @@ -1379,7 +1380,7 @@ class EpisodeResultRow extends BaseItemResultRow {
const ep = this.episode();
const sXeY = `S${pad0(ep.seasonIndex, 2)}E${pad0(ep.index, 2)}`;
const base = `${sXeY} - ${ep.title || 'Episode ' + ep.index}`;
if (PlexUI.isSmallScreen()) {
if (isSmallScreen()) {
return base;
}

Expand Down Expand Up @@ -1410,7 +1411,7 @@ class EpisodeResultRow extends BaseItemResultRow {
#buildMarkerText() {
const episode = this.episode();
const hasPurges = this.hasPurgedMarkers();
const smallScreen = PlexUI.isSmallScreen();
const smallScreen = isSmallScreen();
const markerCount = episode.markerTable().markerCount();
const text = buildNode('span', {}, smallScreen ? markerCount.toString() : plural(markerCount, 'Marker'));
if (smallScreen) {
Expand Down Expand Up @@ -1578,7 +1579,7 @@ class MovieResultRow extends BaseItemResultRow {
markerCount = movie.markerTable().markerCount();
}

const smallScreen = PlexUI.isSmallScreen();
const smallScreen = isSmallScreen();
text = buildNode('span', {}, smallScreen ? markerCount.toString() : plural(markerCount, 'Marker'));
if (smallScreen) {
text.classList.add('smallScreenMarkerCount');
Expand Down
37 changes: 37 additions & 0 deletions Client/Script/WindowResizeEventHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { BaseLog } from '../../Shared/ConsoleLog.js';

/**
* Set of all registered event listeners.
* @type {Set<(e: UIEvent) => void>}*/
const smallScreenListeners = new Set();

let smallScreenCached = false;

/**
* Initializes the global window resize event listener, which acts as a wrapper around individually registered listeners. */
export function SetupWindowResizeEventHandler() {
window.addEventListener('resize', (e) => {
if (smallScreenCached === isSmallScreen()) {
return;
}

BaseLog.verbose(`Window changed from small=${smallScreenCached} to ${!smallScreenCached}, ` +
`triggering ${smallScreenListeners.size} listeners`);
smallScreenCached = !smallScreenCached;
for (const listener of smallScreenListeners) {
listener(e);
}
});
}


/** @returns Whether the current window size is considered small */
export function isSmallScreen() { return document.body.clientWidth < 768; }

/**
* Adds an listener to the window resize event.
* Ensures the event is only triggered when the small/large screen threshold is crossed.
* @param {(e: Event) => void} callback */
export function addWindowResizedListener(callback) {
smallScreenListeners.add(callback);
}
2 changes: 2 additions & 0 deletions Client/Script/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { PlexClientStateManager } from './PlexClientState.js';
import { PurgedMarkerManager } from './PurgedMarkerManager.js';
import { ServerCommands } from './Commands.js';
import ServerPausedOverlay from './ServerPausedOverlay.js';
import { SetupWindowResizeEventHandler } from './WindowResizeEventHandler.js';
import StickySettingsBase from './StickySettings/StickySettingsBase.js';
import { ThumbnailMarkerEdit } from './MarkerEdit.js';
import Tooltip from './Tooltip.js';
Expand All @@ -30,6 +31,7 @@ function setup() {
ThumbnailMarkerEdit.Setup();
StickySettingsBase.Setup();
ServerPausedOverlay.Setup();
SetupWindowResizeEventHandler();

// MarkerBreakdownManager is self-contained - we don't need anything from it,
// and it doesn't need anything from us, so no need to keep a reference to it.
Expand Down

0 comments on commit 5963af9

Please sign in to comment.