Android: add inset spacers for android

This commit is contained in:
Pieter Vander Vennet 2025-07-18 14:15:37 +02:00
parent 381ac4a2f2
commit 877bdfae95
19 changed files with 84 additions and 47 deletions

View file

@ -3075,6 +3075,10 @@ input[type="range"].range-lg::-moz-range-thumb {
border-width: 2px;
}
.border-4 {
border-width: 4px;
}
.border-\[10px\] {
border-width: 10px;
}
@ -5527,7 +5531,7 @@ h2.group {
.warning {
/* The class to convey important information, but not as grave as 'alert' */
background-color: var(--low-interaction-background);
background-color: var(--alert-color);
color: var(--alert-foreground-color);
font-weight: bold;
border-radius: 1em;

View file

@ -36,7 +36,7 @@ export default class SearchState {
constructor(state: ThemeViewState) {
this.state = state
this.showSearchDrawer = state.guistate.pageStates.search
this.searchTerm = QueryParameters.GetQueryParameter("q", "", "The term in the search field")
this.locationSearchers = [
@ -112,8 +112,6 @@ export default class SearchState {
)
this.locationResults = new GeocodingFeatureSource(this.suggestions.stabilized(250))
this.showSearchDrawer = new UIEventSource(false)
this.searchIsFocused.addCallbackAndRunD((sugg) => {
if (sugg) {
this.showSearchDrawer.set(true)

View file

@ -113,6 +113,9 @@ export class AndroidPolyfill {
DatabridgePluginSingleton.request<{ top: number, bottom: number }>({
key: "insets",
}).then((result) => {
if(!result){
return
}
let v = result.value
if(typeof v === "string"){
v = JSON.parse(v)

View file

@ -16,20 +16,21 @@ export type PageType = (typeof MenuState.pageNames)[number]
*/
export class MenuState {
public static readonly pageNames = [
"about_theme",
"background",
"copyright",
"copyright_icons",
"community_index",
"hotkeys",
"privacy",
"filter",
"background",
"about_theme",
"download",
"favourites",
"failedImages",
"usersettings",
"share",
"favourites",
"filter",
"hotkeys",
"menu",
"privacy",
"search",
"share",
"usersettings",
] as const
/**
@ -172,6 +173,7 @@ export class MenuState {
this._selectedElement.setData(undefined)
return true
}
} finally {
this.isClosingAll = false
}

View file

@ -3,6 +3,8 @@
import { sineIn } from "svelte/easing"
import { Store } from "../../Logic/UIEventSource.js"
import { onMount } from "svelte"
import { AndroidPolyfill } from "../../Logic/Web/AndroidPolyfill"
import InsetSpacer from "./InsetSpacer.svelte"
export let shown: Store<boolean>
let transitionParams = {
@ -16,11 +18,17 @@
hidden = !sh
})
// Does not need a 'top-inset-spacer' as the code below will apply the padding automatically
let height = 0
onMount(() => {
function setHeight(){
let topbar = document.getElementById("top-bar")
height = topbar?.clientHeight ?? 0
})
height = (topbar?.clientHeight ?? 0) + AndroidPolyfill.getInsetSizes().top.data
}
onMount(() => setHeight())
AndroidPolyfill.getInsetSizes().top.addCallback(() => setHeight())
</script>
<Drawer
@ -35,11 +43,15 @@
rightOffset="inset-y-0 right-0"
bind:hidden
>
<div class="flex flex-col h-full">
<div class="low-interaction h-screen">
<div class="h-full" style={`padding-top: ${height}px`}>
<div style={`padding-top: ${height}px`}>
<div class="flex h-full flex-col overflow-y-auto">
<slot />
</div>
</div>
</div>
<InsetSpacer clss="low-interaction" height={AndroidPolyfill.getInsetSizes().bottom}/>
</div>
</Drawer>

View file

@ -1,36 +1,37 @@
<script lang="ts">
import { createEventDispatcher } from "svelte"
import { CloseButton } from "flowbite-svelte"
import { AndroidPolyfill } from "../../Logic/Web/AndroidPolyfill"
/**
* The slotted element will be shown on top, with a lower-opacity border
*/
const dispatch = createEventDispatcher<{ close }>()
const top = AndroidPolyfill.getInsetSizes().top
const bottom = AndroidPolyfill.getInsetSizes().bottom
</script>
<!-- Draw the background over the total screen -->
<div
class="absolute left-0 top-0 h-screen w-screen"
style={`background-color: #00000088; z-index: 20; padding-top: calc( max( 1rem, ${$top} ));padding-bottom: calc( max( 1rem, ${$bottom} )); `}
on:click={() => {
console.log("OnClose")
dispatch("close")
}}
style="background-color: #00000088; z-index: 20"
/>
<!-- draw a _second_ absolute div, placed using 'bottom' which will be above the navigation bar on mobile browsers -->
<div
class="pointer-events-none absolute bottom-0 right-0 h-full w-screen p-4 md:p-6"
style="z-index: 21"
on:click={() => {
console.log("Closing...")
dispatch("close")
}}
on:click={() => { dispatch("close") }}
>
<div
class="content normal-background pointer-events-auto relative h-full"
on:click|stopPropagation={() => {}}
>
<div class="h-full rounded-xl">
<div class="h-full">
<!-- THe main content-->
<slot />
</div>
<slot name="close-button">
@ -43,9 +44,9 @@
</div>
<style>
.content {
border-radius: 0.5rem;
overflow-x: hidden;
box-shadow: 0 0 1rem #00000088;
}
.content {
border-radius: 0.5rem;
overflow-x: hidden;
box-shadow: 0 0 1rem #00000088;
}
</style>

View file

@ -1,8 +1,11 @@
<script lang="ts">
import type { Store } from "../../Logic/UIEventSource"
/**
* in pixels
*/
export let height: Store<number>
export let clss: string = ""
</script>
<div style={"height: "+$height+"px; background: red;"} />
<div class={clss+" shrink-0"} style={"height: "+$height+"px"} />

View file

@ -1,6 +1,7 @@
<script lang="ts">
import { Modal } from "flowbite-svelte"
import { UIEventSource } from "../../Logic/UIEventSource"
import { AndroidPolyfill } from "../../Logic/Web/AndroidPolyfill"
/**
* Basically a flowbite-svelte modal made more ergonomical
@ -8,7 +9,7 @@
export let fullscreen: boolean = false
export let bodyPadding = "p-4 md:p-5 "
export let shown: UIEventSource<boolean>
export let shown: UIEventSource<boolean> = new UIEventSource(false)
export let dismissable = true
/**
* Default: 50
@ -17,7 +18,7 @@
const shared =
"in-page normal-background dark:bg-gray-800 rounded-lg border-gray-200 dark:border-gray-700 border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md"
let defaultClass = "relative flex flex-col mx-auto w-full divide-y " + shared
let defaultClass = "relative flex flex-col mx-auto w-full divide-y border-4 border-red-500 " + shared
if (fullscreen) {
defaultClass = shared
}
@ -40,6 +41,9 @@
shown.addCallbackAndRun((sh) => {
_shown = sh
})
let marginTop = AndroidPolyfill.getInsetSizes().top
let marginBottom = AndroidPolyfill.getInsetSizes().bottom
</script>
<Modal
@ -54,6 +58,7 @@
{headerClass}
{backdropClass}
color="none"
style={`margin-top: ${$marginTop}px; margin-bottom: ${$marginBottom}px`}
>
<svelte:fragment slot="header">
{#if $$slots.header}

View file

@ -5,6 +5,8 @@
import SelectedElementTitle from "../BigComponents/SelectedElementTitle.svelte"
import Loading from "./Loading.svelte"
import { onDestroy } from "svelte"
import InsetSpacer from "./InsetSpacer.svelte"
import { AndroidPolyfill } from "../../Logic/Web/AndroidPolyfill"
export let state: SpecialVisualizationState
export let selected: Feature
@ -39,6 +41,7 @@
<Loading />
{:else}
<div class="normal-background flex h-full w-full flex-col" class:absolute>
<InsetSpacer clss="low-interaction" height={AndroidPolyfill.getInsetSizes().top} />
<SelectedElementTitle {state} {layer} selectedElement={selected} />
<SelectedElementView {state} {layer} selectedElement={selected} />
</div>

View file

@ -10,7 +10,6 @@
import OpenIdEditor from "./OpenIdEditor.svelte"
import OpenJosm from "../Base/OpenJosm.svelte"
import MapillaryLink from "./MapillaryLink.svelte"
import UserRelatedState from "../../Logic/State/UserRelatedState"
import ArrowDownTray from "@babeard/svelte-heroicons/mini/ArrowDownTray"
import DownloadPanel from "../DownloadFlow/DownloadPanel.svelte"
import Share from "@babeard/svelte-heroicons/solid/Share"
@ -25,20 +24,12 @@
import { UIEventSource } from "../../Logic/UIEventSource"
import ChartBar from "@babeard/svelte-heroicons/solid/ChartBar"
import QueueList from "@babeard/svelte-heroicons/solid/QueueList"
import { MenuState } from "../../Models/MenuState"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import FeatureSwitchState from "../../Logic/State/FeatureSwitchState"
import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
import type { MapProperties } from "../../Models/MapProperties"
import FavouritesFeatureSource from "../../Logic/FeatureSource/Sources/FavouritesFeatureSource"
import Hotkeys from "../Base/Hotkeys"
import MenuDrawerIndex from "./MenuDrawerIndex.svelte"
import ThemeViewState from "../../Models/ThemeViewState"
export let onlyLink: boolean
export let state: ThemeViewState
let hotkeys = Hotkeys._docs
let userdetails = state.osmConnection.userDetails
let theme = state.theme
let featureSwitches = state.featureSwitches

View file

@ -333,8 +333,9 @@
Android
{/if}
</div>
{#if onlyLink}
<InsetSpacer height={AndroidPolyfill.getInsetSizes().bottom} />
{/if}
</div>
{#if onlyLink}
<InsetSpacer height={AndroidPolyfill.getInsetSizes().bottom} />
{/if}
</div>

View file

@ -11,6 +11,8 @@
import BackButton from "../Base/BackButton.svelte"
import TagRenderingEditableDynamic from "../Popup/TagRendering/TagRenderingEditableDynamic.svelte"
import { LastClickFeatureSource } from "../../Logic/FeatureSource/Sources/LastClickFeatureSource"
import { AndroidPolyfill } from "../../Logic/Web/AndroidPolyfill"
import InsetSpacer from "../Base/InsetSpacer.svelte"
export let state: SpecialVisualizationState
export let selectedElement: Feature
@ -93,5 +95,7 @@
config.classes.join(" ")}
/>
{/each}
<InsetSpacer height={AndroidPolyfill.getInsetSizes().bottom} />
</div>
{/if}

View file

@ -6,7 +6,7 @@
*/
import type { SpecialVisualizationState } from "../SpecialVisualization"
import { Store } from "../../Logic/UIEventSource"
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import type { NoteId, OsmTags, OsmId } from "../../Models/OsmFeature"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
@ -25,6 +25,9 @@
Number of images uploaded succesfully
*/
function getCount(input: Store<string[]>): Store<number> {
if(!input){
return new ImmutableStore(0)
}
if (featureId == "*") {
return input.map((inp) => inp.length)
}

View file

@ -17,6 +17,9 @@
import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
import { default as GeocodeResultSvelte } from "./GeocodeResult.svelte"
/**
* The big overview of all search bar results
*/
export let state: WithSearchState
let activeFilters: Store<(ActiveFilter & FilterSearchResult)[]> =
state.layerState.activeFilters.map((fs) =>

View file

@ -20,6 +20,7 @@
import DeleteButton from "./DeleteButton.svelte"
import StudioHashSetter from "./StudioHashSetter"
import TitledPanel from "../Base/TitledPanel.svelte"
import Popup from "../Base/Popup.svelte"
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw

View file

@ -343,11 +343,13 @@
<!-- Top components -->
<div class="z-4 pointer-events-none absolute left-0 top-0 w-full">
<InsetSpacer height={AndroidPolyfill.getInsetSizes().top}/>
<div
id="top-bar"
class="bg-black-light-transparent pointer-events-auto flex flex-wrap items-center justify-between px-4 py-1"
>
<div class="w-full">
<InsetSpacer height={AndroidPolyfill.getInsetSizes().top}/>
</div>
<!-- Top bar with tools -->
<div class="flex items-center">
<MapControlButton
@ -466,6 +468,7 @@
{#if $selectedElement !== undefined && $selectedLayer !== undefined && !$selectedLayer.popupInFloatover}
<!-- right modal with the selected element view -->
<Drawer
placement="right"
transitionType="fly"

View file

@ -1,4 +1,4 @@
export function dragDetection(htmlElement: HTMLElement, callback: () => {}) {
export function dragDetection(htmlElement: HTMLElement, callback: () => void) {
let isDown = false
const threshold = 5
let start = null

View file

@ -406,7 +406,7 @@ h2.group {
.warning {
/* The class to convey important information, but not as grave as 'alert' */
background-color: var(--low-interaction-background);
background-color: var(--alert-color);
color: var(--alert-foreground-color);
font-weight: bold;
border-radius: 1em;

View file

@ -74,7 +74,7 @@
</div>
</div>
<div class="flex justify-between items-end w-full absolute bottom-0 p-4 h-fit delete-on-load">
<div class="flex justify-between items-end w-full absolute bottom-0 p-8 h-fit delete-on-load">
<!-- IMAGE-START -->
<img aria-hidden="true" class="p-4 h-32 w-32 self-start" src="./assets/svg/add.svg">