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 |      * @param promise | ||||||
|      * @constructor |      * @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) |         const src = new UIEventSource<T>(undefined) | ||||||
|         promise?.then((d) => src.setData(d)) |         promise?.then((d) => src.setData(d)) | ||||||
|         promise?.catch((err) => console.warn("Promise failed:", err)) |         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): Store<J> | ||||||
|     abstract map<J>(f: (t: T) => J, extraStoresToWatch: Store<any>[]): 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) => { |         return this.map((t) => { | ||||||
|             if (t === undefined) { |             if (t === undefined) { | ||||||
|                 return undefined |                 return undefined | ||||||
|  | @ -105,7 +105,7 @@ export abstract class Store<T> implements Readable<T> { | ||||||
|             if (t === null) { |             if (t === null) { | ||||||
|                 return null |                 return null | ||||||
|             } |             } | ||||||
|             return f(t) |             return f(<Exclude<T, undefined | null>> t) | ||||||
|         }, extraStoresToWatch) |         }, extraStoresToWatch) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -603,7 +603,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> { | ||||||
|      */ |      */ | ||||||
|     public static FromPromiseWithErr<T>( |     public static FromPromiseWithErr<T>( | ||||||
|         promise: Promise<T> |         promise: Promise<T> | ||||||
|     ): UIEventSource<{ success: T } | { error: any }> { |     ): UIEventSource<{ success: T } | { error: any } | undefined> { | ||||||
|         const src = new UIEventSource<{ success: T } | { error: any }>(undefined) |         const src = new UIEventSource<{ success: T } | { error: any }>(undefined) | ||||||
|         promise?.then((d) => src.setData({ success: d })) |         promise?.then((d) => src.setData({ success: d })) | ||||||
|         promise?.catch((err) => src.setData({ error: err })) |         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' |      * 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)' |      * 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( |         return new MappedStore( | ||||||
|             this, |             this, | ||||||
|             (t) => { |             (t) => { | ||||||
|                 if (t === undefined) { |                 if (t === undefined) { | ||||||
|                     return undefined |                     return undefined | ||||||
|                 } |                 } | ||||||
|                 return f(t) |                 if (t === null) { | ||||||
|  |                     return null | ||||||
|  |                 } | ||||||
|  |                 return f(<Exclude<T, undefined | null>> t) | ||||||
|             }, |             }, | ||||||
|             extraSources, |             extraSources, | ||||||
|             this._callbacks, |             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 { | export default class NearbyImagesSearch { | ||||||
|     public static readonly services = ["mapillary", "flickr", "kartaview", "wikicommons"] as const |     public static readonly services = ["mapillary", "flickr", "kartaview", "wikicommons"] as const | ||||||
|     public static readonly apiUrls = ["https://api.flickr.com"] |     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[]>([]) |     private readonly _store: UIEventSource<P4CPicture[]> = new UIEventSource<P4CPicture[]>([]) | ||||||
|     public readonly store: Store<P4CPicture[]> = this._store |     public readonly store: Store<P4CPicture[]> = this._store | ||||||
|  |     public readonly allDone: Store<boolean> | ||||||
|     private readonly _options: NearbyImageOptions |     private readonly _options: NearbyImageOptions | ||||||
| 
 | 
 | ||||||
|     constructor(options: NearbyImageOptions, features: IndexedFeatureSource) { |     constructor(options: NearbyImageOptions, features: IndexedFeatureSource) { | ||||||
|         this.individualStores = NearbyImagesSearch.services.map((s) => |         this.individualStores = NearbyImagesSearch.services.map((s) => | ||||||
|             NearbyImagesSearch.buildPictureFetcher(options, 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 |         this._options = options | ||||||
|         if (features !== undefined) { |         if (features !== undefined) { | ||||||
|             const osmImages = new ImagesInLoadedDataFetcher(features).fetchAround({ |             const osmImages = new ImagesInLoadedDataFetcher(features).fetchAround({ | ||||||
|  | @ -93,13 +104,17 @@ export default class NearbyImagesSearch { | ||||||
|     private static buildPictureFetcher( |     private static buildPictureFetcher( | ||||||
|         options: NearbyImageOptions, |         options: NearbyImageOptions, | ||||||
|         fetcher: P4CService |         fetcher: P4CService | ||||||
|     ): Store<{ images: P4CPicture[]; beforeFilter: number }> { |     ): Store<{ images: P4CPicture[]; beforeFilter: number } | null | undefined> { | ||||||
|         const p4cStore = Stores.FromPromise<P4CPicture[]>( |         const p4cStore = Stores.FromPromiseWithErr<P4CPicture[]>( | ||||||
|             NearbyImagesSearch.fetchImages(options, fetcher) |             NearbyImagesSearch.fetchImages(options, fetcher) | ||||||
|         ) |         ) | ||||||
|         const searchRadius = options.searchRadius ?? 100 |         const searchRadius = options.searchRadius ?? 100 | ||||||
|         return p4cStore.map( |         return p4cStore.mapD( | ||||||
|             (images) => { |             (imagesState) => { | ||||||
|  |                 if(imagesState["error"]){ | ||||||
|  |                     return null | ||||||
|  |                 } | ||||||
|  |                 let images = imagesState["success"] | ||||||
|                 if (images === undefined) { |                 if (images === undefined) { | ||||||
|                     return undefined |                     return undefined | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue