Merge pull request #668 from vector-im/bwindels/ts-viewmodel

convert ViewModel to typescript
This commit is contained in:
Bruno Windels 2022-02-15 15:38:22 +01:00 committed by GitHub
commit c6dde63abd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 84 additions and 70 deletions

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "./ViewModel.js"; import {ViewModel} from "./ViewModel";
import {KeyType} from "../matrix/ssss/index"; import {KeyType} from "../matrix/ssss/index";
import {Status} from "./session/settings/KeyBackupViewModel.js"; import {Status} from "./session/settings/KeyBackupViewModel.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "./ViewModel.js"; import {ViewModel} from "./ViewModel";
import {Client} from "../matrix/Client.js"; import {Client} from "../matrix/Client.js";
export class LogoutViewModel extends ViewModel { export class LogoutViewModel extends ViewModel {

View file

@ -20,7 +20,7 @@ import {SessionLoadViewModel} from "./SessionLoadViewModel.js";
import {LoginViewModel} from "./login/LoginViewModel.js"; import {LoginViewModel} from "./login/LoginViewModel.js";
import {LogoutViewModel} from "./LogoutViewModel.js"; import {LogoutViewModel} from "./LogoutViewModel.js";
import {SessionPickerViewModel} from "./SessionPickerViewModel.js"; import {SessionPickerViewModel} from "./SessionPickerViewModel.js";
import {ViewModel} from "./ViewModel.js"; import {ViewModel} from "./ViewModel";
export class RootViewModel extends ViewModel { export class RootViewModel extends ViewModel {
constructor(options) { constructor(options) {

View file

@ -17,7 +17,7 @@ limitations under the License.
import {AccountSetupViewModel} from "./AccountSetupViewModel.js"; import {AccountSetupViewModel} from "./AccountSetupViewModel.js";
import {LoadStatus} from "../matrix/Client.js"; import {LoadStatus} from "../matrix/Client.js";
import {SyncStatus} from "../matrix/Sync.js"; import {SyncStatus} from "../matrix/Sync.js";
import {ViewModel} from "./ViewModel.js"; import {ViewModel} from "./ViewModel";
export class SessionLoadViewModel extends ViewModel { export class SessionLoadViewModel extends ViewModel {
constructor(options) { constructor(options) {

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import {SortedArray} from "../observable/index.js"; import {SortedArray} from "../observable/index.js";
import {ViewModel} from "./ViewModel.js"; import {ViewModel} from "./ViewModel";
import {avatarInitials, getIdentifierColorNumber} from "./avatar.js"; import {avatarInitials, getIdentifierColorNumber} from "./avatar.js";
class SessionItemViewModel extends ViewModel { class SessionItemViewModel extends ViewModel {

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2020 Bruno Windels <bruno@windels.cloud> 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"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with 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 {EventEmitter} from "../utils/EventEmitter";
import {Disposables} from "../utils/Disposables"; import {Disposables} from "../utils/Disposables";
export class ViewModel extends EventEmitter { import type {Disposable} from "../utils/Disposables";
constructor(options = {}) { 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(); super();
this.disposables = null;
this._isDisposed = false;
this._options = options; this._options = options;
} }
childOptions(explicitOptions) { childOptions<T extends Object>(explicitOptions: T): T & Options {
const {navigation, urlCreator, platform} = this._options; return Object.assign({}, this._options, explicitOptions);
return Object.assign({navigation, urlCreator, platform}, explicitOptions);
} }
// makes it easier to pass through dependencies of a sub-view model // 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]; return this._options[name];
} }
track(disposable) { track<D extends Disposable>(disposable: D): D {
if (!this.disposables) { if (!this.disposables) {
this.disposables = new Disposables(); this.disposables = new Disposables();
} }
return this.disposables.track(disposable); return this.disposables.track(disposable);
} }
untrack(disposable) { untrack(disposable: Disposable): undefined {
if (this.disposables) { if (this.disposables) {
return this.disposables.untrack(disposable); return this.disposables.untrack(disposable);
} }
return null; return undefined;
} }
dispose() { dispose(): void {
if (this.disposables) { if (this.disposables) {
this.disposables.dispose(); this.disposables.dispose();
} }
this._isDisposed = true; this._isDisposed = true;
} }
get isDisposed() { get isDisposed(): boolean {
return this._isDisposed; return this._isDisposed;
} }
disposeTracked(disposable) { disposeTracked(disposable: Disposable | undefined): undefined {
if (this.disposables) { if (this.disposables) {
return this.disposables.disposeTracked(disposable); return this.disposables.disposeTracked(disposable);
} }
return null; return undefined;
} }
// TODO: this will need to support binding // 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? // 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. // 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 // just concat for now
let result = ""; let result = "";
for (let i = 0; i < parts.length; ++i) { for (let i = 0; i < parts.length; ++i) {
@ -88,11 +105,11 @@ export class ViewModel extends EventEmitter {
return result; return result;
} }
updateOptions(options) { updateOptions(options: O): void {
this._options = Object.assign(this._options, options); this._options = Object.assign(this._options, options);
} }
emitChange(changedProps) { emitChange(changedProps: any): void {
if (this._options.emitChange) { if (this._options.emitChange) {
this._options.emitChange(changedProps); this._options.emitChange(changedProps);
} else { } else {
@ -100,27 +117,23 @@ export class ViewModel extends EventEmitter {
} }
} }
get platform() { get platform(): Platform {
return this._options.platform; return this._options.platform;
} }
get clock() { get clock(): Clock {
return this._options.platform.clock; return this._options.platform.clock;
} }
get logger() { get logger(): ILogger {
return this.platform.logger; return this.platform.logger;
} }
/** get urlCreator(): URLRouter {
* The url router, only meant to be used to create urls with from view models.
* @return {URLRouter}
*/
get urlCreator() {
return this._options.urlCreator; return this._options.urlCreator;
} }
get navigation() { get navigation(): Navigation {
return this._options.navigation; return this._options.navigation;
} }
} }

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {LoginFailure} from "../../matrix/Client.js"; import {LoginFailure} from "../../matrix/Client.js";
export class CompleteSSOLoginViewModel extends ViewModel { export class CompleteSSOLoginViewModel extends ViewModel {

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import {Client} from "../../matrix/Client.js"; import {Client} from "../../matrix/Client.js";
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {PasswordLoginViewModel} from "./PasswordLoginViewModel.js"; import {PasswordLoginViewModel} from "./PasswordLoginViewModel.js";
import {StartSSOLoginViewModel} from "./StartSSOLoginViewModel.js"; import {StartSSOLoginViewModel} from "./StartSSOLoginViewModel.js";
import {CompleteSSOLoginViewModel} from "./CompleteSSOLoginViewModel.js"; import {CompleteSSOLoginViewModel} from "./CompleteSSOLoginViewModel.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {LoginFailure} from "../../matrix/Client.js"; import {LoginFailure} from "../../matrix/Client.js";
export class PasswordLoginViewModel extends ViewModel { export class PasswordLoginViewModel extends ViewModel {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
export class StartSSOLoginViewModel extends ViewModel{ export class StartSSOLoginViewModel extends ViewModel{
constructor(options) { constructor(options) {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {imageToInfo} from "./common.js"; import {imageToInfo} from "./common.js";
import {RoomType} from "../../matrix/room/common"; import {RoomType} from "../../matrix/room/common";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {addPanelIfNeeded} from "../navigation/index.js"; import {addPanelIfNeeded} from "../navigation/index.js";
function dedupeSparse(roomIds) { function dedupeSparse(roomIds) {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {createEnum} from "../../utils/enum"; import {createEnum} from "../../utils/enum";
import {ConnectionStatus} from "../../matrix/net/Reconnector"; import {ConnectionStatus} from "../../matrix/net/Reconnector";
import {SyncStatus} from "../../matrix/Sync.js"; import {SyncStatus} from "../../matrix/Sync.js";

View file

@ -25,7 +25,7 @@ import {SessionStatusViewModel} from "./SessionStatusViewModel.js";
import {RoomGridViewModel} from "./RoomGridViewModel.js"; import {RoomGridViewModel} from "./RoomGridViewModel.js";
import {SettingsViewModel} from "./settings/SettingsViewModel.js"; import {SettingsViewModel} from "./settings/SettingsViewModel.js";
import {CreateRoomViewModel} from "./CreateRoomViewModel.js"; import {CreateRoomViewModel} from "./CreateRoomViewModel.js";
import {ViewModel} from "../ViewModel.js"; import {ViewModel} from "../ViewModel";
import {RoomViewModelObservable} from "./RoomViewModelObservable.js"; import {RoomViewModelObservable} from "./RoomViewModelObservable.js";
import {RightPanelViewModel} from "./rightpanel/RightPanelViewModel.js"; import {RightPanelViewModel} from "./rightpanel/RightPanelViewModel.js";

View file

@ -16,7 +16,7 @@ limitations under the License.
*/ */
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
const KIND_ORDER = ["roomBeingCreated", "invite", "room"]; const KIND_ORDER = ["roomBeingCreated", "invite", "room"];

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {RoomTileViewModel} from "./RoomTileViewModel.js"; import {RoomTileViewModel} from "./RoomTileViewModel.js";
import {InviteTileViewModel} from "./InviteTileViewModel.js"; import {InviteTileViewModel} from "./InviteTileViewModel.js";
import {RoomBeingCreatedTileViewModel} from "./RoomBeingCreatedTileViewModel.js"; import {RoomBeingCreatedTileViewModel} from "./RoomBeingCreatedTileViewModel.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {RoomType} from "../../../matrix/room/common"; import {RoomType} from "../../../matrix/room/common";
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {MemberTileViewModel} from "./MemberTileViewModel.js"; import {MemberTileViewModel} from "./MemberTileViewModel.js";
import {createMemberComparator} from "./members/comparator.js"; import {createMemberComparator} from "./members/comparator.js";
import {Disambiguator} from "./members/disambiguator.js"; import {Disambiguator} from "./members/disambiguator.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
export class MemberTileViewModel extends ViewModel { export class MemberTileViewModel extends ViewModel {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {RoomDetailsViewModel} from "./RoomDetailsViewModel.js"; import {RoomDetailsViewModel} from "./RoomDetailsViewModel.js";
import {MemberListViewModel} from "./MemberListViewModel.js"; import {MemberListViewModel} from "./MemberListViewModel.js";
import {MemberDetailsViewModel} from "./MemberDetailsViewModel.js"; import {MemberDetailsViewModel} from "./MemberDetailsViewModel.js";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
export class RoomDetailsViewModel extends ViewModel { export class RoomDetailsViewModel extends ViewModel {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
export class ComposerViewModel extends ViewModel { export class ComposerViewModel extends ViewModel {
constructor(roomVM) { constructor(roomVM) {

View file

@ -16,7 +16,7 @@ limitations under the License.
*/ */
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
export class InviteViewModel extends ViewModel { export class InviteViewModel extends ViewModel {
constructor(options) { constructor(options) {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
export class LightboxViewModel extends ViewModel { export class LightboxViewModel extends ViewModel {
constructor(options) { constructor(options) {

View file

@ -16,7 +16,7 @@ limitations under the License.
*/ */
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
export class RoomBeingCreatedViewModel extends ViewModel { export class RoomBeingCreatedViewModel extends ViewModel {
constructor(options) { constructor(options) {

View file

@ -19,7 +19,7 @@ import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
import {ComposerViewModel} from "./ComposerViewModel.js" import {ComposerViewModel} from "./ComposerViewModel.js"
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
import {tilesCreator} from "./timeline/tilesCreator.js"; import {tilesCreator} from "./timeline/tilesCreator.js";
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {imageToInfo} from "../common.js"; import {imageToInfo} from "../common.js";
export class RoomViewModel extends ViewModel { export class RoomViewModel extends ViewModel {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
export class UnknownRoomViewModel extends ViewModel { export class UnknownRoomViewModel extends ViewModel {
constructor(options) { constructor(options) {
@ -55,4 +55,4 @@ export class UnknownRoomViewModel extends ViewModel {
get kind() { get kind() {
return "unknown"; return "unknown";
} }
} }

View file

@ -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... when loading, it just reads events from a sortkey backwards or forwards...
*/ */
import {TilesCollection} from "./TilesCollection.js"; import {TilesCollection} from "./TilesCollection.js";
import {ViewModel} from "../../../ViewModel.js"; import {ViewModel} from "../../../ViewModel";
export class TimelineViewModel extends ViewModel { export class TimelineViewModel extends ViewModel {
constructor(options) { constructor(options) {

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import {UpdateAction} from "../UpdateAction.js"; import {UpdateAction} from "../UpdateAction.js";
import {ViewModel} from "../../../../ViewModel.js"; import {ViewModel} from "../../../../ViewModel";
import {SendStatus} from "../../../../../matrix/room/sending/PendingEvent.js"; import {SendStatus} from "../../../../../matrix/room/sending/PendingEvent.js";
export class SimpleTile extends ViewModel { export class SimpleTile extends ViewModel {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {KeyType} from "../../../matrix/ssss/index"; import {KeyType} from "../../../matrix/ssss/index";
import {createEnum} from "../../../utils/enum"; import {createEnum} from "../../../utils/enum";

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {ViewModel} from "../../ViewModel.js"; import {ViewModel} from "../../ViewModel";
import {KeyBackupViewModel} from "./KeyBackupViewModel.js"; import {KeyBackupViewModel} from "./KeyBackupViewModel.js";
class PushNotificationStatus { class PushNotificationStatus {

View file

@ -30,6 +30,6 @@ export {Navigation} from "./domain/navigation/Navigation.js";
export {ComposerViewModel} from "./domain/session/room/ComposerViewModel.js"; export {ComposerViewModel} from "./domain/session/room/ComposerViewModel.js";
export {MessageComposer} from "./platform/web/ui/session/room/MessageComposer.js"; export {MessageComposer} from "./platform/web/ui/session/room/MessageComposer.js";
export {TemplateView} from "./platform/web/ui/general/TemplateView"; 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 {LoadingView} from "./platform/web/ui/general/LoadingView.js";
export {AvatarView} from "./platform/web/ui/AvatarView.js"; export {AvatarView} from "./platform/web/ui/AvatarView.js";

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2020 Bruno Windels <bruno@windels.cloud> 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"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -18,7 +19,7 @@ export interface IDisposable {
dispose(): void; dispose(): void;
} }
type Disposable = IDisposable | (() => void); export type Disposable = IDisposable | (() => void);
function disposeValue(value: Disposable): void { function disposeValue(value: Disposable): void {
if (typeof value === "function") { if (typeof value === "function") {
@ -33,9 +34,9 @@ function isDisposable(value: Disposable): boolean {
} }
export class Disposables { export class Disposables {
private _disposables: Disposable[] | null = []; private _disposables?: Disposable[] = [];
track(disposable: Disposable): Disposable { track<D extends Disposable>(disposable: D): D {
if (!isDisposable(disposable)) { if (!isDisposable(disposable)) {
throw new Error("Not a disposable"); throw new Error("Not a disposable");
} }
@ -48,16 +49,16 @@ export class Disposables {
return disposable; return disposable;
} }
untrack(disposable: Disposable): null { untrack(disposable: Disposable): undefined {
if (this.isDisposed) { if (this.isDisposed) {
console.warn("Disposables already disposed, cannot untrack"); console.warn("Disposables already disposed, cannot untrack");
return null; return undefined;
} }
const idx = this._disposables!.indexOf(disposable); const idx = this._disposables!.indexOf(disposable);
if (idx >= 0) { if (idx >= 0) {
this._disposables!.splice(idx, 1); this._disposables!.splice(idx, 1);
} }
return null; return undefined;
} }
dispose(): void { dispose(): void {
@ -65,17 +66,17 @@ export class Disposables {
for (const d of this._disposables) { for (const d of this._disposables) {
disposeValue(d); disposeValue(d);
} }
this._disposables = null; this._disposables = undefined;
} }
} }
get isDisposed(): boolean { 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) { if (value === undefined || value === null || this.isDisposed) {
return null; return undefined;
} }
const idx = this._disposables!.indexOf(value); const idx = this._disposables!.indexOf(value);
if (idx !== -1) { if (idx !== -1) {
@ -84,6 +85,6 @@ export class Disposables {
} else { } else {
console.warn("disposable not found, did it leak?", value); console.warn("disposable not found, did it leak?", value);
} }
return null; return undefined;
} }
} }