Merge pull request #668 from vector-im/bwindels/ts-viewmodel
convert ViewModel to typescript
This commit is contained in:
commit
c6dde63abd
33 changed files with 84 additions and 70 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "./ViewModel.js";
|
||||
import {ViewModel} from "./ViewModel";
|
||||
import {KeyType} from "../matrix/ssss/index";
|
||||
import {Status} from "./session/settings/KeyBackupViewModel.js";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "./ViewModel.js";
|
||||
import {ViewModel} from "./ViewModel";
|
||||
import {Client} from "../matrix/Client.js";
|
||||
|
||||
export class LogoutViewModel extends ViewModel {
|
||||
|
|
|
@ -20,7 +20,7 @@ import {SessionLoadViewModel} from "./SessionLoadViewModel.js";
|
|||
import {LoginViewModel} from "./login/LoginViewModel.js";
|
||||
import {LogoutViewModel} from "./LogoutViewModel.js";
|
||||
import {SessionPickerViewModel} from "./SessionPickerViewModel.js";
|
||||
import {ViewModel} from "./ViewModel.js";
|
||||
import {ViewModel} from "./ViewModel";
|
||||
|
||||
export class RootViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import {AccountSetupViewModel} from "./AccountSetupViewModel.js";
|
||||
import {LoadStatus} from "../matrix/Client.js";
|
||||
import {SyncStatus} from "../matrix/Sync.js";
|
||||
import {ViewModel} from "./ViewModel.js";
|
||||
import {ViewModel} from "./ViewModel";
|
||||
|
||||
export class SessionLoadViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {SortedArray} from "../observable/index.js";
|
||||
import {ViewModel} from "./ViewModel.js";
|
||||
import {ViewModel} from "./ViewModel";
|
||||
import {avatarInitials, getIdentifierColorNumber} from "./avatar.js";
|
||||
|
||||
class SessionItemViewModel extends ViewModel {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -21,54 +22,70 @@ limitations under the License.
|
|||
import {EventEmitter} from "../utils/EventEmitter";
|
||||
import {Disposables} from "../utils/Disposables";
|
||||
|
||||
export class ViewModel extends EventEmitter {
|
||||
constructor(options = {}) {
|
||||
import type {Disposable} from "../utils/Disposables";
|
||||
import type {Platform} from "../platform/web/Platform";
|
||||
import type {Clock} from "../platform/web/dom/Clock";
|
||||
import type {ILogger} from "../logging/types";
|
||||
import type {Navigation} from "./navigation/Navigation";
|
||||
import type {URLRouter} from "./navigation/URLRouter";
|
||||
|
||||
type Options = {
|
||||
platform: Platform
|
||||
logger: ILogger
|
||||
urlCreator: URLRouter
|
||||
navigation: Navigation
|
||||
emitChange?: (params: any) => void
|
||||
}
|
||||
|
||||
export class ViewModel<O extends Options = Options> extends EventEmitter<{change: never}> {
|
||||
private disposables?: Disposables;
|
||||
private _isDisposed = false;
|
||||
private _options: O;
|
||||
|
||||
constructor(options: O) {
|
||||
super();
|
||||
this.disposables = null;
|
||||
this._isDisposed = false;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
childOptions(explicitOptions) {
|
||||
const {navigation, urlCreator, platform} = this._options;
|
||||
return Object.assign({navigation, urlCreator, platform}, explicitOptions);
|
||||
childOptions<T extends Object>(explicitOptions: T): T & Options {
|
||||
return Object.assign({}, this._options, explicitOptions);
|
||||
}
|
||||
|
||||
// makes it easier to pass through dependencies of a sub-view model
|
||||
getOption(name) {
|
||||
getOption<N extends keyof O>(name: N): O[N] {
|
||||
return this._options[name];
|
||||
}
|
||||
|
||||
track(disposable) {
|
||||
track<D extends Disposable>(disposable: D): D {
|
||||
if (!this.disposables) {
|
||||
this.disposables = new Disposables();
|
||||
}
|
||||
return this.disposables.track(disposable);
|
||||
}
|
||||
|
||||
untrack(disposable) {
|
||||
untrack(disposable: Disposable): undefined {
|
||||
if (this.disposables) {
|
||||
return this.disposables.untrack(disposable);
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
dispose(): void {
|
||||
if (this.disposables) {
|
||||
this.disposables.dispose();
|
||||
}
|
||||
this._isDisposed = true;
|
||||
}
|
||||
|
||||
get isDisposed() {
|
||||
get isDisposed(): boolean {
|
||||
return this._isDisposed;
|
||||
}
|
||||
|
||||
disposeTracked(disposable) {
|
||||
disposeTracked(disposable: Disposable | undefined): undefined {
|
||||
if (this.disposables) {
|
||||
return this.disposables.disposeTracked(disposable);
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TODO: this will need to support binding
|
||||
|
@ -76,7 +93,7 @@ export class ViewModel extends EventEmitter {
|
|||
//
|
||||
// translated string should probably always be bindings, unless we're fine with a refresh when changing the language?
|
||||
// we probably are, if we're using routing with a url, we could just refresh.
|
||||
i18n(parts, ...expr) {
|
||||
i18n(parts: string[], ...expr: any[]) {
|
||||
// just concat for now
|
||||
let result = "";
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
|
@ -88,11 +105,11 @@ export class ViewModel extends EventEmitter {
|
|||
return result;
|
||||
}
|
||||
|
||||
updateOptions(options) {
|
||||
updateOptions(options: O): void {
|
||||
this._options = Object.assign(this._options, options);
|
||||
}
|
||||
|
||||
emitChange(changedProps) {
|
||||
emitChange(changedProps: any): void {
|
||||
if (this._options.emitChange) {
|
||||
this._options.emitChange(changedProps);
|
||||
} else {
|
||||
|
@ -100,27 +117,23 @@ export class ViewModel extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
get platform() {
|
||||
get platform(): Platform {
|
||||
return this._options.platform;
|
||||
}
|
||||
|
||||
get clock() {
|
||||
get clock(): Clock {
|
||||
return this._options.platform.clock;
|
||||
}
|
||||
|
||||
get logger() {
|
||||
get logger(): ILogger {
|
||||
return this.platform.logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* The url router, only meant to be used to create urls with from view models.
|
||||
* @return {URLRouter}
|
||||
*/
|
||||
get urlCreator() {
|
||||
get urlCreator(): URLRouter {
|
||||
return this._options.urlCreator;
|
||||
}
|
||||
|
||||
get navigation() {
|
||||
get navigation(): Navigation {
|
||||
return this._options.navigation;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {LoginFailure} from "../../matrix/Client.js";
|
||||
|
||||
export class CompleteSSOLoginViewModel extends ViewModel {
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {Client} from "../../matrix/Client.js";
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {PasswordLoginViewModel} from "./PasswordLoginViewModel.js";
|
||||
import {StartSSOLoginViewModel} from "./StartSSOLoginViewModel.js";
|
||||
import {CompleteSSOLoginViewModel} from "./CompleteSSOLoginViewModel.js";
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {LoginFailure} from "../../matrix/Client.js";
|
||||
|
||||
export class PasswordLoginViewModel extends ViewModel {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
|
||||
export class StartSSOLoginViewModel extends ViewModel{
|
||||
constructor(options) {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {imageToInfo} from "./common.js";
|
||||
import {RoomType} from "../../matrix/room/common";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {addPanelIfNeeded} from "../navigation/index.js";
|
||||
|
||||
function dedupeSparse(roomIds) {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {createEnum} from "../../utils/enum";
|
||||
import {ConnectionStatus} from "../../matrix/net/Reconnector";
|
||||
import {SyncStatus} from "../../matrix/Sync.js";
|
||||
|
|
|
@ -25,7 +25,7 @@ import {SessionStatusViewModel} from "./SessionStatusViewModel.js";
|
|||
import {RoomGridViewModel} from "./RoomGridViewModel.js";
|
||||
import {SettingsViewModel} from "./settings/SettingsViewModel.js";
|
||||
import {CreateRoomViewModel} from "./CreateRoomViewModel.js";
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
import {ViewModel} from "../ViewModel";
|
||||
import {RoomViewModelObservable} from "./RoomViewModelObservable.js";
|
||||
import {RightPanelViewModel} from "./rightpanel/RightPanelViewModel.js";
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
|
||||
const KIND_ORDER = ["roomBeingCreated", "invite", "room"];
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {RoomTileViewModel} from "./RoomTileViewModel.js";
|
||||
import {InviteTileViewModel} from "./InviteTileViewModel.js";
|
||||
import {RoomBeingCreatedTileViewModel} from "./RoomBeingCreatedTileViewModel.js";
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {RoomType} from "../../../matrix/room/common";
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {MemberTileViewModel} from "./MemberTileViewModel.js";
|
||||
import {createMemberComparator} from "./members/comparator.js";
|
||||
import {Disambiguator} from "./members/disambiguator.js";
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
|
||||
export class MemberTileViewModel extends ViewModel {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {RoomDetailsViewModel} from "./RoomDetailsViewModel.js";
|
||||
import {MemberListViewModel} from "./MemberListViewModel.js";
|
||||
import {MemberDetailsViewModel} from "./MemberDetailsViewModel.js";
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
|
||||
export class RoomDetailsViewModel extends ViewModel {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
|
||||
export class ComposerViewModel extends ViewModel {
|
||||
constructor(roomVM) {
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
|
||||
export class InviteViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
|
||||
export class LightboxViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
|
||||
export class RoomBeingCreatedViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
|
|
@ -19,7 +19,7 @@ import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
|
|||
import {ComposerViewModel} from "./ComposerViewModel.js"
|
||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||
import {tilesCreator} from "./timeline/tilesCreator.js";
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {imageToInfo} from "../common.js";
|
||||
|
||||
export class RoomViewModel extends ViewModel {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
|
||||
export class UnknownRoomViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
@ -55,4 +55,4 @@ export class UnknownRoomViewModel extends ViewModel {
|
|||
get kind() {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ to the room timeline, which unload entries from memory.
|
|||
when loading, it just reads events from a sortkey backwards or forwards...
|
||||
*/
|
||||
import {TilesCollection} from "./TilesCollection.js";
|
||||
import {ViewModel} from "../../../ViewModel.js";
|
||||
import {ViewModel} from "../../../ViewModel";
|
||||
|
||||
export class TimelineViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {UpdateAction} from "../UpdateAction.js";
|
||||
import {ViewModel} from "../../../../ViewModel.js";
|
||||
import {ViewModel} from "../../../../ViewModel";
|
||||
import {SendStatus} from "../../../../../matrix/room/sending/PendingEvent.js";
|
||||
|
||||
export class SimpleTile extends ViewModel {
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {KeyType} from "../../../matrix/ssss/index";
|
||||
import {createEnum} from "../../../utils/enum";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
import {ViewModel} from "../../ViewModel";
|
||||
import {KeyBackupViewModel} from "./KeyBackupViewModel.js";
|
||||
|
||||
class PushNotificationStatus {
|
||||
|
|
|
@ -30,6 +30,6 @@ export {Navigation} from "./domain/navigation/Navigation.js";
|
|||
export {ComposerViewModel} from "./domain/session/room/ComposerViewModel.js";
|
||||
export {MessageComposer} from "./platform/web/ui/session/room/MessageComposer.js";
|
||||
export {TemplateView} from "./platform/web/ui/general/TemplateView";
|
||||
export {ViewModel} from "./domain/ViewModel.js";
|
||||
export {ViewModel} from "./domain/ViewModel";
|
||||
export {LoadingView} from "./platform/web/ui/general/LoadingView.js";
|
||||
export {AvatarView} from "./platform/web/ui/AvatarView.js";
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -18,7 +19,7 @@ export interface IDisposable {
|
|||
dispose(): void;
|
||||
}
|
||||
|
||||
type Disposable = IDisposable | (() => void);
|
||||
export type Disposable = IDisposable | (() => void);
|
||||
|
||||
function disposeValue(value: Disposable): void {
|
||||
if (typeof value === "function") {
|
||||
|
@ -33,9 +34,9 @@ function isDisposable(value: Disposable): boolean {
|
|||
}
|
||||
|
||||
export class Disposables {
|
||||
private _disposables: Disposable[] | null = [];
|
||||
private _disposables?: Disposable[] = [];
|
||||
|
||||
track(disposable: Disposable): Disposable {
|
||||
track<D extends Disposable>(disposable: D): D {
|
||||
if (!isDisposable(disposable)) {
|
||||
throw new Error("Not a disposable");
|
||||
}
|
||||
|
@ -48,16 +49,16 @@ export class Disposables {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
untrack(disposable: Disposable): null {
|
||||
untrack(disposable: Disposable): undefined {
|
||||
if (this.isDisposed) {
|
||||
console.warn("Disposables already disposed, cannot untrack");
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
const idx = this._disposables!.indexOf(disposable);
|
||||
if (idx >= 0) {
|
||||
this._disposables!.splice(idx, 1);
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
@ -65,17 +66,17 @@ export class Disposables {
|
|||
for (const d of this._disposables) {
|
||||
disposeValue(d);
|
||||
}
|
||||
this._disposables = null;
|
||||
this._disposables = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
get isDisposed(): boolean {
|
||||
return this._disposables === null;
|
||||
return this._disposables === undefined;
|
||||
}
|
||||
|
||||
disposeTracked(value: Disposable): null {
|
||||
disposeTracked(value: Disposable | undefined): undefined {
|
||||
if (value === undefined || value === null || this.isDisposed) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
const idx = this._disposables!.indexOf(value);
|
||||
if (idx !== -1) {
|
||||
|
@ -84,6 +85,6 @@ export class Disposables {
|
|||
} else {
|
||||
console.warn("disposable not found, did it leak?", value);
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue