MapComplete/src/UI/Image/UploadImage.svelte

132 lines
4 KiB
Svelte

<script lang="ts">
/**
* Shows an 'upload'-button which will start the upload for this feature
*/
import type { SpecialVisualizationState } from "../SpecialVisualization"
import { UIEventSource } from "../../Logic/UIEventSource"
import type { OsmTags } from "../../Models/OsmFeature"
import LoginToggle from "../Base/LoginToggle.svelte"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import UploadingImageCounter from "./UploadingImageCounter.svelte"
import FileSelector from "../Base/FileSelector.svelte"
import LoginButton from "../Base/LoginButton.svelte"
import { Translation } from "../i18n/Translation"
import type { Feature } from "geojson"
import Camera from "@babeard/svelte-heroicons/mini/Camera"
export let state: SpecialVisualizationState
export let tags: UIEventSource<OsmTags>
export let targetKey: string = undefined
export let noBlur: boolean = false
export let feature: Feature
/**
* Image to show in the button
* NOT the image to upload!
*/
export let image: string = undefined
if (image === "") {
image = undefined
}
export let labelText: string = undefined
const t = Translations.t.image
let errors = new UIEventSource<Translation[]>([])
async function handleFiles(files: FileList, ignoreGPS: boolean = false) {
const errs = []
for (let i = 0; i < files.length; i++) {
const file = files.item(i)
console.log("Got file", file.name)
try {
const canBeUploaded = state?.imageUploadManager?.canBeUploaded(file)
if (canBeUploaded !== true) {
errs.push(canBeUploaded.error)
continue
}
await state?.imageUploadManager?.uploadImageAndApply(
file,
tags,
targetKey,
noBlur,
feature,
{ ignoreGPS }
)
} catch (e) {
console.error(e)
state.reportError(e, "Could not upload image")
}
}
errors.setData(errs)
}
let maintenanceBusy = false
</script>
<LoginToggle {state}>
<LoginButton clss="small w-full" osmConnection={state.osmConnection} slot="not-logged-in">
<Tr t={Translations.t.image.pleaseLogin} />
</LoginButton>
{#if maintenanceBusy}
<div class="alert">
Due to maintenance, uploading images is currently not possible. Sorry about this!
</div>
{:else}
<div class="my-4 flex flex-col">
<UploadingImageCounter {state} {tags} />
{#each $errors as error}
<Tr t={error} cls="alert" />
{/each}
<FileSelector
accept=".jpg,.jpeg,image/jpeg"
capture="environment"
cls="button border-2 flex flex-col"
multiple={true}
on:submit={(e) => {
handleFiles(e.detail)
e.preventDefault()
e.stopPropagation()
}}
>
<div class="flex w-full items-center justify-center text-2xl">
{#if image !== undefined}
<img src={image} aria-hidden="true" />
{:else}
<Camera class="h-12 w-12 p-1" aria-hidden="true" />
{/if}
{#if labelText}
{labelText}
{:else}
<div class="flex flex-col">
<Tr t={t.addPicture} />
{#if noBlur}
<span class="subtle text-sm">
<Tr t={t.upload.noBlur} />
</span>
{/if}
</div>
{/if}
</div>
</FileSelector>
<FileSelector
accept=".jpg, .jpeg"
cls="flex justify-center md:hidden button"
multiple={true}
on:submit={(e) => {
e.preventDefault()
e.stopPropagation()
return handleFiles(e.detail, true)
}}
>
<Tr t={t.selectFile} />
</FileSelector>
<div class="subtle text-xs italic">
<Tr t={Translations.t.general.attribution.panoramaxLicenseCCBYSA} />
<span class="mx-1"></span>
<Tr t={t.respectPrivacy} />
</div>
</div>
{/if}
</LoginToggle>