Themes: don't do face blurring for some layers (artwork, memorials, ghost_bikes)

This commit is contained in:
Pieter Vander Vennet 2024-10-12 13:36:10 +02:00
parent 7d83cb1a7f
commit 15176a1682
11 changed files with 370 additions and 342 deletions

View file

@ -187,7 +187,7 @@
} }
], ],
"tagRenderings": [ "tagRenderings": [
"images", "images_no_blur",
{ {
"labels": [ "labels": [
"artwork-question" "artwork-question"

View file

@ -142,7 +142,7 @@
], ],
"tagRenderings": [ "tagRenderings": [
"preset_description", "preset_description",
"images", "images_no_blur",
{ {
"question": { "question": {
"en": "Whom is remembered by this ghost bike?", "en": "Whom is remembered by this ghost bike?",

View file

@ -91,7 +91,7 @@
} }
], ],
"tagRenderings": [ "tagRenderings": [
"images", "images_no_blur",
{ {
"id": "memorial-type", "id": "memorial-type",
"labels": [ "labels": [

View file

@ -19,6 +19,13 @@
"*": "{image_carousel()}{image_upload()}" "*": "{image_carousel()}{image_upload()}"
} }
}, },
{
"id": "images_no_blur",
"description": "Same as `images`, but uploaded request to disable blurring to the panoramax server",
"render": {
"*": "{image_carousel()}{image_upload(,,,true)}"
}
},
{ {
"id": "mapillary", "id": "mapillary",
"description": "Shows a button to open Mapillary on this location", "description": "Shows a button to open Mapillary on this location",

14
package-lock.json generated
View file

@ -64,7 +64,7 @@
"opening_hours": "^3.6.0", "opening_hours": "^3.6.0",
"osm-auth": "^2.5.0", "osm-auth": "^2.5.0",
"osmtogeojson": "^3.0.0-beta.5", "osmtogeojson": "^3.0.0-beta.5",
"panoramax-js": "^0.3.6", "panoramax-js": "^0.3.8",
"panzoom": "^9.4.3", "panzoom": "^9.4.3",
"papaparse": "^5.3.1", "papaparse": "^5.3.1",
"pg": "^8.11.3", "pg": "^8.11.3",
@ -16002,9 +16002,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/panoramax-js": { "node_modules/panoramax-js": {
"version": "0.3.6", "version": "0.3.8",
"resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.6.tgz", "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.8.tgz",
"integrity": "sha512-CRdXwh91H6chd1PYptG070ukx+S6IkVaUeQVG91ySevoJoCYOuBT65qkMhRo49X2um1nGcs9UqolW90R57875g==", "integrity": "sha512-l8bUi+urcdqLjckGcEyDmYyAYCKjwFXpk/En7gpi5x32Nq2r9sHq7obX3Jbk1F7zH4rmpKbVtjS97cKEZr9zHQ==",
"dependencies": { "dependencies": {
"@ogcapi-js/features": "^1.1.1", "@ogcapi-js/features": "^1.1.1",
"@ogcapi-js/shared": "^1.1.1", "@ogcapi-js/shared": "^1.1.1",
@ -32087,9 +32087,9 @@
"version": "1.0.0" "version": "1.0.0"
}, },
"panoramax-js": { "panoramax-js": {
"version": "0.3.6", "version": "0.3.8",
"resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.6.tgz", "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.8.tgz",
"integrity": "sha512-CRdXwh91H6chd1PYptG070ukx+S6IkVaUeQVG91ySevoJoCYOuBT65qkMhRo49X2um1nGcs9UqolW90R57875g==", "integrity": "sha512-l8bUi+urcdqLjckGcEyDmYyAYCKjwFXpk/En7gpi5x32Nq2r9sHq7obX3Jbk1F7zH4rmpKbVtjS97cKEZr9zHQ==",
"requires": { "requires": {
"@ogcapi-js/features": "^1.1.1", "@ogcapi-js/features": "^1.1.1",
"@ogcapi-js/shared": "^1.1.1", "@ogcapi-js/shared": "^1.1.1",

View file

@ -208,7 +208,7 @@
"opening_hours": "^3.6.0", "opening_hours": "^3.6.0",
"osm-auth": "^2.5.0", "osm-auth": "^2.5.0",
"osmtogeojson": "^3.0.0-beta.5", "osmtogeojson": "^3.0.0-beta.5",
"panoramax-js": "^0.3.6", "panoramax-js": "^0.3.8",
"panzoom": "^9.4.3", "panzoom": "^9.4.3",
"papaparse": "^5.3.1", "papaparse": "^5.3.1",
"pg": "^8.11.3", "pg": "^8.11.3",

View file

@ -81,11 +81,10 @@ export class ImageUploadManager {
public canBeUploaded(file: File): true | { error: Translation } { public canBeUploaded(file: File): true | { error: Translation } {
const sizeInBytes = file.size const sizeInBytes = file.size
const self = this
if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) { if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) {
const error = Translations.t.image.toBig.Subs({ const error = Translations.t.image.toBig.Subs({
actual_size: Math.floor(sizeInBytes / 1000000) + "MB", actual_size: Math.floor(sizeInBytes / 1000000) + "MB",
max_size: self._uploader.maxFileSizeInMegabytes + "MB", max_size: this._uploader.maxFileSizeInMegabytes + "MB",
}) })
return { error } return { error }
} }
@ -102,7 +101,8 @@ export class ImageUploadManager {
public async uploadImageAndApply( public async uploadImageAndApply(
file: File, file: File,
tagsStore: UIEventSource<OsmTags>, tagsStore: UIEventSource<OsmTags>,
targetKey?: string, targetKey: string,
noblur: boolean,
): Promise<void> { ): Promise<void> {
const canBeUploaded = this.canBeUploaded(file) const canBeUploaded = this.canBeUploaded(file)
if (canBeUploaded !== true) { if (canBeUploaded !== true) {
@ -120,6 +120,7 @@ export class ImageUploadManager {
author, author,
file, file,
targetKey, targetKey,
noblur
) )
if (!uploadResult) { if (!uploadResult) {
return return
@ -139,6 +140,7 @@ export class ImageUploadManager {
author: string, author: string,
blob: File, blob: File,
targetKey: string | undefined, targetKey: string | undefined,
noblur: boolean
): Promise<UploadResult> { ): Promise<UploadResult> {
this.increaseCountFor(this._uploadStarted, featureId) this.increaseCountFor(this._uploadStarted, featureId)
let key: string let key: string
@ -153,12 +155,12 @@ export class ImageUploadManager {
location = GeoOperations.centerpointCoordinates(feature) location = GeoOperations.centerpointCoordinates(feature)
} }
try { try {
;({ key, value, absoluteUrl } = await this._uploader.uploadImage(blob, location, author)) ({ key, value, absoluteUrl } = await this._uploader.uploadImage(blob, location, author, noblur))
} catch (e) { } catch (e) {
this.increaseCountFor(this._uploadRetried, featureId) this.increaseCountFor(this._uploadRetried, featureId)
console.error("Could not upload image, trying again:", e) console.error("Could not upload image, trying again:", e)
try { try {
;({ key, value , absoluteUrl} = await this._uploader.uploadImage(blob, location, author)) ({ key, value , absoluteUrl} = await this._uploader.uploadImage(blob, location, author, noblur))
this.increaseCountFor(this._uploadRetriedSuccess, featureId) this.increaseCountFor(this._uploadRetriedSuccess, featureId)
} catch (e) { } catch (e) {
console.error("Could again not upload image due to", e) console.error("Could again not upload image due to", e)

View file

@ -7,7 +7,8 @@ export interface ImageUploader {
uploadImage( uploadImage(
blob: File, blob: File,
currentGps: [number,number], currentGps: [number,number],
author: string author: string,
noblur: boolean
): Promise<UploadResult> ): Promise<UploadResult>
} }

View file

@ -167,12 +167,12 @@ export class PanoramaxUploader implements ImageUploader {
this._panoramax = new AuthorizedPanoramax(url, token) this._panoramax = new AuthorizedPanoramax(url, token)
} }
async uploadImage(blob: File, currentGps: [number, number], author: string): Promise<{ async uploadImage(blob: File, currentGps: [number, number], author: string, noblur: boolean = false): Promise<{
key: string; key: string;
value: string; value: string;
absoluteUrl: string absoluteUrl: string
}> { }> {
// https://panoramax.openstreetmap.fr/api/docs/swagger#/
const tags = await ExifReader.load(blob) const tags = await ExifReader.load(blob)
const hasDate = tags.DateTime !== undefined const hasDate = tags.DateTime !== undefined
const hasGPS = tags.GPSLatitude !== undefined && tags.GPSLongitude !== undefined const hasGPS = tags.GPSLatitude !== undefined && tags.GPSLongitude !== undefined
@ -184,6 +184,7 @@ export class PanoramaxUploader implements ImageUploader {
const img = <ImageData>await p.addImage(blob, defaultSequence, { const img = <ImageData>await p.addImage(blob, defaultSequence, {
lat: !hasGPS ? lat : undefined, lat: !hasGPS ? lat : undefined,
lon: !hasGPS ? lon : undefined, lon: !hasGPS ? lon : undefined,
isBlurred: noblur,
datetime: !hasDate ? new Date().toISOString() : undefined, datetime: !hasDate ? new Date().toISOString() : undefined,
exifOverride: { exifOverride: {
Artist: author, Artist: author,

View file

@ -4,8 +4,8 @@
*/ */
import type { SpecialVisualizationState } from "../SpecialVisualization" import type { SpecialVisualizationState } from "../SpecialVisualization"
import { ImmutableStore, UIEventSource } from "../../Logic/UIEventSource" import { UIEventSource } from "../../Logic/UIEventSource"
import type { OsmId, OsmTags } from "../../Models/OsmFeature" import type { OsmTags } from "../../Models/OsmFeature"
import LoginToggle from "../Base/LoginToggle.svelte" import LoginToggle from "../Base/LoginToggle.svelte"
import Translations from "../i18n/Translations" import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte" import Tr from "../Base/Tr.svelte"
@ -22,6 +22,7 @@
export let tags: UIEventSource<OsmTags> export let tags: UIEventSource<OsmTags>
export let targetKey: string = undefined export let targetKey: string = undefined
export let layer: LayerConfig export let layer: LayerConfig
export let noBlur: boolean = false
/** /**
* Image to show in the button * Image to show in the button
* NOT the image to upload! * NOT the image to upload!
@ -47,22 +48,22 @@
continue continue
} }
if(layer?.id === "note"){ if (layer?.id === "note") {
const uploadResult = await state?.imageUploadManager.uploadImageWithLicense(tags.data.id, const uploadResult = await state?.imageUploadManager.uploadImageWithLicense(tags.data.id,
state.osmConnection.userDetails.data?.name ?? "Anonymous", state.osmConnection.userDetails.data?.name ?? "Anonymous",
file, "image") file, "image", noBlur)
if(!uploadResult){ if (!uploadResult) {
return return
} }
const url = uploadResult.absoluteUrl const url = uploadResult.absoluteUrl
await state.osmConnection.addCommentToNote(tags.data.id, url) await state.osmConnection.addCommentToNote(tags.data.id, url)
NoteCommentElement.addCommentTo(url, <UIEventSource<any>>tags, { NoteCommentElement.addCommentTo(url, <UIEventSource<any>>tags, {
osmConnection: state.osmConnection, osmConnection: state.osmConnection
}) })
return return
} }
await state?.imageUploadManager.uploadImageAndApply(file, tags, targetKey) await state?.imageUploadManager.uploadImageAndApply(file, tags, targetKey, noBlur)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
state.reportError(e, "Could not upload image") state.reportError(e, "Could not upload image")
@ -96,12 +97,21 @@
{#if labelText} {#if labelText}
{labelText} {labelText}
{:else} {:else}
<Tr t={t.addPicture} /> <div class="flex flex-col">
<Tr t={t.addPicture} />
{#if noBlur}
<span class="subtle text-sm">
Faces will not be blurred
</span>
{/if}
</div>
{/if} {/if}
</div> </div>
</FileSelector> </FileSelector>
<div class="text-xs subtle italic"> <div class="text-xs subtle italic">
<Tr t={Translations.t.general.attribution.panoramaxLicenseCCBYSA}/> <Tr t={Translations.t.general.attribution.panoramaxLicenseCCBYSA} />
<span class="mx-1"></span> <span class="mx-1"></span>
<Tr t={t.respectPrivacy} /> <Tr t={t.respectPrivacy} />
</div> </div>

File diff suppressed because it is too large Load diff