diff --git a/app/assets/javascripts/discourse/app/components/topic-timeline/container.js b/app/assets/javascripts/discourse/app/components/topic-timeline/container.js index 544159ff0b5..ad6baa2beae 100644 --- a/app/assets/javascripts/discourse/app/components/topic-timeline/container.js +++ b/app/assets/javascripts/discourse/app/components/topic-timeline/container.js @@ -10,10 +10,23 @@ import domUtils from "discourse-common/utils/dom-utils"; import I18n from "discourse-i18n"; export const SCROLLER_HEIGHT = 50; -const MIN_SCROLLAREA_HEIGHT = 170; -const MAX_SCROLLAREA_HEIGHT = 300; +const DEFAULT_MIN_SCROLLAREA_HEIGHT = 170; +const DEFAULT_MAX_SCROLLAREA_HEIGHT = 300; const LAST_READ_HEIGHT = 20; +let desktopMinScrollAreaHeight = DEFAULT_MIN_SCROLLAREA_HEIGHT; +let desktopMaxScrollAreaHeight = DEFAULT_MAX_SCROLLAREA_HEIGHT; + +export function setDesktopScrollAreaHeight( + height = { + min: DEFAULT_MIN_SCROLLAREA_HEIGHT, + max: DEFAULT_MAX_SCROLLAREA_HEIGHT, + } +) { + desktopMinScrollAreaHeight = height.min; + desktopMaxScrollAreaHeight = height.max; +} + export default class TopicTimelineScrollArea extends Component { @service appEvents; @service siteSettings; @@ -118,7 +131,7 @@ export default class TopicTimelineScrollArea extends Component { } get style() { - return htmlSafe(`height: ${scrollareaHeight()}px`); + return htmlSafe(`height: ${this.scrollareaHeight}px`); } get beforePadding() { @@ -151,10 +164,29 @@ export default class TopicTimelineScrollArea extends Component { } get topPosition() { - const bottom = scrollareaHeight() - LAST_READ_HEIGHT / 2; + const bottom = this.scrollareaHeight - LAST_READ_HEIGHT / 2; return this.lastReadTop > bottom ? bottom : this.lastReadTop; } + get scrollareaHeight() { + const composerHeight = + document.getElementById("reply-control").offsetHeight || 0, + headerHeight = document.querySelector(".d-header")?.offsetHeight || 0; + + // scrollarea takes up about half of the timeline's height + const availableHeight = + (window.innerHeight - composerHeight - headerHeight) / 2; + + const minHeight = this.args.mobileView + ? DEFAULT_MIN_SCROLLAREA_HEIGHT + : desktopMinScrollAreaHeight; + const maxHeight = this.args.mobileView + ? DEFAULT_MAX_SCROLLAREA_HEIGHT + : desktopMaxScrollAreaHeight; + + return Math.max(minHeight, Math.min(availableHeight, maxHeight)); + } + get startDate() { return timelineDate(this.args.model.createdAt); } @@ -173,12 +205,14 @@ export default class TopicTimelineScrollArea extends Component { } get lastReadHeight() { - return Math.round(this.lastReadPercentage * scrollareaHeight()); + return Math.round(this.lastReadPercentage * this.scrollareaHeight); } @bind calculatePosition() { - this.timelineScrollareaStyle = htmlSafe(`height: ${scrollareaHeight()}px`); + this.timelineScrollareaStyle = htmlSafe( + `height: ${this.scrollareaHeight}px` + ); const topic = this.args.model; const postStream = topic.postStream; @@ -224,7 +258,7 @@ export default class TopicTimelineScrollArea extends Component { } this.before = this.scrollareaRemaining() * this.percentage; - this.after = scrollareaHeight() - this.before - SCROLLER_HEIGHT; + this.after = this.scrollareaHeight - this.before - SCROLLER_HEIGHT; if (this.percentage === null) { return; @@ -232,7 +266,7 @@ export default class TopicTimelineScrollArea extends Component { if (this.hasBackPosition) { this.lastReadTop = Math.round( - this.lastReadPercentage * scrollareaHeight() + this.lastReadPercentage * this.scrollareaHeight ); this.showButton = this.before + SCROLLER_HEIGHT - 5 < this.lastReadTop || @@ -383,7 +417,7 @@ export default class TopicTimelineScrollArea extends Component { } scrollareaRemaining() { - return scrollareaHeight() - SCROLLER_HEIGHT; + return this.scrollareaHeight - SCROLLER_HEIGHT; } willDestroy() { @@ -427,21 +461,6 @@ export default class TopicTimelineScrollArea extends Component { } } -export function scrollareaHeight() { - const composerHeight = - document.getElementById("reply-control").offsetHeight || 0, - headerHeight = document.querySelector(".d-header")?.offsetHeight || 0; - - // scrollarea takes up about half of the timeline's height - const availableHeight = - (window.innerHeight - composerHeight - headerHeight) / 2; - - return Math.max( - MIN_SCROLLAREA_HEIGHT, - Math.min(availableHeight, MAX_SCROLLAREA_HEIGHT) - ); -} - export function timelineDate(date) { const fmt = date.getFullYear() === new Date().getFullYear() diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index a68c5b5b83a..dff4364e707 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -25,6 +25,7 @@ import { import { addOnKeyUpCallback } from "discourse/components/search-menu/search-term"; import { REFRESH_COUNTS_APP_EVENT_NAME as REFRESH_USER_SIDEBAR_CATEGORIES_SECTION_COUNTS_APP_EVENT_NAME } from "discourse/components/sidebar/user/categories-section"; import { forceDropdownForMenuPanels } from "discourse/components/site-header"; +import { setDesktopScrollAreaHeight } from "discourse/components/topic-timeline/container"; import { addTopicTitleDecorator } from "discourse/components/topic-title"; import { addUserMenuProfileTabItem } from "discourse/components/user-menu/profile-tab-content"; import { addDiscoveryQueryParam } from "discourse/controllers/discovery/list"; @@ -142,7 +143,7 @@ import { modifySelectKit } from "select-kit/mixins/plugin-api"; // docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version // using the format described at https://keepachangelog.com/en/1.0.0/. -export const PLUGIN_API_VERSION = "1.17.0"; +export const PLUGIN_API_VERSION = "1.18.0"; // This helper prevents us from applying the same `modifyClass` over and over in test mode. function canModify(klass, type, resolverName, changes) { @@ -1647,6 +1648,15 @@ class PluginApi { addPluginOutletDecorator(outletName, callback, opts || {}); } + /** + * Used to set the min and max height for the topic timeline scroll area on desktop. Pass object with min/max key value pairs. + * Example: + * api.setDesktopTopicTimelineScrollAreaHeight({ min: 50, max: 100 }); + **/ + setDesktopTopicTimelineScrollAreaHeight(height) { + setDesktopScrollAreaHeight(height); + } + /** * Allows altering the topic title in the topic list, and in the topic view * diff --git a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md index e449599c7cf..91470ac0c92 100644 --- a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md +++ b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md @@ -7,6 +7,12 @@ in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.18.0] - 2023-12-1 + +### Added + +- Added `setDesktopTopicTimelineScrollAreaHeight` function, which takes an object with min/max key value pairs as an argument. This is used to adjust the height of the topic timeline on desktop without CSS hacks that break the functionality of the topic timeline. + ## [1.17.0] - 2023-11-30 ### Added