forked from MapComplete/MapComplete
UX: improve 'plantnet detection' UI, fix #1989 (technically, the text was there all along)
This commit is contained in:
parent
01d924374e
commit
6c730f5581
2 changed files with 73 additions and 54 deletions
|
@ -734,7 +734,8 @@
|
||||||
"li1": "take a picture which shows a single leaf",
|
"li1": "take a picture which shows a single leaf",
|
||||||
"li2": "take a picture which shows the bark",
|
"li2": "take a picture which shows the bark",
|
||||||
"li3": "take a picture of the flowers",
|
"li3": "take a picture of the flowers",
|
||||||
"li4": "take a picture of the fruits"
|
"li4": "take a picture of the fruits",
|
||||||
|
"title": "What pictures to take for automatic detection?"
|
||||||
},
|
},
|
||||||
"loadingWikidata": "Loading information about {species}…",
|
"loadingWikidata": "Loading information about {species}…",
|
||||||
"matchPercentage": "{match}% match",
|
"matchPercentage": "{match}% match",
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte"
|
import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte"
|
||||||
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte"
|
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte"
|
||||||
import ArrowPath from "@babeard/svelte-heroicons/mini/ArrowPath"
|
import ArrowPath from "@babeard/svelte-heroicons/mini/ArrowPath"
|
||||||
|
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main entry point for the plantnet wizard
|
* The main entry point for the plantnet wizard
|
||||||
|
@ -23,7 +24,6 @@
|
||||||
*/
|
*/
|
||||||
export let imageUrls: Store<string[]>
|
export let imageUrls: Store<string[]>
|
||||||
export let onConfirm: (wikidataId: string) => void
|
export let onConfirm: (wikidataId: string) => void
|
||||||
let collapsedMode = true
|
|
||||||
let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>(
|
let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>(
|
||||||
undefined
|
undefined
|
||||||
)
|
)
|
||||||
|
@ -35,6 +35,8 @@
|
||||||
*/
|
*/
|
||||||
let selectedOption: string
|
let selectedOption: string
|
||||||
|
|
||||||
|
let running = false
|
||||||
|
let expandExplanation = false
|
||||||
let done = false
|
let done = false
|
||||||
|
|
||||||
function speciesSelected(species: string) {
|
function speciesSelected(species: string) {
|
||||||
|
@ -44,69 +46,52 @@
|
||||||
|
|
||||||
async function detectSpecies() {
|
async function detectSpecies() {
|
||||||
error = undefined
|
error = undefined
|
||||||
collapsedMode = false
|
running = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result: PlantNetResult | "no_plant_detected" = await PlantNet.query(imageUrls.data.slice(0, 5))
|
const result: PlantNetResult | "no_plant_detected" = await PlantNet.query(imageUrls.data.slice(0, 5))
|
||||||
if (result === "no_plant_detected") {
|
if (result === "no_plant_detected") {
|
||||||
error = "no_plant_detected"
|
error = "no_plant_detected"
|
||||||
|
expandExplanation = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
options.set(result.results.filter((r) => r.score > 0.005).slice(0, 8))
|
const filteredResults = result.results.filter((r) => r.score > 0.005).slice(0, 8)
|
||||||
|
expandExplanation = filteredResults.length == 0
|
||||||
|
options.set(filteredResults)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Caught", e)
|
console.error("Caught", e)
|
||||||
error = e
|
error = e
|
||||||
|
running = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col mb-4">
|
||||||
{#if collapsedMode}
|
|
||||||
<button class="w-full" on:click={detectSpecies}>
|
<!-- Error message -->
|
||||||
<Tr t={t.button} />
|
{#if error === "no_plant_detected"}
|
||||||
</button>
|
|
||||||
{:else if error === "no_plant_detected"}
|
|
||||||
<Tr cls="alert" t={t.noPlantDetected} />
|
<Tr cls="alert" t={t.noPlantDetected} />
|
||||||
<button on:click={() => detectSpecies()}>
|
|
||||||
<ArrowPath class="h-6 w-6" />
|
|
||||||
<Tr t={Translations.t.general.retry} />
|
|
||||||
</button>
|
|
||||||
{:else if error !== undefined}
|
{:else if error !== undefined}
|
||||||
<Tr cls="alert" t={t.error.Subs({ error })} />
|
<Tr cls="alert" t={t.error.Subs({ error })} />
|
||||||
<button on:click={() => detectSpecies()}>
|
{/if}
|
||||||
<ArrowPath class="h-6 w-6" />
|
|
||||||
<Tr t={Translations.t.general.retry} />
|
|
||||||
|
<!-- Button. If 'done==false', the button should be shown, otherwise <PlantnetSpeciesList> will handle the flow -->
|
||||||
|
{#if !done && !running && !selectedOption}
|
||||||
|
<button class="w-full flex" on:click={detectSpecies}>
|
||||||
|
<Plantnet_logo class="mr-2 shrink-0 h-8 w-8 rounded-full bg-white p-1" />
|
||||||
|
<span class="flex flex-col items-center">
|
||||||
|
<Tr t={t.button} />
|
||||||
|
{#if error !== undefined}
|
||||||
|
<div class="flex subtle mt-2">
|
||||||
|
|
||||||
|
<ArrowPath class="h-6 w-6" />
|
||||||
|
<Tr t={Translations.t.general.retry} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
{:else if $imageUrls.length === 0}
|
{:else if !selectedOption}
|
||||||
<!-- No urls are available, show the explanation instead-->
|
|
||||||
<div class=" border-region relative mb-1 p-2">
|
|
||||||
<XCircleIcon
|
|
||||||
class="absolute right-0 top-0 m-4 h-8 w-8 cursor-pointer"
|
|
||||||
on:click={() => {
|
|
||||||
collapsedMode = true
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Tr t={t.takeImages} />
|
|
||||||
<Tr t={t.howTo.intro} />
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<Tr t={t.howTo.li0} />
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Tr t={t.howTo.li1} />
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Tr t={t.howTo.li2} />
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Tr t={t.howTo.li3} />
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Tr t={t.howTo.li4} />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{:else if selectedOption === undefined}
|
|
||||||
<PlantNetSpeciesList
|
<PlantNetSpeciesList
|
||||||
{options}
|
{options}
|
||||||
numberOfImages={$imageUrls.length}
|
numberOfImages={$imageUrls.length}
|
||||||
|
@ -115,9 +100,7 @@
|
||||||
<XCircleIcon
|
<XCircleIcon
|
||||||
slot="upper-right"
|
slot="upper-right"
|
||||||
class="m-4 h-8 w-8 cursor-pointer"
|
class="m-4 h-8 w-8 cursor-pointer"
|
||||||
on:click={() => {
|
on:click={() => {running = false}}
|
||||||
collapsedMode = true
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</PlantNetSpeciesList>
|
</PlantNetSpeciesList>
|
||||||
{:else if !done}
|
{:else if !done}
|
||||||
|
@ -158,8 +141,43 @@
|
||||||
<Tr t={t.tryAgain} />
|
<Tr t={t.tryAgain} />
|
||||||
</BackButton>
|
</BackButton>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="low-interaction flex self-end rounded-xl p-2">
|
|
||||||
<Plantnet_logo class="mr-1 h-8 w-8 rounded-full bg-white p-1" />
|
<!-- Explanation -->
|
||||||
<Tr t={t.poweredByPlantnet} />
|
<div class="my-1 low-interaction">
|
||||||
|
|
||||||
|
<AccordionSingle noBorder expanded={expandExplanation}>
|
||||||
|
<div class="subtle flex justify-start text-sm p-1" slot="header">
|
||||||
|
<Tr t={t.howTo.title} />
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-low-interaction border-l border-r border-b flex flex-col">
|
||||||
|
<Tr t={t.takeImages} />
|
||||||
|
<Tr t={t.howTo.intro} />
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<Tr t={t.howTo.li0} />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Tr t={t.howTo.li1} />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Tr t={t.howTo.li2} />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Tr t={t.howTo.li3} />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Tr t={t.howTo.li4} />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- Attribution -->
|
||||||
|
<div class="low-interaction flex items-center self-end rounded-xl p-2 px-3 mt-4 w-fit">
|
||||||
|
<Plantnet_logo class="mr-2 h-8 w-8 rounded-full bg-white p-1" />
|
||||||
|
<Tr t={t.poweredByPlantnet} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</AccordionSingle>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue