forked from mystiq/hydrogen-web
allow injecting the tilesCreator from the Root/Session/RoomViewModel
this changes the API slightly to be more future-proof, as we'll expose it in the SDK now. The function now returns a SimpleTile constructor, rather than an instance. This allows us to test if an entry would render in the timeline without creating a tile, which is something we might want in the matrix layer later on. The function is now called tileClassForEntry, analogue to what we do in TimelineView.
This commit is contained in:
parent
220f35ae03
commit
5445db2a42
17 changed files with 174 additions and 133 deletions
|
@ -18,17 +18,17 @@ limitations under the License.
|
|||
import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
|
||||
import {ComposerViewModel} from "./ComposerViewModel.js"
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar";
|
||||
import {tilesCreator} from "./timeline/tilesCreator.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {imageToInfo} from "../common.js";
|
||||
|
||||
export class RoomViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
const {room} = options;
|
||||
const {room, tileClassForEntry} = options;
|
||||
this._room = room;
|
||||
this._timelineVM = null;
|
||||
this._tilesCreator = null;
|
||||
this._tileClassForEntry = tileClassForEntry;
|
||||
this._tileOptions = undefined;
|
||||
this._onRoomChange = this._onRoomChange.bind(this);
|
||||
this._timelineError = null;
|
||||
this._sendError = null;
|
||||
|
@ -46,12 +46,13 @@ export class RoomViewModel extends ViewModel {
|
|||
this._room.on("change", this._onRoomChange);
|
||||
try {
|
||||
const timeline = await this._room.openTimeline();
|
||||
this._tilesCreator = tilesCreator(this.childOptions({
|
||||
this._tileOptions = this.childOptions({
|
||||
roomVM: this,
|
||||
timeline,
|
||||
}));
|
||||
tileClassForEntry: this._tileClassForEntry,
|
||||
});
|
||||
this._timelineVM = this.track(new TimelineViewModel(this.childOptions({
|
||||
tilesCreator: this._tilesCreator,
|
||||
tileOptions: this._tileOptions,
|
||||
timeline,
|
||||
})));
|
||||
this.emitChange("timelineViewModel");
|
||||
|
@ -161,7 +162,12 @@ export class RoomViewModel extends ViewModel {
|
|||
}
|
||||
|
||||
_createTile(entry) {
|
||||
return this._tilesCreator(entry);
|
||||
if (this._tileOptions) {
|
||||
const Tile = this._tileOptions.tileClassForEntry(entry);
|
||||
if (Tile) {
|
||||
return new Tile(entry, this._tileOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _sendMessage(message, replyingTo) {
|
||||
|
|
|
@ -222,7 +222,7 @@ export function tests() {
|
|||
};
|
||||
const tiles = new MappedList(timeline.entries, entry => {
|
||||
if (entry.eventType === "m.room.message") {
|
||||
return new BaseMessageTile({entry, roomVM: {room}, timeline, platform: {logger}});
|
||||
return new BaseMessageTile(entry, {roomVM: {room}, timeline, platform: {logger}});
|
||||
}
|
||||
return null;
|
||||
}, (tile, params, entry) => tile?.updateEntry(entry, params, function () {}));
|
||||
|
|
|
@ -18,20 +18,27 @@ import {BaseObservableList} from "../../../../observable/list/BaseObservableList
|
|||
import {sortedIndex} from "../../../../utils/sortedIndex";
|
||||
|
||||
// maps 1..n entries to 0..1 tile. Entries are what is stored in the timeline, either an event or fragmentboundary
|
||||
// for now, tileCreator should be stable in whether it returns a tile or not.
|
||||
// for now, tileClassForEntry should be stable in whether it returns a tile or not.
|
||||
// e.g. the decision to create a tile or not should be based on properties
|
||||
// not updated later on (e.g. event type)
|
||||
// also see big comment in onUpdate
|
||||
export class TilesCollection extends BaseObservableList {
|
||||
constructor(entries, tileCreator) {
|
||||
constructor(entries, tileOptions) {
|
||||
super();
|
||||
this._entries = entries;
|
||||
this._tiles = null;
|
||||
this._entrySubscription = null;
|
||||
this._tileCreator = tileCreator;
|
||||
this._tileOptions = tileOptions;
|
||||
this._emitSpontanousUpdate = this._emitSpontanousUpdate.bind(this);
|
||||
}
|
||||
|
||||
_createTile(entry) {
|
||||
const Tile = this._tileOptions.tileClassForEntry(entry);
|
||||
if (Tile) {
|
||||
return new Tile(entry, this._tileOptions);
|
||||
}
|
||||
}
|
||||
|
||||
_emitSpontanousUpdate(tile, params) {
|
||||
const entry = tile.lowerEntry;
|
||||
const tileIdx = this._findTileIdx(entry);
|
||||
|
@ -48,7 +55,7 @@ export class TilesCollection extends BaseObservableList {
|
|||
let currentTile = null;
|
||||
for (let entry of this._entries) {
|
||||
if (!currentTile || !currentTile.tryIncludeEntry(entry)) {
|
||||
currentTile = this._tileCreator(entry);
|
||||
currentTile = this._createTile(entry);
|
||||
if (currentTile) {
|
||||
this._tiles.push(currentTile);
|
||||
}
|
||||
|
@ -121,7 +128,7 @@ export class TilesCollection extends BaseObservableList {
|
|||
return;
|
||||
}
|
||||
|
||||
const newTile = this._tileCreator(entry);
|
||||
const newTile = this._createTile(entry);
|
||||
if (newTile) {
|
||||
if (prevTile) {
|
||||
prevTile.updateNextSibling(newTile);
|
||||
|
@ -150,9 +157,9 @@ export class TilesCollection extends BaseObservableList {
|
|||
const tileIdx = this._findTileIdx(entry);
|
||||
const tile = this._findTileAtIdx(entry, tileIdx);
|
||||
if (tile) {
|
||||
const action = tile.updateEntry(entry, params, this._tileCreator);
|
||||
const action = tile.updateEntry(entry, params);
|
||||
if (action.shouldReplace) {
|
||||
const newTile = this._tileCreator(entry);
|
||||
const newTile = this._createTile(entry);
|
||||
if (newTile) {
|
||||
this._replaceTile(tileIdx, tile, newTile, action.updateParams);
|
||||
newTile.setUpdateEmit(this._emitSpontanousUpdate);
|
||||
|
@ -303,7 +310,10 @@ export function tests() {
|
|||
}
|
||||
}
|
||||
const entries = new ObservableArray([{n: 5}, {n: 10}]);
|
||||
const tiles = new TilesCollection(entries, entry => new UpdateOnSiblingTile(entry));
|
||||
const tileOptions = {
|
||||
tileClassForEntry: entry => UpdateOnSiblingTile,
|
||||
};
|
||||
const tiles = new TilesCollection(entries, tileOptions);
|
||||
let receivedAdd = false;
|
||||
tiles.subscribe({
|
||||
onAdd(idx, tile) {
|
||||
|
@ -326,7 +336,10 @@ export function tests() {
|
|||
}
|
||||
}
|
||||
const entries = new ObservableArray([{n: 5}, {n: 10}, {n: 15}]);
|
||||
const tiles = new TilesCollection(entries, entry => new UpdateOnSiblingTile(entry));
|
||||
const tileOptions = {
|
||||
tileClassForEntry: entry => UpdateOnSiblingTile,
|
||||
};
|
||||
const tiles = new TilesCollection(entries, tileOptions);
|
||||
const events = [];
|
||||
tiles.subscribe({
|
||||
onUpdate(idx, tile) {
|
||||
|
|
|
@ -37,9 +37,9 @@ import {ViewModel} from "../../../ViewModel";
|
|||
export class TimelineViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
const {timeline, tilesCreator} = options;
|
||||
const {timeline, tileOptions} = options;
|
||||
this._timeline = this.track(timeline);
|
||||
this._tiles = new TilesCollection(timeline.entries, tilesCreator);
|
||||
this._tiles = new TilesCollection(timeline.entries, tileOptions);
|
||||
this._startTile = null;
|
||||
this._endTile = null;
|
||||
this._topLoadingPromise = null;
|
||||
|
|
|
@ -21,8 +21,8 @@ const MAX_HEIGHT = 300;
|
|||
const MAX_WIDTH = 400;
|
||||
|
||||
export class BaseMediaTile extends BaseMessageTile {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(entry, options) {
|
||||
super(entry, options);
|
||||
this._decryptedThumbnail = null;
|
||||
this._decryptedFile = null;
|
||||
this._isVisible = false;
|
||||
|
|
|
@ -19,8 +19,8 @@ import {ReactionsViewModel} from "../ReactionsViewModel.js";
|
|||
import {getIdentifierColorNumber, avatarInitials, getAvatarHttpUrl} from "../../../../avatar";
|
||||
|
||||
export class BaseMessageTile extends SimpleTile {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(entry, options) {
|
||||
super(entry, options);
|
||||
this._date = this._entry.timestamp ? new Date(this._entry.timestamp) : null;
|
||||
this._isContinuation = false;
|
||||
this._reactions = null;
|
||||
|
@ -28,7 +28,7 @@ export class BaseMessageTile extends SimpleTile {
|
|||
if (this._entry.annotations || this._entry.pendingAnnotations) {
|
||||
this._updateReactions();
|
||||
}
|
||||
this._updateReplyTileIfNeeded(options.tilesCreator, undefined);
|
||||
this._updateReplyTileIfNeeded(undefined);
|
||||
}
|
||||
|
||||
notifyVisible() {
|
||||
|
@ -122,23 +122,27 @@ export class BaseMessageTile extends SimpleTile {
|
|||
}
|
||||
}
|
||||
|
||||
updateEntry(entry, param, tilesCreator) {
|
||||
const action = super.updateEntry(entry, param, tilesCreator);
|
||||
updateEntry(entry, param) {
|
||||
const action = super.updateEntry(entry, param);
|
||||
if (action.shouldUpdate) {
|
||||
this._updateReactions();
|
||||
}
|
||||
this._updateReplyTileIfNeeded(tilesCreator, param);
|
||||
this._updateReplyTileIfNeeded(param);
|
||||
return action;
|
||||
}
|
||||
|
||||
_updateReplyTileIfNeeded(tilesCreator, param) {
|
||||
_updateReplyTileIfNeeded(param) {
|
||||
const replyEntry = this._entry.contextEntry;
|
||||
if (replyEntry) {
|
||||
// this is an update to contextEntry used for replyPreview
|
||||
const action = this._replyTile?.updateEntry(replyEntry, param, tilesCreator);
|
||||
const action = this._replyTile?.updateEntry(replyEntry, param);
|
||||
if (action?.shouldReplace || !this._replyTile) {
|
||||
this.disposeTracked(this._replyTile);
|
||||
this._replyTile = tilesCreator(replyEntry);
|
||||
const tileClassForEntry = this._options.tileClassForEntry;
|
||||
const ReplyTile = tileClassForEntry(replyEntry);
|
||||
if (ReplyTile) {
|
||||
this._replyTile = new ReplyTile(replyEntry, this._options);
|
||||
}
|
||||
}
|
||||
if(action?.shouldUpdate) {
|
||||
this._replyTile?.emitChange();
|
||||
|
|
|
@ -21,8 +21,8 @@ import {createEnum} from "../../../../../utils/enum";
|
|||
export const BodyFormat = createEnum("Plain", "Html");
|
||||
|
||||
export class BaseTextTile extends BaseMessageTile {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(entry, options) {
|
||||
super(entry, options);
|
||||
this._messageBody = null;
|
||||
this._format = null
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ import {BaseTextTile} from "./BaseTextTile.js";
|
|||
import {UpdateAction} from "../UpdateAction.js";
|
||||
|
||||
export class EncryptedEventTile extends BaseTextTile {
|
||||
updateEntry(entry, params, tilesCreator) {
|
||||
const parentResult = super.updateEntry(entry, params, tilesCreator);
|
||||
updateEntry(entry, params) {
|
||||
const parentResult = super.updateEntry(entry, params);
|
||||
// event got decrypted, recreate the tile and replace this one with it
|
||||
if (entry.eventType !== "m.room.encrypted") {
|
||||
// the "shape" parameter trigger tile recreation in TimelineView
|
||||
|
|
|
@ -20,8 +20,8 @@ import {formatSize} from "../../../../../utils/formatSize";
|
|||
import {SendStatus} from "../../../../../matrix/room/sending/PendingEvent.js";
|
||||
|
||||
export class FileTile extends BaseMessageTile {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(entry, options) {
|
||||
super(entry, options);
|
||||
this._downloadError = null;
|
||||
this._downloading = false;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ import {SimpleTile} from "./SimpleTile.js";
|
|||
import {UpdateAction} from "../UpdateAction.js";
|
||||
|
||||
export class GapTile extends SimpleTile {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(entry, options) {
|
||||
super(entry, options);
|
||||
this._loading = false;
|
||||
this._error = null;
|
||||
this._isAtTop = true;
|
||||
|
@ -81,8 +81,8 @@ export class GapTile extends SimpleTile {
|
|||
this._siblingChanged = true;
|
||||
}
|
||||
|
||||
updateEntry(entry, params, tilesCreator) {
|
||||
super.updateEntry(entry, params, tilesCreator);
|
||||
updateEntry(entry, params) {
|
||||
super.updateEntry(entry, params);
|
||||
if (!entry.isGap) {
|
||||
return UpdateAction.Remove();
|
||||
} else {
|
||||
|
@ -125,7 +125,7 @@ export function tests() {
|
|||
tile.updateEntry(newEntry);
|
||||
}
|
||||
};
|
||||
const tile = new GapTile({entry: new FragmentBoundaryEntry(fragment, true), roomVM: {room}});
|
||||
const tile = new GapTile(new FragmentBoundaryEntry(fragment, true), {roomVM: {room}});
|
||||
await tile.fill();
|
||||
await tile.fill();
|
||||
await tile.fill();
|
||||
|
|
|
@ -18,8 +18,8 @@ limitations under the License.
|
|||
import {BaseMediaTile} from "./BaseMediaTile.js";
|
||||
|
||||
export class ImageTile extends BaseMediaTile {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
constructor(entry, options) {
|
||||
super(entry, options);
|
||||
this._lightboxUrl = this.urlCreator.urlForSegments([
|
||||
// ensure the right room is active if in grid view
|
||||
this.navigation.segment("room", this._room.id),
|
||||
|
|
|
@ -66,23 +66,25 @@ export class RoomMemberTile extends SimpleTile {
|
|||
export function tests() {
|
||||
return {
|
||||
"user removes display name": (assert) => {
|
||||
const tile = new RoomMemberTile({
|
||||
entry: {
|
||||
const tile = new RoomMemberTile(
|
||||
{
|
||||
prevContent: {displayname: "foo", membership: "join"},
|
||||
content: {membership: "join"},
|
||||
stateKey: "foo@bar.com",
|
||||
},
|
||||
});
|
||||
{}
|
||||
);
|
||||
assert.strictEqual(tile.announcement, "foo@bar.com removed their name (foo)");
|
||||
},
|
||||
"user without display name sets a new display name": (assert) => {
|
||||
const tile = new RoomMemberTile({
|
||||
entry: {
|
||||
const tile = new RoomMemberTile(
|
||||
{
|
||||
prevContent: {membership: "join"},
|
||||
content: {displayname: "foo", membership: "join" },
|
||||
stateKey: "foo@bar.com",
|
||||
},
|
||||
});
|
||||
{}
|
||||
);
|
||||
assert.strictEqual(tile.announcement, "foo@bar.com changed their name to foo");
|
||||
},
|
||||
};
|
||||
|
|
|
@ -19,9 +19,9 @@ import {ViewModel} from "../../../../ViewModel";
|
|||
import {SendStatus} from "../../../../../matrix/room/sending/PendingEvent.js";
|
||||
|
||||
export class SimpleTile extends ViewModel {
|
||||
constructor(options) {
|
||||
constructor(entry, options) {
|
||||
super(options);
|
||||
this._entry = options.entry;
|
||||
this._entry = entry;
|
||||
}
|
||||
// view model props for all subclasses
|
||||
// hmmm, could also do instanceof ... ?
|
||||
|
|
94
src/domain/session/room/timeline/tiles/index.ts
Normal file
94
src/domain/session/room/timeline/tiles/index.ts
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {GapTile} from "./GapTile.js";
|
||||
import {TextTile} from "./TextTile.js";
|
||||
import {RedactedTile} from "./RedactedTile.js";
|
||||
import {ImageTile} from "./ImageTile.js";
|
||||
import {VideoTile} from "./VideoTile.js";
|
||||
import {FileTile} from "./FileTile.js";
|
||||
import {LocationTile} from "./LocationTile.js";
|
||||
import {RoomNameTile} from "./RoomNameTile.js";
|
||||
import {RoomMemberTile} from "./RoomMemberTile.js";
|
||||
import {EncryptedEventTile} from "./EncryptedEventTile.js";
|
||||
import {EncryptionEnabledTile} from "./EncryptionEnabledTile.js";
|
||||
import {MissingAttachmentTile} from "./MissingAttachmentTile.js";
|
||||
|
||||
import type {SimpleTile} from "./SimpleTile.js";
|
||||
import type {Room} from "../../../../../matrix/room/Room";
|
||||
import type {Timeline} from "../../../../../matrix/room/timeline/Timeline";
|
||||
import type {FragmentBoundaryEntry} from "../../../../../matrix/room/timeline/entries/FragmentBoundaryEntry";
|
||||
import type {EventEntry} from "../../../../../matrix/room/timeline/entries/EventEntry";
|
||||
import type {PendingEventEntry} from "../../../../../matrix/room/timeline/entries/PendingEventEntry";
|
||||
import type {Options as ViewModelOptions} from "../../../../ViewModel";
|
||||
|
||||
export type TimelineEntry = FragmentBoundaryEntry | EventEntry | PendingEventEntry;
|
||||
export type TileClassForEntryFn = (entry: TimelineEntry) => TileConstructor | undefined;
|
||||
export type Options = ViewModelOptions & {
|
||||
room: Room,
|
||||
timeline: Timeline
|
||||
tileClassForEntry: TileClassForEntryFn;
|
||||
};
|
||||
export type TileConstructor = new (entry: TimelineEntry, options: Options) => SimpleTile;
|
||||
|
||||
export function tileClassForEntry(entry: TimelineEntry): TileConstructor | undefined {
|
||||
if (entry.isGap) {
|
||||
return GapTile;
|
||||
} else if (entry.isPending && entry.pendingEvent.isMissingAttachments) {
|
||||
return MissingAttachmentTile;
|
||||
} else if (entry.eventType) {
|
||||
switch (entry.eventType) {
|
||||
case "m.room.message": {
|
||||
if (entry.isRedacted) {
|
||||
return RedactedTile;
|
||||
}
|
||||
const content = entry.content;
|
||||
const msgtype = content && content.msgtype;
|
||||
switch (msgtype) {
|
||||
case "m.text":
|
||||
case "m.notice":
|
||||
case "m.emote":
|
||||
return TextTile;
|
||||
case "m.image":
|
||||
return ImageTile;
|
||||
case "m.video":
|
||||
return VideoTile;
|
||||
case "m.file":
|
||||
return FileTile;
|
||||
case "m.location":
|
||||
return LocationTile;
|
||||
default:
|
||||
// unknown msgtype not rendered
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
case "m.room.name":
|
||||
return RoomNameTile;
|
||||
case "m.room.member":
|
||||
return RoomMemberTile;
|
||||
case "m.room.encrypted":
|
||||
if (entry.isRedacted) {
|
||||
return RedactedTile;
|
||||
}
|
||||
return EncryptedEventTile;
|
||||
case "m.room.encryption":
|
||||
return EncryptionEnabledTile;
|
||||
default:
|
||||
// unknown type not rendered
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {GapTile} from "./tiles/GapTile.js";
|
||||
import {TextTile} from "./tiles/TextTile.js";
|
||||
import {RedactedTile} from "./tiles/RedactedTile.js";
|
||||
import {ImageTile} from "./tiles/ImageTile.js";
|
||||
import {VideoTile} from "./tiles/VideoTile.js";
|
||||
import {FileTile} from "./tiles/FileTile.js";
|
||||
import {LocationTile} from "./tiles/LocationTile.js";
|
||||
import {RoomNameTile} from "./tiles/RoomNameTile.js";
|
||||
import {RoomMemberTile} from "./tiles/RoomMemberTile.js";
|
||||
import {EncryptedEventTile} from "./tiles/EncryptedEventTile.js";
|
||||
import {EncryptionEnabledTile} from "./tiles/EncryptionEnabledTile.js";
|
||||
import {MissingAttachmentTile} from "./tiles/MissingAttachmentTile.js";
|
||||
|
||||
export function tilesCreator(baseOptions) {
|
||||
const tilesCreator = function tilesCreator(entry, emitUpdate) {
|
||||
const options = Object.assign({entry, emitUpdate, tilesCreator}, baseOptions);
|
||||
if (entry.isGap) {
|
||||
return new GapTile(options);
|
||||
} else if (entry.isPending && entry.pendingEvent.isMissingAttachments) {
|
||||
return new MissingAttachmentTile(options);
|
||||
} else if (entry.eventType) {
|
||||
switch (entry.eventType) {
|
||||
case "m.room.message": {
|
||||
if (entry.isRedacted) {
|
||||
return new RedactedTile(options);
|
||||
}
|
||||
const content = entry.content;
|
||||
const msgtype = content && content.msgtype;
|
||||
switch (msgtype) {
|
||||
case "m.text":
|
||||
case "m.notice":
|
||||
case "m.emote":
|
||||
return new TextTile(options);
|
||||
case "m.image":
|
||||
return new ImageTile(options);
|
||||
case "m.video":
|
||||
return new VideoTile(options);
|
||||
case "m.file":
|
||||
return new FileTile(options);
|
||||
case "m.location":
|
||||
return new LocationTile(options);
|
||||
default:
|
||||
// unknown msgtype not rendered
|
||||
return null;
|
||||
}
|
||||
}
|
||||
case "m.room.name":
|
||||
return new RoomNameTile(options);
|
||||
case "m.room.member":
|
||||
return new RoomMemberTile(options);
|
||||
case "m.room.encrypted":
|
||||
if (entry.isRedacted) {
|
||||
return new RedactedTile(options);
|
||||
}
|
||||
return new EncryptedEventTile(options);
|
||||
case "m.room.encryption":
|
||||
return new EncryptionEnabledTile(options);
|
||||
default:
|
||||
// unknown type not rendered
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return tilesCreator;
|
||||
}
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
// import {RecordRequester, ReplayRequester} from "./matrix/net/request/replay";
|
||||
import {RootViewModel} from "../../domain/RootViewModel.js";
|
||||
import {createNavigation, createRouter} from "../../domain/navigation/index.js";
|
||||
import {tileClassForEntry} from "../../domain/session/room/timeline/tiles/index";
|
||||
// Don't use a default export here, as we use multiple entries during legacy build,
|
||||
// which does not support default exports,
|
||||
// see https://github.com/rollup/plugins/tree/master/packages/multi-entry
|
||||
|
@ -42,6 +43,8 @@ export async function main(platform) {
|
|||
// so we call it that in the view models
|
||||
urlCreator: urlRouter,
|
||||
navigation,
|
||||
// which tiles are supported by the timeline
|
||||
tileClassForEntry
|
||||
});
|
||||
await vm.load();
|
||||
platform.createAndMountRootView(vm);
|
||||
|
|
|
@ -48,6 +48,6 @@ export function viewClassForEntry(vm: SimpleTile): TileViewConstructor {
|
|||
case "redacted":
|
||||
return RedactedView;
|
||||
default:
|
||||
throw new Error(`Tiles of shape "${vm.shape}" are not supported, check the tilesCreator function in the view model`);
|
||||
throw new Error(`Tiles of shape "${vm.shape}" are not supported, check the tileClassForEntry function in the view model`);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue