Commit Graph

162 Commits

Author SHA1 Message Date
Claude 75ee9b7cc4 feat(photos): justified (aspect-preserving) layout option
Adds a Grid/Justified toggle to the photos toolbar. Justified mode packs
tiles into Flickr-style rows scaled to the container width using each
photo's real aspect ratio (from the new /api/photos width/height, falling
back to 1:1 when missing). It composes with the virtualized renderer:
per-group materialization and the off-screen spacer height estimates are
both layout-aware. The choice persists in localStorage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JW6ghFMDtnRYuYNzZhb47M
2026-06-19 10:21:00 +00:00
Claude 824df4d421 feat(photos): keyboard a11y + shift-click range selection
- Tiles are focusable (tabindex / role=button / aria-label) with a
  :focus-visible ring; Enter opens the lightbox (or toggles in selection
  mode), Space toggles selection.
- Shift-click extends the selection from the last anchor across the
  timeline; the range is tracked in the selection Set so it spans
  dematerialized (off-screen) groups, with visible tiles updated at once.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JW6ghFMDtnRYuYNzZhb47M
2026-06-19 10:01:19 +00:00
Claude 081b2b68d8 perf(photos): virtualize the timeline to bound DOM node count
The photos timeline rendered every tile into the DOM and grew it
unbounded on infinite scroll, degrading on large libraries. Each
date-group is now a <section> whose grid is materialized (tiles
inserted) only while near the viewport and dematerialized (emptied,
height frozen as a spacer) once it scrolls away, driven by an
IntersectionObserver rooted on the scroll container. DOM nodes stay
bounded by a few screens regardless of library size.

- Grouping (day/month/year), infinite scroll, multi-select, video
  thumbnails and fade-in are all preserved.
- Selection state and the video-thumbnail cache survive the
  materialize/dematerialize cycle.
- Falls back to full rendering when IntersectionObserver is unavailable.
- Spacer heights are estimated from grid geometry and re-estimated on
  resize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JW6ghFMDtnRYuYNzZhb47M
2026-06-19 09:30:41 +00:00
Bradley Nelson 4427b1613b plugin logging 2026-06-16 23:00:23 -06:00
Edouard Vanbelle c952852d13 chore(front linter): fix warnings 2026-06-15 17:02:51 +02:00
Edouard Vanbelle 5eb4d9117c chore(front): apply biome formatter 2026-06-15 16:30:38 +02:00
DioCrafts 81a93a489b feat: photo/video capture-date pipeline + premium UI/UX overhaul
Backend — Photos timeline now groups by real capture date instead of upload time. New MediaMetadataService (FileLifecycleHook) extracts EXIF DateTimeOriginal from images and container creation_time from videos (mov/mp4/mkv) via nom-exif, timezone-correct (OffsetTimeOriginal), persisting captured_at so the existing media_sort_date trigger takes over. Adds POST /admin/photos/metadata/reextract to backfill existing media. Falls back to upload date when no embedded date exists.

Frontend — premium grid cards: combined metadata line (relative date · size, owner avatar when shared), custom selection checkbox with a clear checked state, uniform full-width 4:3 thumbnail tiles independent of filename length, centered file-type icons, and a hit-test fix so checkbox/star/kebab clicks reach the controls (the decorative thumbnail no longer captures pointer events). Notification messages internationalised across all 16 locales. Broader polish: design tokens, a11y/focus-visible states, brand + PWA assets.

Chore — bump semver-compatible dependencies (cargo upgrade); add nom-exif 3.6.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:24:27 +02:00
Claude 8dab135090 Add embedded Tantivy full-text content search
/api/search now finds files by CONTENT as well as by name: BM25-ranked
matches over extracted text (PDF, Office OOXML/ODF, plain text/code)
with typo-tolerant fuzzy terms and search-as-you-type prefix matching,
served from an embedded Tantivy index at {storage}/.search-index.

Pipeline (all off the request path, mirroring tree-etag + thumbnails):
- statement triggers on storage.files append to a durable dirty queue
  (storage.search_index_dirty) - every write surface (REST, WebDAV,
  NextCloud, WOPI, trash) is covered, crash-safe by construction
- ContentIndexWorker drains the queue on the maintenance pool, extracts
  text once per unique BLAKE3 blob (storage.blob_extracted_text cache:
  N copies = 1 extraction, renames/moves = 0 re-extraction) and applies
  batched single-writer Tantivy commits; queue rows are deleted only
  after the commit succeeds (at-least-once, idempotent upserts)
- the index is a derived artifact: a version-marker mismatch wipes and
  reseeds it from Postgres, which remains the single source of truth

SearchService merges content hits into the existing name search: hits
are hydrated through ONE SQL round-trip that re-applies user scope,
trash state and every active filter (a stale index id can never leak),
scored below name matches, and returned with a plain-text snippet and
a match_source field. Index failure or
OXICLOUD_ENABLE_CONTENT_SEARCH=false degrades to name-only search; a
discard-only janitor keeps the trigger-fed queue bounded while disabled.

The frontend renders the snippet under the file name in list view.

New dependencies: tantivy 0.26, zip 8.6 (deflate only), pdf-extract 0.10.

https://claude.ai/code/session_01Sc7F4xbo83YbFAQ4xEeDrX
2026-06-11 15:16:03 +00:00
Edouard Vanbelle 916b666b13 fix(ui): ensure owner ellipsis on list view 2026-06-07 20:10:05 +02:00
Edouard Vanbelle e4bb5b064a feat(tooltip): add tooltip on users and groups 2026-06-06 18:49:14 +02:00
Edouard Vanbelle 540c947e61 fix(ui): better handling of new folder creation
issue: on folder creation view was wiped and displaying only the new folder
    fix: add a "new" swimlane if in group mode and scroll up to the new created folder
2026-06-05 11:25:09 +02:00
Edouard Vanbelle 64d081ad0b feat(external): permit login via email (magic link) 2026-06-03 00:31:59 +02:00
Edouard Vanbelle 074ca33e1d feat(userVignette): add external badge when needed 2026-06-03 00:31:59 +02:00
Edouard Vanbelle 9fac34f91e feat(ui): add share modal and users
- fix(external users): fix app starting for external users
2026-06-03 00:31:59 +02:00
Edouard Vanbelle d03b9474c6 feat(smtp): add a precious SMTP test for admin only 2026-06-03 00:31:59 +02:00
Edouard Vanbelle 09985f8a95 feat(group): 1st implementation of Groups
this implements first version (manageable only by admin right now)

    routes:

        GET /api/groups
        List subject groups (paginated). Admin-only.

        POST /api/groups
        Create a new ReBAC subject group. Admin-only. The name must match the RFC 5321 local-part shape and be globally unique (case-insensitive).

        GET /api/groups/search
        Search non-virtual groups by name substring. Authenticated only (no admin role required) — backs the share-dialog recipient autocomplete.

        GET /api/groups/{id}
        Fetch a single group's details. Admin-only.

        DELETE /api/groups/{id}
        Delete a group. Cascades to `subject_group_members` (FK) and to `access_grants` rows referencing this group as a subject. Admin-only.

        PATCH /api/groups/{id}
        Update a group's metadata. Admin-only. v1 only persists name renames.

        GET /api/groups/{id}/effective-members
        List every user transitively reached through this group (members of members of members, etc.). Used by admin / audit tooling. Admin-only.

        GET /api/groups/{id}/members
        List the *direct* members of a group (one level only). Admin-only.

        POST /api/groups/{id}/members
        Add a member to a group. Exactly one of `user_id` / `group_id` must be provided. Adding a group-member runs a write-time cycle check and a nesting-depth check (max 8). Admin-only.

        DELETE /api/groups/{id}/members/group/{gid}
        Remove a nested group-member from a group. Admin-only.

        DELETE /api/groups/{id}/members/user/{uid}
        Remove a user-member from a group. Admin-only.

fix hurl

groups

round

groups
2026-05-31 20:57:45 +02:00
Edouard Vanbelle 3bcb3a5b3f ux(tooltip): fix(tooltip): move tooltip into top-bar, that fix issue with RTE languages 2026-05-30 10:38:43 +02:00
Edouard Vanbelle ca1a2bb649 feat(light-dark): normalize light/dark/like-os mode
permits user to define light, dark or like the desktop
2026-05-30 09:36:15 +02:00
Edouard Vanbelle ea83891a61 feat(trash): move trash API to normalized version (with cursor, orderBy) + normalize Trash section to existing components
normalize also component to format badges (expiry, role, etc)
2026-05-30 00:49:32 +02:00
Edouard Vanbelle 6e5c5edd85 chore(ui): apply biome formatter 2026-05-29 13:15:31 +02:00
Edouard Vanbelle ae4fb7603a refactor(front): remove dead code (old Shared section) 2026-05-29 13:13:23 +02:00
Edouard Vanbelle 63722c868e feat(myshares): new version of myshares sections, supporting grants Users + Tokens 2026-05-29 13:12:59 +02:00
Edouard Vanbelle 8800353900 refactor(share,grants): migrate expiration from legacy share into grants, simplify legacy share, normalize shareModal for better UX 2026-05-28 20:00:06 +02:00
Edouard Vanbelle 29d8aab9c0 feat(resourceList): keep consistence in groupby options order accross sectons + add userVignette on owner's swimlane 2026-05-28 12:12:22 +02:00
Edouard Vanbelle 80c9ace108 chore(i18n): add missing translations 2026-05-28 12:12:22 +02:00
Edouard Vanbelle 7f4b329718 feat(itemToolltip): fusion pathTooltip + ownerTooltip into itemToolltip, move it in the header for more visibility 2026-05-28 12:12:22 +02:00
Edouard Vanbelle 5790a1459f feat(folders): add curser and the normalized way to get foler's item list. add reverse order 2026-05-28 12:12:22 +02:00
Edouard Vanbelle 5afb30ebfd feat(swimlane): add swimlane engine with first version on SharedWithMe section
added group by:

        - None (= ordered by folders/file name)
        - Type (Folder first, then Image, Vidao, Audio, Document, etc...)
        - Owner
        - Size (With logarithmic groups))
        - Shared date (with groups: today, last 7 days, last 30 days, then year)
2026-05-28 00:15:05 +02:00
Edouard Vanbelle 6ac4e6177c refactor(js): move multiSelect into batchToolbar + move residual method into relevant components 2026-05-28 00:15:05 +02:00
Edouard Vanbelle 1cd934d594 refactor(resourceList): move grid/list view into a resourceList component, purpose normalize on all sections views 2026-05-28 00:15:04 +02:00
Edouard Vanbelle b0c5e7827e feat(user-avatar): users can now edit there image (image is taken from OIDC picture) 2026-05-27 11:29:33 +02:00
Edouard Vanbelle 8365608bd5 feat(list view): show the owner of the File or Folder in list view 2026-05-25 22:48:59 +02:00
Edouard Vanbelle 79c1a37931 feat(ui): 1 modal to manage shares (users & public share)
fix(share): ensure Authz parent is created/updated on publicShare create/update

fix(ShareModal): do not show Token (public) grants in People section
2026-05-25 22:47:36 +02:00
Edouard Vanbelle 60d53ea779 feat(ui): add section 'Shared with me' 2026-05-25 22:47:32 +02:00
Edouard Vanbelle 191f725199 feat(ui/trash): show original file path in tooltip on mouse over + display thumbnails
* fix: permission also check elements trashed elements
 * tested manually
 * all automated tests ok
2026-05-22 02:26:11 +02:00
Edouard Vanbelle 3c3be9b930 feat(share): permit scrolldown+ keep header sticky on the top
this solve issue raised on #253
2026-05-19 22:52:46 +02:00
Edouard Vanbelle 3557bc596a fix(front:pathTooltip): correct importation of pathTooltip.css 2026-05-19 14:55:37 +02:00
Kamil Alekberov fe0a8c7f72 feat(ui): improve mobile search and consolidate language selector
- On mobile (≤768px), replace the full search bar in the topbar with a
  search icon button; tapping it expands a full-width search overlay
  with a back arrow to collapse (Google Drive-style pattern)
- Escape key also collapses the mobile search overlay
- Hide the redundant inline search icon when the mobile search bar is
  active (submit button already has one)
- Move the language selector from the topbar into the user menu for all
  screen sizes, reducing topbar clutter; it renders as an accordion row
  matching other menu items
- Fix user menu positioning in RTL layouts (Arabic/Persian): anchor to
  left:0 instead of right:0 so the panel opens inward rather than
  off-screen
2026-05-17 18:41:34 +05:00
Dionisio Pozo 412e31388d Merge pull request #347 from abnvle/feat/share-folder-browsing 2026-05-14 00:07:45 +02:00
abnvle e8399443e9 Merge remote-tracking branch 'origin/main' into feat/share-folder-browsing
# Conflicts:
#	static/js/views/public/publicShare.js
2026-05-10 20:46:29 +02:00
Edouard Vanbelle 7697f3d35b feat(ui): handle errors on folder creation or folder/file renaming
- protect file_management_service::rename_file with validate_storage_name
 - remove specific rename modal and use the generic modal class (less duplicate)
 - handle errors on modal action: do not close the modal on error and display this error
 - hide "Go to parent folder" contextMenu if section is files and folder is the same as current one
2026-05-09 00:06:36 +02:00
Edouard Vanbelle 8e1e9fe201 show item path on Recent + Favorites, add go to parent folder, fix Folder browsing in Favorites 2026-05-06 23:36:05 +02:00
abnvle cb454d8aa2 feat(share-public): folder gallery UI in share.html
Replaces the placeholder with a gallery rendered by publicShare.js
against the new public endpoints.

- Grid / list view toggle (localStorage)
- Image thumbs and lazy-loaded video posters
- Click-to-open lightbox with Esc / arrow nav
- ZIP download for the current folder
- Subfolder navigation via URL hash, History API for back

Adds five overlay-related tokens to base/variables.css for the
lightbox surface (on-overlay text, translucent button, drop shadow).

share.html itself only adds an icons.js module import and empties
#share-folder for JS to populate.
2026-05-06 00:01:08 +02:00
abnvle 8527765bf2 style(share-dialog): give share button breathing room
The Share button moved into .share-options in bdb5a6c sat flush
against the section bottom border. Adds 20px bottom padding plus
margin-top:16px and margin-left:auto on the button so it aligns
right with the Close button below.
2026-05-05 21:57:15 +02:00
Edouard Vanbelle f6cd18e5e9 feat: generate thumbnail from client is not found on server
- supported thumbnail filetype: image, pdf, video
- add play character if video's thumbnail is loaded
2026-05-04 21:04:15 +02:00
Edouard Vanbelle f5dade1551 refactor(ui): css: use of variables colors only 2026-04-26 01:16:40 +02:00
Edouard Vanbelle e148a92f5d refactor(ui): use hidden class for upload + menu 2026-04-25 21:10:04 +02:00
Edouard Vanbelle 35fc9a0619 improve(ui): share-dialog: click outside of dialog closes the window 2026-04-25 21:10:04 +02:00
Edouard Vanbelle fc8e529e7d refactor(ui): modal: use hidden class 2026-04-25 21:10:04 +02:00
Edouard Vanbelle a38bcc01de refactor(ui): normalize about modal with hidden class 2026-04-25 21:09:55 +02:00