forked from MapComplete/MapComplete
UX: usertest + fix some surfaced issues, see #2108
This commit is contained in:
parent
45481a879d
commit
f5e71f2f1c
9 changed files with 128 additions and 5 deletions
49
Docs/UserTests/2025-09-12 Usertest Paul.md
Normal file
49
Docs/UserTests/2025-09-12 Usertest Paul.md
Normal file
|
@ -0,0 +1,49 @@
|
|||
User test Paul
|
||||
Tech Skills: High, low OSM knowledge
|
||||
Demography: M, ~22
|
||||
Language: NL
|
||||
MapComplete App (Google-Play versie)
|
||||
|
||||
No predetermined goal to achieve
|
||||
|
||||
- Wilt taalfout fixen: ommetoer via 3 login systemen....
|
||||
Out of scope voor beginners
|
||||
|
||||
- Loginscherm is wit:
|
||||
Chrome openen ernaast
|
||||
Technische bug, maar hoe te fixen?
|
||||
|
||||
- Toiletten: vragen over databron
|
||||
|
||||
- Hackerspace kaart: ik heb twee symbolen, wat is het verschil? Ik heb geen legende?
|
||||
-> Achtergrondkaart selectie? Daar legende?
|
||||
Aanklikken symbooltjes: softwaregericht / makerspace... Ooohhhh
|
||||
- OK, is duidelijk
|
||||
|
||||
- "Geen idee wat panoramax is" > Open Panoramax/Mapillary hier
|
||||
Geen idee wat dit is
|
||||
Heeft wat meer info nodig (!)
|
||||
"Allemaal links naar andere maps..."
|
||||
|
||||
- Zoekfunctie: de dingen staan in de weg
|
||||
-> Ik kan op terug klikken. Ja nee, dat dacht ik al
|
||||
-> Terug terug gaat niet terug
|
||||
-> "Gouda". Ja nee, dat is niet handig...
|
||||
Ik wil een ander thema... Ah ja
|
||||
-> 'Active filters' staat in de weg - max height: 1/2 height
|
||||
-> "Clear text"-knop staat permanent aan, opvolgtest: niet gevonden
|
||||
|
||||
- Kompas: "ooh, het wijzertje is mijn kompas!" -> Popup tonen met "wijst nu naar je kompas"
|
||||
Fixed by adding popovers
|
||||
|
||||
- Trees: icoontje ontbreekt in app
|
||||
Niemand heeft onze boom toegevoegd! Toevoegen
|
||||
"Ja, het is een loofboom"
|
||||
Locatie toevoegen gaat vlot
|
||||
Voeg toe! Gaat vlot
|
||||
Foto toevoegen: gaat ook vlot
|
||||
Plantnet-detectie: gaat vlot, maar niet de juiste boomsoort
|
||||
"Oh, ik kon er gewoon op klikken" -> duidelijk maken voor preview
|
||||
|
||||
- Waarom staan restaurants los van cafés?
|
||||
OSM-keuze
|
|
@ -32,6 +32,17 @@
|
|||
"intro": "Get in touch with other people to get to know them, learn from them, …",
|
||||
"title": "Get in touch with others"
|
||||
},
|
||||
"compass": {
|
||||
"E": "Map has east pointing up",
|
||||
"N": "Map has north pointing up",
|
||||
"NE": "Map has northeast pointing up",
|
||||
"NW": "Map has northwest pointing up",
|
||||
"S": "Map has south pointing up",
|
||||
"SE": "Map has southeast pointing up",
|
||||
"SW": "Map has southwest pointing up",
|
||||
"W": "Map has west pointing up",
|
||||
"toCompass": "The map is now oriented to the device orientation"
|
||||
},
|
||||
"copy": {
|
||||
"button": "Create a copy",
|
||||
"confirm": "Create copy at the specified location",
|
||||
|
|
|
@ -1970,6 +1970,10 @@ input[type="range"].range-lg::-moz-range-thumb {
|
|||
max-height: 16rem;
|
||||
}
|
||||
|
||||
.max-h-\[30vh\] {
|
||||
max-height: 30vh;
|
||||
}
|
||||
|
||||
.max-h-full {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
@ -5346,6 +5350,13 @@ input[type="text"] {
|
|||
* This very important section defines what the various input elements look like within the 'low-interaction' and 'interactive'-blocks
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
/* Disable the 'clear text field' button in chrome */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/********* BUTTONS ***********/
|
||||
|
||||
button, .button {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<div class="sidebar-unit">
|
||||
<script lang="ts">
|
||||
export let clss = ""
|
||||
</script>
|
||||
|
||||
<div class={"sidebar-unit "+clss}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
import Compass_back from "../../assets/svg/Compass_back.svelte"
|
||||
import Compass_needle from "../../assets/svg/Compass_needle.svelte"
|
||||
import North_arrow from "../../assets/svg/North_arrow.svelte"
|
||||
import { Popover } from "flowbite-svelte"
|
||||
import { Translation, TypedTranslation } from "../i18n/Translation"
|
||||
import TrDyn from "../Base/TrDyn.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import { GeoOperations } from "../../Logic/GeoOperations"
|
||||
|
||||
export let mapProperties: { rotation: UIEventSource<number>; allowRotating: Store<boolean> }
|
||||
let orientation = Orientation.singleton.alpha
|
||||
|
@ -17,24 +23,48 @@
|
|||
}
|
||||
})
|
||||
let mapRotation = mapProperties.rotation
|
||||
let showHint = new UIEventSource(false)
|
||||
showHint.stabilized(4000).addCallback(isShown => {
|
||||
if (isShown) {
|
||||
showHint.set(false)
|
||||
}
|
||||
})
|
||||
let hovered = new UIEventSource(false)
|
||||
let focused = new UIEventSource(false)
|
||||
|
||||
let hint: UIEventSource<Translation> = new UIEventSource(undefined)
|
||||
export let size = "h-10 w-10"
|
||||
let wrapperClass = "absolute top-0 left-0 " + size
|
||||
let compassLoaded = Orientation.singleton.gotMeasurement
|
||||
let allowRotation = mapProperties.allowRotating
|
||||
|
||||
function clicked() {
|
||||
showHint.set(true)
|
||||
if (mapProperties.rotation.data === 0) {
|
||||
if (mapProperties.allowRotating.data && compassLoaded.data) {
|
||||
mapProperties.rotation.set(orientation.data)
|
||||
hint.set(Translations.t.compass.toCompass)
|
||||
}
|
||||
} else {
|
||||
mapProperties.rotation.set(0)
|
||||
hint.set(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
let orientationText = mapProperties.rotation.mapD(r => {
|
||||
const key = GeoOperations.bearingToHuman(r)
|
||||
return Translations.t.compass[key]
|
||||
})
|
||||
|
||||
let deviceOrientation = Orientation.singleton.alpha
|
||||
|
||||
Orientation.singleton.fakeMeasurements() // TODO Remove
|
||||
</script>
|
||||
|
||||
{#if $allowRotation || $gotNonZero}
|
||||
<button class={"as-link pointer-events-auto relative " + size} on:click={() => clicked()}>
|
||||
<button class={"as-link pointer-events-auto relative " + size} on:click={() => clicked()}
|
||||
on:mouseenter={() => hovered.set(true)} on:mouseleave={() => hovered.set(false)}
|
||||
on:focus={() => focused.set(true)} on:blur={() => focused.set(false)}>
|
||||
{#if $allowRotation && !$compassLoaded && !$gotNonZero}
|
||||
<div
|
||||
class={"rounded-full border-2 border-dotted border-gray-500 " + wrapperClass}
|
||||
|
@ -61,4 +91,14 @@
|
|||
{/if}
|
||||
{/if}
|
||||
</button>
|
||||
<Popover placement="right" open={$showHint || $hovered || $focused} trigger="null">
|
||||
<div class="flex flex-col">
|
||||
{#if $hint !== undefined}
|
||||
<Tr t={$hint} />
|
||||
{:else if Math.abs($deviceOrientation - (($mapRotation + 360) % 360)) <= 45}
|
||||
<Tr t={Translations.t.compass.toCompass} />
|
||||
{/if}
|
||||
<Tr t={$orientationText} />
|
||||
</div>
|
||||
</Popover>
|
||||
{/if}
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
|
||||
let featureSwitches = state.featureSwitches
|
||||
let showHome = featureSwitches?.featureSwitchBackToThemeOverview ?? new ImmutableStore(true)
|
||||
let allowLogin = featureSwitches?.featureSwitchEnableLogin ?? new ImmutableStore(true)
|
||||
let pg = state.guistate.pageStates
|
||||
let pendingChanges = state?.changes?.pendingChanges
|
||||
export let onlyLink: boolean
|
||||
|
@ -119,7 +120,7 @@
|
|||
|
||||
<div class="flex flex-col gap-y-2 overflow-y-auto px-2 sm:gap-y-3 sm:px-3">
|
||||
{#if $showHome || $isAndroid}
|
||||
<a class="button flex" class:primary={$loggedIn} href={Utils.HomepageLink()}>
|
||||
<a class="button flex" class:primary={$loggedIn || $allowLogin} href={Utils.HomepageLink()}>
|
||||
<Squares2x2 class="h-10 w-10" />
|
||||
{#if Utils.isIframe}
|
||||
<Tr t={Translations.t.general.seeIndex} />
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
import { WithSearchState } from "../../Models/ThemeViewState/WithSearchState"
|
||||
|
||||
export let activeFilters: (FilterSearchResult & ActiveFilter)[]
|
||||
export let clss = ""
|
||||
let language = Locale.language
|
||||
let mergedActiveFilters = FilterSearch.mergeSemiIdenticalLayers(activeFilters, $language)
|
||||
$: mergedActiveFilters = FilterSearch.mergeSemiIdenticalLayers(activeFilters, $language)
|
||||
|
@ -54,7 +55,7 @@
|
|||
</script>
|
||||
|
||||
{#if mergedActiveFilters.length > 0 || $nonactiveLayers.length > 0}
|
||||
<SidebarUnit>
|
||||
<SidebarUnit {clss}>
|
||||
<div class="flex justify-between">
|
||||
<h3><Tr t={t.activeFilters} /></h3>
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
<div class="low-interaction flex flex-col gap-y-2 p-4">
|
||||
{#if $allowFilters}
|
||||
<ActiveFilters {state} activeFilters={$activeFilters} />
|
||||
<ActiveFilters clss={"flex-shrink "+ ($searchTerm.length > 0 ? "max-h-[30vh]" : "")} {state} activeFilters={$activeFilters} />
|
||||
{/if}
|
||||
{#if $searchTerm.length === 0 && $activeFilters.length === 0}
|
||||
<div class="items-center p-8 text-center">
|
||||
|
|
|
@ -186,6 +186,12 @@ input[type="text"] {
|
|||
* This very important section defines what the various input elements look like within the 'low-interaction' and 'interactive'-blocks
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
/* Disable the 'clear text field' button in chrome */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
/********* BUTTONS ***********/
|
||||
|
||||
button, .button {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue