Skip to content

Add query string integration for the search - #4628

Open
ildyria wants to merge 1 commit into
masterfrom
search-improvements
Open

Add query string integration for the search#4628
ildyria wants to merge 1 commit into
masterfrom
search-improvements

Conversation

@ildyria

@ildyria ildyria commented Aug 16, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Search terms now stay synchronized with the page URL.
    • Bookmarked search links automatically restore and run the saved search.
    • Returning from a photo preserves the active search query.
    • Search URLs update when searches are performed and remove the query when cleared.
    • Empty searches no longer add unnecessary URL parameters.

@ildyria
ildyria requested a review from a team as a code owner August 16, 2026 21:01
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The v7 and v8 search views now synchronize search state with the q URL parameter. Bookmarked searches execute after loading, clearing removes q, and photo navigation preserves the search term.

Changes

Search route synchronization

Layer / File(s) Summary
Gallery search URL synchronization
resources/js/v7/views/gallery-panels/Search.vue, resources/js/v8/views/gallery-panels/Search.vue
Both search views preload q, update it on search, remove it on clear, preserve it during photo navigation, and execute bookmarked searches.
Search-aware photo route construction
resources/js/composables/photo/photoRoute.ts
Search-photo routes include the current non-empty search term as q.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🟡 Moderate · up to bfcaa

The search URL integration can leave users seeing stale results or lose the active query when changing album scope, and mounted searches may not update when the URL changes. These are concrete correctness issues that should be fixed before merging.

Poem

I’m a rabbit with a query to spare,
q hops through routes with care.
Search, clear, bookmark, and return,
Each path remembers what you learn.
Carrots cheer the synced search flow! 🐇

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 02ca59e5-9369-4ab4-b96c-9b2a122b19a4

📥 Commits

Reviewing files that changed from the base of the PR and between 9f5efec and bfcaac7.

📒 Files selected for processing (3)
  • resources/js/composables/photo/photoRoute.ts
  • resources/js/v7/views/gallery-panels/Search.vue
  • resources/js/v8/views/gallery-panels/Search.vue

Included review availability: Your plan includes up to 8 reviews per rolling hour; 7 remain after this review.

Comment on lines +218 to +220
function onClear() {
searchStore.clear();
searchStore.searchTerm = undefined;

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.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Invalidate pending searches before clearing in both search views.

Both handlers clear local state without invalidating an active SearchState.search() request. A late response can restore results after q and searchTerm were removed.

  • resources/js/v7/views/gallery-panels/Search.vue#L218-L220: invalidate or cancel the active request before clearing.
  • resources/js/v8/views/gallery-panels/Search.vue#L218-L220: apply the same request invalidation.
📍 Affects 2 files
  • resources/js/v7/views/gallery-panels/Search.vue#L218-L220 (this comment)
  • resources/js/v8/views/gallery-panels/Search.vue#L218-L220

Comment on lines +562 to +566
if (typeof route.query.q === "string" && route.query.q.length > 0) {
// Bookmarked/shared URL: run the search that the query string encodes.
onSearch(route.query.q);
}

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

for file in resources/js/v7/views/gallery-panels/Search.vue resources/js/v8/views/gallery-panels/Search.vue; do
  echo "===== $file: outline and relevant symbols ====="
  ast-grep outline "$file" 2>/dev/null | sed -n '1,220p'
  echo "===== $file: route/search lifecycle references ====="
  rg -n -C 8 'route\.query|useRoute|onMounted|watch|onSearch|clear|searchTerm|router\.' "$file"
done

Repository: LycheeOrg/Lychee

Length of output: 20041


🏁 Script executed:

#!/bin/bash
set -eu

echo "===== Search.vue watcher tails ====="
for file in resources/js/v7/views/gallery-panels/Search.vue resources/js/v8/views/gallery-panels/Search.vue; do
  echo "--- $file ---"
  sed -n '580,700p' "$file"
done

echo "===== SearchState store ====="
search_state=$(fd -i -t f 'SearchState' . | head -n 1)
printf '%s\n' "$search_state"
sed -n '1,280p' "$search_state"

echo "===== search route definitions and query navigation ====="
rg -n -C 10 'name:\s*["'\'']search["'\'']|path:.*search|query:\s*\{[^}]*q|query\.q' resources/js routes tests 2>/dev/null | sed -n '1,320p'

echo "===== Search view tests/references ====="
rg -n -C 8 'gallery-panels/Search|query.*q|SearchState|onClear|clearScope' tests resources/js --glob '*.{ts,tsx,js,jsx,vue}' 2>/dev/null | sed -n '1,360p'

Repository: LycheeOrg/Lychee

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
from pathlib import Path
import re

files = [
    Path("resources/js/v7/views/gallery-panels/Search.vue"),
    Path("resources/js/v8/views/gallery-panels/Search.vue"),
]
route_file = Path("resources/js/router/paths.ts")

route_text = route_file.read_text()
route_match = re.search(
    r'name:\s*"search",\s*\n\s*path:\s*"([^"]+)",\s*\n\s*props:\s*true',
    route_text,
)
assert route_match, "search route definition not found"
print(f"search route: name=search path={route_match.group(1)} props=true")

for path in files:
    text = path.read_text()
    mounted = re.search(
        r'onMounted\(async \(\) => \{(?P<body>.*?)\n\}\);',
        text,
        re.S,
    )
    assert mounted, f"{path}: onMounted block not found"
    body = mounted.group("body")

    q_mount_calls_search = bool(
        re.search(
            r'if\s*\(\s*typeof route\.query\.q === "string"'
            r'.*?onSearch\(route\.query\.q\)',
            body,
            re.S,
        )
    )
    q_watchers = re.findall(
        r'watch\s*\(\s*\(\)\s*=>\s*route\.query\.q',
        text,
    )
    query_read_count = len(re.findall(r'route\.query\.q', text))
    param_watchers = re.findall(
        r'watch\s*\(\s*\(\)\s*=>\s*route\.params\.[A-Za-z0-9_]+',
        text,
    )

    assert q_mount_calls_search, f"{path}: mount-time q search was not found"
    assert not q_watchers, f"{path}: unexpected q watcher found"
    print(
        f"{path}: mount_q_search=True, q_watchers={len(q_watchers)}, "
        f"route_query_q_reads={query_read_count}, param_watchers={param_watchers}"
    )

# Model the relevant lifecycle transition without importing repository code:
# the same named route/path keeps the mounted Search component, so only
# onMounted and the existing param watcher can react to a query-only change.
states = [
    ("mounted", "q=alpha", "onMounted runs and calls onSearch(alpha)"),
    ("same Search route", "q=beta", "no onMounted call and no q watcher"),
    ("same Search route", "q absent", "no onMounted call and no q watcher"),
]
print("query-only transition model:")
for state in states:
    print(f"  {state[0]}: {state[1]} -> {state[2]}")
PY

Repository: LycheeOrg/Lychee

Length of output: 776


Synchronize q after mount in both search views.

When route.query.q changes on the mounted search route, neither view starts the new search or clears stale results. Add a watcher in both files that searches for a non-empty q and clears the store when q is absent or empty.

📍 Affects 2 files
  • resources/js/v7/views/gallery-panels/Search.vue#L562-L566 (this comment)
  • resources/js/v8/views/gallery-panels/Search.vue#L575-L578

Comment on lines +213 to +215
if (route.query.q !== terms) {
router.replace({ query: { ...route.query, q: terms } });
}

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '205,276p' resources/js/v8/views/gallery-panels/Search.vue

Repository: LycheeOrg/Lychee

Length of output: 2591


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- Search.vue route/search references ---'
rg -n -C 5 'clearScope|onSearch|searchTerm|router\.replace|name:\s*"search"' resources/js/v8/views/gallery-panels/Search.vue

printf '%s\n' '--- Search route definitions and navigation helpers ---'
rg -n -C 4 'name:\s*["'\"']search|path:.*search|albumId.*photoId|usePhotoRoute' resources/js resources -g '*.ts' -g '*.js' -g '*.vue' | head -240

printf '%s\n' '--- Search store implementation and usages ---'
rg -n -C 5 'searchTerm|function search|search\(' resources/js/v8 -g '*.ts' -g '*.vue' | head -300

Repository: LycheeOrg/Lychee

Length of output: 34191


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- Candidate router files ---'
fd -t f -e ts -e js resources/js | rg -i 'router|route'

printf '%s\n' '--- SearchState implementation ---'
fd -t f resources/js | rg 'SearchState'
for f in $(fd -t f resources/js | rg 'SearchState'); do
	echo "--- $f ---"
	wc -l "$f"
	ast-grep outline "$f"
done

printf '%s\n' '--- SearchState source ---'
f="$(fd -t f resources/js | rg 'SearchState' | head -n 1)"
sed -n '1,260p' "$f"

printf '%s\n' '--- Router construction and search route ---'
for f in $(fd -t f -e ts -e js resources/js | rg -i 'router|route'); do
	rg -n -C 5 'createRouter|createWebHistory|name:\s*["'\"']search|path:.*search' "$f" || true
done

Repository: LycheeOrg/Lychee

Length of output: 539


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- Candidate router files ---'
fd -t f -e ts -e js . resources/js | rg -i 'router|route' || true

printf '%s\n' '--- SearchState files ---'
fd -t f . resources/js | rg 'SearchState' || true

printf '%s\n' '--- Router and SearchState references ---'
rg -n -C 5 'createRouter|createWebHistory|name:\s*["'\"']search|path:.*search|searchTerm|function search' resources/js -g '*.ts' -g '*.js' | head -400

Repository: LycheeOrg/Lychee

Length of output: 8426


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- SearchState actions ---'
sed -n '1,125p' resources/js/stores/SearchState.ts

printf '%s\n' '--- v8 route assembly ---'
sed -n '1,180p' resources/js/v8/router/routes.ts
sed -n '1,115p' resources/js/router/paths.ts

printf '%s\n' '--- Vue Router dependency versions ---'
rg -n '"vue-router"|"vue":' package.json package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null | head -40 || true

printf '%s\n' '--- All clearScope implementations ---'
rg -n -C 12 'function clearScope|clear-scope' resources/js/v8 resources/js/composables

Repository: LycheeOrg/Lychee

Length of output: 21862


Preserve q when clearing the album scope. clearScope() starts a q-less router.replace() and then calls onSearch() synchronously. When route.query.q already equals terms, onSearch() skips its replacement, so the navigation can remove q. Chain the navigation with .then(), or include q in the same navigation while preserving other query parameters.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant