diff --git a/Logic/Actors/StrayClickHandler.ts b/Logic/Actors/StrayClickHandler.ts index 4e9f90a62..0ba1a850a 100644 --- a/Logic/Actors/StrayClickHandler.ts +++ b/Logic/Actors/StrayClickHandler.ts @@ -53,18 +53,11 @@ export default class StrayClickHandler { popupAnchor: [0, -45], }), }) - const popup = L.popup({ - autoPan: true, - autoPanPaddingTopLeft: [15, 15], - closeOnEscapeKey: true, - autoClose: true, - }).setContent("
") + self._lastMarker.addTo(leafletMap.data) - self._lastMarker.bindPopup(popup) self._lastMarker.on("click", () => { if (leafletMap.data.getZoom() < Constants.userJourney.minZoomLevelToAddNewPoints) { - self._lastMarker.closePopup() leafletMap.data.flyTo( clickCoor, Constants.userJourney.minZoomLevelToAddNewPoints @@ -72,7 +65,6 @@ export default class StrayClickHandler { return } - uiToShow.AttachTo("strayclick") uiToShow.Activate() }) }) diff --git a/Models/Constants.ts b/Models/Constants.ts index 0bea8bda3..b1b94ced9 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -1,7 +1,7 @@ import { Utils } from "../Utils" export default class Constants { - public static vNumber = "0.24.1" + public static vNumber = "0.25.0" public static ImgurApiKey = "7070e7167f0a25a" public static readonly mapillary_client_token_v4 = diff --git a/UI/Base/ScrollableFullScreen.ts b/UI/Base/ScrollableFullScreen.ts index 24d98922d..842cdfd35 100644 --- a/UI/Base/ScrollableFullScreen.ts +++ b/UI/Base/ScrollableFullScreen.ts @@ -1,8 +1,7 @@ -import { UIElement } from "../UIElement" import Svg from "../../Svg" import Combine from "./Combine" -import { FixedUiElement } from "./FixedUiElement" -import { UIEventSource } from "../../Logic/UIEventSource" +import {FixedUiElement} from "./FixedUiElement" +import {UIEventSource} from "../../Logic/UIEventSource" import Hash from "../../Logic/Web/Hash" import BaseUIElement from "../BaseUIElement" import Title from "./Title" @@ -16,12 +15,11 @@ import Title from "./Title" * * */ -export default class ScrollableFullScreen extends UIElement { +export default class ScrollableFullScreen { private static readonly empty = new FixedUiElement("") private static _currentlyOpen: ScrollableFullScreen public isShown: UIEventSource private hashToShow: string - private _component: BaseUIElement private _fullscreencomponent: BaseUIElement private _resetScrollSignal: UIEventSource = new UIEventSource(undefined) @@ -37,7 +35,6 @@ export default class ScrollableFullScreen extends UIElement { setHash?: true | boolean } ) { - super() this.hashToShow = hashToShow this.isShown = isShown @@ -45,20 +42,11 @@ export default class ScrollableFullScreen extends UIElement { throw "HashToShow should be defined as it is vital for the 'back' key functionality" } - const desktopOptions = { - mode: "desktop", - resetScrollSignal: this._resetScrollSignal, - } - const mobileOptions = { mode: "mobile", resetScrollSignal: this._resetScrollSignal, } - this._component = this.BuildComponent( - title(desktopOptions), - content(desktopOptions) - ).SetClass("hidden md:block") this._fullscreencomponent = this.BuildComponent( title(mobileOptions), content(mobileOptions).SetClass("pb-20") @@ -95,17 +83,15 @@ export default class ScrollableFullScreen extends UIElement { }) } - InnerRender(): BaseUIElement { - return this._component - } - Destroy() { - super.Destroy() - this._component.Destroy() this._fullscreencomponent.Destroy() } - Activate(): void { + /** + * Actually show this in the 'fullscreen'-div + * @constructor + */ + public Activate(): void { this.isShown.setData(true) this._fullscreencomponent.AttachTo("fullscreen") const fs = document.getElementById("fullscreen") diff --git a/UI/BigComponents/LeftControls.ts b/UI/BigComponents/LeftControls.ts index 0c4fc6631..6cae112d3 100644 --- a/UI/BigComponents/LeftControls.ts +++ b/UI/BigComponents/LeftControls.ts @@ -45,30 +45,21 @@ export default class LeftControls extends Combine { }) ).SetClass("inline-block w-full h-full") - const featureBox = new VariableUiElement( - feature.map((feature) => { - if (feature === undefined) { - return undefined - } - return new Lazy(() => { - const tagsSource = state.allElements.getEventSourceById( - feature.properties.id - ) - return new FeatureInfoBox(tagsSource, currentViewFL.layerDef, state, { - hashToShow: "currentview", - isShown: guiState.currentViewControlIsOpened, - }).SetClass("md:floating-element-width") - }) - }) - ) - .SetStyle("width: 40rem") - .SetClass("block") - return new Toggle( - featureBox, - new MapControlButton(icon), - guiState.currentViewControlIsOpened - ) + feature.map((feature) => { + if (feature === undefined) { + return undefined + } + const tagsSource = state.allElements.getEventSourceById( + feature.properties.id + ) + return new FeatureInfoBox(tagsSource, currentViewFL.layerDef, state, { + hashToShow: "currentview", + isShown: guiState.currentViewControlIsOpened, + }) + }) + + return new MapControlButton(icon) }).onClick(() => { guiState.currentViewControlIsOpened.setData(true) }), @@ -79,14 +70,9 @@ export default class LeftControls extends Combine { ) ) - const toggledDownload = new Toggle( - new AllDownloads(guiState.downloadControlIsOpened, state).SetClass( - "block p-1 rounded-full md:floating-element-width" - ), - new MapControlButton(Svg.download_svg()).onClick(() => - guiState.downloadControlIsOpened.setData(true) - ), - guiState.downloadControlIsOpened + new AllDownloads(guiState.downloadControlIsOpened, state) + const toggledDownload = new MapControlButton(Svg.download_svg()).onClick(() => + guiState.downloadControlIsOpened.setData(true) ) const downloadButtonn = new Toggle( @@ -98,21 +84,19 @@ export default class LeftControls extends Combine { ) ) - const toggledFilter = new Toggle( - new ScrollableFullScreen( - () => Translations.t.general.layerSelection.title.Clone(), - () => - new FilterView(state.filteredLayers, state.overlayToggles, state).SetClass( - "block p-1" - ), - "filters", - guiState.filterViewIsOpened - ).SetClass("rounded-lg md:floating-element-width"), - new MapControlButton(Svg.layers_svg()).onClick(() => - guiState.filterViewIsOpened.setData(true) - ), + + new ScrollableFullScreen( + () => Translations.t.general.layerSelection.title.Clone(), + () => + new FilterView(state.filteredLayers, state.overlayToggles, state).SetClass( + "block p-1" + ), + "filters", guiState.filterViewIsOpened ) + const toggledFilter = new MapControlButton(Svg.layers_svg()).onClick(() => + guiState.filterViewIsOpened.setData(true) + ) const filterButton = new Toggle(toggledFilter, undefined, state.featureSwitchFilter) @@ -127,18 +111,19 @@ export default class LeftControls extends Combine { undefined, new Lazy( () => - new Toggle( - new ScrollableFullScreen( - () => Translations.t.general.attribution.attributionTitle, - () => new CopyrightPanel(state), - "copyright", - guiState.copyrightViewIsOpened - ), - new MapControlButton(Svg.copyright_svg()).onClick(() => - guiState.copyrightViewIsOpened.setData(true) - ), + { + + new ScrollableFullScreen( + () => Translations.t.general.attribution.attributionTitle, + () => new CopyrightPanel(state), + "copyright", guiState.copyrightViewIsOpened - ) + ); + return new MapControlButton(Svg.copyright_svg()).onClick(() => + guiState.copyrightViewIsOpened.setData(true) + ) + + } ), state.featureSwitchWelcomeMessage ) diff --git a/UI/DefaultGUI.ts b/UI/DefaultGUI.ts index 019589b49..2702b3846 100644 --- a/UI/DefaultGUI.ts +++ b/UI/DefaultGUI.ts @@ -1,7 +1,7 @@ import FeaturePipelineState from "../Logic/State/FeaturePipelineState" import State from "../State" -import { Utils } from "../Utils" -import { UIEventSource } from "../Logic/UIEventSource" +import {Utils} from "../Utils" +import {UIEventSource} from "../Logic/UIEventSource" import FullWelcomePaneWithTabs from "./BigComponents/FullWelcomePaneWithTabs" import MapControlButton from "./MapControlButton" import Svg from "../Svg" @@ -17,7 +17,7 @@ import ScrollableFullScreen from "./Base/ScrollableFullScreen" import Translations from "./i18n/Translations" import SimpleAddUI from "./BigComponents/SimpleAddUI" import StrayClickHandler from "../Logic/Actors/StrayClickHandler" -import { DefaultGuiState } from "./DefaultGuiState" +import {DefaultGuiState} from "./DefaultGuiState" import LayerConfig from "../Models/ThemeConfig/LayerConfig" import * as home_location_json from "../assets/layers/home_location/home_location.json" import NewNoteUi from "./Popup/NewNoteUi" @@ -27,9 +27,9 @@ import FilteredLayer from "../Models/FilteredLayer" import ExtraLinkButton from "./BigComponents/ExtraLinkButton" /** - * The default MapComplete GUI initializor + * The default MapComplete GUI initializer * - * Adds a welcome pane, contorl buttons, ... etc to index.html + * Adds a welcome pane, control buttons, ... etc to index.html */ export default class DefaultGUI { private readonly guiState: DefaultGuiState @@ -53,7 +53,7 @@ export default class DefaultGUI { Utils.downloadJson("./service-worker-version") .then((data) => console.log("Service worker", data)) - .catch((e) => console.log("Service worker not active")) + .catch((_) => console.log("Service worker not active")) } public setupClickDialogOnMap( @@ -218,7 +218,7 @@ export default class DefaultGUI { private InitWelcomeMessage(): BaseUIElement { const isOpened = this.guiState.welcomeMessageIsOpened - const fullOptions = new FullWelcomePaneWithTabs( + new FullWelcomePaneWithTabs( isOpened, this.guiState.welcomeMessageOpenedTab, this.state @@ -242,10 +242,6 @@ export default class DefaultGUI { isOpened.setData(false) }) - return new Toggle( - fullOptions.SetClass("welcomeMessage pointer-events-auto"), - help.SetClass("pointer-events-auto"), - isOpened - ) + return help.SetClass("pointer-events-auto") } } diff --git a/UI/ShowDataLayer/ShowDataLayerImplementation.ts b/UI/ShowDataLayer/ShowDataLayerImplementation.ts index a5f5e299a..637a8da5b 100644 --- a/UI/ShowDataLayer/ShowDataLayerImplementation.ts +++ b/UI/ShowDataLayer/ShowDataLayerImplementation.ts @@ -1,11 +1,13 @@ -import { Store, UIEventSource } from "../../Logic/UIEventSource" +import {Store, UIEventSource} from "../../Logic/UIEventSource" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import { ShowDataLayerOptions } from "./ShowDataLayerOptions" -import { ElementStorage } from "../../Logic/ElementStorage" +import {ShowDataLayerOptions} from "./ShowDataLayerOptions" +import {ElementStorage} from "../../Logic/ElementStorage" import RenderingMultiPlexerFeatureSource from "../../Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource" import ScrollableFullScreen from "../Base/ScrollableFullScreen" +import {LeafletMouseEvent} from "leaflet"; +import Hash from "../../Logic/Web/Hash"; /* -// import 'leaflet-polylineoffset'; +// import 'leaflet-polylineoffset'; We don't actually import it here. It is imported in the 'MinimapImplementation'-class, which'll result in a patched 'L' object. Even though actually importing this here would seem cleaner, we don't do this as this breaks some scripts: - Scripts are ran in ts-node @@ -41,7 +43,7 @@ export default class ShowDataLayerImplementation { * Note: the key of this dictionary is 'feature.properties.id+features.geometry.type' as one feature might have multiple presentations * @private */ - private readonly leafletLayersPerId = new Map() + private readonly leafletLayersPerId = new Map void }>() private readonly showDataLayerid: number private readonly createPopup: ( tags: UIEventSource, @@ -128,11 +130,7 @@ export default class ShowDataLayerImplementation { if (v === undefined) { return } - const leafletLayer = v.leafletlayer const feature = v.feature - if (leafletLayer.getPopup().isOpen()) { - return - } if (selected.properties.id !== feature.properties.id) { return } @@ -143,11 +141,7 @@ export default class ShowDataLayerImplementation { console.log("Not opening the popup for", feature, "as probably renamed") return } - if ( - selected.geometry.type === feature.geometry.type // If a feature is rendered both as way and as point, opening one popup might trigger the other to open, which might trigger the one to open again - ) { - leafletLayer.openPopup() - } + v.activateFunc(null) } private update(options: ShowDataLayerOptions): boolean { @@ -323,64 +317,51 @@ export default class ShowDataLayerImplementation { * @param leafletLayer * @private */ - private postProcessFeature(feature, leafletLayer: L.Layer) { + private postProcessFeature(feature, leafletLayer: L.Evented) { const layer: LayerConfig = this._layerToShow if (layer.title === undefined || !this._enablePopups) { // No popup action defined -> Don't do anything // or probably a map in the popup - no popups needed! return } - - const popup = L.popup( - { - autoPan: true, - closeOnEscapeKey: true, - closeButton: false, - autoPanPaddingTopLeft: [15, 15], - }, - leafletLayer - ) - - leafletLayer.bindPopup(popup) - + const key = feature.properties.id + if(this.leafletLayersPerId.has(key)){ + const activate = this.leafletLayersPerId.get(key) + leafletLayer.addEventListener('click', activate.activateFunc) + if(Hash.hash.data === key ){ + activate.activateFunc(null) + } + return; + } let infobox: ScrollableFullScreen = undefined - const id = `popup-${feature.properties.id}-${feature.geometry.type}-${ - this.showDataLayerid - }-${this._cleanCount}-${feature.pointRenderingIndex ?? feature.lineRenderingIndex}-${ - feature.multiLineStringIndex ?? "" - }` - popup.setContent( - `
Popup for ${feature.properties.id} ${feature.geometry.type} ${id} is loading
` - ) - const createpopup = this.createPopup - leafletLayer.on("popupopen", () => { + const self = this + + function activate (event: LeafletMouseEvent) { + console.log("Activating!") if (infobox === undefined) { const tags = - this.allElements?.getEventSourceById(feature.properties.id) ?? + self.allElements?.getEventSourceById(key) ?? new UIEventSource(feature.properties) - infobox = createpopup(tags, layer) + infobox = self.createPopup(tags, layer) - infobox.isShown.addCallback((isShown) => { - if (!isShown) { - leafletLayer.closePopup() - } + self.unregister.push(() => { + console.log("Destroying infobox") + infobox.Destroy() }) } - infobox.AttachTo(id) infobox.Activate() - this.unregister.push(() => { - console.log("Destroying infobox") - infobox.Destroy() - }) - if (this._selectedElement?.data?.properties?.id !== feature.properties.id) { - this._selectedElement?.setData(feature) - } - }) + } + + leafletLayer.addEventListener('click', activate) + // Add the feature to the index to open the popup when needed - this.leafletLayersPerId.set(feature.properties.id + feature.geometry.type, { + this.leafletLayersPerId.set(key, { feature: feature, - leafletlayer: leafletLayer, + activateFunc: activate, }) + if(Hash.hash.data === key ){ + activate(null) + } } } diff --git a/css/index-tailwind-output.css b/css/index-tailwind-output.css index 3b599d2e1..96ad02a02 100644 --- a/css/index-tailwind-output.css +++ b/css/index-tailwind-output.css @@ -728,10 +728,6 @@ video { margin: 0.25rem; } -.m-2 { - margin: 0.5rem; -} - .m-4 { margin: 1rem; } @@ -740,6 +736,10 @@ video { margin: 1.25rem; } +.m-2 { + margin: 0.5rem; +} + .m-0\.5 { margin: 0.125rem; } @@ -799,14 +799,6 @@ video { margin-top: 1rem; } -.mt-6 { - margin-top: 1.5rem; -} - -.mr-1 { - margin-right: 0.25rem; -} - .mr-2 { margin-right: 0.5rem; } @@ -847,6 +839,10 @@ video { margin-bottom: 2.5rem; } +.mr-1 { + margin-right: 0.25rem; +} + .mt-0 { margin-top: 0px; } @@ -855,6 +851,10 @@ video { margin-top: 2rem; } +.mt-6 { + margin-top: 1.5rem; +} + .mb-8 { margin-bottom: 2rem; } @@ -956,10 +956,6 @@ video { height: 3rem; } -.h-8 { - height: 2rem; -} - .h-4 { height: 1rem; } @@ -980,6 +976,10 @@ video { height: 1.5rem; } +.h-8 { + height: 2rem; +} + .h-32 { height: 8rem; } @@ -1004,10 +1004,6 @@ video { height: 12rem; } -.max-h-7 { - max-height: 1.75rem; -} - .max-h-20vh { max-height: 20vh; } @@ -1020,6 +1016,10 @@ video { max-height: 1rem; } +.max-h-7 { + max-height: 1.75rem; +} + .max-h-8 { max-height: 2rem; } @@ -1048,14 +1048,6 @@ video { width: 3rem; } -.w-8 { - width: 2rem; -} - -.w-1\/3 { - width: 33.333333%; -} - .w-4 { width: 1rem; } @@ -1072,6 +1064,10 @@ video { width: 2.75rem; } +.w-8 { + width: 2rem; +} + .w-min { width: -webkit-min-content; width: min-content; @@ -1216,6 +1212,10 @@ video { place-content: center; } +.content-center { + align-content: center; +} + .content-start { align-content: flex-start; } @@ -1317,14 +1317,14 @@ video { border-radius: 9999px; } -.rounded { - border-radius: 0.25rem; -} - .rounded-3xl { border-radius: 1.5rem; } +.rounded { + border-radius: 0.25rem; +} + .rounded-md { border-radius: 0.375rem; } @@ -1346,14 +1346,14 @@ video { border-bottom-left-radius: 0.25rem; } -.border-2 { - border-width: 2px; -} - .border { border-width: 1px; } +.border-2 { + border-width: 2px; +} + .border-4 { border-width: 4px; } @@ -1414,11 +1414,6 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-gray-200 { - --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity)); -} - .bg-red-400 { --tw-bg-opacity: 1; background-color: rgb(248 113 113 / var(--tw-bg-opacity)); @@ -1439,6 +1434,11 @@ video { background-color: rgb(0 0 0 / var(--tw-bg-opacity)); } +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + .bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); @@ -1565,6 +1565,10 @@ video { padding-top: 0.125rem; } +.pb-4 { + padding-bottom: 1rem; +} + .pl-6 { padding-left: 1.5rem; } @@ -2555,14 +2559,14 @@ input { margin-right: auto; } - .sm\:mr-2 { - margin-right: 0.5rem; - } - .sm\:mt-5 { margin-top: 1.25rem; } + .sm\:mr-2 { + margin-right: 0.5rem; + } + .sm\:flex { display: flex; } @@ -2700,6 +2704,10 @@ input { height: 3rem; } + .md\:w-1\/3 { + width: 33.333333%; + } + .md\:w-2\/6 { width: 33.333333%; } diff --git a/css/mobile.css b/css/mobile.css index de0babf2c..42532a321 100644 --- a/css/mobile.css +++ b/css/mobile.css @@ -8,10 +8,6 @@ Contains tweaks for small screens display: none !important; } - .desktop\:max-h-65vh { - max-height: 65vh; - } - } diff --git a/theme.html b/theme.html index e9a6b6e7c..88c973bc9 100644 --- a/theme.html +++ b/theme.html @@ -48,7 +48,7 @@
- +