Removes a tag (by name, matching the tag's full path value) from the
matched assets via DELETE /tags/:id/assets. The tag is looked up
without creating it — removing a tag that doesn't exist is a no-op
rather than an error, so add/remove pairs are safe in the same
workflow.
Registered in the node palette, action node, run-detail view, and
action config (same tag-name field as Add Tag).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Updated albumColumns and AlbumThumbnail components to display placeholder when no thumbnail is available.
- added album_user table (album ownership moved here, role='owner')
- drop asset.deviceId/deviceAssetId and albums.ownerId
- asset.duration varchar -> integer (milliseconds)
- removed isArchived instead use visibility
The /api/assets/albums-by-assets route accepts a POST body shaped
{ assetIds: string[] } and is invoked from the bulk-duplicate-finder
page with every asset across every duplicate group. With a large
duplicate set the body easily exceeds Next.js's default 1 MB
bodyParser limit and the route returns 413 before the handler runs.
Concrete case: a library with ~14,500 duplicate groups produces a
request body around 1.4-1.8 MB, which is rejected. The page renders
but never finishes loading (413 in browser console).
Fix: add the per-route Next.js bodyParser config to bump the limit
to 10 MB, leaving plenty of headroom for very large libraries while
still bounding worst-case request size.
Upstream already shows the selected ring + clickable check badge on each
thumbnail. This adds the missing piece for dense grids: a slight opacity
reduction on non-selected items while a selection is in progress, so the
selected set stays visible at a glance.
Implemented by passing selectionMode={selectable && selectedIds.length > 0}
from AssetGrid to LazyGridImage; LazyGridImage applies opacity-60 to its
container when selectionMode && !photo.isSelected.
- Updated FindInput component to use rc-mentions for better performance and flexibility.
- Removed unused styles related to react-mentions and added new styles for rc-mentions in globals.scss.
- Enhanced search functionality to handle mentions and clear input more effectively.
- Updated FindPage to manage searched queries and loading state.
Today the Analytics heatmap hard-codes "last 12 months" both in the SQL
(`WHERE fileCreatedAt >= CURRENT_DATE - INTERVAL '1 YEAR'`) and in the
frontend's month labels loop. Users with multi-year libraries can't look
back at 2018 or 2020 from this view.
Changes:
- API `/api/analytics/statistics/heatmap` now accepts an optional `year`
query param. With it, the query spans the full calendar year (Jan 1 to
Dec 31) and `fillMissingDates` walks that range. Without it, the legacy
rolling 12-month behaviour is preserved (including the "skip the
repeating current month from last year" seam guard).
- Response shape changed from `[]` to `{ data, year, availableYears }`.
`availableYears` comes from a DISTINCT EXTRACT(YEAR ...) over the user's
assets so the UI can render a correct dropdown without guessing.
- Component shows a Select next to the heatmap: "Last 12 months" (default)
plus one entry per year that actually has assets. Month labels and the
`weeksPerMonth` computation switch accordingly.
- No migrations needed; drizzle query only.
Callers of `getHeatMapData()` now receive an object — there was only one
caller (the heatmap component) so the change is localised.
Two small fixes in PeopleFilters:
1. `handleChange` preserved the current page when any other filter changed.
Symptom: the user is on page 2, types a name in the search box, and the
list shows zero results until they click back to page 1 manually. The new
query returns fewer total people, so page=2 is past the end.
Fix: force page=1 whenever the change doesn't explicitly set `page`.
2. The DropdownMenuTrigger for the sort menu had a leftover
`onClick={() => handleChange({ page: nextPage })}` — looks copy-pasted
from the "next page" button right above it. Opening the sort menu would
silently advance the pagination. Dropped; Radix's DropdownMenuTrigger
opens the popover by itself.
Small-to-medium LLMs (qwen2.5:7b locally, Gemini 2.0 flash in #218) frequently echo the prompt's "Today's date is …" context back as a `takenAfter: <today>` filter even when the user query has no date reference. This silently filters out all results (photos cannot be taken in the future), surfacing as "No results found / Taken After 2026-04-19" in the UI.
Two changes:
1. Tighten the prompt to explicitly say today's date should only be used to resolve relative expressions that actually appear in the query.
2. Guardrail: if the model still returns `takenAfter >= today` (or `takenBefore > today`), drop it. This is narrow and defensible — a future date literally cannot match any asset, so removing it never loses a valid match. No locale-specific regex, no guessing intent; just reject provably invalid filters.
Repro with qwen2.5:7b via Ollama OpenAI-compat endpoint, exact prompt that parseFindQuery produces today:
Input: "beach"
Output: {"query":"beach","takenAfter":"2026-04-19"}
With this patch the stale `takenAfter` is dropped before hitting Immich.
Ref: #218 (same symptom reported with Gemini)
The /api/find/search handler was hard-coding `Authorization: Bearer ${currentUser?.accessToken}`. When Power Tools authenticates via `IMMICH_API_KEY` (no cookie session), `accessToken` is undefined and Immich returns 401 — which surfaces in the UI as "No results found", making the feature silently unusable in API-key deployments.
This swaps the inline header construction for the existing `getUserHeaders()` helper in `src/helpers/user.helper.ts`, which already handles both modes: `x-api-key` when `isUsingAPIKey`, `Authorization: Bearer …` otherwise.
Also adds an explicit 403 when there's no authenticated user, instead of letting the request flow forward with `Bearer undefined`.
Repro (before):
curl -X POST http://localhost:8001/api/find/search -d '{"query":"beach"}' \
→ {"assets":[],"filters":{…},"error":"Failed to fetch assets"}
After:
same request → 40 assets with embeddings matching "beach"
This updates the container image to the official immich-power-tools repository; no other configuration changes were made.
Updated from previous (now deprecated) image references. Some files were still referencing the old image instance ´ghcr.io/varun-raj/immich-power-tools:latest´, updated them to ´ghcr.io/immich-power-tools/immich-power-tools:latest´ across the project (README.md, docker-compose.yml, and docker-compose-all-immich.yml).
- Show full condition details on IF/Switch nodes with person thumbnails
- Show album name and tag on action nodes
- Add dark mode support for React Flow controls via colorMode
- Center images in lightbox preview
- Fix leaflet marker icons for both Webpack and Turbopack bundlers
- Add import_api_key setting with auto-generate endpoint and settings UI
- Import job runner uses import API key when available, falls back to session
- Show ApiKeyGate empty state in both workflow and import pages when key missing
- Replace workflow API key warning popover with full gate overlay
- Redesign person cards: square avatar, hover action toolbar, cleaner layout
- Birthday field now uses popover with calendar + natural language input
- Fix autocomplete dropdown clipping inside overflow-hidden cards via portal
- People grid column slider persisted to localStorage (min 3, max 20)
Add delete with confirm dialog to asset lightbox (always visible, handles
deletion internally with local state update). Force dark theme on asset
info panel and fix text color inheritance. Add edge-to-edge image display
in lightbox by removing slide padding. Show open-in-immich link on hover
only. Add workflow page title breadcrumb. Add one-click workflow API key
generation that creates the key in Immich and saves it automatically.
Add beta badge to Workflows in the sidebar. Include settings page
improvements, workflow detail updates, profile info and sidebar
nav refinements, and validate-api-key endpoint.
- Implemented Nextcloud shared link detection and processing in the import workflow.
- Created a new processor for handling Nextcloud shared links, including asset downloading and uploading to Immich.
- Enhanced existing import functionality to support platform differentiation between Immich and Nextcloud.
- Added utility functions for parsing file names and guessing content types.
- Updated thumbnail and video endpoints to accommodate Nextcloud's API structure.
- Modified the import shared page to handle Nextcloud URLs and passwords.
- Refactored asset upload logic to streamline the process for both platforms.
Redesign import-shared with sticky import bar, dense gallery grid,
progress bar, and cleaner landing state. Add password-protected
shared link support - detects 401 "Password required" from Immich
and shows a password input. Also reduce asset grid spacing and
replace "Open in Immich" text with a link icon.
Reorganize the exif analytics page into labeled sections (Camera & Gear,
Location, Technical, Storage) with icon headers. Replace donut charts
with horizontal bar charts for multi-category EXIF distributions.
Improve heatmap with emerald color scale, day labels, and legend.
Add polished stat cards with icons and skeleton loading states.