100 Commits
Author SHA1 Message Date
LeoVasanko bb1659e076 Internal and external auth cache 5 minutes. 2026-08-14 03:47:03 +00:00
LeoVasanko c445061451 preview: restore strict 10s request deadline
The mediapreview error-handling refactor dropped the outer
asyncio.wait_for around preview generation. Pool-internal timeouts only
bound individual stages (idle-worker wait, worker request, OO HTTP
calls); queueing on top of them let requests run far past 10s and
eventually return 200 instead of 503. Wrap both generate paths in
wait_for(PREVIEW_TIMEOUT) again — cancellation propagates correctly:
the pool dispatcher drops cancelled futures, and the OnlyOffice manager
cancels orphaned conversion tasks.
2026-08-13 07:55:48 +00:00
LeoVasanko 43fd7df098 Bump mediapreview version 2026-08-13 07:49:09 +00:00
LeoVasanko 768ccd7739 startup box: show mediapreview version next to cista version
Version comes from importlib.metadata (the package has no version
constant), making it obvious at a glance which mediapreview build the
running server resolved.
2026-08-13 07:46:29 +00:00
LeoVasanko 321a86acf8 5 min cache for auth checks to reduce spam. 2026-08-13 07:23:22 +00:00
LeoVasanko b5f4f67813 oosetup: return exit code, not the secret
The mediapreview setup_docker() return value (the JWT secret) was passed
through to main() and sys.exit(), printing it a second time on stderr
with a failure exit code. The secret is already printed to stdout in the
finally block; return 0 on success.
2026-08-13 07:16:17 +00:00
LeoVasanko 697a9416e8 Bump mediapreview version. 2026-08-13 06:58:10 +00:00
LeoVasanko d005ae1d88 Remove vestigial docker-compose.yml
OnlyOffice setup is done entirely by mediapreview (cista --oosetup ->
mediapreview.office.setup_docker: image build, oonet network creation,
docker run). Nothing referenced this compose file; it was a leftover
from before the preview functionality moved to the mediapreview package.
2026-08-13 06:55:37 +00:00
LeoVasanko 3d8e20de8f onlyoffice: isolated oonet network in compose; print JWT secret from --oosetup
- docker-compose: attach the OnlyOffice container to the internal-only
  oonet network (fixed name matching mediapreview's OO_NETWORK, fixed
  container IP 172.30.0.2); no published ports, no outbound internet.
- --oosetup prints ONLYOFFICE_JWT_SECRET=<key> at the end regardless of
  build outcome (the secret is deterministically derived from config).
2026-08-13 06:53:46 +00:00
LeoVasanko 54d7129bfc Re-run search whenever file list updates. 2026-08-13 05:11:48 +00:00
LeoVasanko 0c9fe7638c Move preview error handling to mediapreview. 2026-08-13 04:29:25 +00:00
LeoVasanko 226f96c477 Make Order keycaps 1 2 3 clickable to choose sort order by mouse. 2026-08-13 04:26:42 +00:00
LeoVasanko 29e816cb53 Root logger config to consistently print emojis. 2026-08-13 01:03:29 +00:00
LeoVasanko 7a0e473fb4 Drop watch websockets on session loss, purge SSO cache on logout
- Successful SSO /auth/api/validate responses are cached per credential
  and perm/renew URL for 10s, so watch websocket re-checks do not hammer
  the auth backend. A POST to the logout endpoint purges all cached
  entries for the request's credentials immediately, so logout/login
  flows are not served stale successes.
- The watch websocket now re-validates auth before each forwarded
  message and every 10s when idle (SSO and built-in sessions alike).
  When the session is gone the client gets an auth error message and
  the socket is closed, instead of streaming updates forever.
- Token-authenticated (API/share token) sockets are exempt from
  re-validation; they are checked once at handshake.
2026-08-12 21:20:12 +00:00
LeoVasanko bd96b2c7ba Cleaner error logging: sanic loggers at INFO, 499/503 for cancelled requests, shortened preview error reasons
- Force sanic.root/error/server back to INFO from before_server_start, after
  dev mode's runtime setLevel(DEBUG) — kills the useless 'Error Page:' noise
- Silence mediapreview.pool WARNINGs (timeouts already in access log extra);
  they previously fell to logging.lastResort with no level prefix
- Handle CancelledError with 499 (client disconnect / RequestCancelled) or
  503 (server shutdown) instead of Sanic's default 500 error page
- 422 preview failures now log 'backend: reason' in the access log, with
  upstream error text shortened (first line, no [Errno] prefix, cut at ': ');
  dev mode prints the full original error to console
2026-08-12 03:45:39 +00:00
LeoVasanko 3405248554 Another attempt at silencing useless WebSocket log noise. 2026-08-12 02:47:59 +00:00
LeoVasanko 0c3c3615ce Restructured preview functionality into a separate mediapreview package. 2026-08-12 00:06:56 +00:00
LeoVasanko 07305538dc Graceful one-Ctrl-C shutdown with preview activity
- Preview workers ignore SIGINT (pool mode only) and load tracerite, so
  Ctrl-C no longer dumps a KeyboardInterrupt traceback per worker.
- Spawn workers in their own process group and kill with killpg, so a
  SIGKILLed worker cannot orphan an in-flight ffmpeg grandchild.
- Fail all pending and in-flight preview futures when the pool closes
  instead of orphaning them until timeout; never restart the pool once
  shut down (mid-shutdown requests get a quiet 'preview cancelled' 503).
- Re-raise CancelledError in the preview route instead of responding on
  a torn-down connection ('NoneType' is_closing crash).
- Log preview failures with logger.exception where they occur (in the
  worker, whose stderr is inherited) instead of re-logging a traceback-
  less error string in the parent.
2026-08-11 21:32:16 +00:00
LeoVasanko f3b3b5efd9 Silence OnlyOffice log spam when server is unreachable
- Cache docker bridge IP auto-detection (it cannot change at runtime),
  so the debug message is logged once instead of per preview.
- Log availability transitions only (unreachable/back), re-probing every
  30s via the existing TTL cache.
- Skip office conversion attempts entirely while OnlyOffice is known to
  be down; fail with a quiet 'onlyoffice error' 503.
2026-08-11 21:32:16 +00:00
LeoVasanko 8613d6c25e HDR-capable preview pipeline
- Video rotation (0/90/180/270) now stays fully in planar YUV420,
  preserving 10-bit HDR (yuv420p10le via PyAV uint16 planes) and the
  source colorspace; no more RGB round-trip.
- AVIF images now go through the ffmpeg CLI path like HEIC: pyvips drops
  CICP colour metadata, turning HDR sources into washed-out SDR previews.
- Fix pyvips "out of order read" on JPEGs needing EXIF rotation by
  reopening with random access only when autorot actually rotates.
2026-08-11 20:36:13 +00:00
LeoVasanko 5ed627d9f4 Quieter SVT-AV1 when encoding video previews. 2026-08-11 16:07:34 +00:00
LeoVasanko f0c3f7a7f9 Silence WebSocket connection closed log messages (we have our own access logging). 2026-08-11 14:41:07 +00:00
LeoVasanko 953ec628a0 Add -nostdin to ffmpeg preview conversions to suppress keyboard prompts 2026-08-11 05:32:27 +00:00
LeoVasanko e678c8c267 Put the failing ffmpeg command on its own line in error messages 2026-08-11 05:31:30 +00:00
LeoVasanko 69d58f99e3 Drop noisy ffmpeg fallback for non-HEIC images, quiet ffmpeg output
A corrupt TIFF in production produced a wall of ffmpeg error output:
pyvips could not decode it, the generic ffmpeg fallback was tried, and
ffmpeg's TIFF decoder failed just the same — with banner, configuration
and stream-mapping spam included.

- Non-HEIC images are now decoded by pyvips only; a pyvips failure
  raises a clean one-line ValueError ("cannot decode image: ...", a 422
  like any other undecodable file) instead of invoking ffmpeg. The
  ffmpeg path is kept for HEIC/HEIF, where pyvips genuinely falls short
  (tile assembly, HDR metadata).
- ffmpeg runs with -hide_banner -loglevel error -nostats: error output
  is still shown on failure, without the version/configuration/progress
  noise. The -s insertion index no longer depends on fixed positions.
2026-08-11 05:29:32 +00:00
LeoVasanko 36764885ed Silence pyvips deprecation and INFO spam in preview worker
- AVIF saves: replace deprecated strip=True with keep="none" (libvips
  8.15+; production already runs a version that deprecates strip).
- Set the pyvips logger to WARNING in the worker: its INFO messages
  ("threadpool completed ...") are pure spam on every operation.
2026-08-11 05:11:44 +00:00
LeoVasanko 5a82560cf2 Format preview worker logs like the main process, tagged with worker pid
Worker stderr is now inherited by the parent, so its log lines land in the
server log — but they arrived with the default logging format and a noisy
"preview-worker config=..." line at every spawn.

- Extract the emoji level-prefix formatting from cista.sanic_logging into
  cista.util.logformat, which has no Sanic dependency (the worker must not
  import Sanic: import-time prints could corrupt the stdout protocol).
- Worker configures its stderr handler with the same emoji prefixes plus a
  worker[pid] tag, and the config-loaded info message is removed.
2026-08-11 05:05:07 +00:00
LeoVasanko 7b1c6f6772 Fix preview pool permanently wedging after worker stderr pipe fills
Production symptom: previews of all types (pdf/pyvips/onlyoffice) start
hitting the 10s timeout and never recover until server restart, while the
rest of the server stays healthy.

Root cause (reproduced on Python 3.12): workers were spawned with
stderr=PIPE that nothing drained after startup. Once the OS pipe buffer
filled from accumulated worker tracebacks and library warnings, asyncio
flow control stopped the parent reading it and the worker blocked forever
mid-request on a stderr write. The 10s timeout then fired, but
_replace_worker hung forever in proc.wait() even after kill() — the
flow-control-paused pipe transport never sees EOF — permanently wedging
one dispatcher per stuck worker. Once all dispatchers were stuck, every
preview request timed out. Restart cleared it.

Fixes:
- Spawn workers with inherited stderr (stderr=None) so worker diagnostics
  go straight to the server log and no undrained pipe can exist.
- Bound proc.wait() in worker kill() with a 5s grace timeout so a wedged
  transport can never hang a dispatcher; log the worker pid instead.
- Guard the dispatch loop with an outer exception handler so a dispatcher
  can never die silently and shrink pool capacity.
- Retry failed worker replacement spawns with 1s-30s backoff instead of
  silently shrinking the pool.
- Fix latent crash: except-tuple referenced msgspec.json.DecodeError,
  which does not exist in the installed msgspec; any protocol failure
  would itself raise AttributeError. Use msgspec.DecodeError.
- Worker: redirect Python-level sys.stdout to stderr in persistent mode
  and keep the raw buffer solely for the binary protocol, so a library
  print() can never corrupt the command channel again (cf. the pymupdf
  deprecation warning that crashed workers at startup).
- Worker: close the pymupdf document explicitly in process_pdf.
- Log worker pid on timeout/protocol/checksum failures, and log failed
  kills and replacement retries, for future production diagnostics.

Add tests/test_preview_pool.py with an end-to-end regression recreating
the wedged-worker setup (piped, undrained stderr) plus kill-grace,
respawn-retry and dispatcher-survival tests.
2026-08-11 04:57:20 +00:00
LeoVasanko c025e7af95 Fix deprecation warning from fitz being renamed to pymupdf: update import. 2026-08-11 02:23:48 +00:00
LeoVasanko 3bad311e35 Tell Paskia SSO not to renew session on WebSocket connections where we cannot pass back the refreshed cookie. 2026-08-11 02:08:01 +00:00
LeoVasanko fdc4fe0a3e Forward client user-agent to SSO backend on validation refreshes. Matches function of existing proxy_auth_request (copies all headers) and proxy_auth_websocket (copies user-agent when present). 2026-08-10 14:08:17 +00:00
LeoVasanko 5df2308bdb Silence CPY copyright rule; make format_access_log tail args keyword-only
Newer ruff flagged CPY001 across the codebase (copyright notices are not
wanted here, rule disabled) and PLR0917 on format_access_log. duration_ms
and extra are now keyword-only at the single call site.
2026-07-28 02:37:12 +00:00
LeoVasanko f4c44ce1aa Remove unused frontend test framework
vitest, @vue/test-utils, jsdom and @types/jsdom were installed but no
frontend tests exist or are planned. Removing them also drops the
deprecated glob@10 dependency chain (js-beautify). type-check now uses
tsconfig.app.json.
2026-07-28 02:32:26 +00:00
LeoVasanko 49232f11cc Fix rename flow: KeepAlive-cached view watchers cleared cursor on stale props
Deactivated FileExplorer/Gallery instances stay alive in KeepAlive with
frozen, potentially empty document props. Their empty-folder watcher
cleared store.cursor and yanked focus to the breadcrumb on every cursor
change, breaking rename via gallery pen and keyboard entry into the
file list, and hiding the explorer rename button.

- Guard cursor watchers in FileExplorer/Gallery with an isActive flag
  (set on activated, cleared on deactivated)
- Declare emits in GalleryFigure (rename/menu fell through to the root
  anchor as native listeners)
- Show the explorer rename button on row hover with a delayed fade-in
  instead of only on the keyboard-focused row
2026-07-28 02:16:23 +00:00
LeoVasanko 1258eff42d Fix preview worker pool leak: ffmpeg must not inherit worker stdin
The ffmpeg fallback in the preview worker inherited the worker's stdin
pipe (the framed request protocol). When a slow conversion was killed
at the 10s timeout, the orphaned ffmpeg grandchild kept that pipe open,
so the parent's proc.wait() blocked forever waiting for pipe EOF —
permanently sticking one dispatcher per event until the whole pool
starved and every preview request (pdf, image, office) returned 503.

- Run ffmpeg with stdin=DEVNULL (also stops it eating protocol bytes)
- Drop start_new_session (only needed for group kills, POSIX-only)
- Stop logging the master secret at worker startup
2026-07-28 01:14:15 +00:00
LeoVasanko 718d46e3f9 Fix search in subdirectories (problem saving search field in URL). 2026-06-17 04:01:21 +00:00
LeoVasanko 92d9c40a28 Center file rename input in gallery mode to be more consistent with normal titles. 2026-06-17 03:43:01 +00:00
LeoVasanko 4f646fb344 Fix layout when there is more space than needed to display file explorer (don't scale larger) or gallery (don't bottom align). 2026-06-17 03:30:20 +00:00
LeoVasanko d6304d0029 Frontend linter changes. 2026-06-16 22:13:27 +00:00
LeoVasanko 77e35cf0fc fix(frontend): new file and folder creation hang, empty folder UX
- Replace circular watchEffects in FileExplorer/Gallery with explicit watchers

  to stop recursive Vue updates when creating items in empty folders.

- Move EmptyFolder rendering inside FileExplorer/Gallery so empty/list swaps

  no longer trigger folder slide transitions.

- Keep EmptyFolder text size consistent across list and gallery views.
2026-06-16 22:09:53 +00:00
LeoVasanko bf8a049b92 Use canonical paths for editor and fix route transitions 2026-05-07 02:18:55 +00:00
LeoVasanko 6d7f44bd88 Add view caching and preserve folder/editor UI state 2026-05-07 02:12:03 +00:00
LeoVasanko e2097a1563 Fix empty state vertical centering in explorer 2026-05-07 01:53:16 +00:00
LeoVasanko b864936eaa Lint 2026-05-07 01:44:27 +00:00
LeoVasanko 72b3c0d8ce feat(frontend): add text editor flow and create-file UX
- replace textarea editor with CodeMirror and syntax highlighting\n- integrate editor mode header (save button, hide unused controls)\n- fix breadcrumb/editor navigation behavior and transitions\n- add Create File action with ghost-rename flow and auto-open in editor\n- refine create-file icon shape and plus cutout alignment
2026-05-06 02:17:17 +00:00
LeoVasanko 07daf372e8 Rudimentary text file editing support. 2026-05-06 00:20:19 +00:00
LeoVasanko e979d679b2 feat(frontend): add simultaneous slide transitions on directory navigation
- Detect navigation direction (forward/backward) via router beforeEach guard
- Store transition direction in Pinia for cross-component access
- Wrap ExplorerView content in a CSS grid transition wrapper so old and new
  views overlap in the same grid cell during animation
- Add slide-forward/slide-backward transition classes with translate3d
  for GPU-accelerated, simultaneous enter/leave without gaps
- Keep fixed-position search loader outside the transition
2026-05-05 16:07:07 +00:00
LeoVasanko eea66c0013 Rename selection clear button label 2026-05-05 03:00:10 +00:00
LeoVasanko 9220c457c0 Use link icon for the share link button. 2026-05-05 02:58:43 +00:00
LeoVasanko d5b77932ea Allow anonymous share links in public mode 2026-05-05 02:47:18 +00:00
LeoVasanko 9b9d3e1cc1 Adjust gallery checkbox size and spacing 2026-05-05 02:38:25 +00:00
LeoVasanko 536efc4ce1 Regression: inotify optional on unsupported platforms 2026-05-05 02:32:47 +00:00
LeoVasanko 1b2267587f Fix empty root shown as missing folder 2026-05-05 02:26:41 +00:00
LeoVasanko 2864e9f041 Hide tiny Other slice in disk space chart 2026-05-05 02:20:55 +00:00
LeoVasanko b5a94b5eee Frontend upload batch space check with 512 MiB margin
- Verify single queue: uploads append to upqueue and are processed
  sequentially by one worker (parallel only within a single file).
- Before accepting a new batch, calculate total size minus existing
  files that will be overwritten.
- Reject the whole batch if free space < net need + 512 MiB margin.
- Show a toast with human-readable needed vs available space.
2026-05-05 02:13:18 +00:00
LeoVasanko d4be755d46 Enforce 128 MiB minimum free space on uploads
- Add cista/util/diskspace.py with MIN_FREE_BYTES limit and cached
  check_free_space() helper.
- Check available space in File.write() before ftruncate/write.
- Catch ENOSPC in File.write and re-raise as InsufficientStorageError.
- upload_file_chunk catches both proactive and ENOSPC errors and
  returns HTTP 507 Insufficient Storage.
- Add tests for low-disk rejection and ENOSPC handling.
2026-05-05 01:46:30 +00:00
LeoVasanko 07089aa9a7 frontend: add About dialog and unify global dialog backdrop 2026-05-03 23:40:54 +00:00
LeoVasanko c3146744b7 PageUp/PgDn/Home/End navigation; fix rename API path; immediate local rename update 2026-05-03 22:58:51 +00:00
LeoVasanko 48d7435d0b Allow portrait documents to render somewhat taller because gaps were being left between them depending on window width. 2026-05-03 18:36:14 +00:00
LeoVasanko 3e80325053 Smoother scrolling in gallery when using keyboard navigation. 2026-05-03 18:33:19 +00:00
LeoVasanko 31fc02ddbf Keep the file extension always visible but discreetly as part of the filename. Fix Escape in rename field. 2026-05-03 18:22:03 +00:00
LeoVasanko 2406ea87b0 Gallery mode file extension and filename display improvements. 2026-05-03 17:26:25 +00:00
LeoVasanko 3a1dd2b7da Show document icon when no preview is available or has failed. While loading, pulse the icon. 2026-05-02 19:54:38 +00:00
LeoVasanko 3df6b079c9 Better logging of ffmpeg errors 2026-05-02 19:49:06 +00:00
LeoVasanko af804e2c9f Less noisy preview timeout logging 2026-05-02 19:30:16 +00:00
LeoVasanko 1dc0c4441a Fixes on server startup and shutdown with Sanic internals. Parallel shutdown tasks as non-blocking async tasks to avoid blocking the event loop and causing a warning of that. 2026-05-02 19:22:23 +00:00
LeoVasanko c7ba0d5a04 Dynamically adjusting layout to maximize screen space used for document previews. Row width changes with aspect ratio of items on that row. Server side tracking of size as part of the main listing. 2026-05-02 18:45:44 +00:00
LeoVasanko 0071058b29 Avoid gallery layout collapse while previews are still loading. Maintain the boxes fixed size regardless. 2026-05-02 16:19:42 +00:00
LeoVasanko 338c74de69 Avoid noisy output on normal WebSocket closing. 2026-05-02 16:12:42 +00:00
LeoVasanko b13f08eab2 Avoid InvalidStateError on conversion tasks trying to set their result after preview cancelled. 2026-05-02 16:04:21 +00:00
LeoVasanko 5d566d6deb Restore CISTA_HOME internal environment passing of config dir removed in commit 31e0197, that was not being passed across processes. 2026-05-02 05:47:24 +00:00
LeoVasanko 5c4965a86b Skip removal of PLR2004. 2026-05-02 05:33:32 +00:00
LeoVasanko bd7291e9ef Lint: unused arguments 2026-05-02 05:26:47 +00:00
LeoVasanko 2fa52229cc Exception nazi and other suppression removals. Added tests on auth flows that were simplified to linter requirements. 2026-05-02 05:22:56 +00:00
LeoVasanko 2dea459d8f Update fastapi-vue-setup 1.3.1 to avoid ruff errors. Fixed devserver script on platforms where Sanic needs AppServer. 2026-05-02 05:03:43 +00:00
LeoVasanko 922069c603 Imports to top of file (ruff rule now). Refactor a couple of import cycles by implementing clear hierarchy of modules. 2026-05-02 04:46:34 +00:00
LeoVasanko 5c7c7343ad Fix logging regressions from unrelated changes and ruff changing emoji into i. Simplified custom logger. 2026-05-02 04:16:38 +00:00
LeoVasanko 593d16d8c5 Use tracerite for human-readable tracebacks. 2026-05-02 03:50:20 +00:00
LeoVasanko 20d8d317fa Ruff linting. 2026-05-02 03:31:51 +00:00
LeoVasanko 8d89c397a4 frontend: format store typing layout 2026-05-02 03:12:50 +00:00
LeoVasanko 1bec73f4cd onlyoffice previews much faster and more robust, added --oosetup helper, improved error/log handling 2026-05-02 03:10:17 +00:00
LeoVasanko 4dd1d4c7e6 Fix AVIF preview encoding for yuvj video frames 2026-05-02 00:37:53 +00:00
LeoVasanko 84ef91a360 preview: move OnlyOffice unavailable from warning log to access log extra 2026-05-01 23:20:01 +00:00
LeoVasanko 421d90e9c5 frontend: trim document formats, simplify type getters, use FILE_TYPES consistently
- Trim document extension list to common office formats only
  (doc/docx/xls/xlsx/ppt/pptx/odt/ods/odp/rtf), removing txt/md/csv/html/xml/etc.
- Simplify Doc getters: merge guard clauses into single returns
  (img, previewable, previewurl, ext).
- Simplify MediaPreview.preview() into single boolean expression.
- Use global FILE_TYPES instead of inline extension lists.
2026-05-01 23:17:40 +00:00
LeoVasanko 8b4e622aef preview: remove ffprobe fallback and unused json import
_get_image_dimensions now relies solely on pyvips header reading.
If pyvips cannot read the header the function returns None and the
caller encodes at full resolution rather than falling back to ffprobe.
Remove unused stdlib json import.
2026-05-01 22:51:58 +00:00
LeoVasanko 13f32c57ab preview: ffmpeg CLI fallback for HEIC/HDR, worker pool fixes, logging improvements
- Use ffmpeg CLI directly for HEIC/HEIF previews (bypassing pyvips which
  cannot encode >8-bit AVIF on current system). ffmpeg handles tile
  assembly, EXIF rotation, HDR metadata and ICC profiles automatically.
- pyvips remains primary for other image formats; ffmpeg is fallback.
- Simplify _get_image_dimensions() to use pyvips header read for all
  formats including HEIC, with ffprobe as fallback.
- Move all imports to top of preview.py; remove lazy OnlyOffice import.
- Worker pool: add readiness handshake (\x01 byte), bounded idle wait
  with PREVIEW_TIMEOUT, eager module import before signalling.
- Fix dispatch data check bug (was 'if data is not None' -> 'if data').
- Add logger.exception for unhandled preview/dispatch errors.
- EmojiFormatter now includes tracebacks for exception logs.
- Return 503 on preview timeouts instead of 504.
2026-05-01 22:48:30 +00:00
LeoVasanko 25a2a5f20c Separate OnlyOffice async handling, add office_previews WS flag, framed worker protocol
- Move OnlyOffice conversion out of worker subprocesses into async event loop
  using httpx.AsyncClient with shared client and clean shutdown hook
- Add OOConversionManager with in-flight deduplication (asyncio.Future) and
  configurable concurrency limit (OO_MAX_CONCURRENT=2)
- Add 10s total timeout for office previews via asyncio.wait_for
- Return 503 when OnlyOffice is unavailable, 504 on timeout
- Remove office handling from worker dispatch(); workers now only do
  images, video, and PDFs
- Replace PNG tempfile bridge with framed binary input protocol on worker
  stdin: (json_size)(data_size)(json)(raw_data)
- Add process_image_buffer() for in-memory AVIF conversion via pyvips
- Add office_previews to WS server message, cached every 30s from OO
  availability check
- Frontend gates only office document previews on office_previews flag;
  images, video, PDFs remain unconditional
- Change default OnlyOffice port from 8080 to 8988
2026-05-01 03:42:03 +00:00
LeoVasanko 041090cce9 preview: increase timeout to 10s, add priority queue scheduling (images > video > pdf > office) 2026-04-27 04:51:41 +00:00
LeoVasanko ec6db7b53f Add sort-order keycap hints next to search bar
Show 'Order [1] [2] [3]' keycaps to the right of the search bar
when the viewport is at least 800px wide. These visual hints
match the existing '/' search keycap style and correspond to
the existing keyboard shortcuts for sorting:
  1 = name (alphabetical)
  2 = modified (newest first)
  3 = size (largest first)

Hints are hidden on narrow viewports and when text input fields are focused.
2026-04-26 08:02:40 +00:00
LeoVasanko 575df1214b session: rename cookie to 'cista', add __Host- prefix on HTTPS 2026-04-27 03:56:07 +00:00
LeoVasanko 1927c24053 Revert an accidental change of functionality that was breaking file listings, originally done for linting purposes in commit 3767fb0. 2026-04-26 07:47:27 +00:00
LeoVasanko 6242c76be8 Add share token support with virtual filesystem and selection toolbar button 2026-04-26 07:46:14 +00:00
LeoVasanko 87a92838c2 Add benchmark script for OnlyOffice output formats
Benchmarks three preview pipelines across all sample documents:
- BMP → AVIF (via pyvips)
- PNG → AVIF (via pyvips) — selected for production
- PNG only (no compression)

Results confirm PNG → AVIF as the optimal path:
- ~30 ms AVIF encode overhead
- 2.1× size reduction vs raw PNG
- Slightly faster than BMP → AVIF
2026-04-26 07:28:52 +00:00
LeoVasanko 8c93a4f2b5 Add OnlyOffice-based preview for office documents
Replace Aspose.Words with OnlyOffice Document Server for generating
bitmap previews of office documents (Word, Excel, PowerPoint, etc.).

Backend:
- Add cista/onlyoffice.py conversion client
- Convert office docs directly to PNG via OnlyOffice, then AVIF via pyvips
- Make office previews optional based on OnlyOffice availability
- Remove Aspose.Words dependency and all related code
- Add spreadsheet and presentation format support

Frontend:
- Mark office files as previewable in Document.ts
- Add office extensions to MediaPreview.vue preview list
- Fix pre-existing @ts-ignore in HeaderMain.vue

Tests:
- Fix test_lrucache.py parameter name (open -> opener)

Also run ruff format across the codebase to satisfy linter checks.
2026-04-26 06:59:01 +00:00
LeoVasanko eb5ff82de6 frontend: add biome checks and pre-commit integration (excluding preview files) 2026-04-26 06:43:06 +00:00
LeoVasanko 942b54d795 lint: apply manual ruff cleanup (non-preview files) 2026-04-26 06:16:42 +00:00
LeoVasanko 18ee0f3f56 sso: use /auth/api/check for token permission checks 2026-04-26 05:46:09 +00:00
LeoVasanko f8b2c9494a WebDAV sync support, access tokens, REST control endpoints (#10)
Implement complete WebDAV file serving compatible with various clients from Windows File Explorer to more specialized sync tools. The old control WebSocket has been updated to part-DAV, part REST API instead. Implemented user:pass BASIC auth. Added UI and backend for creating tokens that avoid the need to use actual username and password for requests from CLI or DAV.
2026-04-26 04:22:52 +00:00
LeoVasanko 9ac571463a Uploads by PUT range requests rather than WS, remove dead code WS handlers (#9)
Increases block size to 16 MiB and adjusts progress display to work smoothly with that. Also removes download WS that was already unused. Provides faster upload speed than over WS.
2026-04-25 01:55:52 +00:00
LeoVasanko d52b24372a Remove CISTA_PIL and Pillow preview mode 2026-04-25 02:06:40 +00:00