From 1bf1700bab1ce8bde4d471c0751001afff107ca5 Mon Sep 17 00:00:00 2001 From: wjtje <33957974+wjtje@users.noreply.github.com> Date: Fri, 3 Feb 2023 22:28:11 +0100 Subject: [PATCH] Move MoreScreen to svelte --- UI/Base/SubtleButton.svelte | 14 +- UI/BigComponents/CustomGeneratorButton.svelte | 38 +++ UI/BigComponents/HiddenThemeList.svelte | 37 +++ UI/BigComponents/MoreScreen.ts | 218 ++---------------- UI/BigComponents/NoThemeResultButton.svelte | 65 ++++++ .../ProfessionalServicesButton.svelte | 24 ++ UI/BigComponents/ThemeButton.svelte | 110 +++++++++ UI/BigComponents/ThemesList.svelte | 83 +++++++ UI/BigComponents/UnofficialThemeList.svelte | 35 +++ 9 files changed, 419 insertions(+), 205 deletions(-) create mode 100644 UI/BigComponents/CustomGeneratorButton.svelte create mode 100644 UI/BigComponents/HiddenThemeList.svelte create mode 100644 UI/BigComponents/NoThemeResultButton.svelte create mode 100644 UI/BigComponents/ProfessionalServicesButton.svelte create mode 100644 UI/BigComponents/ThemeButton.svelte create mode 100644 UI/BigComponents/ThemesList.svelte create mode 100644 UI/BigComponents/UnofficialThemeList.svelte diff --git a/UI/Base/SubtleButton.svelte b/UI/Base/SubtleButton.svelte index e6666eb8e9..261c556a61 100644 --- a/UI/Base/SubtleButton.svelte +++ b/UI/Base/SubtleButton.svelte @@ -5,14 +5,14 @@ import Img from "./Img" import Translations from "../i18n/Translations" - export let imageUrl: string | BaseUIElement - export let message: string | BaseUIElement + export let imageUrl: string | BaseUIElement = undefined + export let message: string | BaseUIElement = undefined export let options: { url?: string | Store newTab?: boolean imgSize?: string extraClasses?: string - } + } = {} let href = typeof options?.url == "string" ? options.url : "" @@ -27,7 +27,7 @@ } // Image - if (imgElem != undefined) { + if (imgElem && imageUrl) { let img: BaseUIElement const imgClasses = "block justify-center flex-none mr-4 " + (options?.imgSize ?? "h-11 w-11") @@ -43,7 +43,7 @@ } // Message - if (msgElem != undefined) { + if (msgElem && message) { let msg = Translations.W(message)?.SetClass("block text-ellipsis no-images flex-shrink") msgElem.replaceWith(msg.ConstructElement()) } @@ -74,5 +74,9 @@ :global(img) { @apply block justify-center flex-none mr-4 h-11 w-11; } + + :global(span) { + @apply block text-ellipsis flex-shrink; + } } diff --git a/UI/BigComponents/CustomGeneratorButton.svelte b/UI/BigComponents/CustomGeneratorButton.svelte new file mode 100644 index 0000000000..d11eac2389 --- /dev/null +++ b/UI/BigComponents/CustomGeneratorButton.svelte @@ -0,0 +1,38 @@ + + +
+ {#if $userDetails.csCount < Constants.userJourney.themeGeneratorReadOnlyUnlock} + + {t.requestATheme.toString()} + + {:else} + + + + + {t.createYourOwnTheme.toString()} + + {/if} +
diff --git a/UI/BigComponents/HiddenThemeList.svelte b/UI/BigComponents/HiddenThemeList.svelte new file mode 100644 index 0000000000..5432b05875 --- /dev/null +++ b/UI/BigComponents/HiddenThemeList.svelte @@ -0,0 +1,37 @@ + + + + +

{t.previouslyHiddenTitle.toString()}

+

+ {t.hiddenExplanation.Subs({ + hidden_discovered: knownThemes.length.toString(), + total_hidden: hiddenThemes.length.toString(), + })} +

+
+
diff --git a/UI/BigComponents/MoreScreen.ts b/UI/BigComponents/MoreScreen.ts index 05775dd470..540ddcd23a 100644 --- a/UI/BigComponents/MoreScreen.ts +++ b/UI/BigComponents/MoreScreen.ts @@ -1,24 +1,23 @@ -import { VariableUiElement } from "../Base/VariableUIElement" import Svg from "../../Svg" import Combine from "../Base/Combine" import { SubtleButton } from "../Base/SubtleButton" import Translations from "../i18n/Translations" import personal from "../../assets/themes/personal/personal.json" -import Constants from "../../Models/Constants" import BaseUIElement from "../BaseUIElement" import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import { ImmutableStore, Store, Stores, UIEventSource } from "../../Logic/UIEventSource" +import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" import Loc from "../../Models/Loc" -import { OsmConnection } from "../../Logic/Osm/OsmConnection" import UserRelatedState from "../../Logic/State/UserRelatedState" -import Toggle from "../Input/Toggle" import { Utils } from "../../Utils" import Title from "../Base/Title" import themeOverview from "../../assets/generated/theme_overview.json" import { Translation } from "../i18n/Translation" import { TextField } from "../Input/TextField" -import FilteredCombine from "../Base/FilteredCombine" import Locale from "../i18n/Locale" +import SvelteUIElement from "../Base/SvelteUIElement" +import ThemesList from "./ThemesList.svelte" +import HiddenThemeList from "./HiddenThemeList.svelte" +import UnofficialThemeList from "./UnofficialThemeList.svelte" export default class MoreScreen extends Combine { private static readonly officialThemes: { @@ -40,13 +39,6 @@ export default class MoreScreen extends Combine { onMainScreen: boolean = false ) { const tr = Translations.t.general.morescreen - let themeButtonStyle = "" - let themeListStyle = "" - if (onMainScreen) { - themeButtonStyle = "h-32 min-h-32 max-h-32 text-ellipsis overflow-hidden" - themeListStyle = - "md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-g4 gap-4" - } const search = new TextField({ placeholder: tr.searchForATheme, @@ -107,38 +99,26 @@ export default class MoreScreen extends Combine { super([ new Combine([searchBar]).SetClass("flex justify-center"), - MoreScreen.createOfficialThemesList( + new SvelteUIElement(ThemesList, { state, - themeButtonStyle, - themeListStyle, - search.GetValue() - ), - MoreScreen.createPreviouslyVistedHiddenList( + onMainScreen, + search: search.GetValue(), + themes: MoreScreen.officialThemes, + }), + new SvelteUIElement(HiddenThemeList, { state, - themeButtonStyle, - themeListStyle, - search.GetValue() - ), - MoreScreen.createUnofficialThemeList( - themeButtonStyle, + onMainScreen, + search: search.GetValue(), + }), + new SvelteUIElement(UnofficialThemeList, { state, - themeListStyle, - search.GetValue() - ), + onMainScreen, + search: search.GetValue(), + }), tr.streetcomplete.Clone().SetClass("block text-base mx-10 my-3 mb-10"), ]) } - private static NothingFound(search: UIEventSource): BaseUIElement { - const t = Translations.t.general.morescreen - return new Combine([ - new Title(t.noMatchingThemes, 5).SetClass("w-max font-bold"), - new SubtleButton(Svg.search_disable_ui(), t.noSearch, { imgSize: "h-6" }) - .SetClass("h-12 w-max") - .onClick(() => search.setData("")), - ]).SetClass("flex flex-col items-center w-full") - } - private static createUrlFor( layout: { id: string; definition?: string }, isCustom: boolean, @@ -239,102 +219,6 @@ export default class MoreScreen extends Combine { new SubtleButton(undefined, t.button, { url: "./professional.html" }), ]).SetClass("flex flex-col border border-gray-300 p-2 rounded-lg") } - private static createUnofficialThemeList( - buttonClass: string, - state: UserRelatedState, - themeListClasses: string, - search: UIEventSource - ): BaseUIElement { - var currentIds: Store = state.installedUserThemes - - var stableIds = Stores.ListStabilized(currentIds) - return new VariableUiElement( - stableIds.map((ids) => { - const allThemes: { element: BaseUIElement; predicate?: (s: string) => boolean }[] = - [] - for (const id of ids) { - const themeInfo = state.GetUnofficialTheme(id) - if (themeInfo === undefined) { - continue - } - const link = MoreScreen.createLinkButton(state, themeInfo, true) - if (link !== undefined) { - allThemes.push({ - element: link.SetClass(buttonClass), - predicate: (s) => id.toLowerCase().indexOf(s) >= 0, - }) - } - } - if (allThemes.length <= 0) { - return undefined - } - return new Combine([ - Translations.t.general.customThemeIntro, - new FilteredCombine(allThemes, search, { - innerClasses: themeListClasses, - onEmpty: MoreScreen.NothingFound(search), - }), - ]) - }) - ) - } - - private static createPreviouslyVistedHiddenList( - state: UserRelatedState, - buttonClass: string, - themeListStyle: string, - search: UIEventSource - ): BaseUIElement { - const t = Translations.t.general.morescreen - const prefix = "mapcomplete-hidden-theme-" - const hiddenThemes = themeOverview.filter((layout) => layout.hideFromOverview) - const hiddenTotal = hiddenThemes.length - - return new Toggle( - new VariableUiElement( - state.osmConnection.preferencesHandler.preferences.map((allPreferences) => { - const knownThemes: Set = new Set( - Utils.NoNull( - Object.keys(allPreferences) - .filter((key) => key.startsWith(prefix)) - .map((key) => - key.substring(prefix.length, key.length - "-enabled".length) - ) - ) - ) - - if (knownThemes.size === 0) { - return undefined - } - - const knownThemeDescriptions = hiddenThemes - .filter((theme) => knownThemes.has(theme.id)) - .map((theme) => ({ - element: MoreScreen.createLinkButton(state, theme)?.SetClass( - buttonClass - ), - predicate: MoreScreen.MatchesLayoutFunc(theme), - })) - - const knownLayouts = new FilteredCombine(knownThemeDescriptions, search, { - innerClasses: themeListStyle, - onEmpty: MoreScreen.NothingFound(search), - }) - - return new Combine([ - new Title(t.previouslyHiddenTitle), - t.hiddenExplanation.Subs({ - hidden_discovered: "" + knownThemes.size, - total_hidden: "" + hiddenTotal, - }), - knownLayouts, - ]) - }) - ).SetClass("flex flex-col"), - undefined, - state.osmConnection.isLoggedIn - ) - } private static MatchesLayoutFunc(layout: { id: string @@ -365,70 +249,4 @@ export default class MoreScreen extends Combine { return false } } - - private static createOfficialThemesList( - state: { osmConnection: OsmConnection; locationControl?: UIEventSource }, - buttonClass: string, - themeListStyle: string, - search: UIEventSource - ): BaseUIElement { - let buttons: { element: BaseUIElement; predicate?: (s: string) => boolean }[] = - MoreScreen.officialThemes.map((layout) => { - if (layout === undefined) { - console.trace("Layout is undefined") - return undefined - } - if (layout.hideFromOverview) { - return undefined - } - const button = MoreScreen.createLinkButton(state, layout)?.SetClass(buttonClass) - if (layout.id === personal.id) { - const element = new VariableUiElement( - state.osmConnection.userDetails - .map((userdetails) => userdetails.csCount) - .map((csCount) => { - if (csCount < Constants.userJourney.personalLayoutUnlock) { - return undefined - } else { - return button - } - }) - ) - return { element } - } - - return { element: button, predicate: MoreScreen.MatchesLayoutFunc(layout) } - }) - - const professional = MoreScreen.CreateProffessionalSerivesButton() - const customGeneratorLink = MoreScreen.createCustomGeneratorButton(state) - buttons.splice(0, 0, { element: customGeneratorLink }, { element: professional }) - return new FilteredCombine(buttons, search, { - innerClasses: themeListStyle, - onEmpty: MoreScreen.NothingFound(search), - }) - } - - /* - * Returns either a link to the issue tracker or a link to the custom generator, depending on the achieved number of changesets - * */ - private static createCustomGeneratorButton(state: { - osmConnection: OsmConnection - }): VariableUiElement { - const tr = Translations.t.general.morescreen - return new VariableUiElement( - state.osmConnection.userDetails.map((userDetails) => { - if (userDetails.csCount < Constants.userJourney.themeGeneratorReadOnlyUnlock) { - return new SubtleButton(null, tr.requestATheme.Clone(), { - url: "https://github.com/pietervdvn/MapComplete/issues", - newTab: true, - }) - } - return new SubtleButton(Svg.pencil_ui(), tr.createYourOwnTheme.Clone(), { - url: "https://pietervdvn.github.io/mc/legacy/070/customGenerator.html", - newTab: false, - }) - }) - ) - } } diff --git a/UI/BigComponents/NoThemeResultButton.svelte b/UI/BigComponents/NoThemeResultButton.svelte new file mode 100644 index 0000000000..f9a439c45f --- /dev/null +++ b/UI/BigComponents/NoThemeResultButton.svelte @@ -0,0 +1,65 @@ + + + + + +
{t.noMatchingThemes.toString()}
+ +
+ + diff --git a/UI/BigComponents/ProfessionalServicesButton.svelte b/UI/BigComponents/ProfessionalServicesButton.svelte new file mode 100644 index 0000000000..d0f3bd0e14 --- /dev/null +++ b/UI/BigComponents/ProfessionalServicesButton.svelte @@ -0,0 +1,24 @@ + + +
+ + + {t.hookMore.toString()} + + + {t.button.toString()} + +
+ + diff --git a/UI/BigComponents/ThemeButton.svelte b/UI/BigComponents/ThemeButton.svelte new file mode 100644 index 0000000000..5749036327 --- /dev/null +++ b/UI/BigComponents/ThemeButton.svelte @@ -0,0 +1,110 @@ + + +{#if theme.id !== personal.id || $userDetails.csCount > Constants.userJourney.personalLayoutUnlock} +
+ + + + + {title} + {description} + + + +
+{/if} + + diff --git a/UI/BigComponents/ThemesList.svelte b/UI/BigComponents/ThemesList.svelte new file mode 100644 index 0000000000..5446e49129 --- /dev/null +++ b/UI/BigComponents/ThemesList.svelte @@ -0,0 +1,83 @@ + + + + +
+ +
+ {#if ($search === undefined || $search === "") && !isCustom} + + + {/if} + + {#each filteredThemes as theme} + {#if theme !== undefined && !(hideThemes && theme?.hideFromOverview)} + + {/if} + {/each} +
+ + {#if filteredThemes.length == 0} + + {/if} +
+ + diff --git a/UI/BigComponents/UnofficialThemeList.svelte b/UI/BigComponents/UnofficialThemeList.svelte new file mode 100644 index 0000000000..8775953af6 --- /dev/null +++ b/UI/BigComponents/UnofficialThemeList.svelte @@ -0,0 +1,35 @@ + + + + + + {@html t.customThemeIntro.toString()} + +