diff --git a/web/src/lib/components/base/meta_tags.svelte b/web/src/lib/components/base/meta_tags.svelte
index 308eaede..a95711a7 100644
--- a/web/src/lib/components/base/meta_tags.svelte
+++ b/web/src/lib/components/base/meta_tags.svelte
@@ -210,8 +210,10 @@
: title,
);
- let robotsParams = $state("");
- if (additionalRobotsProps) {
+ let robotsParams = $derived.by(() => {
+ if (!additionalRobotsProps) {
+ return "";
+ }
const {
nosnippet,
maxSnippet,
@@ -223,12 +225,12 @@
unavailableAfter,
} = additionalRobotsProps;
- robotsParams = `${nosnippet ? ",nosnippet" : ""}${maxSnippet ? `,max-snippet:${maxSnippet}` : ""}${
+ return `${nosnippet ? ",nosnippet" : ""}${maxSnippet ? `,max-snippet:${maxSnippet}` : ""}${
maxImagePreview ? `,max-image-preview:${maxImagePreview}` : ""
}${noarchive ? ",noarchive" : ""}${unavailableAfter ? `,unavailable_after:${unavailableAfter}` : ""}${
noimageindex ? ",noimageindex" : ""
}${maxVideoPreview ? `,max-video-preview:${maxVideoPreview}` : ""}${notranslate ? ",notranslate" : ""}`;
- }
+ });
$effect(() => {
if (!robots && additionalRobotsProps) {
diff --git a/web/src/lib/components/comment/comment_card.svelte b/web/src/lib/components/comment/comment_card.svelte
index 5696d373..12f289ae 100644
--- a/web/src/lib/components/comment/comment_card.svelte
+++ b/web/src/lib/components/comment/comment_card.svelte
@@ -2,8 +2,8 @@
import type { Comment } from "$lib/models/comment";
import { formatTimeSince } from "$lib/util/format_util";
import { _ } from "svelte-i18n";
+ import { untrack } from "svelte";
import { fade } from "svelte/transition";
- import TextField from "../base/text_field.svelte";
import { handleFromRecordWithIRI } from "$lib/util/activitypub_util";
import Editor from "../base/editor.svelte";
@@ -18,7 +18,7 @@
let editing: boolean = $state(false);
- let editedComment = $state(comment.text);
+ let editedComment = $state(untrack(() => comment.text));
$effect(() => {
editedComment = comment.text;
diff --git a/web/src/lib/components/map/style_switcher.svelte b/web/src/lib/components/map/style_switcher.svelte
index 6078cc9e..9f6f7baa 100644
--- a/web/src/lib/components/map/style_switcher.svelte
+++ b/web/src/lib/components/map/style_switcher.svelte
@@ -3,6 +3,7 @@
import { _ } from "svelte-i18n";
import RadioGroup, { type RadioItem } from "../base/radio_group.svelte";
import { defaultMapState } from "$lib/vendor/maplibre-layer-manager/layers";
+ import { untrack } from "svelte";
interface Props {
settings: StyleSwitcherControlOptions;
@@ -10,7 +11,7 @@
let { settings }: Props = $props();
- let mapState = $state(settings.state);
+ let mapState = $state(untrack(() => settings.state));
let container: HTMLDivElement;
diff --git a/web/src/lib/components/notification/notification_card.svelte b/web/src/lib/components/notification/notification_card.svelte
index 989a3768..c4a4bacc 100644
--- a/web/src/lib/components/notification/notification_card.svelte
+++ b/web/src/lib/components/notification/notification_card.svelte
@@ -4,6 +4,7 @@
type Notification,
} from "$lib/models/notification";
import { formatTimeSince } from "$lib/util/format_util";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
interface Props {
@@ -16,11 +17,15 @@
let { notification, onclick }: Props = $props();
- const avatarSrc = notification.expand?.author.icon
- ? notification.expand.author.icon
- : `https://api.dicebear.com/7.x/initials/svg?seed=${notification.expand?.author.preferred_username ?? ""}&backgroundType=gradientLinear`;
+ const avatarSrc = untrack(() =>
+ notification.expand?.author.icon
+ ? notification.expand.author.icon
+ : `https://api.dicebear.com/7.x/initials/svg?seed=${notification.expand?.author.preferred_username ?? ""}&backgroundType=gradientLinear`,
+ );
- const timeSince = formatTimeSince(new Date(notification.created ?? ""));
+ const timeSince = untrack(() =>
+ formatTimeSince(new Date(notification.created ?? "")),
+ );
function getTitle(n: Notification) {
switch (n.type) {
diff --git a/web/src/lib/components/settings/email_modal.svelte b/web/src/lib/components/settings/email_modal.svelte
index ec503ce0..3c9be737 100644
--- a/web/src/lib/components/settings/email_modal.svelte
+++ b/web/src/lib/components/settings/email_modal.svelte
@@ -2,6 +2,7 @@
import Modal from "$lib/components/base/modal.svelte";
import { validator } from "@felte/validator-zod";
import { createForm } from "felte";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
import { z } from "zod";
import TextField from "../base/text_field.svelte";
@@ -24,7 +25,7 @@
const { form, errors, setFields, setErrors } = createForm<{
email: string;
}>({
- initialValues: { email: email },
+ initialValues: { email: untrack(() => email) },
extend: validator({
schema: z.object({
email: z
diff --git a/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte b/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte
index d857b2b0..29aa150f 100644
--- a/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte
+++ b/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte
@@ -36,19 +36,21 @@
modal.openModal();
}
+ const getInitialFormValues = () => ({
+ email: integration?.komoot?.email ?? "",
+ password: integration?.komoot?.password ?? "",
+ completed: integration?.komoot?.completed ?? true,
+ planned: integration?.komoot?.planned ?? true,
+ active: integration?.komoot?.active ?? false,
+ privacy: integration?.komoot?.privacy ?? "original",
+ });
+
const {
form,
errors,
data: d,
} = createForm({
- initialValues: {
- email: integration?.komoot?.email ?? "",
- password: integration?.komoot?.password ?? "",
- completed: integration?.komoot?.completed ?? true,
- planned: integration?.komoot?.planned ?? true,
- active: integration?.komoot?.active ?? false,
- privacy: integration?.komoot?.privacy ?? "original",
- },
+ initialValues: getInitialFormValues(),
extend: validator({
schema: KomootSchema,
}),
diff --git a/web/src/lib/components/settings/integrations/strava_settings_modal.svelte b/web/src/lib/components/settings/integrations/strava_settings_modal.svelte
index b7ce0381..a5afec83 100644
--- a/web/src/lib/components/settings/integrations/strava_settings_modal.svelte
+++ b/web/src/lib/components/settings/integrations/strava_settings_modal.svelte
@@ -36,20 +36,22 @@
modal.openModal();
}
+ const getInitialFormValues = () => ({
+ clientId: integration?.strava?.clientId ?? "",
+ clientSecret: integration?.strava?.clientSecret ?? "",
+ routes: integration?.strava?.routes ?? true,
+ activities: integration?.strava?.activities ?? true,
+ active: integration?.strava?.active ?? false,
+ after: integration?.strava?.after,
+ privacy: integration?.komoot?.privacy ?? "original",
+ });
+
const {
form,
errors,
data: formData,
} = createForm({
- initialValues: {
- clientId: integration?.strava?.clientId ?? "",
- clientSecret: integration?.strava?.clientSecret ?? "",
- routes: integration?.strava?.routes ?? true,
- activities: integration?.strava?.activities ?? true,
- active: integration?.strava?.active ?? false,
- after: integration?.strava?.after,
- privacy: integration?.komoot?.privacy ?? "original",
- },
+ initialValues: getInitialFormValues(),
extend: validator({
schema: StravaSchema,
}),
diff --git a/web/src/lib/components/share_info.svelte b/web/src/lib/components/share_info.svelte
index c3f0bb91..34161de9 100644
--- a/web/src/lib/components/share_info.svelte
+++ b/web/src/lib/components/share_info.svelte
@@ -1,11 +1,8 @@
diff --git a/web/src/lib/components/trail/like_button.svelte b/web/src/lib/components/trail/like_button.svelte
index 7eda5b49..368c7207 100644
--- a/web/src/lib/components/trail/like_button.svelte
+++ b/web/src/lib/components/trail/like_button.svelte
@@ -8,6 +8,7 @@
} from "$lib/stores/trail_like_store";
import { currentUser } from "$lib/stores/user_store";
import confetti from "canvas-confetti";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
interface Props {
@@ -18,7 +19,7 @@
let { trail }: Props = $props();
- let likeCount = $state(trail.like_count);
+ let likeCount = $state(untrack(() => trail.like_count));
let loading = $state(false);
@@ -66,8 +67,10 @@
}
let trailLike = $state(
- trail.expand?.trail_like_via_trail?.find(
- (l) => l.actor === $currentUser?.actor,
+ untrack(() =>
+ trail.expand?.trail_like_via_trail?.find(
+ (l) => l.actor === $currentUser?.actor,
+ ),
),
);
diff --git a/web/src/lib/components/trail/photo_picker.svelte b/web/src/lib/components/trail/photo_picker.svelte
index 7920fb3b..ab386333 100644
--- a/web/src/lib/components/trail/photo_picker.svelte
+++ b/web/src/lib/components/trail/photo_picker.svelte
@@ -141,6 +141,7 @@
? 'outline-dashed outline-input-border'
: ''}"
role="dialog"
+ tabindex="0"
ondragover={handlePhotoDragOver}
ondragleave={handlePhotoDragLeave}
ondrop={handlePhotoDrop}
diff --git a/web/src/lib/components/trail/trail_info_panel.svelte b/web/src/lib/components/trail/trail_info_panel.svelte
index d674441b..19a076e7 100644
--- a/web/src/lib/components/trail/trail_info_panel.svelte
+++ b/web/src/lib/components/trail/trail_info_panel.svelte
@@ -27,12 +27,11 @@
import { show_toast } from "$lib/stores/toast_store.svelte";
import * as M from "maplibre-gl";
import "photoswipe/style.css";
- import { onMount } from "svelte";
+ import { onMount, untrack } from "svelte";
import { _ } from "svelte-i18n";
import Button from "../base/button.svelte";
import Chip from "../base/chip.svelte";
import SkeletonNotificationCard from "../base/skeleton_notification_card.svelte";
- import Textarea from "../base/textarea.svelte";
import CommentCard from "../comment/comment_card.svelte";
import EmptyStateComment from "../empty_states/empty_state_comment.svelte";
import EmptyStateDescription from "../empty_states/empty_state_description.svelte";
@@ -77,7 +76,7 @@
let summitLogModal: SummitLogModal;
let confirmModal: ConfirmModal;
- let trail = $state(initTrail);
+ let trail = $state(untrack(() => initTrail));
const tabs = [
$_("summit-book"),
@@ -93,14 +92,14 @@
let newComment: Comment = $state({
text: "",
author: "",
- trail: handle + "/" + (trail.id ?? ""),
+ trail: untrack(() => handle) + "/" + (trail.id ?? ""),
});
- let commentsLoading: boolean = $state(activeTab == 2);
+ let commentsLoading: boolean = $state(untrack(() => activeTab == 2));
let commentCreateLoading: boolean = $state(false);
let commentDeleteLoading: boolean = false;
- let summitLogsLoading: boolean = $state(activeTab == 0);
+ let summitLogsLoading: boolean = $state(untrack(() => activeTab == 0));
let summitLogCreateLoading: boolean = $state(false);
let fullDescription: boolean = $state(false);
diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte
index 16ca6821..baea3a50 100644
--- a/web/src/routes/+page.svelte
+++ b/web/src/routes/+page.svelte
@@ -25,14 +25,14 @@
import { getIconForLocation } from "$lib/util/icon_util.js";
import { Canvas } from "@threlte/core";
import { marked } from "marked";
- import { onMount } from "svelte";
+ import { onMount, untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
let searchDropdownItems: SearchItem[] = $state([]);
- let feed = $state(data.feed);
+ let feed = $state(untrack(() => data.feed));
let pagination = $derived({
page: feed.page,
diff --git a/web/src/routes/lists/[[handle]]/[[id]]/+page.svelte b/web/src/routes/lists/[[handle]]/[[id]]/+page.svelte
index 0058867c..3ef94a33 100644
--- a/web/src/routes/lists/[[handle]]/[[id]]/+page.svelte
+++ b/web/src/routes/lists/[[handle]]/[[id]]/+page.svelte
@@ -28,7 +28,7 @@
import { handleFromRecordWithIRI } from "$lib/util/activitypub_util.js";
import * as M from "maplibre-gl";
- import { onMount } from "svelte";
+ import { onMount, untrack } from "svelte";
import { _ } from "svelte-i18n";
import { slide } from "svelte/transition";
@@ -41,10 +41,10 @@
const pagination: { page: number; totalPages: number } = $state({
page: 1,
- totalPages: data.lists.totalPages,
+ totalPages: untrack(() => data.lists.totalPages),
});
- let lists: List[] = $state(data.lists.items);
+ let lists: List[] = $state(untrack(() => data.lists.items));
let confirmModal: ConfirmModal | undefined = $state();
let listShareModal: ListShareModal | undefined = $state();
@@ -56,7 +56,9 @@
let markers: M.Marker[] = $state([]);
let selectedList: List | null = $state(
- page.params.handle && page.params.id ? data.lists.items[0] : null,
+ untrack(() =>
+ page.params.handle && page.params.id ? data.lists.items[0] : null,
+ ),
);
let selectedTrail: Trail | null = $state(null);
diff --git a/web/src/routes/lists/edit/[id]/+page.svelte b/web/src/routes/lists/edit/[id]/+page.svelte
index dfce62b3..f7f2c041 100644
--- a/web/src/routes/lists/edit/[id]/+page.svelte
+++ b/web/src/routes/lists/edit/[id]/+page.svelte
@@ -37,11 +37,11 @@
import { validator } from "@felte/validator-zod";
import { createForm } from "felte";
import { z } from "zod";
- import { onMount } from "svelte";
+ import { onMount, untrack } from "svelte";
let { data } = $props();
- let previewURL = $state(data.previewUrl ?? "");
+ let previewURL = $state(untrack(() => data.previewUrl ?? ""));
let searchDropdownItems: SearchItem[] = $state([]);
let activeTrailIndex: number = $state(-1);
@@ -76,17 +76,19 @@
.optional(),
});
+ const getInitialFormValues = () => ({
+ ...data.list,
+ public: data.list.id
+ ? data.list.public
+ : page.data.settings?.privacy?.lists === "public",
+ });
+
const {
form,
errors,
data: formData,
} = createForm>({
- initialValues: {
- ...data.list,
- public: data.list.id
- ? data.list.public
- : page.data.settings?.privacy?.lists === "public",
- },
+ initialValues: getInitialFormValues(),
extend: validator({
schema: ClientListCreateSchema,
}),
diff --git a/web/src/routes/login/+page.svelte b/web/src/routes/login/+page.svelte
index cad19cc7..9e80874c 100644
--- a/web/src/routes/login/+page.svelte
+++ b/web/src/routes/login/+page.svelte
@@ -21,7 +21,9 @@
let { data: pageData }: PageProps = $props();
- const authProviders = pageData.authMethods.oauth2.providers;
+ const authProviders = $derived.by(
+ () => pageData.authMethods.oauth2.providers,
+ );
const { form, errors, data } = createForm({
initialValues: {
diff --git a/web/src/routes/map/trail/[handle]/[id]/+page.svelte b/web/src/routes/map/trail/[handle]/[id]/+page.svelte
index 59a26da8..868581d6 100644
--- a/web/src/routes/map/trail/[handle]/[id]/+page.svelte
+++ b/web/src/routes/map/trail/[handle]/[id]/+page.svelte
@@ -6,11 +6,12 @@
import { getFileURL } from "$lib/util/file_util.js";
import * as M from "maplibre-gl";
import "photoswipe/style.css";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
- const trail = $state(data.trail);
+ const trail = $state(untrack(() => data.trail));
let markers: M.Marker[] = $state([]);
diff --git a/web/src/routes/profile/[handle]/+page.svelte b/web/src/routes/profile/[handle]/+page.svelte
index 8919755a..8b7cc3ae 100644
--- a/web/src/routes/profile/[handle]/+page.svelte
+++ b/web/src/routes/profile/[handle]/+page.svelte
@@ -9,6 +9,7 @@
import { profile_feed_index } from "$lib/stores/profile_store.js";
import { theme } from "$lib/stores/theme_store.js";
import { getFileURL } from "$lib/util/file_util.js";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
@@ -18,7 +19,7 @@
feed = data.feed
})
- let feed = $state(data.feed);
+ let feed = $state(untrack(() => data.feed));
let loading: boolean = false;
diff --git a/web/src/routes/profile/[handle]/stats/+page.svelte b/web/src/routes/profile/[handle]/stats/+page.svelte
index 88c32319..57cdebf8 100644
--- a/web/src/routes/profile/[handle]/stats/+page.svelte
+++ b/web/src/routes/profile/[handle]/stats/+page.svelte
@@ -29,6 +29,7 @@
Title,
Tooltip,
} from "chart.js";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
@@ -43,9 +44,9 @@
BarElement,
);
- let summitLogs: SummitLog[] = $state(data.logs);
+ let summitLogs: SummitLog[] = $state(untrack(() => data.logs));
- const filter = $state(data.filter);
+ const filter = $state(untrack(() => data.filter));
const categorySelectItems: SelectItem[] = $categories.map((c) => ({
value: c.id,
diff --git a/web/src/routes/profile/[handle]/trails/+page.svelte b/web/src/routes/profile/[handle]/trails/+page.svelte
index 602c1127..66e9b4f0 100644
--- a/web/src/routes/profile/[handle]/trails/+page.svelte
+++ b/web/src/routes/profile/[handle]/trails/+page.svelte
@@ -4,6 +4,7 @@
import type { TrailFilter } from "$lib/models/trail.js";
import { profile_trails_index } from "$lib/stores/profile_store.js";
import { show_toast } from "$lib/stores/toast_store.svelte.js";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
@@ -11,14 +12,14 @@
let loading = $state(true);
let pagination = $state({
- page: data.trails.page,
- totalPages: data.trails.totalPages,
+ page: untrack(() => data.trails.page),
+ totalPages: untrack(() => data.trails.totalPages),
items: 12,
});
- let trails = $state(data.trails);
+ let trails = $state(untrack(() => data.trails));
- let filter: TrailFilter = $state(data.filter);
+ let filter: TrailFilter = $state(untrack(() => data.filter));
async function handleFilterUpdate() {
loading = true;
diff --git a/web/src/routes/profile/[handle]/users/[type]/+page.svelte b/web/src/routes/profile/[handle]/users/[type]/+page.svelte
index ec5a931c..1b483d9c 100644
--- a/web/src/routes/profile/[handle]/users/[type]/+page.svelte
+++ b/web/src/routes/profile/[handle]/users/[type]/+page.svelte
@@ -3,10 +3,11 @@
import { follows_index } from "$lib/stores/follow_store.js";
import { show_toast } from "$lib/stores/toast_store.svelte.js";
import { APIError } from "$lib/util/api_util.js";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
- let follows = $state(data.follows);
+ let follows = $state(untrack(() => data.follows));
$effect(() => {
page.params.type;
diff --git a/web/src/routes/settings/integrations/+page.svelte b/web/src/routes/settings/integrations/+page.svelte
index 0f33ac1c..6a7bb830 100644
--- a/web/src/routes/settings/integrations/+page.svelte
+++ b/web/src/routes/settings/integrations/+page.svelte
@@ -13,11 +13,12 @@
integrations_update,
} from "$lib/stores/integration_store.js";
import { show_toast } from "$lib/stores/toast_store.svelte.js";
+ import { untrack } from "svelte";
import { _ } from "svelte-i18n";
let { data } = $props();
- let integration = $state(data.integration);
+ let integration = $state(untrack(() => data.integration));
const scope = "read_all,activity:read_all";
const redirectUri = page.url.href + "/callback/strava";
@@ -29,7 +30,7 @@
let komootSettingsModal: KomootSettingsModal;
let komootToggleValue: boolean = $state(
- data.integration?.komoot?.active ?? false,
+ untrack(() => data.integration?.komoot?.active ?? false),
);
async function onSettingsSave(
diff --git a/web/src/routes/settings/profile/+page.svelte b/web/src/routes/settings/profile/+page.svelte
index 90c70767..c6a7549e 100644
--- a/web/src/routes/settings/profile/+page.svelte
+++ b/web/src/routes/settings/profile/+page.svelte
@@ -1,31 +1,32 @@