MapComplete/src/UI/BigComponents/ShareScreen.svelte

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

172 lines
5.5 KiB
Svelte
Raw Normal View History

2023-09-16 18:52:42 +02:00
<script lang="ts">
/**
* A screen showing:
* - A link to share the current view
* - Some query parameters that can be enabled/disabled
* - The code to embed MC as IFrame
*/
import ThemeViewState from "../../Models/ThemeViewState"
import { QueryParameters } from "../../Logic/Web/QueryParameters"
import Tr from "../Base/Tr.svelte"
import Translations from "../i18n/Translations"
import { Utils } from "../../Utils"
import { DocumentDuplicateIcon } from "@rgossiaux/svelte-heroicons/outline"
import ToSvelte from "../Base/ToSvelte.svelte"
import Img from "../Base/Img"
import Qr from "../../Utils/Qr"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
2024-06-16 19:00:43 +02:00
import Share from "@babeard/svelte-heroicons/solid/Share"
import Constants from "../../Models/Constants"
import Copyable from "../Base/Copyable.svelte"
2023-09-16 18:52:42 +02:00
export let state: ThemeViewState
const tr = Translations.t.general.sharescreen
let url = window.location
let linkToShare: string = undefined
/**
* In some cases (local deploys, custom themes), we need to set the URL to `/theme.html?layout=xyz` instead of `/xyz?...`
* Note that the 'layout='-param will be included automatically
2023-09-16 18:52:42 +02:00
*/
let needsThemeRedirect = url.port !== "" || url.hostname.match(/^[0-9]/) || !state.layout.official
let layoutId = state.layout.id
let baseLink =
`${url.protocol}//${url.host}/${needsThemeRedirect ? "theme.html" : layoutId}?`
2023-09-16 18:52:42 +02:00
let showWelcomeMessage = true
let enableLogin = true
let enableFilters = true
let enableBackground = true
let enableGeolocation = true
function calculateLinkToShare(
showWelcomeMessage: boolean,
enableLogin: boolean,
enableFilters: boolean,
enableBackground: boolean,
enableGeolocation: boolean) {
2023-09-16 18:52:42 +02:00
const layout = state.layout
let excluded = Utils.NoNull([
showWelcomeMessage ? undefined : "fs-welcome-message",
enableLogin ? undefined : "fs-enable-login",
enableFilters ? undefined : "fs-filter",
enableBackground ? undefined : "fs-background",
enableGeolocation ? undefined : "fs-geolocation",
2023-09-16 18:52:42 +02:00
])
const layerParamsWhitelist: string[] = ["fs-layers-enabled=false"]
const layerParamsBlacklist: string[] = []
for (const flayer of state.layerState.filteredLayers.values()) {
const id = flayer.layerDef.id
if (flayer.layerDef.filterIsSameAs) {
continue
}
if (id.indexOf("note_import") >= 0) {
continue
}
if (Constants.added_by_default.indexOf(<any>id) >= 0) {
continue
}
const enabled = flayer.isDisplayed.data
if (enabled) {
layerParamsWhitelist.push("layer-" + id + "=true")
} else {
layerParamsBlacklist.push("layer-" + id + "=false")
}
}
const layersBlack = layerParamsBlacklist.join("&")
const layersWhite = layerParamsWhitelist.join("&")
const layers = layersBlack.length < layersWhite.length ? layerParamsBlacklist : layerParamsWhitelist
const params = QueryParameters.GetParts(new Set(excluded))
.filter(part => !part.startsWith("layer-"))
.concat(...layers)
.concat(excluded.map((k) => k + "=" + false))
linkToShare = baseLink + Utils.Dedup(params).join("&")
2023-09-16 18:52:42 +02:00
if (layout.definitionRaw !== undefined) {
linkToShare += "&userlayout=" + (layout.definedAtUrl ?? layout.id)
}
}
$: calculateLinkToShare(showWelcomeMessage, enableLogin, enableFilters, enableBackground, enableGeolocation)
let iframeCode: string
$: iframeCode = `<iframe src="${linkToShare}"
${enableGeolocation ? 'allow="geolocation"' : ""} width="100%" height="100%" style="min-width: 250px; min-height: 250px"
title="${state.layout.title?.txt ?? "MapComplete"} with MapComplete">
</iframe>`
Array.from(state.layerState.filteredLayers.values()).forEach(flayer => flayer.isDisplayed.addCallbackAndRunD(_ => {
calculateLinkToShare(showWelcomeMessage, enableLogin, enableFilters, enableBackground, enableGeolocation)
}))
</script>
<div class="flex flex-col">
<div class="flex flex-col">
<Tr t={tr.intro} />
<Copyable {state} text={linkToShare}/>
</div>
<div class="flex justify-center">
2024-04-13 02:40:21 +02:00
<ToSvelte
construct={() => new Img(new Qr(linkToShare).toImageElement(125)).SetStyle("width: 125px")}
/>
</div>
2023-09-16 18:52:42 +02:00
<Tr t={tr.embedIntro} />
<Copyable text={iframeCode}/>
<AccordionSingle>
<div slot="header">
<Tr t={tr.options}/>
</div>
<div class="link-underline my-1 flex flex-col">
<label>
<input bind:checked={showWelcomeMessage} type="checkbox" id="share_show_welcome" />
<Tr t={tr.fsWelcomeMessage} />
</label>
<label>
2024-04-13 02:40:21 +02:00
<input bind:checked={enableLogin} type="checkbox" id="share_enable_login" />
<Tr t={tr.fsUserbadge} />
</label>
<label>
<input bind:checked={enableFilters} type="checkbox" id="share_enable_filter" />
<Tr t={tr.fsFilter} />
</label>
<label>
<input bind:checked={enableBackground} type="checkbox" id="share_enable_background" />
<Tr t={tr.fsBackground} />
</label>
<label>
<input bind:checked={enableGeolocation} type="checkbox" id="share_enable_geolocation" />
<Tr t={tr.fsGeolocation} />
</label>
<span>
<Tr t={tr.stateIsIncluded}/>
<a class="inline-block w-fit cursor-pointer" on:click={() => state.guistate.filtersPanelIsOpened.set(true)}>
<Tr t={tr.openLayers}/>
</a>
</span>
<Tr cls="link-underline" t={tr.documentation} />
</div>
</AccordionSingle>
</div>