From 82409984dcbab4c9a6fa21fa437e12ea93597c55 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Mon, 18 Dec 2023 01:30:02 +0100 Subject: [PATCH] Better compass arrow --- assets/svg/circle.svg | 46 +++++++++++--- assets/svg/compass_arrow.svg | 39 ++++++++++++ assets/svg/compass_arrow.svg.license | 2 + assets/svg/license_info.json | 8 +++ public/css/index-tailwind-output.css | 49 ++++++++------- src/Logic/Web/Orientation.ts | 15 ++++- src/Models/ThemeViewState.ts | 11 ++++ src/UI/Base/MapControlButton.svelte | 3 +- .../BigComponents/GeolocationControl.svelte | 44 +++++++++++++ src/UI/BigComponents/GeolocationControl.ts | 61 ++----------------- src/UI/ThemeViewGUI.svelte | 32 ++++------ src/assets/svg/Circle.svelte | 2 +- src/assets/svg/Compass_arrow.svelte | 4 ++ src/index.css | 15 +++++ theme.html | 2 +- 15 files changed, 219 insertions(+), 114 deletions(-) create mode 100644 assets/svg/compass_arrow.svg create mode 100644 assets/svg/compass_arrow.svg.license create mode 100644 src/UI/BigComponents/GeolocationControl.svelte create mode 100644 src/assets/svg/Compass_arrow.svelte diff --git a/assets/svg/circle.svg b/assets/svg/circle.svg index fc6efd4fc..0da26a179 100644 --- a/assets/svg/circle.svg +++ b/assets/svg/circle.svg @@ -1,9 +1,39 @@ - - - - - + + + + + diff --git a/assets/svg/compass_arrow.svg b/assets/svg/compass_arrow.svg new file mode 100644 index 000000000..a950b8cda --- /dev/null +++ b/assets/svg/compass_arrow.svg @@ -0,0 +1,39 @@ + + + + + + diff --git a/assets/svg/compass_arrow.svg.license b/assets/svg/compass_arrow.svg.license new file mode 100644 index 000000000..2452bee1e --- /dev/null +++ b/assets/svg/compass_arrow.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Pieter Vander Vennet +SPDX-License-Identifier: CC0 \ No newline at end of file diff --git a/assets/svg/license_info.json b/assets/svg/license_info.json index 0ba4ac2b9..80f667176 100644 --- a/assets/svg/license_info.json +++ b/assets/svg/license_info.json @@ -241,6 +241,14 @@ "authors": [], "sources": [] }, + { + "path": "compass_arrow.svg", + "license": "CC0-1.0", + "authors": [ + "Pieter Vander Vennet" + ], + "sources": [] + }, { "path": "confirm.svg", "license": "CC0-1.0", diff --git a/public/css/index-tailwind-output.css b/public/css/index-tailwind-output.css index 1092273a2..f6461b087 100644 --- a/public/css/index-tailwind-output.css +++ b/public/css/index-tailwind-output.css @@ -729,14 +729,6 @@ video { bottom: 0px; } -.top-1\/2 { - top: 50%; -} - -.left-1\/2 { - left: 50%; -} - .right-4 { right: 1rem; } @@ -1126,10 +1118,6 @@ video { height: 0px; } -.h-5 { - height: 1.25rem; -} - .h-4 { height: 1rem; } @@ -1150,6 +1138,10 @@ video { height: 2.75rem; } +.h-5 { + height: 1.25rem; +} + .h-48 { height: 12rem; } @@ -1240,10 +1232,6 @@ video { width: 0px; } -.w-5 { - width: 1.25rem; -} - .w-4 { width: 1rem; } @@ -1272,6 +1260,10 @@ video { width: auto; } +.w-5 { + width: 1.25rem; +} + .w-10 { width: 2.5rem; } @@ -1346,10 +1338,6 @@ video { cursor: pointer; } -.cursor-wait { - cursor: wait; -} - .resize { resize: both; } @@ -1745,11 +1733,6 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-red-500 { - --tw-bg-opacity: 1; - background-color: rgb(239 68 68 / var(--tw-bg-opacity)); -} - .bg-white\/50 { background-color: rgb(255 255 255 / 0.5); } @@ -2756,6 +2739,18 @@ a.link-underline { overflow: visible !important; } +.compass_arrow { + width: calc( 2.5rem - 1px ) ; + height: calc( 2.5rem - 1px ) +} + +@media (min-width: 640px) { + .compass_arrow { + width: calc( 2.75rem - 1px ) ; + height: calc( 2.75rem - 1px ) + } +} + @-webkit-keyframes glowing-drop-shadow { from { -webkit-filter: drop-shadow(5px 5px 60px rgb(128 128 128 / 0.6)); @@ -2863,6 +2858,10 @@ a.link-underline { margin: 0.5rem; } + .sm\:m-1 { + margin: 0.25rem; + } + .sm\:mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; diff --git a/src/Logic/Web/Orientation.ts b/src/Logic/Web/Orientation.ts index b85829212..9177f93a2 100644 --- a/src/Logic/Web/Orientation.ts +++ b/src/Logic/Web/Orientation.ts @@ -1,4 +1,4 @@ -import { UIEventSource } from "../UIEventSource" +import { Stores, UIEventSource } from "../UIEventSource" /** * Exports the device orientation as UIEventSources and detects 'shakes' @@ -33,8 +33,19 @@ export class Orientation { constructor() {} - public fakeMeasurements() { + public fakeMeasurements(rotateAlpha: boolean = true) { + console.log("Starting fake measurements of orientation sensors", { + alpha: this.alpha, + beta: this.beta, + gamma: this.gamma, + absolute: this.absolute, + }) this.alpha.setData(45) + if (rotateAlpha) { + Stores.Chronic(25).addCallback((date) => + this.alpha.setData(-(date.getTime() / 10) % 360) + ) + } this.beta.setData(20) this.gamma.setData(30) this.absolute.setData(true) diff --git a/src/Models/ThemeViewState.ts b/src/Models/ThemeViewState.ts index 087f43d48..24e399797 100644 --- a/src/Models/ThemeViewState.ts +++ b/src/Models/ThemeViewState.ts @@ -60,6 +60,7 @@ import { Imgur } from "../Logic/ImageProviders/Imgur" import NearbyFeatureSource from "../Logic/FeatureSource/Sources/NearbyFeatureSource" import FavouritesFeatureSource from "../Logic/FeatureSource/Sources/FavouritesFeatureSource" import { ProvidedImage } from "../Logic/ImageProviders/ImageProvider" +import { GeolocationControlState } from "../UI/BigComponents/GeolocationControl" /** * @@ -112,6 +113,8 @@ export default class ThemeViewState implements SpecialVisualizationState { readonly selectedLayer: UIEventSource readonly userRelatedState: UserRelatedState readonly geolocation: GeoLocationHandler + readonly geolocationControl: GeolocationControlState + readonly lastGeolocationRequestMoment: UIEventSource = new UIEventSource(undefined) readonly imageUploadManager: ImageUploadManager @@ -191,6 +194,7 @@ export default class ThemeViewState implements SpecialVisualizationState { this.mapProperties, this.userRelatedState.gpsLocationHistoryRetentionTime ) + this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties) this.availableLayers = AvailableRasterLayers.layersAvailableAt(this.mapProperties.location) @@ -591,6 +595,13 @@ export default class ThemeViewState implements SpecialVisualizationState { Translations.t.hotkeyDocumentation.selectAerial, () => setLayerCategory("photo") ) + Hotkeys.RegisterHotkey( + { nomod: "L" }, + Translations.t.hotkeyDocumentation.geolocate, + () => { + this.geolocationControl.handleClick() + } + ) return true }) } diff --git a/src/UI/Base/MapControlButton.svelte b/src/UI/Base/MapControlButton.svelte index ec36f102e..64be2524f 100644 --- a/src/UI/Base/MapControlButton.svelte +++ b/src/UI/Base/MapControlButton.svelte @@ -12,11 +12,12 @@ export let arialabel: Translation = undefined + diff --git a/src/UI/BigComponents/GeolocationControl.svelte b/src/UI/BigComponents/GeolocationControl.svelte new file mode 100644 index 000000000..f323f263b --- /dev/null +++ b/src/UI/BigComponents/GeolocationControl.svelte @@ -0,0 +1,44 @@ + + +{#if !$allowMoving} + +{:else if $currentGPSLocation !== undefined } + + {#if $lastClickWasRecent} + + {:else} + + {/if} +{:else if $geopermission === "prompt"} + +{:else if $geopermission === "requested"} + + +{:else if $geopermission === "denied"} + +{:else} + +{/if} diff --git a/src/UI/BigComponents/GeolocationControl.ts b/src/UI/BigComponents/GeolocationControl.ts index 0ca17ed22..846e3e960 100644 --- a/src/UI/BigComponents/GeolocationControl.ts +++ b/src/UI/BigComponents/GeolocationControl.ts @@ -1,9 +1,5 @@ -import { VariableUiElement } from "../Base/VariableUIElement" -import Svg from "../../Svg" import { Store, UIEventSource } from "../../Logic/UIEventSource" import GeoLocationHandler from "../../Logic/Actors/GeoLocationHandler" -import Hotkeys from "../Base/Hotkeys" -import Translations from "../i18n/Translations" import Constants from "../../Models/Constants" import { MapProperties } from "../../Models/MapProperties" @@ -11,11 +7,12 @@ import { MapProperties } from "../../Models/MapProperties" * Displays an icon depending on the state of the geolocation. * Will set the 'lock' if clicked twice */ -export class GeolocationControl extends VariableUiElement { +export class GeolocationControlState { public readonly lastClick = new UIEventSource(undefined) + public readonly lastClickWithinThreeSecs: Store private readonly _geolocationHandler: GeoLocationHandler private readonly _mapProperties: MapProperties - private readonly _lastClickWithinThreeSecs: Store + constructor( geolocationHandler: GeoLocationHandler, state: MapProperties, @@ -41,60 +38,12 @@ export class GeolocationControl extends VariableUiElement { return timeDiff <= Constants.zoomToLocationTimeout } ) - const geolocationState = geolocationHandler?.geolocationState - super( - geolocationState?.permission?.map( - (permission) => { - if (permission === "denied") { - return Svg.location_refused_svg() - } - if (!geolocationState.allowMoving.data) { - return Svg.location_locked_svg() - } - - if (geolocationState.currentGPSLocation.data === undefined) { - if (permission === "prompt") { - return Svg.location_empty_svg() - } - // Position not yet found, but permission is either requested or granted: we spin to indicate activity - const icon = - !geolocationHandler.mapHasMoved.data || lastRequestWithinTimeout.data - ? Svg.location_svg() - : Svg.location_empty_svg() - return icon - .SetClass("cursor-wait") - .SetStyle("animation: spin 4s linear infinite;") - } - - // We have a location, so we show a dot in the center - - if (lastClickWithinThreeSecs.data) { - return Svg.location_unlocked_svg() - } - - // We have a location, so we show a dot in the center - return Svg.location_svg() - }, - [ - geolocationState.currentGPSLocation, - geolocationState.allowMoving, - geolocationHandler.mapHasMoved, - lastClickWithinThreeSecs, - lastRequestWithinTimeout, - ] - ) - ) this._geolocationHandler = geolocationHandler this._mapProperties = state this.lastClick = lastClick - this._lastClickWithinThreeSecs = lastClickWithinThreeSecs - - this.onClick(() => this.handleClick()) - Hotkeys.RegisterHotkey({ nomod: "L" }, Translations.t.hotkeyDocumentation.geolocate, () => { - this.handleClick() - }) + this.lastClickWithinThreeSecs = lastClickWithinThreeSecs lastClick.addCallbackAndRunD((_) => { window.setTimeout(() => { @@ -148,7 +97,7 @@ export class GeolocationControl extends VariableUiElement { state.zoom.update((z) => z + 3) } - if (this._lastClickWithinThreeSecs.data) { + if (this.lastClickWithinThreeSecs.data) { geolocationState.allowMoving.setData(false) lastClick.setData(undefined) return diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index fdf3d7d03..43acb1a66 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -6,7 +6,6 @@ import MapControlButton from "./Base/MapControlButton.svelte" import ToSvelte from "./Base/ToSvelte.svelte" import If from "./Base/If.svelte" - import { GeolocationControl } from "./BigComponents/GeolocationControl" import type { Feature } from "geojson" import SelectedElementView from "./BigComponents/SelectedElementView.svelte" import LayerConfig from "../Models/ThemeConfig/LayerConfig" @@ -65,6 +64,8 @@ import ImageOperations from "./Image/ImageOperations.svelte" import VisualFeedbackPanel from "./BigComponents/VisualFeedbackPanel.svelte" import { Orientation } from "../Logic/Web/Orientation" + import GeolocationControl from "./BigComponents/GeolocationControl.svelte" + import Compass_arrow from "../assets/svg/Compass_arrow.svelte" export let state: ThemeViewState let layout = state.layout @@ -111,8 +112,6 @@ ) let previewedImage = state.previewedImage - let geolocationControl = new GeolocationControl(state.geolocation, mapproperties, state.lastGeolocationRequestMoment) - function forwardEventToMap(e: KeyboardEvent) { const mlmap = state.map.data if (!mlmap) { @@ -262,27 +261,20 @@ -
+
+ state.geolocationControl.handleClick()} + on:keydown={forwardEventToMap} + > + + {#if $compassLoaded} - diff --git a/src/assets/svg/Circle.svelte b/src/assets/svg/Circle.svelte index 0b2323c3e..f76f4cabc 100644 --- a/src/assets/svg/Circle.svelte +++ b/src/assets/svg/Circle.svelte @@ -1,4 +1,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/svg/Compass_arrow.svelte b/src/assets/svg/Compass_arrow.svelte new file mode 100644 index 000000000..575a8c45f --- /dev/null +++ b/src/assets/svg/Compass_arrow.svelte @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/src/index.css b/src/index.css index cb490720a..a58d3ee72 100644 --- a/src/index.css +++ b/src/index.css @@ -590,6 +590,21 @@ a.link-underline { overflow: visible !important; } +.compass_arrow { + width: calc( 2.5rem - 1px ) ; + height: calc( 2.5rem - 1px ) +} + +@media (min-width: 640px) { + .compass_arrow { + width: calc( 2.75rem - 1px ) ; + height: calc( 2.75rem - 1px ) + } +} + + + + @-webkit-keyframes glowing-drop-shadow { from { filter: drop-shadow(5px 5px 60px rgb(128 128 128 / 0.6)); diff --git a/theme.html b/theme.html index 1d7ef0123..2578954e6 100644 --- a/theme.html +++ b/theme.html @@ -4,7 +4,7 @@ - +