import { ImageUploader } from "./ImageUploader"; import LinkImageAction from "../Osm/Actions/LinkImageAction"; import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore"; import { OsmId, OsmTags } from "../../Models/OsmFeature"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import { Store, UIEventSource } from "../UIEventSource"; import { OsmConnection } from "../Osm/OsmConnection"; import { Changes } from "../Osm/Changes"; import Translations from "../../UI/i18n/Translations"; import NoteCommentElement from "../../UI/Popup/NoteCommentElement"; /** * The ImageUploadManager has a */ export class ImageUploadManager { private readonly _uploader: ImageUploader; private readonly _featureProperties: FeaturePropertiesStore; private readonly _layout: LayoutConfig; private readonly _uploadStarted: Map> = new Map(); private readonly _uploadFinished: Map> = new Map(); private readonly _uploadFailed: Map> = new Map(); private readonly _uploadRetried: Map> = new Map(); private readonly _uploadRetriedSuccess: Map> = new Map(); private readonly _osmConnection: OsmConnection; private readonly _changes: Changes; constructor(layout: LayoutConfig, uploader: ImageUploader, featureProperties: FeaturePropertiesStore, osmConnection: OsmConnection, changes: Changes) { this._uploader = uploader; this._featureProperties = featureProperties; this._layout = layout; this._osmConnection = osmConnection; this._changes = changes; } /** * Gets various counters. * Note that counters can only increase * If a retry was a success, both 'retrySuccess' _and_ 'uploadFinished' will be increased * @param featureId: the id of the feature you want information for. '*' has a global counter */ public getCountsFor(featureId: string | "*"): { retried: Store; uploadStarted: Store; retrySuccess: Store; failed: Store; uploadFinished: Store } { return { uploadStarted: this.getCounterFor(this._uploadStarted, featureId), uploadFinished: this.getCounterFor(this._uploadFinished, featureId), retried: this.getCounterFor(this._uploadRetried, featureId), failed: this.getCounterFor(this._uploadFailed, featureId), retrySuccess: this.getCounterFor(this._uploadRetriedSuccess, featureId) }; } /** * Uploads the given image, applies the correct title and license for the known user. * Will then add this image to the OSM-feature or the OSM-note */ public async uploadImageAndApply(file: File, tagsStore: UIEventSource) : Promise{ const sizeInBytes = file.size; const tags= tagsStore.data const featureId = tags.id; const self = this; if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) { this.increaseCountFor(this._uploadStarted, featureId); this.increaseCountFor(this._uploadFailed, featureId); throw ( Translations.t.image.toBig.Subs({ actual_size: Math.floor(sizeInBytes / 1000000) + "MB", max_size: self._uploader.maxFileSizeInMegabytes + "MB" }).txt ); } const licenseStore = this._osmConnection?.GetPreference("pictures-license", "CC0"); const license = licenseStore?.data ?? "CC0"; const matchingLayer = this._layout?.getMatchingLayer(tags); const title = matchingLayer?.title?.GetRenderValue(tags)?.Subs(tags)?.textFor("en") ?? tags.name ?? "https//osm.org/" + tags.id; const description = [ "author:" + this._osmConnection.userDetails.data.name, "license:" + license, "osmid:" + tags.id ].join("\n"); console.log("Upload done, creating "); const action = await this.uploadImageWithLicense(featureId, title, description, file); if(!isNaN(Number( featureId))){ // THis is a map note const url = action._url await this._osmConnection.addCommentToNote(featureId, url) NoteCommentElement.addCommentTo(url, > tagsStore, {osmConnection: this._osmConnection}) return } await this._changes.applyAction(action); } private async uploadImageWithLicense( featureId: OsmId, title: string, description: string, blob: File ): Promise { this.increaseCountFor(this._uploadStarted, featureId); const properties = this._featureProperties.getStore(featureId); let key: string; let value: string; try { ({ key, value } = await this._uploader.uploadImage(title, description, blob)); } catch (e) { this.increaseCountFor(this._uploadRetried, featureId); console.error("Could not upload image, trying again:", e); try { ({ key, value } = await this._uploader.uploadImage(title, description, blob)); this.increaseCountFor(this._uploadRetriedSuccess, featureId); } catch (e) { console.error("Could again not upload image due to", e); this.increaseCountFor(this._uploadFailed, featureId); } } console.log("Uploading done, creating action for", featureId); const action = new LinkImageAction(featureId, key, value, properties, { theme: this._layout.id, changeType: "add-image" }); this.increaseCountFor(this._uploadFinished, featureId); return action; } private getCounterFor(collection: Map>, key: string | "*") { if (this._featureProperties.aliases.has(key)) { key = this._featureProperties.aliases.get(key); } if (!collection.has(key)) { collection.set(key, new UIEventSource(0)); } return collection.get(key); } private increaseCountFor(collection: Map>, key: string | "*") { const counter = this.getCounterFor(collection, key); counter.setData(counter.data + 1); const global = this.getCounterFor(collection, "*"); global.setData(counter.data + 1); } }