forked from mystiq/hydrogen-web
Get placeholder->room logic working
Feels somewhat hacky, but it mostly works with the caveats: - Room names / avatars bleed between rooms when there are updates. - Clicking on a room doesn't immediately highlight it on the list
This commit is contained in:
parent
cc69fc099d
commit
1b6d9db7cd
6 changed files with 52 additions and 11 deletions
|
@ -33,8 +33,7 @@ export class LeftPanelViewModel extends ViewModel {
|
|||
this._sync = sync;
|
||||
const sync3List = new Sync3ObservableList(sync, rooms);
|
||||
const list = new ConcatList(invites.sortValues((a,b) => a.compare(b)), sync3List);
|
||||
this._tileViewModelsMap = this._mapTileViewModels(list);
|
||||
this._tileViewModels = this._tileViewModelsMap;
|
||||
this._tileViewModels = this._mapTileViewModels(list);
|
||||
this._currentTileVM = null;
|
||||
this._setupNavigation();
|
||||
this._closeUrl = this.urlCreator.urlForSegment("session");
|
||||
|
@ -106,10 +105,23 @@ export class LeftPanelViewModel extends ViewModel {
|
|||
this._currentTileVM?.close();
|
||||
this._currentTileVM = null;
|
||||
if (roomId) {
|
||||
this._currentTileVM = this._tileViewModelsMap.get(roomId);
|
||||
// find the vm for the room. Previously we used a map to do this but sync3 only gives
|
||||
// us a list. We could've re-mapped things in the observable pipeline but we don't need
|
||||
// these values to be kept up-to-date when a O(n) search on click isn't particularly
|
||||
// expensive.
|
||||
let targetVM;
|
||||
for ( let vm of this._tileViewModels ) {
|
||||
if (vm.id === roomId) {
|
||||
targetVM = vm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetVM) {
|
||||
this._currentTileVM = targetVM;
|
||||
this._currentTileVM?.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleGrid() {
|
||||
const room = this.navigation.path.get("room");
|
||||
|
|
|
@ -34,6 +34,10 @@ export class RoomTileViewModel extends BaseTileViewModel {
|
|||
return this._url;
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this._room.id;
|
||||
}
|
||||
|
||||
compare(other) {
|
||||
return this._compareFn(this._room.id, other._room.id);
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ export class Sync3 {
|
|||
this.status = new ObservableValue(SyncStatus.Stopped);
|
||||
this.error = null;
|
||||
// Hydrogen only has 1 list currently (no DM section) so we only need 1 range
|
||||
this.ranges = [[0, 4]];
|
||||
this.ranges = [[0, 49]];
|
||||
this.roomIndexToRoomId = {};
|
||||
this.roomIdToRoomIndex = {};
|
||||
this.totalRooms = 0;
|
||||
|
|
|
@ -19,7 +19,7 @@ import { BaseObservableList } from "./BaseObservableList";
|
|||
import { findAndUpdateInArray } from "./common";
|
||||
|
||||
export type Mapper<F, T> = (value: F) => T
|
||||
export type Updater<F, T> = (mappedValue: T, params: any, value: F) => void;
|
||||
export type Updater<F, T> = (mappedValue: T, params: any, value: F) => any;
|
||||
|
||||
export class BaseMappedList<F, T, R = T> extends BaseObservableList<T> {
|
||||
protected _sourceList: BaseObservableList<F>;
|
||||
|
@ -56,10 +56,21 @@ export function runAdd<F, T, R>(list: BaseMappedList<F, T, R>, index: number, ma
|
|||
}
|
||||
|
||||
export function runUpdate<F, T, R>(list: BaseMappedList<F, T, R>, index: number, value: F, params: any): void {
|
||||
const mappedValue = list._mappedValues![index];
|
||||
let mappedValue = list._mappedValues![index];
|
||||
if (list._updater) {
|
||||
list._updater(mappedValue, params, value);
|
||||
// allow updates to completely remap the underlying data type
|
||||
// TODO: do we need to unsubscribe from anything here?
|
||||
let newMappedValue = list._updater(mappedValue, params, value);
|
||||
if (newMappedValue) {
|
||||
if (!params) {
|
||||
params = {};
|
||||
}
|
||||
params.oldValue = mappedValue;
|
||||
mappedValue = newMappedValue;
|
||||
list._mappedValues![index] = mappedValue;
|
||||
}
|
||||
}
|
||||
// pass the new updated value down the chain
|
||||
list.emitUpdate(index, mappedValue, params);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import { IView } from "./types";
|
|||
export interface IOptions<T, V> extends IParentOptions<T, V> {
|
||||
itemHeight: number;
|
||||
overflowItems?: number;
|
||||
shouldRecreateItem?: (value: any, oldValue: any) => boolean;
|
||||
onRangeVisible?: (range: ListRange) => void;
|
||||
}
|
||||
|
||||
|
@ -33,15 +34,17 @@ export class LazyListView<T, V extends IView> extends ListView<T, V> {
|
|||
private overflowItems: number;
|
||||
private scrollContainer?: HTMLElement;
|
||||
private onRangeVisible?: (range: ListRange) => void;
|
||||
private shouldRecreateItem?: (value: any, oldValue: any) => boolean;
|
||||
|
||||
constructor(
|
||||
{ itemHeight, onRangeVisible, overflowItems = 20, ...options }: IOptions<T, V>,
|
||||
{ itemHeight, onRangeVisible, shouldRecreateItem, overflowItems = 20, ...options }: IOptions<T, V>,
|
||||
childCreator: (value: T) => V
|
||||
) {
|
||||
super(options, childCreator);
|
||||
this.itemHeight = itemHeight;
|
||||
this.overflowItems = overflowItems;
|
||||
this.onRangeVisible = onRangeVisible; // function(ItemRange)
|
||||
this.onRangeVisible = onRangeVisible;
|
||||
this.shouldRecreateItem = shouldRecreateItem;
|
||||
}
|
||||
|
||||
handleEvent(e: Event) {
|
||||
|
@ -190,9 +193,13 @@ export class LazyListView<T, V extends IView> extends ListView<T, V> {
|
|||
|
||||
onUpdate(i: number, value: T, params: any) {
|
||||
if (this.renderRange!.containsIndex(i)) {
|
||||
if (this.shouldRecreateItem && this.shouldRecreateItem(value, params?.oldValue)) {
|
||||
super.recreateItem(this.renderRange!.toLocalIndex(i), value);
|
||||
} else {
|
||||
this.updateChild(this.renderRange!.toLocalIndex(i), value, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private applyRemoveAddResult(result: AddRemoveResult<T>) {
|
||||
// order is important here, the new range can have a different start
|
||||
|
|
|
@ -19,6 +19,8 @@ import {TemplateView} from "../../general/TemplateView";
|
|||
import {RoomTileView} from "./RoomTileView.js";
|
||||
import {InviteTileView} from "./InviteTileView.js";
|
||||
import { PlaceholderRoomTileView } from "./PlaceholderRoomTileView";
|
||||
import { PlaceholderRoomTileViewModel } from "../../../../../domain/session/leftpanel/PlaceholderRoomTileViewModel";
|
||||
import { RoomTileViewModel } from "../../../../../domain/session/leftpanel/RoomTileViewModel";
|
||||
|
||||
class FilterField extends TemplateView {
|
||||
render(t, options) {
|
||||
|
@ -67,6 +69,11 @@ export class LeftPanelView extends TemplateView {
|
|||
onRangeVisible: (range) => {
|
||||
vm.loadRoomRange(range);
|
||||
},
|
||||
shouldRecreateItem: (value, oldValue) => {
|
||||
const isOldRoom = oldValue instanceof RoomTileViewModel;
|
||||
const isNewRoom = value instanceof RoomTileViewModel;
|
||||
return isOldRoom != isNewRoom;
|
||||
}
|
||||
},
|
||||
tileVM => {
|
||||
if (tileVM.kind === "invite") {
|
||||
|
|
Loading…
Reference in a new issue