forked from MapComplete/MapComplete
		
	Core: improve typing of mapD
This commit is contained in:
		
							parent
							
								
									09ea799ad4
								
							
						
					
					
						commit
						ab5ec29c02
					
				
					 2 changed files with 30 additions and 12 deletions
				
			
		|  | @ -31,7 +31,7 @@ export class Stores { | |||
|      * @param promise | ||||
|      * @constructor | ||||
|      */ | ||||
|     public static FromPromise<T>(promise: Promise<T>): Store<T> { | ||||
|     public static FromPromise<T>(promise: Promise<T>): Store<T | undefined> { | ||||
|         const src = new UIEventSource<T>(undefined) | ||||
|         promise?.then((d) => src.setData(d)) | ||||
|         promise?.catch((err) => console.warn("Promise failed:", err)) | ||||
|  | @ -97,7 +97,7 @@ export abstract class Store<T> implements Readable<T> { | |||
|     abstract map<J>(f: (t: T) => J): Store<J> | ||||
|     abstract map<J>(f: (t: T) => J, extraStoresToWatch: Store<any>[]): Store<J> | ||||
| 
 | ||||
|     public mapD<J>(f: (t: T) => J, extraStoresToWatch?: Store<any>[]): Store<J> { | ||||
|     public mapD<J>(f: (t: Exclude<T, undefined | null>) => J, extraStoresToWatch?: Store<any>[]): Store<J> { | ||||
|         return this.map((t) => { | ||||
|             if (t === undefined) { | ||||
|                 return undefined | ||||
|  | @ -105,7 +105,7 @@ export abstract class Store<T> implements Readable<T> { | |||
|             if (t === null) { | ||||
|                 return null | ||||
|             } | ||||
|             return f(t) | ||||
|             return f(<Exclude<T, undefined | null>> t) | ||||
|         }, extraStoresToWatch) | ||||
|     } | ||||
| 
 | ||||
|  | @ -603,7 +603,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> { | |||
|      */ | ||||
|     public static FromPromiseWithErr<T>( | ||||
|         promise: Promise<T> | ||||
|     ): UIEventSource<{ success: T } | { error: any }> { | ||||
|     ): UIEventSource<{ success: T } | { error: any } | undefined> { | ||||
|         const src = new UIEventSource<{ success: T } | { error: any }>(undefined) | ||||
|         promise?.then((d) => src.setData({ success: d })) | ||||
|         promise?.catch((err) => src.setData({ error: err })) | ||||
|  | @ -771,18 +771,21 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> { | |||
|      * Monoidal map which results in a read-only store. 'undefined' is passed 'as is' | ||||
|      * Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)' | ||||
|      */ | ||||
|     public mapD<J>(f: (t: T) => J, extraSources: Store<any>[] = []): Store<J | undefined> { | ||||
|     public mapD<J>(f: (t: Exclude<T, undefined | null>) => J, extraSources: Store<any>[] = []): Store<J | undefined> { | ||||
|         return new MappedStore( | ||||
|             this, | ||||
|             (t) => { | ||||
|                 if (t === undefined) { | ||||
|                     return undefined | ||||
|                 } | ||||
|                 return f(t) | ||||
|                 if (t === null) { | ||||
|                     return null | ||||
|                 } | ||||
|                 return f(<Exclude<T, undefined | null>> t) | ||||
|             }, | ||||
|             extraSources, | ||||
|             this._callbacks, | ||||
|             this.data === undefined ? undefined : f(this.data) | ||||
|             (this.data === undefined || this.data === null) ?(<undefined | null> this.data) : f(<any> this.data) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,15 +40,26 @@ export interface P4CPicture { | |||
| export default class NearbyImagesSearch { | ||||
|     public static readonly services = ["mapillary", "flickr", "kartaview", "wikicommons"] as const | ||||
|     public static readonly apiUrls = ["https://api.flickr.com"] | ||||
|     private readonly individualStores: Store<{ images: P4CPicture[]; beforeFilter: number }>[] | ||||
|     private readonly individualStores: Store<{ images: P4CPicture[]; beforeFilter: number } | undefined>[] | ||||
|     private readonly _store: UIEventSource<P4CPicture[]> = new UIEventSource<P4CPicture[]>([]) | ||||
|     public readonly store: Store<P4CPicture[]> = this._store | ||||
|     public readonly allDone: Store<boolean> | ||||
|     private readonly _options: NearbyImageOptions | ||||
| 
 | ||||
|     constructor(options: NearbyImageOptions, features: IndexedFeatureSource) { | ||||
|         this.individualStores = NearbyImagesSearch.services.map((s) => | ||||
|             NearbyImagesSearch.buildPictureFetcher(options, s) | ||||
|         ) | ||||
| 
 | ||||
|         const allDone = new UIEventSource(false) | ||||
|         this.allDone = allDone | ||||
|         const self = this | ||||
|         function updateAllDone(){ | ||||
|             const stillRunning = self.individualStores.some(store => store.data === undefined) | ||||
|             allDone.setData(!stillRunning) | ||||
|         } | ||||
|         self.individualStores.forEach(s => s.addCallback(_ => updateAllDone())) | ||||
| 
 | ||||
|         this._options = options | ||||
|         if (features !== undefined) { | ||||
|             const osmImages = new ImagesInLoadedDataFetcher(features).fetchAround({ | ||||
|  | @ -93,13 +104,17 @@ export default class NearbyImagesSearch { | |||
|     private static buildPictureFetcher( | ||||
|         options: NearbyImageOptions, | ||||
|         fetcher: P4CService | ||||
|     ): Store<{ images: P4CPicture[]; beforeFilter: number }> { | ||||
|         const p4cStore = Stores.FromPromise<P4CPicture[]>( | ||||
|     ): Store<{ images: P4CPicture[]; beforeFilter: number } | null | undefined> { | ||||
|         const p4cStore = Stores.FromPromiseWithErr<P4CPicture[]>( | ||||
|             NearbyImagesSearch.fetchImages(options, fetcher) | ||||
|         ) | ||||
|         const searchRadius = options.searchRadius ?? 100 | ||||
|         return p4cStore.map( | ||||
|             (images) => { | ||||
|         return p4cStore.mapD( | ||||
|             (imagesState) => { | ||||
|                 if(imagesState["error"]){ | ||||
|                     return null | ||||
|                 } | ||||
|                 let images = imagesState["success"] | ||||
|                 if (images === undefined) { | ||||
|                     return undefined | ||||
|                 } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue