diff --git a/Logic/Actors/StrayClickHandler.ts b/Logic/Actors/StrayClickHandler.ts deleted file mode 100644 index c4fac415b7..0000000000 --- a/Logic/Actors/StrayClickHandler.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UIEventSource } from "../UIEventSource" -import FilteredLayer from "../../Models/FilteredLayer" -import ScrollableFullScreen from "../../UI/Base/ScrollableFullScreen" -import BaseUIElement from "../../UI/BaseUIElement" - -/** - * The stray-click-handler adds a marker to the map if no feature was clicked. - * Shows the given uiToShow-element in the messagebox - * - * Note: the actual implementation is in StrayClickHandlerImplementation - */ -export default class StrayClickHandler { - public static construct = ( - state: { - LastClickLocation: UIEventSource<{ lat: number; lon: number }> - selectedElement: UIEventSource - filteredLayers: UIEventSource - leafletMap: UIEventSource - }, - uiToShow: ScrollableFullScreen, - iconToShow: BaseUIElement - ) => { - return undefined - } -} diff --git a/Logic/ContributorCount.ts b/Logic/ContributorCount.ts index d3ee51df48..a3095a2f34 100644 --- a/Logic/ContributorCount.ts +++ b/Logic/ContributorCount.ts @@ -11,13 +11,13 @@ export default class ContributorCount { private lastUpdate: Date = undefined constructor(state: { - bounds: Store + mapProperties: { bounds: Store } dataIsLoading: Store perLayer: ReadonlyMap }) { this.perLayer = state.perLayer const self = this - state.bounds.mapD( + state.mapProperties.bounds.mapD( (bbox) => { self.update(bbox) }, diff --git a/Logic/FeatureSource/Actors/GeoIndexedStore.ts b/Logic/FeatureSource/Actors/GeoIndexedStore.ts index 792641bfa8..39eb02f58a 100644 --- a/Logic/FeatureSource/Actors/GeoIndexedStore.ts +++ b/Logic/FeatureSource/Actors/GeoIndexedStore.ts @@ -1,4 +1,4 @@ -import { FeatureSource , FeatureSourceForLayer } from "../FeatureSource" +import { FeatureSource, FeatureSourceForLayer } from "../FeatureSource" import { Feature } from "geojson" import { BBox } from "../../BBox" import { GeoOperations } from "../../GeoOperations" @@ -26,9 +26,12 @@ export default class GeoIndexedStore implements FeatureSource { public GetFeaturesWithin(bbox: BBox): Feature[] { // TODO optimize const bboxFeature = bbox.asGeoJson({}) - return this.features.data.filter( - (f) => GeoOperations.intersect(f, bboxFeature) !== undefined - ) + return this.features.data.filter((f) => { + if (f.geometry.type === "Point") { + return bbox.contains(<[number, number]>f.geometry.coordinates) + } + return GeoOperations.intersect(f, bboxFeature) !== undefined + }) } } diff --git a/Logic/State/FeaturePipelineState.ts b/Logic/State/FeaturePipelineState.ts deleted file mode 100644 index a63ad9028e..0000000000 --- a/Logic/State/FeaturePipelineState.ts +++ /dev/null @@ -1,17 +0,0 @@ -import SelectedFeatureHandler from "../Actors/SelectedFeatureHandler" -import Hash from "../Web/Hash" -import MetaTagRecalculator from "../FeatureSource/Actors/MetaTagRecalculator" - -export default class FeaturePipelineState { - /** - * The piece of code which fetches data from various sources and shows it on the background map - */ - public readonly featurePipeline: FeaturePipeline - private readonly metatagRecalculator: MetaTagRecalculator - - constructor() { - this.metatagRecalculator = new MetaTagRecalculator(this, this.featurePipeline) - this.metatagRecalculator.registerSource(this.currentView) - new SelectedFeatureHandler(Hash.hash, this) - } -} diff --git a/Logic/Tags/RegexTag.ts b/Logic/Tags/RegexTag.ts index 2b46e94074..c9693212e0 100644 --- a/Logic/Tags/RegexTag.ts +++ b/Logic/Tags/RegexTag.ts @@ -244,7 +244,7 @@ export class RegexTag extends TagsFilter { return [] } - asChange(properties: Record): { k: string; v: string }[] { + asChange(): { k: string; v: string }[] { if (this.invert) { return [] } diff --git a/Models/ThemeViewState.ts b/Models/ThemeViewState.ts index bd4ce1eb37..6023a0dda1 100644 --- a/Models/ThemeViewState.ts +++ b/Models/ThemeViewState.ts @@ -222,6 +222,14 @@ export default class ThemeViewState implements SpecialVisualizationState { } } ) + /* + Hotkeys.RegisterHotkey( + { shift: "O" }, + Translations.t.hotkeyDocumentation.selectMapnik, + () => { + this.state.backgroundLayer.setData(AvailableBaseLayers.osmCarto) + } + )//*/ } /** diff --git a/UI/Base/ScrollableFullScreen.ts b/UI/Base/ScrollableFullScreen.ts index 6a9261d94a..7cb97f8313 100644 --- a/UI/Base/ScrollableFullScreen.ts +++ b/UI/Base/ScrollableFullScreen.ts @@ -107,9 +107,6 @@ export default class ScrollableFullScreen { } } - Destroy() { - this._fullscreencomponent.Destroy() - } /** * Actually show this in the 'fullscreen'-div @@ -163,7 +160,4 @@ export default class ScrollableFullScreen { ) } - static ActivateCurrent() { - ScrollableFullScreen._currentlyOpen?.Activate() - } } diff --git a/UI/Base/TabbedComponent.ts b/UI/Base/TabbedComponent.ts index 59e64c5b51..4e3eff50fc 100644 --- a/UI/Base/TabbedComponent.ts +++ b/UI/Base/TabbedComponent.ts @@ -5,6 +5,9 @@ import BaseUIElement from "../BaseUIElement" import { VariableUiElement } from "./VariableUIElement" export class TabbedComponent extends Combine { + /** + * @deprecated + */ constructor( elements: { header: BaseUIElement | string; content: BaseUIElement | string }[], openedTab: UIEventSource | number = 0, diff --git a/UI/BigComponents/CopyrightPanel.ts b/UI/BigComponents/CopyrightPanel.ts index 0a7d2bb845..f841c12387 100644 --- a/UI/BigComponents/CopyrightPanel.ts +++ b/UI/BigComponents/CopyrightPanel.ts @@ -113,7 +113,7 @@ export default class CopyrightPanel extends Combine { constructor(state: { layout: LayoutConfig - bounds: Store + mapProperties: { bounds: Store } osmConnection: OsmConnection dataIsLoading: Store perLayer: ReadonlyMap @@ -121,7 +121,7 @@ export default class CopyrightPanel extends Combine { const t = Translations.t.general.attribution const layoutToUse = state.layout - const iconAttributions: BaseUIElement[] = layoutToUse.usedImages.map( + const iconAttributions: BaseUIElement[] = Utils.Dedup(layoutToUse.usedImages).map( CopyrightPanel.IconAttribution ) diff --git a/UI/BigComponents/FilterviewWithFields.svelte b/UI/BigComponents/FilterviewWithFields.svelte index 9683cca6a0..3d37065033 100644 --- a/UI/BigComponents/FilterviewWithFields.svelte +++ b/UI/BigComponents/FilterviewWithFields.svelte @@ -38,7 +38,7 @@ fieldTypes[field.name + "}"] = field.type; const src = new UIEventSource(initialState[field.name] ?? ""); fieldValues[field.name + "}"] = src; - onDestroy(src.addCallback(v => { + onDestroy(src.addCallback(() => { setFields(); })); } diff --git a/UI/BigComponents/FullWelcomePaneWithTabs.ts b/UI/BigComponents/FullWelcomePaneWithTabs.ts deleted file mode 100644 index c42f7e103b..0000000000 --- a/UI/BigComponents/FullWelcomePaneWithTabs.ts +++ /dev/null @@ -1,131 +0,0 @@ -import ThemeIntroductionPanel from "./ThemeIntroductionPanel" -import Svg from "../../Svg" -import Translations from "../i18n/Translations" -import ShareScreen from "./ShareScreen" -import MoreScreen from "./MoreScreen" -import Constants from "../../Models/Constants" -import Combine from "../Base/Combine" -import { TabbedComponent } from "../Base/TabbedComponent" -import { UIEventSource } from "../../Logic/UIEventSource" -import UserDetails, { OsmConnection } from "../../Logic/Osm/OsmConnection" -import ScrollableFullScreen from "../Base/ScrollableFullScreen" -import BaseUIElement from "../BaseUIElement" -import Toggle from "../Input/Toggle" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import { Utils } from "../../Utils" -import UserRelatedState from "../../Logic/State/UserRelatedState" -import Loc from "../../Models/Loc" -import FilteredLayer from "../../Models/FilteredLayer" -import Hotkeys from "../Base/Hotkeys" - -export default class FullWelcomePaneWithTabs extends ScrollableFullScreen { - public static MoreThemesTabIndex = 1 - - constructor( - isShown: UIEventSource, - currentTab: UIEventSource, - state: { - layoutToUse: LayoutConfig - osmConnection: OsmConnection - featureSwitchShareScreen: UIEventSource - featureSwitchMoreQuests: UIEventSource - locationControl: UIEventSource - featurePipeline: FeaturePipeline - backgroundLayer: UIEventSource - filteredLayers: UIEventSource - } & UserRelatedState, - guistate?: { userInfoIsOpened: UIEventSource } - ) { - const layoutToUse = state.layoutToUse - super( - () => layoutToUse.title.Clone(), - () => FullWelcomePaneWithTabs.GenerateContents(state, currentTab, isShown, guistate), - "welcome", - isShown - ) - } - - private static ConstructBaseTabs( - state: { - layoutToUse: LayoutConfig - osmConnection: OsmConnection - featureSwitchShareScreen: UIEventSource - featureSwitchMoreQuests: UIEventSource - featurePipeline: FeaturePipeline - locationControl: UIEventSource - backgroundLayer: UIEventSource - filteredLayers: UIEventSource - } & UserRelatedState, - isShown: UIEventSource, - currentTab: UIEventSource, - guistate?: { userInfoIsOpened: UIEventSource } - ): { header: string | BaseUIElement; content: BaseUIElement }[] { - const tabs: { header: string | BaseUIElement; content: BaseUIElement }[] = [ - { - header: ``, - content: new ThemeIntroductionPanel(isShown, currentTab, state, guistate), - }, - ] - - if (state.featureSwitchMoreQuests.data) { - tabs.push({ - header: Svg.add_img, - content: new Combine([ - Translations.t.general.morescreen.intro, - new MoreScreen(state), - ]).SetClass("flex flex-col"), - }) - } - - if (state.featureSwitchShareScreen.data) { - tabs.push({ header: Svg.share_img, content: new ShareScreen(state) }) - } - - return tabs - } - - private static GenerateContents( - state: { - layoutToUse: LayoutConfig - osmConnection: OsmConnection - featureSwitchShareScreen: UIEventSource - featureSwitchMoreQuests: UIEventSource - featurePipeline: FeaturePipeline - locationControl: UIEventSource - backgroundLayer: UIEventSource - filteredLayers: UIEventSource - } & UserRelatedState, - currentTab: UIEventSource, - isShown: UIEventSource, - guistate?: { userInfoIsOpened: UIEventSource } - ) { - const tabs = FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab, guistate) - const tabsWithAboutMc = [ - ...FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab, guistate), - ] - - tabsWithAboutMc.push({ - header: Svg.help, - content: new Combine([ - Translations.t.general.aboutMapcomplete.Subs({ - osmcha_link: Utils.OsmChaLinkFor(7), - }), - "
Version " + Constants.vNumber, - Hotkeys.generateDocumentationDynamic(), - ]).SetClass("link-underline"), - }) - - tabs.forEach((c) => c.content.SetClass("p-4")) - tabsWithAboutMc.forEach((c) => c.content.SetClass("p-4")) - - return new Toggle( - new TabbedComponent(tabsWithAboutMc, currentTab), - new TabbedComponent(tabs, currentTab), - state.osmConnection.userDetails.map( - (userdetails: UserDetails) => - userdetails.loggedIn && - userdetails.csCount >= Constants.userJourney.mapCompleteHelpUnlock - ) - ) - } -} diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index 0caa5f8cb4..559be07d65 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -33,9 +33,3 @@ export interface PresetInfo extends PresetConfig { layerToAddTo: FilteredLayer boundsFactor?: 0.25 | number } - -export default class SimpleAddUI extends Combine { - constructor(state: SpecialVisualizationState) { - super([]) - } -} diff --git a/UI/DefaultGUI.ts b/UI/DefaultGUI.ts index 0cc76e64b4..93650590e4 100644 --- a/UI/DefaultGUI.ts +++ b/UI/DefaultGUI.ts @@ -1,33 +1,15 @@ -import FeaturePipelineState from "../Logic/State/FeaturePipelineState" import { Utils } from "../Utils" -import { UIEventSource } from "../Logic/UIEventSource" -import FullWelcomePaneWithTabs from "./BigComponents/FullWelcomePaneWithTabs" -import MapControlButton from "./MapControlButton" -import Svg from "../Svg" import Toggle from "./Input/Toggle" -import BaseUIElement from "./BaseUIElement" import LeftControls from "./BigComponents/LeftControls" import RightControls from "./BigComponents/RightControls" import CenterMessageBox from "./CenterMessageBox" 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 NewNoteUi from "./Popup/NewNoteUi" import Combine from "./Base/Combine" -import FilteredLayer from "../Models/FilteredLayer" import ExtraLinkButton from "./BigComponents/ExtraLinkButton" -import { VariableUiElement } from "./Base/VariableUIElement" -import Img from "./Base/Img" -import UserInformationPanel from "./BigComponents/UserInformation" -import { LoginToggle } from "./Popup/LoginButton" -import { FixedUiElement } from "./Base/FixedUiElement" import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler" -import Hotkeys from "./Base/Hotkeys" import CopyrightPanel from "./BigComponents/CopyrightPanel" -import SvelteUIElement from "./Base/SvelteUIElement" -import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte" /** * The default MapComplete GUI initializer @@ -36,17 +18,14 @@ import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte" */ export default class DefaultGUI { private readonly guiState: DefaultGuiState - private readonly state: FeaturePipelineState private readonly geolocationHandler: GeoLocationHandler | undefined - constructor(state: FeaturePipelineState, guiState: DefaultGuiState) { - this.state = state + constructor(guiState: DefaultGuiState) { this.guiState = guiState } public setup() { this.SetupUIElements() - this.SetupMap() if ( this.state.layoutToUse.customCss !== undefined && @@ -54,131 +33,24 @@ export default class DefaultGUI { ) { Utils.LoadCustomCss(this.state.layoutToUse.customCss) } - - Hotkeys.RegisterHotkey( - { shift: "O" }, - Translations.t.hotkeyDocumentation.selectMapnik, - () => { - this.state.backgroundLayer.setData(AvailableBaseLayers.osmCarto) - } - ) - } - - public setupClickDialogOnMap( - filterViewIsOpened: UIEventSource, - state: FeaturePipelineState - ) { - const hasPresets = state.layoutToUse.layers.some((layer) => layer.presets.length > 0) - const noteLayer: FilteredLayer = state.filteredLayers.data.filter( - (l) => l.layerDef.id === "note" - )[0] - let addNewNoteDialog: (isShown: UIEventSource) => BaseUIElement = undefined - if (noteLayer !== undefined) { - addNewNoteDialog = (isShown) => new NewNoteUi(noteLayer, isShown, state) - } - - function setup() { - if (!hasPresets && addNewNoteDialog === undefined) { - return // nothing to do - } - const newPointDialogIsShown = new UIEventSource(false) - const addNewPoint = new ScrollableFullScreen( - () => - hasPresets - ? Translations.t.general.add.title - : Translations.t.notes.createNoteTitle, - ({ resetScrollSignal }) => { - let addNew = undefined - if (hasPresets) { - addNew = new SimpleAddUI( - newPointDialogIsShown, - resetScrollSignal, - filterViewIsOpened, - state - ) - } - let addNote = undefined - if (noteLayer !== undefined) { - addNote = addNewNoteDialog(newPointDialogIsShown) - } - return new Combine([addNew, addNote]).SetClass("flex flex-col font-lg text-lg") - }, - "new", - newPointDialogIsShown - ) - - let noteMarker = undefined - if (!hasPresets && addNewNoteDialog !== undefined) { - noteMarker = new Combine([ - Svg.note_svg().SetClass("absolute bottom-0").SetStyle("height: 40px"), - Svg.addSmall_svg() - .SetClass("absolute w-6 animate-pulse") - .SetStyle("right: 10px; bottom: -8px;"), - ]) - .SetClass("block relative h-full") - .SetStyle("left: calc( 50% - 15px )") // This is a bit hacky, yes I know! - } - } - - if (noteLayer !== undefined) { - setup() - } else { - state.featureSwitchAddNew.addCallbackAndRunD((addNewAllowed) => { - if (addNewAllowed) { - setup() - return true - } - }) - } - } - - private SetupMap() { - if (Utils.runningFromConsole) { - return - } - const state = this.state - const guiState = this.guiState - - this.setupClickDialogOnMap(guiState.filterViewIsOpened, state) - - const selectedElement: FilteredLayer = state.filteredLayers.data.filter( - (l) => l.layerDef.id === "selected_element" - )[0] - new ShowDataLayer({ - leafletMap: state.leafletMap, - layerToShow: selectedElement.layerDef, - features: state.selectedElementsLayer, - state, - }) } private SetupUIElements() { - const state = this.state const guiState = this.guiState - const self = this - const extraLink = Toggle.If( state.featureSwitchExtraLinkEnabled, () => new ExtraLinkButton(state, state.layoutToUse.extraLink) ) - const welcomeMessageMapControl = Toggle.If(state.featureSwitchWelcomeMessage, () => - self.InitWelcomeMessage() - ) - new ScrollableFullScreen( () => Translations.t.general.attribution.attributionTitle, () => new CopyrightPanel(state), "copyright", guiState.copyrightViewIsOpened ) - const copyright = new MapControlButton(Svg.copyright_svg()).onClick(() => - guiState.copyrightViewIsOpened.setData(true) - ) - new Combine([welcomeMessageMapControl, copyright, extraLink]) - .SetClass("flex flex-col") - .AttachTo("top-left") + + new Combine([extraLink]).SetClass("flex flex-col").AttachTo("top-left") new Combine([ new ExtraLinkButton(state, { @@ -198,13 +70,4 @@ export default class DefaultGUI { new CenterMessageBox(state).AttachTo("centermessage") document?.getElementById("centermessage")?.classList?.add("pointer-events-none") } - - private InitWelcomeMessage(): BaseUIElement { - return new FullWelcomePaneWithTabs( - new UIEventSource(false), - this.guiState.welcomeMessageOpenedTab, - this.state, - this.guiState - ) - } } diff --git a/UI/Reviews/SingleReview.ts b/UI/Reviews/SingleReview.ts index b1b1c89afb..ee18ca3d00 100644 --- a/UI/Reviews/SingleReview.ts +++ b/UI/Reviews/SingleReview.ts @@ -9,7 +9,6 @@ import { Store } from "../../Logic/UIEventSource" export default class SingleReview extends Combine { constructor(review: Review & { madeByLoggedInUser: Store }) { - const d = review const date = new Date(review.iat * 1000) const reviewAuthor = review.metadata.nickname ?? diff --git a/UI/ThemeViewGUI.svelte b/UI/ThemeViewGUI.svelte index 05e8622e34..f42464a68c 100644 --- a/UI/ThemeViewGUI.svelte +++ b/UI/ThemeViewGUI.svelte @@ -28,6 +28,7 @@ import UserRelatedState from "../Logic/State/UserRelatedState"; import LoginToggle from "./Base/LoginToggle.svelte"; import LoginButton from "./Base/LoginButton.svelte"; + import CopyrightPanel from "./BigComponents/CopyrightPanel.js"; export let state: ThemeViewState; let layout = state.layout; @@ -149,6 +150,12 @@ + +
+ +
+ + new CopyrightPanel(state)}> diff --git a/Utils.ts b/Utils.ts index 531516bc76..fe2c49ff09 100644 --- a/Utils.ts +++ b/Utils.ts @@ -308,6 +308,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return str } + /** + * Creates a new array with all elements from 'arr' in such a way that every element will be kept only once + * Elements are returned in the same order as they appear in the lists + * @param arr + * @constructor + */ public static Dedup(arr: string[]): string[] { if (arr === undefined) { return undefined diff --git a/assets/layers/usersettings/usersettings.json b/assets/layers/usersettings/usersettings.json index 7de6fa1402..0ba213d637 100644 --- a/assets/layers/usersettings/usersettings.json +++ b/assets/layers/usersettings/usersettings.json @@ -40,7 +40,7 @@ "then": { "special": { "type": "link", - "href": "{_backend}/messages/inbox", + "href": "{_backend}/messages/inbox", "text": { "en": "Open your inbox", "nl": "Ga naar je inbox" @@ -393,4 +393,4 @@ } ], "mapRendering": null -} +} \ No newline at end of file diff --git a/assets/tagRenderings/questions.json b/assets/tagRenderings/questions.json index f188c181f8..aa7afa4df2 100644 --- a/assets/tagRenderings/questions.json +++ b/assets/tagRenderings/questions.json @@ -2019,4 +2019,4 @@ "pl": "Nazwa sieci to {internet_access:ssid}" } } -} +} \ No newline at end of file diff --git a/langs/en.json b/langs/en.json index 1db77d93ba..43cf285b3f 100644 --- a/langs/en.json +++ b/langs/en.json @@ -146,6 +146,7 @@ "openMapillary": "Open Mapillary here", "openOsmcha": "See latest edits made with {theme}", "themeBy": "Theme maintained by {author}", + "title": "Copyright and attribution", "translatedBy": "MapComplete has been translated by {contributors} and {hiddenCount} more contributors" }, "back": "Back", diff --git a/test.ts b/test.ts index 6c8590cccf..59243ea891 100644 --- a/test.ts +++ b/test.ts @@ -15,8 +15,6 @@ async function main() { const state = new ThemeViewState(layout) const main = new SvelteUIElement(ThemeViewGUI, { state }) - state.guistate.menuIsOpened.setData(true) - state.guistate.menuViewTab.setData("settings") main.AttachTo("maindiv") } @@ -24,7 +22,6 @@ async function testspecial() { const layout = new LayoutConfig(theme, true) // qp.data === "" ? : new AllKnownLayoutsLazy().get(qp.data) const state = new ThemeViewState(layout) - state.guistate.openUsersettings("picture-license") const all = SpecialVisualizations.specialVisualizations.map((s) => SpecialVisualizations.renderExampleOfSpecial(state, s) )