fix TS errors in TimelineView

This commit is contained in:
Bruno Windels 2021-09-16 15:49:03 +02:00
parent 00aa40ea7b
commit d9ddeaf107

View File

@ -15,7 +15,8 @@ limitations under the License.
*/ */
import {ListView} from "../../general/ListView"; import {ListView} from "../../general/ListView";
import {TemplateView, TemplateBuilder} from "../../general/TemplateView.js"; import {TemplateView, Builder} from "../../general/TemplateView";
import {IObservableValue} from "../../general/BaseUpdateView";
import {GapView} from "./timeline/GapView.js"; import {GapView} from "./timeline/GapView.js";
import {TextMessageView} from "./timeline/TextMessageView.js"; import {TextMessageView} from "./timeline/TextMessageView.js";
import {ImageView} from "./timeline/ImageView.js"; import {ImageView} from "./timeline/ImageView.js";
@ -25,9 +26,15 @@ import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js";
import {AnnouncementView} from "./timeline/AnnouncementView.js"; import {AnnouncementView} from "./timeline/AnnouncementView.js";
import {RedactedView} from "./timeline/RedactedView.js"; import {RedactedView} from "./timeline/RedactedView.js";
import {SimpleTile} from "../../../../../domain/session/room/timeline/tiles/SimpleTile.js"; import {SimpleTile} from "../../../../../domain/session/room/timeline/tiles/SimpleTile.js";
import {TimelineViewModel} from "../../../../../domain/session/room/timeline/TimelineViewModel.js";
import {BaseObservableList as ObservableList} from "../../../../../observable/list/BaseObservableList.js"; import {BaseObservableList as ObservableList} from "../../../../../observable/list/BaseObservableList.js";
//import {TimelineViewModel} from "../../../../../domain/session/room/timeline/TimelineViewModel.js";
interface TimelineViewModel extends IObservableValue {
showJumpDown: boolean;
tiles: ObservableList<SimpleTile>;
setVisibleTileRange(start?: SimpleTile, end?: SimpleTile);
}
type TileView = GapView | AnnouncementView | TextMessageView | type TileView = GapView | AnnouncementView | TextMessageView |
ImageView | VideoView | FileView | MissingAttachmentView | RedactedView; ImageView | VideoView | FileView | MissingAttachmentView | RedactedView;
type TileViewConstructor = (this: TileView, SimpleTile) => void; type TileViewConstructor = (this: TileView, SimpleTile) => void;
@ -71,7 +78,7 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
private tilesView?: TilesListView; private tilesView?: TilesListView;
private resizeObserver?: ResizeObserver; private resizeObserver?: ResizeObserver;
render(t: TemplateBuilder, vm: TimelineViewModel) { render(t: Builder<TimelineViewModel>, vm: TimelineViewModel) {
// assume this view will be mounted in the parent DOM straight away // assume this view will be mounted in the parent DOM straight away
requestAnimationFrame(() => { requestAnimationFrame(() => {
// do initial scroll positioning // do initial scroll positioning
@ -103,38 +110,41 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
return root; return root;
} }
private get scroller() { private get scrollNode(): HTMLElement {
return this.root().firstElementChild as HTMLElement; return (this.root()! as HTMLElement).firstElementChild! as HTMLElement;
}
private get tilesNode(): HTMLElement {
return this.tilesView!.root()! as HTMLElement;
} }
private jumpDown() { private jumpDown() {
const {scroller} = this; const {scrollNode} = this;
this.stickToBottom = true; this.stickToBottom = true;
scroller.scrollTop = scroller.scrollHeight; scrollNode.scrollTop = scrollNode.scrollHeight;
} }
public unmount() { public unmount() {
super.unmount(); super.unmount();
if (this.resizeObserver) { if (this.resizeObserver) {
this.resizeObserver.unobserve(this.root()); this.resizeObserver.unobserve(this.root()! as Element);
this.resizeObserver = null; this.resizeObserver = undefined;
} }
} }
private restoreScrollPosition() { private restoreScrollPosition() {
const {scroller} = this; const {scrollNode, tilesNode} = this;
const tiles = this.tilesView!.root() as HTMLElement;
const missingTilesHeight = scroller.clientHeight - tiles.clientHeight; const missingTilesHeight = scrollNode.clientHeight - tilesNode.clientHeight;
if (missingTilesHeight > 0) { if (missingTilesHeight > 0) {
tiles.style.setProperty("margin-top", `${missingTilesHeight}px`); tilesNode.style.setProperty("margin-top", `${missingTilesHeight}px`);
// we don't have enough tiles to fill the viewport, so set all as visible // we don't have enough tiles to fill the viewport, so set all as visible
const len = this.value.tiles.length; const len = this.value.tiles.length;
this.updateVisibleRange(0, len - 1); this.updateVisibleRange(0, len - 1);
} else { } else {
tiles.style.removeProperty("margin-top"); tilesNode.style.removeProperty("margin-top");
if (this.stickToBottom) { if (this.stickToBottom) {
scroller.scrollTop = scroller.scrollHeight; scrollNode.scrollTop = scrollNode.scrollHeight;
} else if (this.anchoredNode) { } else if (this.anchoredNode) {
const newAnchoredBottom = bottom(this.anchoredNode!); const newAnchoredBottom = bottom(this.anchoredNode!);
if (newAnchoredBottom !== this.anchoredBottom) { if (newAnchoredBottom !== this.anchoredBottom) {
@ -142,10 +152,10 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
// scrollBy tends to create less scroll jumps than reassigning scrollTop as it does // scrollBy tends to create less scroll jumps than reassigning scrollTop as it does
// not depend on reading scrollTop, which might be out of date as some platforms // not depend on reading scrollTop, which might be out of date as some platforms
// run scrolling off the main thread. // run scrolling off the main thread.
if (typeof scroller.scrollBy === "function") { if (typeof scrollNode.scrollBy === "function") {
scroller.scrollBy(0, bottomDiff); scrollNode.scrollBy(0, bottomDiff);
} else { } else {
scroller.scrollTop = scroller.scrollTop + bottomDiff; scrollNode.scrollTop = scrollNode.scrollTop + bottomDiff;
} }
this.anchoredBottom = newAnchoredBottom; this.anchoredBottom = newAnchoredBottom;
} }
@ -156,9 +166,8 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
} }
private onScroll(): void { private onScroll(): void {
const {scroller} = this; const {scrollNode, tilesNode} = this;
const {scrollHeight, scrollTop, clientHeight} = scroller; const {scrollHeight, scrollTop, clientHeight} = scrollNode;
const tiles = this.tilesView!.root() as HTMLElement;
let bottomNodeIndex; let bottomNodeIndex;
this.stickToBottom = Math.abs(scrollHeight - (scrollTop + clientHeight)) < 1; this.stickToBottom = Math.abs(scrollHeight - (scrollTop + clientHeight)) < 1;
@ -168,12 +177,12 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
} else { } else {
const viewportBottom = scrollTop + clientHeight; const viewportBottom = scrollTop + clientHeight;
// console.log(`viewportBottom: ${viewportBottom} (${scrollTop} + ${clientHeight})`); // console.log(`viewportBottom: ${viewportBottom} (${scrollTop} + ${clientHeight})`);
const anchoredNodeIndex = findFirstNodeIndexAtOrBelow(tiles, viewportBottom); const anchoredNodeIndex = findFirstNodeIndexAtOrBelow(tilesNode, viewportBottom);
this.anchoredNode = tiles.childNodes[anchoredNodeIndex] as HTMLElement; this.anchoredNode = tilesNode.childNodes[anchoredNodeIndex] as HTMLElement;
this.anchoredBottom = bottom(this.anchoredNode!); this.anchoredBottom = bottom(this.anchoredNode!);
bottomNodeIndex = anchoredNodeIndex; bottomNodeIndex = anchoredNodeIndex;
} }
let topNodeIndex = findFirstNodeIndexAtOrBelow(tiles, scrollTop, bottomNodeIndex); let topNodeIndex = findFirstNodeIndexAtOrBelow(tilesNode, scrollTop, bottomNodeIndex);
this.updateVisibleRange(topNodeIndex, bottomNodeIndex); this.updateVisibleRange(topNodeIndex, bottomNodeIndex);
} }