Compare commits
4 commits
master
...
madlittlem
Author | SHA1 | Date | |
---|---|---|---|
|
ca1e45e04e | ||
|
8356fbf70f | ||
|
5805ce0310 | ||
|
dcc508c037 |
14 changed files with 179 additions and 57 deletions
|
@ -2,6 +2,6 @@
|
||||||
"name": "hydrogen-view-sdk",
|
"name": "hydrogen-view-sdk",
|
||||||
"description": "Embeddable matrix client library, including view components",
|
"description": "Embeddable matrix client library, including view components",
|
||||||
"version": "0.0.4",
|
"version": "0.0.4",
|
||||||
"main": "./hydrogen.es.js",
|
"main": "./lib-build/hydrogen.es.js",
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
rm -rf target
|
rm -rf target/*
|
||||||
yarn run vite build -c vite.sdk-assets-config.js
|
yarn run vite build -c vite.sdk-assets-config.js
|
||||||
yarn run vite build -c vite.sdk-lib-config.js
|
yarn run vite build -c vite.sdk-lib-config.js
|
||||||
yarn tsc -p tsconfig-declaration.json
|
yarn tsc -p tsconfig-declaration.json
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../
|
||||||
import {tilesCreator} from "./timeline/tilesCreator.js";
|
import {tilesCreator} from "./timeline/tilesCreator.js";
|
||||||
import {ViewModel} from "../../ViewModel.js";
|
import {ViewModel} from "../../ViewModel.js";
|
||||||
|
|
||||||
|
console.log('RoomViewModel asdfwafeawfefewfewaeafwafewefw');
|
||||||
export class RoomViewModel extends ViewModel {
|
export class RoomViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
|
@ -45,6 +46,7 @@ export class RoomViewModel extends ViewModel {
|
||||||
this._room.on("change", this._onRoomChange);
|
this._room.on("change", this._onRoomChange);
|
||||||
try {
|
try {
|
||||||
const timeline = await this._room.openTimeline();
|
const timeline = await this._room.openTimeline();
|
||||||
|
console.log('timeline', timeline.entries);
|
||||||
this._tilesCreator = tilesCreator(this.childOptions({
|
this._tilesCreator = tilesCreator(this.childOptions({
|
||||||
roomVM: this,
|
roomVM: this,
|
||||||
timeline,
|
timeline,
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {ViewModel} from "../../../ViewModel.js";
|
||||||
|
|
||||||
export class TimelineViewModel extends ViewModel {
|
export class TimelineViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
console.log('TimelineViewModel asdf', options)
|
||||||
super(options);
|
super(options);
|
||||||
const {timeline, tilesCreator} = options;
|
const {timeline, tilesCreator} = options;
|
||||||
this._timeline = this.track(timeline);
|
this._timeline = this.track(timeline);
|
||||||
|
|
|
@ -87,7 +87,7 @@ export class BaseMessageTile extends SimpleTile {
|
||||||
}
|
}
|
||||||
|
|
||||||
get isOwn() {
|
get isOwn() {
|
||||||
return this._entry.sender === this._ownMember.userId;
|
return this._entry.sender === this._ownMember?.userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isContinuation() {
|
get isContinuation() {
|
||||||
|
|
|
@ -24,5 +24,12 @@ export {SessionViewModel} from "./domain/session/SessionViewModel.js";
|
||||||
export {SessionView} from "./platform/web/ui/session/SessionView.js";
|
export {SessionView} from "./platform/web/ui/session/SessionView.js";
|
||||||
export {RoomViewModel} from "./domain/session/room/RoomViewModel.js";
|
export {RoomViewModel} from "./domain/session/room/RoomViewModel.js";
|
||||||
export {RoomView} from "./platform/web/ui/session/room/RoomView.js";
|
export {RoomView} from "./platform/web/ui/session/room/RoomView.js";
|
||||||
|
export {MediaRepository} from "./matrix/net/MediaRepository";
|
||||||
|
export {TilesCollection} from "./domain/session/room/timeline/TilesCollection.js";
|
||||||
|
export {tilesCreator} from "./domain/session/room/timeline/tilesCreator.js";
|
||||||
|
export {FragmentIdComparer} from "./matrix/room/timeline/FragmentIdComparer.js";
|
||||||
|
export {EventEntry} from "./matrix/room/timeline/entries/EventEntry.js";
|
||||||
|
export {encodeKey, decodeKey, encodeEventIdKey, decodeEventIdKey} from "./matrix/storage/idb/stores/TimelineEventStore";
|
||||||
|
export {Timeline} from "./matrix/room/timeline/Timeline.js";
|
||||||
export {TimelineViewModel} from "./domain/session/room/timeline/TimelineViewModel.js";
|
export {TimelineViewModel} from "./domain/session/room/timeline/TimelineViewModel.js";
|
||||||
export {TimelineView} from "./platform/web/ui/session/room/TimelineView";
|
export {TimelineView} from "./platform/web/ui/session/room/TimelineView";
|
||||||
|
|
|
@ -86,6 +86,7 @@ export class Timeline {
|
||||||
const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(20, txn, log));
|
const readerRequest = this._disposables.track(this._timelineReader.readFromEnd(20, txn, log));
|
||||||
try {
|
try {
|
||||||
const entries = await readerRequest.complete();
|
const entries = await readerRequest.complete();
|
||||||
|
console.log('entries', entries)
|
||||||
this._loadContextEntriesWhereNeeded(entries);
|
this._loadContextEntriesWhereNeeded(entries);
|
||||||
this._setupEntries(entries);
|
this._setupEntries(entries);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -199,8 +200,10 @@ export class Timeline {
|
||||||
if (!this._localEntries?.hasSubscriptions) {
|
if (!this._localEntries?.hasSubscriptions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// find any local relations to this new remote event
|
// find any local relations to these new remote events or maybe these
|
||||||
for (const pee of this._localEntries) {
|
// new remote events reference one of the other new remote events we have.
|
||||||
|
const entryList = new ConcatList(entries, this._localEntries);
|
||||||
|
for (const pee of entryList) {
|
||||||
// this will work because we set relatedEventId when removing remote echos
|
// this will work because we set relatedEventId when removing remote echos
|
||||||
if (pee.relatedEventId) {
|
if (pee.relatedEventId) {
|
||||||
const relationTarget = entries.find(e => e.id === pee.relatedEventId);
|
const relationTarget = entries.find(e => e.id === pee.relatedEventId);
|
||||||
|
|
|
@ -54,6 +54,7 @@ async function readRawTimelineEntriesWithTxn(roomId, eventKey, direction, amount
|
||||||
} else {
|
} else {
|
||||||
eventsWithinFragment = await timelineStore.eventsBefore(roomId, eventKey, amount);
|
eventsWithinFragment = await timelineStore.eventsBefore(roomId, eventKey, amount);
|
||||||
}
|
}
|
||||||
|
console.log('readRawTimelineEntriesWithTxn eventsWithinFragment', eventsWithinFragment)
|
||||||
let eventEntries = eventsWithinFragment.map(e => new EventEntry(e, fragmentIdComparer));
|
let eventEntries = eventsWithinFragment.map(e => new EventEntry(e, fragmentIdComparer));
|
||||||
entries = directionalConcat(entries, eventEntries, direction);
|
entries = directionalConcat(entries, eventEntries, direction);
|
||||||
// prepend or append eventsWithinFragment to entries, and wrap them in EventEntry
|
// prepend or append eventsWithinFragment to entries, and wrap them in EventEntry
|
||||||
|
|
|
@ -40,20 +40,20 @@ interface TimelineEventEntry {
|
||||||
|
|
||||||
type TimelineEventStorageEntry = TimelineEventEntry & { key: string, eventIdKey: string };
|
type TimelineEventStorageEntry = TimelineEventEntry & { key: string, eventIdKey: string };
|
||||||
|
|
||||||
function encodeKey(roomId: string, fragmentId: number, eventIndex: number): string {
|
export function encodeKey(roomId: string, fragmentId: number, eventIndex: number): string {
|
||||||
return `${roomId}|${encodeUint32(fragmentId)}|${encodeUint32(eventIndex)}`;
|
return `${roomId}|${encodeUint32(fragmentId)}|${encodeUint32(eventIndex)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeKey(key: string): { roomId: string, eventKey: EventKey } {
|
export function decodeKey(key: string): { roomId: string, eventKey: EventKey } {
|
||||||
const [roomId, fragmentId, eventIndex] = key.split("|");
|
const [roomId, fragmentId, eventIndex] = key.split("|");
|
||||||
return {roomId, eventKey: new EventKey(decodeUint32(fragmentId), decodeUint32(eventIndex))};
|
return {roomId, eventKey: new EventKey(decodeUint32(fragmentId), decodeUint32(eventIndex))};
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeEventIdKey(roomId: string, eventId: string): string {
|
export function encodeEventIdKey(roomId: string, eventId: string): string {
|
||||||
return `${roomId}|${eventId}`;
|
return `${roomId}|${eventId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeEventIdKey(eventIdKey: string): { roomId: string, eventId: string } {
|
export function decodeEventIdKey(eventIdKey: string): { roomId: string, eventId: string } {
|
||||||
const [roomId, eventId] = eventIdKey.split("|");
|
const [roomId, eventId] = eventIdKey.split("|");
|
||||||
return {roomId, eventId};
|
return {roomId, eventId};
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ export class ListView<T, V extends IView> implements IView, IListObserver<T> {
|
||||||
const root = this._root = el(this._tagName, attr);
|
const root = this._root = el(this._tagName, attr);
|
||||||
this.loadList();
|
this.loadList();
|
||||||
if (this._onItemClick) {
|
if (this._onItemClick) {
|
||||||
root.addEventListener("click", this);
|
//root.addEventListener("click", this);
|
||||||
}
|
}
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ export abstract class TemplateView<T extends IObservableValue> extends BaseUpdat
|
||||||
const builder = new TemplateBuilder(this) as Builder<T>;
|
const builder = new TemplateBuilder(this) as Builder<T>;
|
||||||
try {
|
try {
|
||||||
this._root = this.render(builder, this._value);
|
this._root = this.render(builder, this._value);
|
||||||
|
console.log('this._root', this._root)
|
||||||
} finally {
|
} finally {
|
||||||
builder.close();
|
builder.close();
|
||||||
}
|
}
|
||||||
|
@ -287,6 +288,55 @@ export class TemplateBuilder<T extends IObservableValue> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const node = document.createElementNS(ns, name);
|
const node = document.createElementNS(ns, name);
|
||||||
|
|
||||||
|
const attrMap = {};
|
||||||
|
if(attributes) {
|
||||||
|
for(let [key, value] of Object.entries(attributes)) {
|
||||||
|
let attrName = key;
|
||||||
|
if (key === "className") {
|
||||||
|
attrName = "class";
|
||||||
|
}
|
||||||
|
|
||||||
|
// binding for className as object of className => enabled
|
||||||
|
if (typeof value === "object") {
|
||||||
|
if (key !== "className" || value === null) {
|
||||||
|
// Ignore non-className objects.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (objHasFns(value)) {
|
||||||
|
//this._addClassNamesBinding(node, value);
|
||||||
|
attrMap[attrName] = classNames(value, value);
|
||||||
|
} else {
|
||||||
|
attrMap[attrName] = classNames(value, this._value);
|
||||||
|
}
|
||||||
|
} else if (this._isEventHandler(key, value)) {
|
||||||
|
// no-op
|
||||||
|
} else if (typeof value === "function") {
|
||||||
|
//this._addAttributeBinding(node, key, value);
|
||||||
|
attrMap[attrName] = value(this._value);
|
||||||
|
} else {
|
||||||
|
attrMap[attrName] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const attrString = Object.keys(attrMap)
|
||||||
|
.map((attrKey) => {
|
||||||
|
return `${attrKey}="${attrMap[attrKey]}"`;
|
||||||
|
})
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
const childenStrings = [];
|
||||||
|
for (let child of [].concat(children)) {
|
||||||
|
console.log('child', child)
|
||||||
|
if (typeof child === "function") {
|
||||||
|
//child = this._addTextBinding(child);
|
||||||
|
childenStrings.push('todo');
|
||||||
|
}
|
||||||
|
childenStrings.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<${name} ${attrString}>${childenStrings.join('')}</${name}>`;
|
||||||
|
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
this._setNodeAttributes(node, attributes);
|
this._setNodeAttributes(node, attributes);
|
||||||
|
@ -303,6 +353,8 @@ export class TemplateBuilder<T extends IObservableValue> {
|
||||||
view(view: IView, mountOptions?: IMountArgs): ViewNode {
|
view(view: IView, mountOptions?: IMountArgs): ViewNode {
|
||||||
this._templateView.addSubView(view);
|
this._templateView.addSubView(view);
|
||||||
return mountView(view, mountOptions);
|
return mountView(view, mountOptions);
|
||||||
|
|
||||||
|
//return view.render(this, this._value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// map a value to a view, every time the value changes
|
// map a value to a view, every time the value changes
|
||||||
|
@ -322,7 +374,8 @@ export class TemplateBuilder<T extends IObservableValue> {
|
||||||
if (view) {
|
if (view) {
|
||||||
return this.view(view);
|
return this.view(view);
|
||||||
} else {
|
} else {
|
||||||
return document.createComment("node binding placeholder");
|
//return document.createComment("node binding placeholder");
|
||||||
|
return '<!-- node binding placeholder -->';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -337,7 +390,8 @@ export class TemplateBuilder<T extends IObservableValue> {
|
||||||
if (!rootNode) {
|
if (!rootNode) {
|
||||||
// TODO: this will confuse mapView which assumes that
|
// TODO: this will confuse mapView which assumes that
|
||||||
// a comment node means there is no view to clean up
|
// a comment node means there is no view to clean up
|
||||||
return document.createComment("map placeholder");
|
//return document.createComment("map placeholder");
|
||||||
|
return '<!-- map placeholder -->';
|
||||||
}
|
}
|
||||||
return rootNode;
|
return rootNode;
|
||||||
});
|
});
|
||||||
|
@ -365,16 +419,16 @@ export class TemplateBuilder<T extends IObservableValue> {
|
||||||
You should not call the TemplateBuilder (e.g. `t.xxx()`) at all from the side effect,
|
You should not call the TemplateBuilder (e.g. `t.xxx()`) at all from the side effect,
|
||||||
instead use tags from html.ts to help you construct any DOM you need. */
|
instead use tags from html.ts to help you construct any DOM you need. */
|
||||||
mapSideEffect<R>(mapFn: (value: T) => R, sideEffect: (newV: R, oldV: R | undefined) => void) {
|
mapSideEffect<R>(mapFn: (value: T) => R, sideEffect: (newV: R, oldV: R | undefined) => void) {
|
||||||
let prevValue = mapFn(this._value);
|
// let prevValue = mapFn(this._value);
|
||||||
const binding = () => {
|
// const binding = () => {
|
||||||
const newValue = mapFn(this._value);
|
// const newValue = mapFn(this._value);
|
||||||
if (prevValue !== newValue) {
|
// if (prevValue !== newValue) {
|
||||||
sideEffect(newValue, prevValue);
|
// sideEffect(newValue, prevValue);
|
||||||
prevValue = newValue;
|
// prevValue = newValue;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
this._addBinding(binding);
|
// this._addBinding(binding);
|
||||||
sideEffect(prevValue, undefined);
|
// sideEffect(prevValue, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ export function el(elementName: string, attributes?: BasicAttributes<never> | Ch
|
||||||
}
|
}
|
||||||
|
|
||||||
export function elNS(ns: string, elementName: string, attributes?: BasicAttributes<never> | Child | Child[], children?: Child | Child[]): Element {
|
export function elNS(ns: string, elementName: string, attributes?: BasicAttributes<never> | Child | Child[], children?: Child | Child[]): Element {
|
||||||
|
//console.log('html elNS', new Error().stack);
|
||||||
if (attributes && isChildren(attributes)) {
|
if (attributes && isChildren(attributes)) {
|
||||||
children = attributes;
|
children = attributes;
|
||||||
attributes = undefined;
|
attributes = undefined;
|
||||||
|
@ -67,6 +68,27 @@ export function elNS(ns: string, elementName: string, attributes?: BasicAttribut
|
||||||
|
|
||||||
const e = document.createElementNS(ns, elementName);
|
const e = document.createElementNS(ns, elementName);
|
||||||
|
|
||||||
|
const attrMap = {};
|
||||||
|
if (attributes) {
|
||||||
|
for (let [name, value] of Object.entries(attributes)) {
|
||||||
|
if (typeof value === "object") {
|
||||||
|
// Only className should ever be an object; be careful
|
||||||
|
// here anyway and ignore object-valued non-className attributes.
|
||||||
|
value = (value !== null && name === "className") ? classNames(value, undefined) : false;
|
||||||
|
}
|
||||||
|
attrMap[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const attrString = Object.keys(attrMap)
|
||||||
|
.map((attrKey) => {
|
||||||
|
return `${attrKey}="${attrMap[attrKey]}"`;
|
||||||
|
})
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
return `<${elementName} ${attrString}>${[].concat(children).join('')}</${elementName}>`;
|
||||||
|
|
||||||
|
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
for (let [name, value] of Object.entries(attributes)) {
|
for (let [name, value] of Object.entries(attributes)) {
|
||||||
if (typeof value === "object") {
|
if (typeof value === "object") {
|
||||||
|
@ -93,7 +115,8 @@ export function elNS(ns: string, elementName: string, attributes?: BasicAttribut
|
||||||
}
|
}
|
||||||
|
|
||||||
export function text(str: string): Text {
|
export function text(str: string): Text {
|
||||||
return document.createTextNode(str);
|
return str;
|
||||||
|
//return document.createTextNode(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HTML_NS: string = "http://www.w3.org/1999/xhtml";
|
export const HTML_NS: string = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
|
@ -57,16 +57,34 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
|
||||||
|
|
||||||
render(t: Builder<TimelineViewModel>, 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
|
||||||
this.restoreScrollPosition();
|
// this.restoreScrollPosition();
|
||||||
});
|
// });
|
||||||
|
console.log('vm.tiles', vm.tiles)
|
||||||
|
|
||||||
|
const childrenRenders = [];
|
||||||
|
for(const entry of vm.tiles) {
|
||||||
|
const View = viewClassForEntry(entry);
|
||||||
|
if (View) {
|
||||||
|
const view = new View(entry);
|
||||||
|
const childrenRender = view.render(t, entry);
|
||||||
|
console.log('childrenRender', childrenRender)
|
||||||
|
childrenRenders.push(childrenRender);
|
||||||
|
//childrenViews.push();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.tilesView = new TilesListView(vm.tiles, () => this.restoreScrollPosition());
|
this.tilesView = new TilesListView(vm.tiles, () => this.restoreScrollPosition());
|
||||||
const root = t.div({className: "Timeline"}, [
|
const root = t.div({className: "Timeline"}, [
|
||||||
t.div({
|
t.div(
|
||||||
className: "Timeline_scroller bottom-aligned-scroll",
|
{
|
||||||
onScroll: () => this.onScroll()
|
className: "Timeline_scroller bottom-aligned-scroll",
|
||||||
}, t.view(this.tilesView)),
|
onScroll: () => this.onScroll()
|
||||||
|
},
|
||||||
|
//t.view(this.tilesView)
|
||||||
|
childrenRenders
|
||||||
|
),
|
||||||
t.button({
|
t.button({
|
||||||
className: {
|
className: {
|
||||||
"Timeline_jumpDown": true,
|
"Timeline_jumpDown": true,
|
||||||
|
@ -77,12 +95,12 @@ export class TimelineView extends TemplateView<TimelineViewModel> {
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (typeof ResizeObserver === "function") {
|
// if (typeof ResizeObserver === "function") {
|
||||||
this.resizeObserver = new ResizeObserver(() => {
|
// this.resizeObserver = new ResizeObserver(() => {
|
||||||
this.restoreScrollPosition();
|
// this.restoreScrollPosition();
|
||||||
});
|
// });
|
||||||
this.resizeObserver.observe(root);
|
// this.resizeObserver.observe(root);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,26 +21,36 @@ import {ReplyPreviewError, ReplyPreviewView} from "./ReplyPreviewView.js";
|
||||||
export class TextMessageView extends BaseMessageView {
|
export class TextMessageView extends BaseMessageView {
|
||||||
renderMessageBody(t, vm) {
|
renderMessageBody(t, vm) {
|
||||||
const time = t.time({className: {hidden: !vm.date}}, vm.date + " " + vm.time);
|
const time = t.time({className: {hidden: !vm.date}}, vm.date + " " + vm.time);
|
||||||
const container = t.div({
|
|
||||||
className: {
|
const parts = [];
|
||||||
"Timeline_messageBody": true,
|
for (const part of vm.body.parts) {
|
||||||
statusMessage: vm => vm.shape === "message-status",
|
parts.push(renderPart(part));
|
||||||
}
|
}
|
||||||
}, t.mapView(vm => vm.replyTile, replyTile => {
|
|
||||||
if (this._isReplyPreview) {
|
const container = t.div(
|
||||||
// if this._isReplyPreview = true, this is already a reply preview, don't nest replies for now.
|
{
|
||||||
return null;
|
className: {
|
||||||
}
|
"Timeline_messageBody": true,
|
||||||
else if (vm.isReply && !replyTile) {
|
statusMessage: vm => vm.shape === "message-status",
|
||||||
return new ReplyPreviewError();
|
}
|
||||||
}
|
},
|
||||||
else if (replyTile) {
|
parts,
|
||||||
return new ReplyPreviewView(replyTile);
|
// t.mapView(vm => vm.replyTile, replyTile => {
|
||||||
}
|
// if (this._isReplyPreview) {
|
||||||
else {
|
// // if this._isReplyPreview = true, this is already a reply preview, don't nest replies for now.
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}));
|
// else if (vm.isReply && !replyTile) {
|
||||||
|
// return new ReplyPreviewError();
|
||||||
|
// }
|
||||||
|
// else if (replyTile) {
|
||||||
|
// return new ReplyPreviewView(replyTile);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
);
|
||||||
|
|
||||||
const shouldRemove = (element) => element?.nodeType === Node.ELEMENT_NODE && element.className !== "ReplyPreviewView";
|
const shouldRemove = (element) => element?.nodeType === Node.ELEMENT_NODE && element.className !== "ReplyPreviewView";
|
||||||
|
|
||||||
|
@ -54,6 +64,9 @@ export class TextMessageView extends BaseMessageView {
|
||||||
container.appendChild(time);
|
container.appendChild(time);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue