forked from MapComplete/MapComplete
Feature: add "recently visited themes" on index page
This commit is contained in:
parent
1723f268c0
commit
4db2c86c0f
5 changed files with 47 additions and 21 deletions
|
@ -616,6 +616,7 @@
|
|||
"intro": "Maps about various topics which you can contribute to",
|
||||
"learnMore": "Learn more",
|
||||
"logIn": "Log in to see other themes you previously visited",
|
||||
"recentThemes": "Recently visited themes",
|
||||
"title": "MapComplete"
|
||||
},
|
||||
"inspector": {
|
||||
|
|
|
@ -1140,10 +1140,6 @@ input[type="range"].range-lg::-moz-range-thumb {
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.\!relative {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
@ -2565,6 +2561,10 @@ input[type="range"].range-lg::-moz-range-thumb {
|
|||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-rows-2 {
|
||||
grid-template-rows: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
@ -8729,6 +8729,10 @@ svg.apply-fill path {
|
|||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.md\:grid-rows-1 {
|
||||
grid-template-rows: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.md\:flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
import { AndroidPolyfill } from "../Logic/Web/AndroidPolyfill"
|
||||
import Forgejo from "../assets/svg/Forgejo.svelte"
|
||||
import Locale from "./i18n/Locale"
|
||||
|
||||
AndroidPolyfill.init().then(() => console.log("Android polyfill setup completed"))
|
||||
const featureSwitches = new OsmConnectionFeatureSwitches()
|
||||
const osmConnection = new OsmConnection({
|
||||
|
@ -35,13 +36,15 @@
|
|||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
),
|
||||
)
|
||||
})
|
||||
const state = new UserRelatedState(osmConnection)
|
||||
const t = Translations.t.index
|
||||
const tu = Translations.t.general
|
||||
const tr = Translations.t.general.morescreen
|
||||
|
||||
const recentThemes = state.recentlyVisitedThemes.value.mapD(themes => themes.map(thId => ThemeSearch.officialThemesById.get(thId)))
|
||||
|
||||
let userLanguages = osmConnection.userDetails.map((ud) => ud?.languages ?? [])
|
||||
let search: UIEventSource<string | undefined> = new UIEventSource<string>("")
|
||||
let searchStable = search.stabilized(100)
|
||||
|
@ -64,6 +67,7 @@
|
|||
const customThemes: Store<MinimalThemeInformation[]> = Stores.ListStabilized<string>(
|
||||
state.installedUserThemes
|
||||
).mapD((stableIds) => Utils.NoNullInplace(stableIds.map((id) => state.getUnofficialTheme(id))))
|
||||
|
||||
function filtered(themes: Store<MinimalThemeInformation[]>): Store<MinimalThemeInformation[]> {
|
||||
const searchIndex = Locale.language.map(language => {
|
||||
return new ThemeSearchIndex(language, themes.data)
|
||||
|
@ -97,7 +101,7 @@
|
|||
let customSearched: Store<MinimalThemeInformation[]> = filtered(customThemes)
|
||||
|
||||
let searchIsFocussed = new UIEventSource(false)
|
||||
document.addEventListener("keydown", function (event) {
|
||||
document.addEventListener("keydown", function(event) {
|
||||
if (event.ctrlKey && event.code === "KeyF") {
|
||||
searchIsFocussed.set(true)
|
||||
event.preventDefault()
|
||||
|
@ -162,6 +166,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<LoginToggle {state}>
|
||||
{#if $recentThemes.length > 2}
|
||||
<div class="my-4">
|
||||
<h2>
|
||||
<Tr t={Translations.t.index.recentThemes} />
|
||||
</h2>
|
||||
<ThemesList {state} themes={$recentThemes} onlyIcons />
|
||||
</div>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
|
||||
<Searchbar
|
||||
value={search}
|
||||
placeholder={tr.searchForATheme}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
||||
import type { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
|
@ -10,7 +9,7 @@
|
|||
export let theme: MinimalThemeInformation & { isOfficial?: boolean }
|
||||
let isCustom: boolean = theme.id.startsWith("https://") || theme.id.startsWith("http://")
|
||||
export let state: { layoutToUse?: { id: string }; osmConnection: OsmConnection }
|
||||
|
||||
export let iconOnly: boolean = false
|
||||
$: title = Translations.T(
|
||||
theme.title,
|
||||
!isCustom && !theme.mustHaveLanguage ? "themes:" + theme.id + ".title" : undefined
|
||||
|
@ -71,12 +70,17 @@
|
|||
)
|
||||
</script>
|
||||
|
||||
<a class="low-interaction my-1 flex w-full items-center text-ellipsis rounded p-1" href={$href}>
|
||||
<Marker icons={theme.icon} size="block h-8 w-8 sm:h-11 sm:w-11 m-1 sm:mx-2 md:mx-4 shrink-0" />
|
||||
|
||||
<span class="flex flex-col overflow-hidden text-ellipsis text-xl font-bold">
|
||||
<Tr cls="" t={title} />
|
||||
<Tr cls="subtle text-base" t={description} />
|
||||
<slot />
|
||||
</span>
|
||||
</a>
|
||||
{#if iconOnly}
|
||||
<a class="low-interaction my-1 rounded p-1" href={$href}>
|
||||
<Marker icons={theme.icon} size="w-8 h-8 sm:w-11 sm:h-11" />
|
||||
</a>
|
||||
{:else}
|
||||
<a class="low-interaction my-1 flex w-full items-center text-ellipsis rounded p-1" href={$href}>
|
||||
<Marker icons={theme.icon} size="block h-8 w-8 sm:h-11 sm:w-11 m-1 sm:mx-2 md:mx-4 shrink-0" />
|
||||
<span class="flex flex-col overflow-hidden text-ellipsis text-xl font-bold">
|
||||
<Tr cls="" t={title} />
|
||||
<Tr cls="subtle text-base" t={description} />
|
||||
<slot />
|
||||
</span>
|
||||
</a>
|
||||
{/if}
|
||||
|
|
|
@ -7,19 +7,21 @@
|
|||
import { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export let search: UIEventSource<string>
|
||||
export let search: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
export let themes: MinimalThemeInformation[]
|
||||
export let state: { osmConnection: OsmConnection }
|
||||
|
||||
export let onlyIcons: boolean = false
|
||||
export let hasSelection: boolean = true
|
||||
</script>
|
||||
|
||||
<section class="w-full">
|
||||
<slot name="title" />
|
||||
<div class="theme-list my-2 gap-4 md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3">
|
||||
<div
|
||||
class={onlyIcons ? "flex gap-x-2 flex-wrap items-center justify-center" : ("theme-list my-2 gap-4 md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3")}>
|
||||
{#each themes as theme (theme.id)}
|
||||
<ThemeButton {theme} {state}>
|
||||
<ThemeButton {theme} {state} iconOnly={onlyIcons}>
|
||||
{#if $search && hasSelection && themes?.[0] === theme}
|
||||
<span class="thanks hidden-on-mobile" aria-hidden="true">
|
||||
<Tr t={Translations.t.general.morescreen.enterToOpen} />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue