Feature: add emergency image backup. If uploading images fails, they are saved into local storage and uploaded later on. Part of #2111, but also #2342

This commit is contained in:
Pieter Vander Vennet 2025-04-06 15:32:58 +02:00
parent 7380841205
commit 9f3d198068
9 changed files with 313 additions and 8 deletions

View file

@ -11,6 +11,7 @@ import { Translation } from "../../UI/i18n/Translation"
import { IndexedFeatureSource } from "../FeatureSource/FeatureSource"
import { GeoOperations } from "../GeoOperations"
import { Feature } from "geojson"
import EmergencyImageBackup from "./EmergencyImageBackup"
/**
* The ImageUploadManager has a
@ -85,7 +86,7 @@ export class ImageUploadManager {
uploadFinished: this.getCounterFor(this._uploadFinished, featureId),
retried: this.getCounterFor(this._uploadRetried, featureId),
failed: this.getCounterFor(this._uploadFailed, featureId),
retrySuccess: this.getCounterFor(this._uploadRetriedSuccess, featureId),
retrySuccess: this.getCounterFor(this._uploadRetriedSuccess, featureId)
}
}
@ -94,10 +95,14 @@ export class ImageUploadManager {
if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) {
const error = Translations.t.image.toBig.Subs({
actual_size: Math.floor(sizeInBytes / 1000000) + "MB",
max_size: this._uploader.maxFileSizeInMegabytes + "MB",
max_size: this._uploader.maxFileSizeInMegabytes + "MB"
})
return { error }
}
const ext = file.name.split(".").at(-1).toLowerCase()
if (ext !== "jpg" && ext !== "jpeg") {
return { error: new Translation({ en: "Only JPG-files are allowed" }) }
}
return true
}
@ -148,13 +153,24 @@ export class ImageUploadManager {
properties,
{
theme: tags?.data?.["_orig_theme"] ?? this._theme.id,
changeType: "add-image",
changeType: "add-image"
}
)
await this._changes.applyAction(action)
}
/**
* Uploads an image; returns undefined if the image upload failed.
* Errors are handled internally
* @param featureId
* @param author
* @param blob
* @param targetKey
* @param noblur
* @param feature
* @param options
*/
public async uploadImageWithLicense(
featureId: string,
author: string,
@ -162,14 +178,21 @@ export class ImageUploadManager {
targetKey: string | undefined,
noblur: boolean,
feature: Feature,
ignoreGps: boolean = false
): Promise<UploadResult> {
options?: {
ignoreGps?: boolean,
noBackup?: boolean,
overwriteGps?: GeolocationCoordinates
}
): Promise<UploadResult | undefined> {
this.increaseCountFor(this._uploadStarted, featureId)
let key: string
let value: string
let absoluteUrl: string
let location: [number, number] = undefined
if (this._gps.data && !ignoreGps) {
if (options?.overwriteGps) {
location = [options.overwriteGps.longitude, options.overwriteGps.latitude]
} else if (this._gps.data && !options?.ignoreGps) {
location = [this._gps.data.longitude, this._gps.data.latitude]
}
{
@ -210,13 +233,21 @@ export class ImageUploadManager {
} catch (e) {
console.error("Could again not upload image due to", e)
this.increaseCountFor(this._uploadFailed, featureId)
if (!options?.noBackup) {
EmergencyImageBackup.singleton.addFailedImage({
blob, author, noblur, featureId, targetKey, ignoreGps: options?.ignoreGps,
layoutId: this._theme.id,
lastGpsLocation: this._gps.data,
date: new Date().getTime()
})
}
await this._reportError(
e,
JSON.stringify({
ctx: "While uploading an image in the Image Upload Manager",
featureId,
author,
targetKey,
targetKey
})
)
return undefined