Rewrite index page in svelte, rewrite language picker in Svelte, fix #1612

This commit is contained in:
Pieter Vander Vennet 2023-11-19 01:05:15 +01:00
parent 303d3a0337
commit d638237e38
16 changed files with 265 additions and 333 deletions

View file

@ -725,14 +725,6 @@ video {
left: 0px;
}
.top-2 {
top: 0.5rem;
}
.right-3 {
right: 0.75rem;
}
.bottom-0 {
bottom: 0px;
}
@ -777,18 +769,22 @@ video {
margin: 2rem;
}
.m-5 {
margin: 1.25rem;
.m-4 {
margin: 1rem;
}
.m-3 {
margin: 0.75rem;
}
.m-0 {
margin: 0px;
}
.m-2 {
margin: 0.5rem;
}
.m-4 {
margin: 1rem;
}
.m-1 {
margin: 0.25rem;
}
@ -797,14 +793,6 @@ video {
margin: 0.125rem;
}
.m-0 {
margin: 0px;
}
.m-3 {
margin: 0.75rem;
}
.m-6 {
margin: 1.5rem;
}
@ -823,16 +811,16 @@ video {
margin-bottom: 0.25rem;
}
.mx-1 {
margin-left: 0.25rem;
margin-right: 0.25rem;
}
.my-4 {
margin-top: 1rem;
margin-bottom: 1rem;
}
.mx-1 {
margin-left: 0.25rem;
margin-right: 0.25rem;
}
.my-2 {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
@ -853,14 +841,22 @@ video {
margin-right: 3rem;
}
.mr-2 {
margin-right: 0.5rem;
.mt-4 {
margin-top: 1rem;
}
.mr-4 {
margin-right: 1rem;
}
.mr-2 {
margin-right: 0.5rem;
}
.mb-16 {
margin-bottom: 4rem;
}
.mr-6 {
margin-right: 1.5rem;
}
@ -897,10 +893,6 @@ video {
margin-top: 0.5rem;
}
.mt-4 {
margin-top: 1rem;
}
.mb-2 {
margin-bottom: 0.5rem;
}
@ -917,10 +909,6 @@ video {
margin-left: 1rem;
}
.mt-3 {
margin-top: 0.75rem;
}
.mb-10 {
margin-bottom: 2.5rem;
}
@ -1058,24 +1046,24 @@ video {
height: 2rem;
}
.h-16 {
height: 4rem;
.h-12 {
height: 3rem;
}
.h-6 {
height: 1.5rem;
}
.h-12 {
height: 3rem;
}
.h-fit {
height: -webkit-fit-content;
height: -moz-fit-content;
height: fit-content;
}
.h-16 {
height: 4rem;
}
.h-4 {
height: 1rem;
}
@ -1152,16 +1140,16 @@ video {
width: 2rem;
}
.w-16 {
width: 4rem;
.w-12 {
width: 3rem;
}
.w-6 {
width: 1.5rem;
}
.w-12 {
width: 3rem;
.w-16 {
width: 4rem;
}
.w-screen {
@ -1809,6 +1797,11 @@ video {
line-height: 1.75rem;
}
.text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
@ -1829,20 +1822,11 @@ video {
line-height: 1.25rem;
}
.text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.font-bold {
font-weight: 700;
}
.font-extrabold {
font-weight: 800;
}
@ -1851,6 +1835,10 @@ video {
font-weight: 600;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
@ -1927,21 +1915,6 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.text-gray-900 {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.text-gray-800 {
--tw-text-opacity: 1;
color: rgb(31 41 55 / var(--tw-text-opacity));
}
.text-gray-500 {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity));
}
.underline {
text-decoration-line: underline;
}
@ -2753,11 +2726,6 @@ a.link-underline {
margin-right: 0.25rem;
}
.sm\:mx-auto {
margin-left: auto;
margin-right: auto;
}
.sm\:mt-2 {
margin-top: 0.5rem;
}
@ -2766,10 +2734,6 @@ a.link-underline {
margin-right: 0.25rem;
}
.sm\:mt-5 {
margin-top: 1.25rem;
}
.sm\:mr-4 {
margin-right: 1rem;
}
@ -2790,10 +2754,6 @@ a.link-underline {
width: 6rem;
}
.sm\:max-w-xl {
max-width: 36rem;
}
.sm\:flex-nowrap {
flex-wrap: nowrap;
}
@ -2822,15 +2782,6 @@ a.link-underline {
padding-top: 0.25rem;
}
.sm\:text-center {
text-align: center;
}
.sm\:text-5xl {
font-size: 3rem;
line-height: 1;
}
.sm\:text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
@ -2842,25 +2793,17 @@ a.link-underline {
margin: 0.25rem;
}
.md\:m-2 {
margin: 0.5rem;
}
.md\:mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.md\:mr-2 {
margin-right: 0.5rem;
}
.md\:mt-5 {
margin-top: 1.25rem;
}
.md\:mt-4 {
margin-top: 1rem;
.md\:mr-2 {
margin-right: 0.5rem;
}
.md\:grid {
@ -2932,14 +2875,6 @@ a.link-underline {
margin-right: 0px;
}
.lg\:ml-40 {
margin-left: 10rem;
}
.lg\:w-3\/4 {
width: 75%;
}
.lg\:w-5\/12 {
width: 41.666667%;
}
@ -2951,17 +2886,9 @@ a.link-underline {
.lg\:grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.lg\:text-left {
text-align: left;
}
}
@media (min-width: 1280px) {
.xl\:inline {
display: inline;
}
.xl\:w-4\/12 {
width: 33.333333%;
}

View file

@ -21,6 +21,7 @@ export default class UserDetails {
public account_created: string
public tracesCount: number = 0
public description: string
public languages: string[]
constructor(backend: string) {
this.backend = backend
@ -89,6 +90,7 @@ export class OsmConnection {
ud.unreadMessages = 0
ud.name = "Fake user"
ud.totalMessages = 42
ud.languages = ["en"]
}
const self = this
this.UpdateCapabilities()
@ -193,7 +195,7 @@ export class OsmConnection {
method: "GET",
path: "/api/0.6/user/details",
},
function (err, details) {
function (err, details: XMLDocument) {
if (err != null) {
console.log(err)
self.loadingStatus.setData("error")
@ -222,11 +224,14 @@ export class OsmConnection {
data.name = userInfo.getAttribute("display_name")
data.account_created = userInfo.getAttribute("account_created")
data.uid = Number(userInfo.getAttribute("id"))
data.languages = Array.from(
userInfo.getElementsByTagName("languages")[0].getElementsByTagName("lang")
).map((l) => l.textContent)
data.csCount = Number.parseInt(
userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? 0
userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? "0"
)
data.tracesCount = Number.parseInt(
userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? 0
userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? "0"
)
data.img = undefined

View file

@ -42,6 +42,10 @@ export default class UserRelatedState {
public readonly showCrosshair: UIEventSource<"yes" | undefined>
public readonly fixateNorth: UIEventSource<undefined | "yes">
public readonly homeLocation: FeatureSource
/**
* The language as saved into the preferences of the user, if logged in.
* Note that this is _different_ from the languages a user can set via the osm.org interface here: https://www.openstreetmap.org/preferences
*/
public readonly language: UIEventSource<string>
public readonly preferredBackgroundLayer: UIEventSource<
string | "photo" | "map" | "osmbasedmap" | undefined
@ -134,7 +138,7 @@ export default class UserRelatedState {
return
}
this.language.addCallbackAndRunD((language) => Locale.language.setData(language))
this.language.syncWith(Locale.language)
}
private static initUserRelatedState(): LayerConfig {

View file

@ -9,7 +9,9 @@ import { RasterLayerProperties } from "./RasterLayerProperties"
export class AvailableRasterLayers {
public static EditorLayerIndex: (Feature<Polygon, EditorLayerIndexProperties> &
RasterLayerPolygon)[] = <any>editorlayerindex.features
public static globalLayers: RasterLayerPolygon[] = globallayers.layers.map(
public static globalLayers: RasterLayerPolygon[] = globallayers.layers
.filter((properties) => properties.id !== "osm.carto" /*Added separately*/)
.map(
(properties) =>
<RasterLayerPolygon>{
type: "Feature",
@ -74,6 +76,7 @@ export class AvailableRasterLayers {
}
return GeoOperations.inside(lonlat, eliPolygon)
})
matching.unshift(AvailableRasterLayers.osmCarto)
matching.push(AvailableRasterLayers.maptilerDefaultLayer)
matching.push(...AvailableRasterLayers.globalLayers)
return matching

View file

@ -0,0 +1,74 @@
<script lang="ts">
import { OsmConnectionFeatureSwitches } from "../Logic/State/FeatureSwitchState";
import { OsmConnection } from "../Logic/Osm/OsmConnection";
import { QueryParameters } from "../Logic/Web/QueryParameters";
import UserRelatedState from "../Logic/State/UserRelatedState";
import LanguagePicker from "./InputElement/LanguagePicker.svelte";
import Translations from "./i18n/Translations";
import Logo from "../assets/svg/Logo.svelte";
import Tr from "./Base/Tr.svelte";
import ToSvelte from "./Base/ToSvelte.svelte";
import MoreScreen from "./BigComponents/MoreScreen";
import LoginToggle from "./Base/LoginToggle.svelte";
import Pencil from "../assets/svg/Pencil.svelte";
import Login from "../assets/svg/Login.svelte";
import Constants from "../Models/Constants";
const featureSwitches = new OsmConnectionFeatureSwitches();
const osmConnection = new OsmConnection({
fakeUser: featureSwitches.featureSwitchFakeUser.data,
oauth_token: QueryParameters.GetQueryParameter(
"oauth_token",
undefined,
"Used to complete the login"
)
});
const state = new UserRelatedState(osmConnection);
const t = Translations.t.index;
let userLanguages = osmConnection.userDetails.map(ud => ud.languages);
</script>
<div class="flex flex-col m-4">
<div class="self-end">
<LanguagePicker assignTo={state.language} availableLanguages={t.title.SupportedLanguages()}
preferredLanguages={userLanguages} />
</div>
<div class="flex mt-4">
<div class="flex-none m-3">
<Logo alt="MapComplete Logo" class="w-12 h-12 sm:h-24 sm:w-24" />
</div>
<div class="flex flex-col">
<h1 class="tracking-tight font-extrabold md:text-6xl m-0">
<Tr t={t.title} />
</h1>
<Tr cls="my-4 mr-4 text-base font-semibold sm:text-lg md:mt-5 md:text-xl lg:mx-0"
t={Translations.t.index.intro} />
</div>
</div>
<ToSvelte construct={new MoreScreen(state, true)} />
<LoginToggle state={state}>
<div slot="not-logged-in">
<button class="w-full" on:click={() => osmConnection.AttemptLogin()}>
<Login class="w-6 h-6 mr-2 "/>
<Tr t={Translations.t.index.logIn} />
</button>
</div>
<a class="w-full h-fit button" href={window.location.protocol + "//" + window.location.host + "/studio.html"}>
<Pencil class="w-6 h-6 mr-2" />
<Tr t={ Translations.t.general.morescreen.createYourOwnTheme} />
</a>
</LoginToggle>
<Tr cls="link-underline" t={Translations.t.general.aboutMapComplete.intro}/>
<div class="subtle self-end mb-16">
v{Constants.vNumber}
</div>
</div>

View file

@ -1,69 +0,0 @@
import UserRelatedState from "../Logic/State/UserRelatedState"
import { FixedUiElement } from "./Base/FixedUiElement"
import Combine from "./Base/Combine"
import MoreScreen from "./BigComponents/MoreScreen"
import Translations from "./i18n/Translations"
import Constants from "../Models/Constants"
import LanguagePicker from "./LanguagePicker"
import IndexText from "./BigComponents/IndexText"
import { LoginToggle } from "./Popup/LoginButton"
import { ImmutableStore } from "../Logic/UIEventSource"
import { OsmConnection } from "../Logic/Osm/OsmConnection"
import { QueryParameters } from "../Logic/Web/QueryParameters"
import { OsmConnectionFeatureSwitches } from "../Logic/State/FeatureSwitchState"
import { SubtleButton } from "./Base/SubtleButton"
import Svg from "../Svg"
import Link from "./Base/Link"
export default class AllThemesGui {
setup() {
try {
const featureSwitches = new OsmConnectionFeatureSwitches()
const osmConnection = new OsmConnection({
fakeUser: featureSwitches.featureSwitchFakeUser.data,
oauth_token: QueryParameters.GetQueryParameter(
"oauth_token",
undefined,
"Used to complete the login"
),
})
const state = new UserRelatedState(osmConnection)
const intro = new Combine([
new LanguagePicker(
Translations.t.index.title.SupportedLanguages(),
state.language
).SetClass("flex absolute top-2 right-3"),
new IndexText(),
])
new Combine([
intro,
new MoreScreen(state, true),
new LoginToggle(
new Link(
new Combine([
Svg.pencil_svg().SetClass("w-6 h-6 mr-2"),
Translations.t.general.morescreen.createYourOwnTheme,
]).SetClass("flex p-2"),
window.location.protocol + "//" + window.location.host + "/studio.html"
).SetClass("w-full h-fit button"),
Translations.t.index.logIn,
{
osmConnection,
featureSwitchUserbadge: new ImmutableStore(true),
}
).SetClass("flex justify-center w-full"),
Translations.t.general.aboutMapComplete.intro.SetClass("link-underline"),
new FixedUiElement("v" + Constants.vNumber).SetClass("block"),
])
.SetClass("block m-5 lg:w-3/4 lg:ml-40")
.AttachTo("main")
} catch (e) {
console.error(">>>> CRITICAL", e)
new FixedUiElement(
"Seems like no layers are compiled - check the output of `npm run generate:layeroverview`. Is this visible online? Contact pietervdvn immediately!"
)
.SetClass("alert")
.AttachTo("main")
}
}
}

View file

@ -1,14 +1,31 @@
<script lang="ts">
import { UIEventSource } from "../../Logic/UIEventSource.js"
import { UIEventSource } from "../../Logic/UIEventSource.js";
/**
* For some stupid reason, it is very hard to bind inputs
*/
export let value: UIEventSource<number>
let i: number = value.data
$: value.setData(i)
export let value: UIEventSource<any>
let i: any = value.data
let htmlElement : HTMLSelectElement
function selectAppropriateValue(){
if(!htmlElement){
return;
}
const v = value.data
for (let option of htmlElement.getElementsByTagName("option")) {
if(option.value === v){
option.selected = true
return
}
}
}
value.addCallbackD(() => selectAppropriateValue())
$: {
if(htmlElement){
selectAppropriateValue()
}
}
</script>
<select bind:value={i}>
<select bind:this={htmlElement} on:change={(e) => {value.setData(e.srcElement.value)}}>
<slot />
</select>

View file

@ -4,25 +4,7 @@ import { FixedUiElement } from "../Base/FixedUiElement"
export default class IndexText extends Combine {
constructor() {
super([
new FixedUiElement(
`<img class="w-12 h-12 sm:h-24 sm:w-24" src="./assets/svg/logo.svg" alt="MapComplete Logo">`
).SetClass("flex-none m-3"),
new Combine([
Translations.t.index.title.SetClass(
"text-2xl tracking-tight font-extrabold text-gray-900 sm:text-5xl md:text-6xl block text-gray-800 xl:inline"
),
Translations.t.index.intro.SetClass(
"mt-3 text-base font-semibold text-gray-500 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0"
),
Translations.t.index.pickTheme.SetClass(
"mt-3 text-base sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0"
),
]).SetClass("flex flex-col sm:text-center lg:text-left m-1 mt-2 md:m-2 md:mt-4"),
])
super([])
this.SetClass("flex flex-row")
}

View file

@ -0,0 +1,67 @@
<script lang="ts">
// Languages in the language itself
import native from "../../assets/language_native.json";
// Translated languages
import language_translations from "../../assets/language_translations.json";
import { UIEventSource } from "../../Logic/UIEventSource";
import Locale from "../i18n/Locale";
import { LanguageIcon } from "@babeard/svelte-heroicons/solid";
import Dropdown from "../Base/Dropdown.svelte";
/**
* Languages one can choose from
* Defaults to _all_ languages known by MapComplete
*/
export let availableLanguages: string[] = Object.keys(native);
/**
* EventStore to assign to, defaults to 'Locale.langauge'
*/
export let assignTo: UIEventSource<string> = Locale.language;
export let preferredLanguages: UIEventSource<string[]>;
let preferredFiltered: string[] = undefined;
preferredLanguages.addCallbackAndRunD(preferredLanguages => {
let lng = navigator.language;
if (lng === "en-US") {
lng = "en";
}
if (preferredLanguages?.indexOf(lng) < 0) {
preferredLanguages?.push(lng);
}
preferredFiltered = preferredLanguages?.filter(l => availableLanguages.indexOf(l) >= 0);
});
let current = Locale.language;
</script>
{#if availableLanguages?.length > 1}
<form class="flex items-center">
<LanguageIcon class="h-4 w-4 mr-1" />
<Dropdown value={assignTo}>
{#if preferredFiltered}
{#each preferredFiltered as language}
<option value={language} class="font-bold">
{native[language] ?? ""}
{#if language !== $current}
({language_translations[language]?.[$current] ?? language})
{/if}
</option>
{/each}
<option disabled></option>
{/if}
{#each availableLanguages as language}
<option value={language} class="font-bold">
{native[language] ?? ""}
{#if language !== $current}
({(language_translations[language]?.[$current] + " - " + language) ?? language})
{/if}
</option>
{/each}
</Dropdown>
</form>
{/if}

View file

@ -1,67 +0,0 @@
import { DropDown } from "./Input/DropDown"
import Locale from "./i18n/Locale"
import BaseUIElement from "./BaseUIElement"
import native from "../assets/language_native.json"
import language_translations from "../assets/language_translations.json"
import { Translation } from "./i18n/Translation"
import Lazy from "./Base/Lazy"
import Toggle from "./Input/Toggle"
import LanguageUtils from "../Utils/LanguageUtils"
import { UIEventSource } from "../Logic/UIEventSource"
import { QueryParameters } from "../Logic/Web/QueryParameters"
export default class LanguagePicker extends Toggle {
constructor(languages: string[], assignTo: UIEventSource<string>) {
console.log("Constructing a language picker for languages", languages)
if (
languages === undefined ||
languages.length <= 1 ||
QueryParameters.wasInitialized("language")
) {
super(undefined, undefined, undefined)
} else {
const normalPicker = LanguagePicker.dropdownFor(languages, assignTo ?? Locale.language)
const fullPicker = new Lazy(() =>
LanguagePicker.dropdownFor(allLanguages, assignTo ?? Locale.language)
)
super(fullPicker, normalPicker, Locale.showLinkToWeblate)
const allLanguages: string[] = LanguageUtils.usedLanguagesSorted
}
}
private static dropdownFor(
languages: string[],
assignTo: UIEventSource<string>
): BaseUIElement {
return new DropDown(
undefined,
languages
.filter((lang) => lang !== "_context")
.map((lang) => {
return { value: lang, shown: LanguagePicker.hybrid(lang) }
}),
assignTo
)
}
private static hybrid(lang: string): Translation {
const nativeText = native[lang] ?? lang
const translation = {}
const trans = language_translations[lang]
if (trans === undefined) {
return new Translation({ "*": nativeText })
}
for (const key in trans) {
if (key.startsWith("_")) {
continue
}
const translationInKey = language_translations[lang][key]
if (nativeText.toLowerCase() === translationInKey.toLowerCase()) {
translation[key] = nativeText
} else {
translation[key] = nativeText + " (" + translationInKey + ")"
}
}
return new Translation(translation)
}
}

View file

@ -45,7 +45,6 @@ import { GeoOperations } from "../Logic/GeoOperations"
import CreateNewNote from "./Popup/CreateNewNote.svelte"
import AddNewPoint from "./Popup/AddNewPoint/AddNewPoint.svelte"
import UserProfile from "./BigComponents/UserProfile.svelte"
import LanguagePicker from "./LanguagePicker"
import Link from "./Base/Link"
import LayerConfig from "../Models/ThemeConfig/LayerConfig"
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
@ -78,6 +77,7 @@ import Questionbox from "./Popup/TagRendering/Questionbox.svelte"
import { TagUtils } from "../Logic/Tags/TagUtils"
import Giggity from "./BigComponents/Giggity.svelte"
import ThemeViewState from "../Models/ThemeViewState"
import LanguagePicker from "./InputElement/LanguagePicker.svelte"
class NearbyImageVis implements SpecialVisualization {
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
@ -453,10 +453,10 @@ export default class SpecialVisualizations {
needsUrls: [],
docs: "A component to set the language of the user interface",
constr(state: SpecialVisualizationState): BaseUIElement {
return new LanguagePicker(
state.layout.language,
state.userRelatedState.language
)
return new SvelteUIElement(LanguagePicker, {
assignTo: state.userRelatedState.language,
availableLanguages: state.layout.language,
})
},
},
{

View file

@ -1,16 +1,15 @@
<script lang="ts">
// Testing grounds
import { UIEventSource } from "../Logic/UIEventSource"
import TabbedGroup from "./Base/TabbedGroup.svelte"
let tab = new UIEventSource(1)
console.log("Tab control", tab)
import LanguagePicker from "./InputElement/LanguagePicker.svelte";
import Translations from "./i18n/Translations";
import Tr from "./Base/Tr.svelte";
import Locale from "./i18n/Locale";
let language = Locale.language
</script>
<TabbedGroup {tab}>
<div slot="title0">Title 0</div>
<div slot="content0">Content 0 loaded</div>
<div class="w-full">
<LanguagePicker preferredLanguages={["nl", "en"]}/>
<div slot="title1">Title 1</div>
<div slot="content1">Content 1</div>
</TabbedGroup>
<Tr t={Translations.t.general.download.downloadAsPdf}/>
{$language}
</div>

View file

@ -48,13 +48,13 @@
import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte";
import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte";
import StateIndicator from "./BigComponents/StateIndicator.svelte";
import LanguagePicker from "./LanguagePicker";
import Locale from "./i18n/Locale";
import ShareScreen from "./BigComponents/ShareScreen.svelte";
import UploadingImageCounter from "./Image/UploadingImageCounter.svelte";
import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte";
import Cross from "../assets/svg/Cross.svelte";
import Summary from "./BigComponents/Summary.svelte";
import LanguagePicker from "./InputElement/LanguagePicker.svelte";
export let state: ThemeViewState;
let layout = state.layout;
@ -263,7 +263,7 @@
</div>
<LoginToggle ignoreLoading={true} {state}>
{#if $showCrosshair === "yes" && ($currentZoom >= 17 || $arrowKeysWereUsed !== undefined) }
{#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $arrowKeysWereUsed !== undefined }
<div
class="pointer-events-none absolute top-0 left-0 flex h-full w-full items-center justify-center"
>
@ -466,7 +466,7 @@
<!-- All shown components are set by 'usersettings.json', which happily uses some special visualisations created specifically for it -->
<LoginToggle {state}>
<div class="flex flex-col" slot="not-logged-in">
<ToSvelte construct={() => new LanguagePicker(layout.language, Locale.language)} />
<LanguagePicker availableLanguages={layout.language} />
<Tr cls="alert" t={Translations.t.userinfo.notLoggedIn} />
<LoginButton clss="primary" osmConnection={state.osmConnection} />
</div>

View file

@ -56,6 +56,9 @@ export default class Locale {
if (typeof navigator !== "undefined") {
browserLanguage = navigator.languages?.[0] ?? navigator.language ?? "en"
console.log("Browser language is", browserLanguage)
if (browserLanguage === "en-US") {
browserLanguage = "en"
}
}
source = LocalStorageSource.Get("language", browserLanguage)
}
@ -75,6 +78,7 @@ export default class Locale {
Locale.showLinkToWeblate.setData(Locale.showLinkToWeblate.data || tr)
})
console.log("Initial language:", source, source.data)
return source
}
}

View file

@ -1,5 +1,6 @@
import AllThemesGui from "./UI/AllThemesGui"
import { QueryParameters } from "./Logic/Web/QueryParameters"
import SvelteUIElement from "./UI/Base/SvelteUIElement"
import AllThemesGui from "./UI/AllThemesGui.svelte"
const layout = QueryParameters.GetQueryParameter("layout", undefined).data ?? ""
const customLayout = QueryParameters.GetQueryParameter("userlayout", undefined).data ?? ""
@ -27,4 +28,4 @@ if (layout !== "") {
)
}
new AllThemesGui().setup()
new SvelteUIElement(AllThemesGui, {}).AttachTo("main")

View file

@ -1,19 +1,4 @@
import { Utils } from "./Utils"
import SvelteUIElement from "./UI/Base/SvelteUIElement"
import PointRenderingConfig from "./Models/ThemeConfig/PointRenderingConfig"
import { UIEventSource } from "./Logic/UIEventSource"
import Marker from "./UI/Map/Marker.svelte"
import Qrcode from "qrcode-generator"
import { FixedUiElement } from "./UI/Base/FixedUiElement"
function generateQr(message: string, attachTo: string) {
const typeNumber = 0
const errorCorrectionLevel = "L"
const qr = Qrcode(typeNumber, errorCorrectionLevel)
qr.addData(message)
qr.make()
document.getElementById(attachTo).innerHTML = qr.createImgTag()
}
generateQr(
"http://127.0.0.1:1234/theme.html?layout=cyclofix&z=14&lat=51.21571770000094&lon=3.219866599996749&layer-range=true&layer-gps_location=false#theme-menu:download",
"qr"
)
import Test from "./UI/Test.svelte"
new SvelteUIElement(Test, {}).AttachTo("maindiv")