Add global data bindings for mobile and tablet device sizes

This commit is contained in:
Andrew Kingston 2021-08-13 11:24:47 +01:00
parent ec83a77ce9
commit 47ca925003
7 changed files with 109 additions and 36 deletions

View File

@ -17,7 +17,13 @@ export const getBindableProperties = (asset, componentId) => {
const contextBindings = getContextBindings(asset, componentId)
const userBindings = getUserBindings()
const urlBindings = getUrlBindings(asset)
return [...contextBindings, ...userBindings, ...urlBindings]
const deviceBindings = getDeviceBindings()
return [
...deviceBindings,
...urlBindings,
...contextBindings,
...userBindings,
]
}
/**
@ -221,6 +227,27 @@ const getUserBindings = () => {
return bindings
}
/**
* Gets all device bindings that are globally available.
*/
const getDeviceBindings = () => {
let bindings = []
if (get(store).clientFeatures?.deviceAwareness) {
const safeDevice = makePropSafe("device")
bindings.push({
type: "context",
runtimeBinding: `${safeDevice}.${makePropSafe("mobile")}`,
readableBinding: `Device.Mobile`,
})
bindings.push({
type: "context",
runtimeBinding: `${safeDevice}.${makePropSafe("tablet")}`,
readableBinding: `Device.Tablet`,
})
}
return bindings
}
/**
* Gets all bindable properties from URL parameters.
*/

View File

@ -35,6 +35,7 @@ const INITIAL_FRONTEND_STATE = {
clientFeatures: {
spectrumThemes: false,
intelligentLoading: false,
deviceAwareness: false,
},
currentFrontEndType: "none",
selectedScreenId: "",

View File

@ -38,7 +38,7 @@
</section>
{#if filteredColumns?.length}
<section>
<div class="heading">Columns</div>
<div class="heading">Bindable Values</div>
<ul>
{#each filteredColumns as { readableBinding }}
<li

View File

@ -5,7 +5,6 @@
import NotificationDisplay from "./NotificationDisplay.svelte"
import ConfirmationDisplay from "./ConfirmationDisplay.svelte"
import PeekScreenDisplay from "./PeekScreenDisplay.svelte"
import Provider from "./Provider.svelte"
import SDK from "../sdk"
import {
createContextStore,
@ -16,12 +15,13 @@
builderStore,
appStore,
} from "../store"
import { TableNames, ActionTypes } from "../constants"
import SettingsBar from "./preview/SettingsBar.svelte"
import SelectionIndicator from "./preview/SelectionIndicator.svelte"
import HoverIndicator from "./preview/HoverIndicator.svelte"
import { Layout, Heading, Body } from "@budibase/bbui"
import ErrorSVG from "../../../builder/assets/error.svg"
import UserBindingsProvider from "./UserBindingsProvider.svelte"
import DeviceBindingsProvider from "./DeviceBindingsProvider.svelte"
// Provide contexts
setContext("sdk", SDK)
@ -41,16 +41,6 @@
}
})
// Register this as a refreshable datasource so that user changes cause
// the user object to be refreshed
$: actions = [
{
type: ActionTypes.RefreshDatasource,
callback: () => authStore.actions.fetchUser(),
metadata: { dataSource: { type: "table", tableId: TableNames.USERS } },
},
]
// Handle no matching route - this is likely a permission error
$: {
if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) {
@ -93,30 +83,32 @@
</Layout>
</div>
{:else if $screenStore.activeLayout}
<Provider key="user" data={$authStore} {actions}>
<div id="app-root" class:preview={$builderStore.inBuilder}>
{#key $screenStore.activeLayout._id}
<Component instance={$screenStore.activeLayout.props} />
<UserBindingsProvider>
<DeviceBindingsProvider>
<div id="app-root" class:preview={$builderStore.inBuilder}>
{#key $screenStore.activeLayout._id}
<Component instance={$screenStore.activeLayout.props} />
{/key}
</div>
<NotificationDisplay />
<ConfirmationDisplay />
<PeekScreenDisplay />
<!-- Key block needs to be outside the if statement or it breaks -->
{#key $builderStore.selectedComponentId}
{#if $builderStore.inBuilder}
<SettingsBar />
{/if}
{/key}
</div>
<NotificationDisplay />
<ConfirmationDisplay />
<PeekScreenDisplay />
<!-- Key block needs to be outside the if statement or it breaks -->
{#key $builderStore.selectedComponentId}
<!--
We don't want to key these by componentID as they control their own
re-mounting to avoid flashes.
-->
{#if $builderStore.inBuilder}
<SettingsBar />
<SelectionIndicator />
<HoverIndicator />
{/if}
{/key}
<!--
We don't want to key these by componentID as they control their own
re-mounting to avoid flashes.
-->
{#if $builderStore.inBuilder}
<SelectionIndicator />
<HoverIndicator />
{/if}
</Provider>
</DeviceBindingsProvider>
</UserBindingsProvider>
{/if}
</div>
{/if}

View File

@ -0,0 +1,33 @@
<script>
import Provider from "./Provider.svelte"
import { onMount } from "svelte"
const tabletBreakpoint = 768
const desktopBreakpoint = 1280
let screenWidth = window.innerWidth
const resizeObserver = new ResizeObserver(entries => {
if (entries?.[0]) {
screenWidth = entries[0].contentRect?.width
}
})
$: mobile = screenWidth && screenWidth < tabletBreakpoint
$: tablet =
screenWidth &&
screenWidth >= tabletBreakpoint &&
screenWidth < desktopBreakpoint
$: data = { mobile, tablet }
onMount(() => {
const doc = document.documentElement
resizeObserver.observe(doc)
return () => {
resizeObserver.unobserve(doc)
}
})
</script>
<Provider key="device" {data}>
<slot />
</Provider>

View File

@ -0,0 +1,19 @@
<script>
import Provider from "./Provider.svelte"
import { authStore } from "../store"
import { ActionTypes, TableNames } from "../constants"
// Register this as a refreshable datasource so that user changes cause
// the user object to be refreshed
$: actions = [
{
type: ActionTypes.RefreshDatasource,
callback: () => authStore.actions.fetchUser(),
metadata: { dataSource: { type: "table", tableId: TableNames.USERS } },
},
]
</script>
<Provider key="user" data={$authStore} {actions}>
<slot />
</Provider>

View File

@ -1,7 +1,8 @@
{
"features": {
"spectrumThemes": true,
"intelligentLoading": true
"intelligentLoading": true,
"deviceAwareness": true
},
"layout": {
"name": "Layout",