UI: fix behaviour of hotkey "escape" when closing previews and nearby images popups

This commit is contained in:
Pieter Vander Vennet 2025-03-13 16:53:12 +01:00
parent ae84207555
commit e22929bb35
6 changed files with 73 additions and 49 deletions

View file

@ -4,6 +4,7 @@ import UserRelatedState from "../Logic/State/UserRelatedState"
import { Utils } from "../Utils"
import Zoomcontrol from "../UI/Zoomcontrol"
import { LocalStorageSource } from "../Logic/Web/LocalStorageSource"
import { ProvidedImage } from "../Logic/ImageProviders/ImageProvider"
export type PageType = (typeof MenuState.pageNames)[number]
@ -27,7 +28,7 @@ export class MenuState {
"favourites",
"usersettings",
"share",
"menu",
"menu"
] as const
/**
@ -38,6 +39,9 @@ export class MenuState {
undefined
)
public static readonly nearbyImagesFeature: UIEventSource<object> = new UIEventSource<object>(
undefined
)
public readonly pageStates: Record<PageType, UIEventSource<boolean>>
public readonly highlightedLayerInFilters: UIEventSource<string> = new UIEventSource<string>(
@ -45,6 +49,7 @@ export class MenuState {
)
public highlightedUserSetting: UIEventSource<string> = new UIEventSource<string>(undefined)
private readonly _selectedElement: UIEventSource<any> | undefined
private isClosingAll = false
constructor(selectedElement: UIEventSource<any> | undefined) {
this._selectedElement = selectedElement
@ -129,29 +134,49 @@ export class MenuState {
* Returns 'true' if at least one menu was opened
*/
public closeAll(): boolean {
console.log("Closing all")
if (this.isClosingAll) {
return true
}
this.isClosingAll = true
const ps = this.pageStates
if (ps.menu.data) {
ps.menu.set(false)
return true
}
try {
if (MenuState.previewedImage.data !== undefined) {
MenuState.previewedImage.setData(undefined)
return true
}
for (const key in ps) {
const toggle = ps[key]
const wasOpen = toggle.data
toggle.setData(false)
if (wasOpen) {
if (ps.menu.data) {
ps.menu.set(false)
return true
}
}
if (this._selectedElement.data) {
this._selectedElement.setData(undefined)
return true
if (MenuState.previewedImage.data !== undefined) {
MenuState.previewedImage.setData(undefined)
return true
}
if (MenuState.nearbyImagesFeature.data !== undefined) {
MenuState.nearbyImagesFeature.setData(undefined)
return true
}
for (const key in ps) {
const toggle = ps[key]
const wasOpen = toggle.data
toggle.setData(false)
if (wasOpen) {
return true
}
}
if (this._selectedElement.data) {
this._selectedElement.setData(undefined)
return true
}
} finally {
this.isClosingAll = false
}
}
public setPreviewedImage(img?: Partial<ProvidedImage>) {
if (img === undefined && !this.isClosingAll) {
return
}
MenuState.previewedImage.setData(img)
}
}

View file

@ -14,6 +14,8 @@ export default class Hotkeys {
}[]
> = new UIEventSource([])
private static readonly seenKeys: Set<string> = new Set()
/**
* Register a hotkey
* @param key
@ -51,6 +53,9 @@ export default class Hotkeys {
}
}
const keyString = JSON.stringify(key)
this.seenKeys.add(keyString)
this._docs.data.push({ key, documentation, alsoTriggeredBy })
this._docs.ping()
if (Utils.runningFromConsole) {

View file

@ -56,6 +56,7 @@
<slot name="header" />
</h1>
{/if}
<slot name="closebutton" />
</svelte:fragment>
<slot />
{#if $$slots.footer}

View file

@ -11,7 +11,6 @@
import ImageOperations from "./ImageOperations.svelte"
import Popup from "../Base/Popup.svelte"
import { onDestroy } from "svelte"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import type { Feature, Point } from "geojson"
import Loading from "../Base/Loading.svelte"
import Translations from "../i18n/Translations"
@ -19,8 +18,9 @@
import DotMenu from "../Base/DotMenu.svelte"
import LoadingPlaceholder from "../Base/LoadingPlaceholder.svelte"
import { MenuState } from "../../Models/MenuState"
import ThemeViewState from "../../Models/ThemeViewState"
export let image: Partial<ProvidedImage>
export let image: Partial<ProvidedImage> & { id: string; url: string }
let fallbackImage: string = undefined
if (image.provider === Mapillary.singleton) {
fallbackImage = "./assets/svg/blocked.svg"
@ -28,7 +28,7 @@
let imgEl: HTMLImageElement
export let imgClass: string = undefined
export let state: SpecialVisualizationState = undefined
export let state: ThemeViewState = undefined
export let attributionFormat: "minimal" | "medium" | "large" = "medium"
let previewedImage: UIEventSource<Partial<ProvidedImage>> = MenuState.previewedImage
export let canZoom = previewedImage !== undefined
@ -36,9 +36,7 @@
let showBigPreview = new UIEventSource(false)
onDestroy(
showBigPreview.addCallbackAndRun((shown) => {
if (!shown) {
previewedImage?.set(undefined)
}
state.guistate.setPreviewedImage(shown ? image : undefined)
})
)
if (previewedImage) {

View file

@ -89,17 +89,6 @@
imgClass="max-h-64 w-auto sm:h-32 md:h-64"
attributionFormat="minimal"
>
<!--
<div slot="preview-action" class="self-center" >
<LoginToggle {state} silentFail={true}>
{#if linkable}
<label class="normal-background p-2 rounded-full pointer-events-auto">
<input bind:checked={$isLinked} type="checkbox" />
<SpecialTranslation t={t.link} {tags} {state} {layer} {feature} />
</label>
{/if}
</LoginToggle>
</div>-->
</AttributedImage>
<LoginToggle {state} silentFail={true}>
{#if linkable}

View file

@ -1,22 +1,19 @@
<script lang="ts">
import { UIEventSource } from "../../Logic/UIEventSource"
import type { OsmTags } from "../../Models/OsmFeature"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import type { Feature } from "geojson"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import NearbyImages from "./NearbyImages.svelte"
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
import Camera_plus from "../../assets/svg/Camera_plus.svelte"
import LoginToggle from "../Base/LoginToggle.svelte"
import { ariaLabel } from "../../Utils/ariaLabel"
import { Accordion, AccordionItem, Modal } from "flowbite-svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
import Popup from "../Base/Popup.svelte"
import ThemeViewState from "../../Models/ThemeViewState"
import { onDestroy } from "svelte"
import { MenuState } from "../../Models/MenuState"
import { CloseButton } from "flowbite-svelte"
export let tags: UIEventSource<OsmTags>
export let state: SpecialVisualizationState
export let state: ThemeViewState
export let lon: number
export let lat: number
export let feature: Feature
@ -27,6 +24,16 @@
let enableLogin = state.featureSwitches.featureSwitchEnableLogin
export let shown = new UIEventSource(false)
onDestroy(MenuState.nearbyImagesFeature.addCallback(something => {
if (something !== feature) {
shown.set(false)
}
}))
onDestroy(shown.addCallbackAndRun(isShown => {
if (isShown) {
MenuState.nearbyImagesFeature.set(feature)
}
}))
</script>
{#if enableLogin.data}
@ -37,10 +44,9 @@
>
<Tr t={t.seeNearby} />
</button>
<Popup {shown} bodyPadding="p-4">
<span slot="header">
<Tr t={t.seeNearby} />
</span>
<Popup {shown} bodyPadding="p-4" dismissable={false}>
<Tr slot="header" t={t.seeNearby} />
<CloseButton slot="closebutton" on:click={() => shown?.set(false)} />
<NearbyImages {tags} {state} {lon} {lat} {feature} {linkable} {layer} />
</Popup>
{/if}