| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  | import Combine from "../Base/Combine"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							|  |  |  | import {SlideShow} from "../Image/SlideShow"; | 
					
						
							|  |  |  | import Toggle from "../Input/Toggle"; | 
					
						
							|  |  |  | import Loading from "../Base/Loading"; | 
					
						
							|  |  |  | import {AttributedImage} from "../Image/AttributedImage"; | 
					
						
							|  |  |  | import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders"; | 
					
						
							|  |  |  | import Svg from "../../Svg"; | 
					
						
							|  |  |  | import BaseUIElement from "../BaseUIElement"; | 
					
						
							|  |  |  | import {InputElement} from "../Input/InputElement"; | 
					
						
							|  |  |  | import {VariableUiElement} from "../Base/VariableUIElement"; | 
					
						
							|  |  |  | import Translations from "../i18n/Translations"; | 
					
						
							|  |  |  | import {Mapillary} from "../../Logic/ImageProviders/Mapillary"; | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  | import {SubtleButton} from "../Base/SubtleButton"; | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export interface P4CPicture { | 
					
						
							|  |  |  |     pictureUrl: string, | 
					
						
							|  |  |  |     date: number, | 
					
						
							|  |  |  |     coordinates: { lat: number, lng: number }, | 
					
						
							|  |  |  |     provider: "Mapillary" | string, | 
					
						
							|  |  |  |     author, | 
					
						
							|  |  |  |     license, | 
					
						
							|  |  |  |     detailsUrl: string, | 
					
						
							|  |  |  |     direction, | 
					
						
							|  |  |  |     osmTags: object /*To copy straight into OSM!*/ | 
					
						
							|  |  |  |     , | 
					
						
							|  |  |  |     thumbUrl: string, | 
					
						
							|  |  |  |     details: { | 
					
						
							|  |  |  |         isSpherical: boolean, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  | export interface NearbyImageOptions { | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  |     lon: number, | 
					
						
							|  |  |  |     lat: number, | 
					
						
							|  |  |  |     radius: number, | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  |     maxDaysOld?: 1095 | number, | 
					
						
							|  |  |  |     blacklist: UIEventSource<{url: string}[]>, | 
					
						
							|  |  |  |     shownImagesCount?: UIEventSource<number>, | 
					
						
							|  |  |  |     towardscenter?: boolean; | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default class NearbyImages extends VariableUiElement { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(options: NearbyImageOptions) { | 
					
						
							|  |  |  |         const t = Translations.t.image.nearbyPictures | 
					
						
							|  |  |  |         const P4C = require("../../vendor/P4C.min") | 
					
						
							|  |  |  |         const picManager = new P4C.PicturesManager({}); | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  |         const shownImages = options.shownImagesCount ?? new UIEventSource(25); | 
					
						
							|  |  |  |         const loadedPictures = | 
					
						
							|  |  |  |             UIEventSource.FromPromise<P4CPicture[]>( | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  |             picManager.startPicsRetrievalAround(new P4C.LatLng(options.lat, options.lon), options.radius, { | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  |                 mindate: new Date().getTime() - (options.maxDaysOld ?? (3*365)) * 24 * 60 * 60 * 1000, | 
					
						
							|  |  |  |                 towardscenter: options.towardscenter | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  |             }) | 
					
						
							|  |  |  |         ).map(images => { | 
					
						
							|  |  |  |             console.log("Images are" ,images, "blacklisted is", options.blacklist.data) | 
					
						
							|  |  |  |             images?.sort((a, b) => b.date - a.date) | 
					
						
							|  |  |  |             return images ?.filter(i => !(options.blacklist?.data?.some(blacklisted =>  | 
					
						
							|  |  |  |                     Mapillary.sameUrl(i.pictureUrl, blacklisted.url))) | 
					
						
							|  |  |  |                 && i.details.isSpherical === false); | 
					
						
							|  |  |  |         }, [options.blacklist]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  |         const loadMoreButton = new Combine([new SubtleButton(Svg.add_svg(), t.loadMore).onClick(() => { | 
					
						
							|  |  |  |             shownImages.setData(shownImages.data + 25) | 
					
						
							|  |  |  |         })]).SetClass("flex flex-col justify-center") | 
					
						
							|  |  |  |         const imageElements = loadedPictures.map(imgs => { | 
					
						
							|  |  |  |             const elements =  (imgs ?? []).slice(0, shownImages.data).map(i => this.prepareElement(i)); | 
					
						
							|  |  |  |             if(imgs !== undefined && elements.length < imgs.length){ | 
					
						
							|  |  |  |                 // We effectively sliced some items, so we can increase the count
 | 
					
						
							|  |  |  |                 elements.push(loadMoreButton) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return elements; | 
					
						
							|  |  |  |         },[shownImages]); | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  |         super(loadedPictures.map(images => { | 
					
						
							|  |  |  |             if(images === undefined){ | 
					
						
							|  |  |  |               return  new Loading(t.loading); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if(images.length === 0){ | 
					
						
							|  |  |  |                 return t.nothingFound.SetClass("alert block") | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-05-13 01:19:53 +02:00
										 |  |  |             return new SlideShow(imageElements) | 
					
						
							| 
									
										
										
										
											2022-05-06 12:41:24 +02:00
										 |  |  |         })); | 
					
						
							|  |  |  |                 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected prepareElement(info: P4CPicture): BaseUIElement { | 
					
						
							|  |  |  |         const provider = AllImageProviders.byName(info.provider); | 
					
						
							|  |  |  |         return new AttributedImage({url: info.pictureUrl, provider}) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private asAttributedImage(info: P4CPicture): AttributedImage { | 
					
						
							|  |  |  |         const provider = AllImageProviders.byName(info.provider); | 
					
						
							|  |  |  |         return new AttributedImage({url: info.thumbUrl, provider, date: new Date(info.date)}) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     protected asToggle(info:P4CPicture): Toggle { | 
					
						
							|  |  |  |         const imgNonSelected = this.asAttributedImage(info); | 
					
						
							|  |  |  |         const imageSelected = this.asAttributedImage(info); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const nonSelected = new Combine([imgNonSelected]).SetClass("relative block") | 
					
						
							|  |  |  |         const hoveringCheckmark = | 
					
						
							|  |  |  |             new Combine([Svg.confirm_svg().SetClass("block w-24 h-24 -ml-12 -mt-12")]).SetClass("absolute left-1/2 top-1/2 w-0") | 
					
						
							|  |  |  |         const selected = new Combine([ | 
					
						
							|  |  |  |             imageSelected, | 
					
						
							|  |  |  |             hoveringCheckmark, | 
					
						
							|  |  |  |         ]).SetClass("relative block") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new Toggle(selected, nonSelected).SetClass("").ToggleOnClick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class SelectOneNearbyImage extends NearbyImages implements InputElement<P4CPicture> { | 
					
						
							|  |  |  |     private readonly value: UIEventSource<P4CPicture>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(options: NearbyImageOptions & {value?: UIEventSource<P4CPicture>}) { | 
					
						
							|  |  |  |         super(options) | 
					
						
							|  |  |  |         this.value = options.value ?? new UIEventSource<P4CPicture>(undefined); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetValue(): UIEventSource<P4CPicture> { | 
					
						
							|  |  |  |         return this.value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     IsValid(t: P4CPicture): boolean { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected prepareElement(info: P4CPicture): BaseUIElement { | 
					
						
							|  |  |  |         const toggle = super.asToggle(info) | 
					
						
							|  |  |  |         toggle.isEnabled.addCallback(enabled => { | 
					
						
							|  |  |  |             if (enabled) { | 
					
						
							|  |  |  |                 this.value.setData(info) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.value.addCallback(inf => { | 
					
						
							|  |  |  |             if(inf !== info){ | 
					
						
							|  |  |  |                 toggle.isEnabled.setData(false) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return toggle | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |