157 lines
3.6 KiB
TypeScript
157 lines
3.6 KiB
TypeScript
// (C) Copyright 2015 Moodle Pty Ltd.
|
|
//
|
|
// 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.
|
|
|
|
/**
|
|
* Updates listener.
|
|
*/
|
|
export interface CoreItemsManagerSourceListener<Item> {
|
|
onItemsUpdated?(items: Item[]): void;
|
|
onReset?(): void;
|
|
}
|
|
|
|
/**
|
|
* Items collection source data.
|
|
*/
|
|
export abstract class CoreItemsManagerSource<Item = unknown> {
|
|
|
|
protected items: Item[] | null = null;
|
|
protected listeners: CoreItemsManagerSourceListener<Item>[] = [];
|
|
protected dirty = false;
|
|
protected loaded = false;
|
|
protected loadedPromise: Promise<void>;
|
|
protected resolveLoaded!: () => void;
|
|
|
|
constructor() {
|
|
this.loadedPromise = new Promise(resolve => this.resolveLoaded = resolve);
|
|
}
|
|
|
|
/**
|
|
* Check whether the source is dirty.
|
|
*
|
|
* @returns Whether the source is dirty.
|
|
*/
|
|
isDirty(): boolean {
|
|
return this.dirty;
|
|
}
|
|
|
|
/**
|
|
* Check whether data is loaded.
|
|
*
|
|
* @returns Whether data is loaded.
|
|
*/
|
|
isLoaded(): boolean {
|
|
return this.loaded;
|
|
}
|
|
|
|
/**
|
|
* Return a promise that is resolved when the data is loaded.
|
|
*
|
|
* @returns Promise.
|
|
*/
|
|
waitForLoaded(): Promise<void> {
|
|
return this.loadedPromise;
|
|
}
|
|
|
|
/**
|
|
* Mark the source as initialized.
|
|
*/
|
|
protected setLoaded(): void {
|
|
this.loaded = true;
|
|
this.resolveLoaded();
|
|
}
|
|
|
|
/**
|
|
* Set whether the source as dirty.
|
|
*
|
|
* When a source is dirty, the next load request will reload items from the beginning.
|
|
*
|
|
* @param dirty Whether source should be marked as dirty or not.
|
|
*/
|
|
setDirty(dirty: boolean): void {
|
|
this.dirty = dirty;
|
|
}
|
|
|
|
/**
|
|
* Get collection items.
|
|
*
|
|
* @returns Items.
|
|
*/
|
|
getItems(): Item[] | null {
|
|
return this.items;
|
|
}
|
|
|
|
/**
|
|
* Reset collection data.
|
|
*/
|
|
reset(): void {
|
|
this.items = null;
|
|
this.dirty = false;
|
|
this.loaded = false;
|
|
|
|
this.listeners.forEach(listener => listener.onReset?.call(listener));
|
|
}
|
|
|
|
/**
|
|
* Load items.
|
|
*/
|
|
abstract load(): Promise<void>;
|
|
|
|
/**
|
|
* Register a listener.
|
|
*
|
|
* @param listener Listener.
|
|
* @returns Unsubscribe function.
|
|
*/
|
|
addListener(listener: CoreItemsManagerSourceListener<Item>): () => void {
|
|
this.listeners.push(listener);
|
|
|
|
return () => this.removeListener(listener);
|
|
}
|
|
|
|
/**
|
|
* Remove a listener.
|
|
*
|
|
* @param listener Listener.
|
|
*/
|
|
removeListener(listener: CoreItemsManagerSourceListener<Item>): void {
|
|
const index = this.listeners.indexOf(listener);
|
|
|
|
if (index === -1) {
|
|
return;
|
|
}
|
|
|
|
this.listeners.splice(index, 1);
|
|
}
|
|
|
|
/**
|
|
* Update the collection items.
|
|
*
|
|
* @param items Items.
|
|
*/
|
|
protected setItems(items: Item[]): void {
|
|
this.items = items;
|
|
this.setLoaded();
|
|
|
|
this.notifyItemsUpdated();
|
|
}
|
|
|
|
/**
|
|
* Notify that items have been updated.
|
|
*/
|
|
protected notifyItemsUpdated(): void {
|
|
this.listeners.forEach(listener => listener.onItemsUpdated?.call(listener, this.items));
|
|
}
|
|
|
|
}
|