Merge branch 'develop' into 2daysLimit
Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com>
This commit is contained in:
commit
60f4cf75c3
56 changed files with 1593 additions and 134 deletions
6
front/src/Stores/PictureStore.ts
Normal file
6
front/src/Stores/PictureStore.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import type { Readable } from "svelte/store";
|
||||
|
||||
/**
|
||||
* A store that contains the player/companion avatar picture
|
||||
*/
|
||||
export type PictureStore = Readable<string | undefined>;
|
|
@ -12,7 +12,7 @@ let idCount = 0;
|
|||
function createPlayersStore() {
|
||||
let players = new Map<number, PlayerInterface>();
|
||||
|
||||
const { subscribe, set, update } = writable(players);
|
||||
const { subscribe, set, update } = writable<Map<number, PlayerInterface>>(players);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
|
|
122
front/src/Stores/Utils/MapStore.ts
Normal file
122
front/src/Stores/Utils/MapStore.ts
Normal file
|
@ -0,0 +1,122 @@
|
|||
import type { Readable, Subscriber, Unsubscriber, Writable } from "svelte/store";
|
||||
import { get, readable, writable } from "svelte/store";
|
||||
|
||||
/**
|
||||
* Is it a Map? Is it a Store? No! It's a MapStore!
|
||||
*
|
||||
* The MapStore behaves just like a regular JS Map, but... it is also a regular Svelte store.
|
||||
*
|
||||
* As a bonus, you can also get a store on any given key of the map.
|
||||
*
|
||||
* For instance:
|
||||
*
|
||||
* const mapStore = new MapStore<string, string>();
|
||||
* mapStore.getStore('foo').subscribe((value) => {
|
||||
* console.log('Foo key has been written to the store. New value: ', value);
|
||||
* });
|
||||
* mapStore.set('foo', 'bar');
|
||||
*
|
||||
*
|
||||
* Even better, if the items stored in map contain stores, you can directly get the store to those values:
|
||||
*
|
||||
* const mapStore = new MapStore<string, {
|
||||
* nestedStore: Readable<string>
|
||||
* }>();
|
||||
*
|
||||
* mapStore.getNestedStore('foo', item => item.nestedStore).subscribe((value) => {
|
||||
* console.log('Foo key has been written to the store or the nested store has been updated. New value: ', value);
|
||||
* });
|
||||
* mapStore.set('foo', {
|
||||
* nestedStore: writable('bar')
|
||||
* });
|
||||
* // Whenever the nested store is updated OR the 'foo' key is overwritten, the store returned by mapStore.getNestedStore
|
||||
* // will be triggered.
|
||||
*/
|
||||
export class MapStore<K, V> extends Map<K, V> implements Readable<Map<K, V>> {
|
||||
private readonly store = writable(this);
|
||||
private readonly storesByKey = new Map<K, Writable<V | undefined>>();
|
||||
|
||||
subscribe(run: Subscriber<Map<K, V>>, invalidate?: (value?: Map<K, V>) => void): Unsubscriber {
|
||||
return this.store.subscribe(run, invalidate);
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear();
|
||||
this.store.set(this);
|
||||
this.storesByKey.forEach((store) => {
|
||||
store.set(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
delete(key: K): boolean {
|
||||
const result = super.delete(key);
|
||||
if (result) {
|
||||
this.store.set(this);
|
||||
this.storesByKey.get(key)?.set(undefined);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
set(key: K, value: V): this {
|
||||
super.set(key, value);
|
||||
this.store.set(this);
|
||||
this.storesByKey.get(key)?.set(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
getStore(key: K): Readable<V | undefined> {
|
||||
const store = writable(this.get(key), () => {
|
||||
return () => {
|
||||
// No more subscribers!
|
||||
this.storesByKey.delete(key);
|
||||
};
|
||||
});
|
||||
this.storesByKey.set(key, store);
|
||||
return store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an "inner" store inside a value stored in the map.
|
||||
*/
|
||||
getNestedStore<T>(key: K, accessor: (value: V) => Readable<T> | undefined): Readable<T | undefined> {
|
||||
const initVal = this.get(key);
|
||||
let initStore: Readable<T> | undefined;
|
||||
let initStoreValue: T | undefined;
|
||||
if (initVal) {
|
||||
initStore = accessor(initVal);
|
||||
if (initStore !== undefined) {
|
||||
initStoreValue = get(initStore);
|
||||
}
|
||||
}
|
||||
|
||||
return readable(initStoreValue, (set) => {
|
||||
const storeByKey = this.getStore(key);
|
||||
|
||||
let unsubscribeDeepStore: Unsubscriber | undefined;
|
||||
const unsubscribe = storeByKey.subscribe((newMapValue) => {
|
||||
if (unsubscribeDeepStore) {
|
||||
unsubscribeDeepStore();
|
||||
}
|
||||
if (newMapValue === undefined) {
|
||||
set(undefined);
|
||||
} else {
|
||||
const deepValueStore = accessor(newMapValue);
|
||||
if (deepValueStore !== undefined) {
|
||||
set(get(deepValueStore));
|
||||
|
||||
unsubscribeDeepStore = deepValueStore.subscribe((value) => {
|
||||
set(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
if (unsubscribeDeepStore) {
|
||||
unsubscribeDeepStore();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue