Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@
let imageInput: HTMLInputElement;
let images: FileList | null = $state(null);

// blob: URLs only resolve within the browser tab/session that created
// them via URL.createObjectURL — they can't be persisted or viewed later
// (e.g. after the post is saved and reloaded from the profile page), so
// selected files must be read as base64 data URLs instead, matching the
// "Add Photo" flow inside the post composer (post/+page.svelte) and the
// desktop create-post modal (CreatePostModal.svelte).
function readFileAsDataUrl(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
const result = e.target?.result;
if (typeof result === 'string') resolve(result);
else reject(new Error('Failed to read file as data URL'));
};
reader.onerror = () => reject(reader.error ?? new Error('Failed to read file'));
reader.readAsDataURL(file);
});
}

const handleNavClick = (newTab: string) => {
// activeTab = newTab;
isNavigatingThroughNav.value = true;
Expand Down Expand Up @@ -53,14 +72,26 @@
!_activeTab.includes('post/audience')
) {
if (uploadedImages.value) revokeImageUrls(uploadedImages.value);
uploadedImages.value = Array.from(images).map((file) => ({
url: URL.createObjectURL(file),
alt: file.name
}));
const selectedFiles = Array.from(images);
images = null; // To prevent re-triggering the effect and thus making an infinite loop with /post route's effect when the length of uploadedImages goes to 0
if (uploadedImages.value.length > 0) {
goto('/post');
}
(async () => {
try {
uploadedImages.value = await Promise.all(
selectedFiles.map(async (file) => ({
url: await readFileAsDataUrl(file),
alt: file.name,
size: file.size
}))
);
if (uploadedImages.value.length > 0) {
goto('/post');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What does the ESLint rule svelte/no-navigation-without-resolverequire, and how shouldgoto()calls inside Svelte 5$effect blocks be handled?

💡 Result:

The ESLint rule svelte/no-navigation-without-resolve requires that internal navigation operations—specifically HTML tags, and SvelteKit’s goto, pushState, and replaceState functions—be wrapped with the resolve function from $app/paths [1][2]. This ensures that your application correctly respects the base path, preventing broken links or navigation failures in environments where the app is deployed to a sub-path [1][3]. The rule is part of the plugin:svelte/recommended set [1][4]. It evaluates the path argument provided to these functions; if you attempt to use hardcoded paths (e.g., goto('/dashboard')) without the resolve wrapper, the linter will trigger an error [1][5]. Regarding goto calls inside Svelte 5 $effect blocks: The rule itself does not treat $effect blocks differently; it checks if the path argument passed to goto is explicitly wrapped in resolve [1][5]. To handle this correctly: 1. Wrap the path in resolve: Always pass the result of resolve into goto [1]. Example: goto(resolve('/your-path')). 2. Avoid complex string interpolation or concatenation that the linter cannot statically analyze [5][6]. The rule has difficulty tracking complex expressions, so keeping the resolve call as the direct wrapper for the path string is the safest practice [5]. 3. For programmatic external navigation, use window.location instead, as the rule does not apply to it [1][2]. 4. If you have a legitimate case where the rule is flagging code that is already correctly resolved (or complex logic the linter fails to resolve), you can disable the rule for specific lines using an ESLint ignore comment, though you should verify that your path is indeed correctly prefixed with the base path [1]. If your navigation logic involves dynamic search parameters, note that the rule expects the entire path to be resolved. While you can construct complex URLs, the safest pattern is to ensure that the base path prefixing is handled by resolve before or at the moment of navigation [5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file around the reported line
sed -n '1,160p' platforms/pictique/client/src/lib/fragments/BottomNav/BottomNav.svelte

# Find the lint rule and any related config/usages in the repo
rg -n "no-navigation-without-resolve|resolve\\(|goto\\(" platforms/pictique/client/src -g '!**/node_modules/**'

Repository: MetaState-Prototype-Project/prototype

Length of output: 9816


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate ESLint config and any explicit svelte rule settings
git ls-files | rg '(^|/)(eslint|eslint\.config|\.eslintrc|svelte\.config|vite\.config|package\.json)$'

# Search for the rule name and related Svelte lint config in repo files
rg -n "no-navigation-without-resolve|plugin:svelte/recommended|svelte.*recommended|eslint-plugin-svelte|resolve\\(" . \
  -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**'

Repository: MetaState-Prototype-Project/prototype

Length of output: 21429


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' platforms/pictique/client/eslint.config.js
printf '\n---\n'
sed -n '1,220p' packages/ui/eslint.config.js
printf '\n---\n'
sed -n '1,160p' platforms/pictique/client/package.json

Repository: MetaState-Prototype-Project/prototype

Length of output: 4226


🌐 Web query:

Does eslint-plugin-svelteincludesvelte/no-navigation-without-resolveinsvelte.configs.recommended, and what does ignoreLinks: true change?

💡 Result:

Yes, the svelte/no-navigation-without-resolve rule is included in the plugin:svelte/recommended configuration [1][2]. It was added to the recommended rule set in version 3.12.0 of eslint-plugin-svelte [1][3]. Regarding the ignoreLinks: true option: Setting ignoreLinks to true instructs the ESLint rule to ignore <a> tag href attributes during its validation [1][4]. By default, this option is false [1][4], meaning the rule will flag <a> tags that use navigation paths without wrapping them in the SvelteKit resolve() function [1][4]. Setting it to true effectively disables the rule's enforcement on HTML links, which is often used as a workaround if the rule produces false positives or is too restrictive for certain link patterns in a project [5][6][7].

Citations:


Use resolve() for this navigation

platforms/pictique/client/src/lib/fragments/BottomNav/BottomNav.svelte:87 still calls goto('/post') directly. This package enables svelte/no-navigation-without-resolve, so this should be goto(resolve('/post')) (with resolve imported from $app/paths).

🧰 Tools
🪛 ESLint

[error] 87-87: Unexpected goto() call without resolve().

(svelte/no-navigation-without-resolve)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platforms/pictique/client/src/lib/fragments/BottomNav/BottomNav.svelte` at
line 87, The BottomNav navigation still bypasses the required path resolution,
so update the navigation in BottomNav.svelte to use goto(resolve('/post'))
instead of calling goto('/post') directly. Make sure resolve is imported from
$app/paths in the same component, and keep the change scoped to the existing
navigation handler so it satisfies svelte/no-navigation-without-resolve.

}
} catch (error) {
console.error('Failed to read selected images:', error);
uploadedImages.value = null;
alert('Failed to process selected images. Please try again.');
}
})();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
});
</script>
Expand Down
Loading