Commit Graph

17 Commits

Author SHA1 Message Date
Will Miao e09fe5888b refactor(reorder): drop the Alt + Arrow shortcut, keep drag only
The reorder shortcut cannot be made reliable in this UI. `Alt + Arrow` is
the browser's tab-history / back-forward gesture on several platforms,
and the modal already binds bare `ArrowLeft`/`ArrowRight` to model
navigation, so the binding either did nothing — a keypress with nothing
focused never reaches a listener on the tag list — or fought the browser.
An affordance that occasionally navigates the page away is worse than
having no keyboard path at all, so drop it.

Reordering is pointer-only again: drag the chip (tags) or its `⠿` grip
(trigger words, whose chip body is click-to-edit). Everything that existed
only to serve the shortcut goes with it — the keydown listener, the hover
tracking used to resolve the target chip, the aria-live announcements, the
per-grip position labels and `moveItemWithinContainer`. The grip becomes a
decorative, non-focusable `<span>` (`aria-hidden`, behind a 5px drag
threshold) instead of a `<button>`, so it no longer promises a keyboard
action it cannot perform.

The tooltip and hint drop the shortcut mention in all 10 locales
(`common.reorder.dragHandle` = "Drag to reorder" and the localised
equivalents); `common.reorder.ariaLabel` and `common.reorder.announcement`
are pruned from every locale by the sync script. The i18n guidelines
record the decision so no shortcut is re-added without re-adding the keys.
2026-09-17 09:07:24 +08:00
Will Miao 01137eed88 feat(frontend): one grip reorder affordance for tags and trigger words
Model tags could already be reordered by dragging a chip, but the only
hint was a `cursor: grab` on `.metadata-item` — a hover-only, mouse-only
signal that also leaked into the bulk add-tags modal, where the chips are
not sortable at all. Trigger words could not be reordered, and their
order matters: "Copy Trigger Words" and the insert-into-node action join
the array as-is to build a prompt.

Both editors now share one vocabulary: a `⠿` grip that appears whenever
the list has something to order, plus `Alt + arrow` keyboard moves with
an aria-live announcement. Whether the chip body is draggable is a
property of the item rather than of the feature:

- tags have no click action of their own, so the whole chip stays
  draggable (`handleSelector: null`), with a 5px threshold so a click on
  the grip only focuses it
- trigger words keep click-to-edit on the body, so a drag starts from the
  grip only
- the grip is the element that opts out of touch scrolling
  (`touch-action: none`), so touch users drag by the grip in both editors
- reordering is offered only while editing: trigger words reveal the grip
  from `.edit-mode`, tags from the edit container, which stays hidden
  outside edit mode

The drag engine moves out of ModelTags.js into shared/pointerSort.js,
which now marks sortable containers with `pointer-sort-enabled` so only
lists that really sort show the grab cursor. Labels, the sortable flag,
the keyboard handler and the live region live in
shared/reorderSupport.js, and both editors render the same three
`common.reorder.*` keys (translations follow in the next commit).

Two inherited engine bugs are fixed on the way: the drop position was
only settled when an animation frame was still pending, so a fast drag
(or one that started by crossing the threshold) fell back into its
original slot; and the guard that stops a drop from triggering the chip's
own click handler was removed on a timer, swallowing unrelated clicks
until the next task.
2026-09-16 08:22:46 +08:00
Will Miao 8260bd022d feat(ui): improve discoverability of hidden interactions
- Expand onboarding tour from 8 to 11 steps: marquee drag-select,
  drag card to sidebar folder, and the three context menus
  (card / bulk / global); enrich bulk-mode step with range-select
  and exit tips
- Add Replay Tutorial button to help modal Getting Started tab
- Add Shortcuts cheat-sheet tab to help modal, opened directly via
  the '?' key when not typing
- Fix trigger-word tooltip to mention double-click to edit
- Keep checkpoint/embedding send tooltips truthful (no replace mode)

Sync new i18n keys to all locales (placeholders pending translation)
2026-09-03 18:16:00 +08:00
Will Miao 7fa40023b0 fix(trigger-words): edit tag on double click 2026-04-21 22:31:56 +08:00
Will Miao 3c8acdb65e fix(trigger-words): support stable inline editing 2026-04-21 22:18:35 +08:00
Will Miao 37f0e8f213 fix(trigger-words): raise group word limit 2026-04-21 16:35:25 +08:00
Will Miao 8ecdd016e6 Increase trigger words limit from 30 to 100 2026-02-25 17:11:21 +08:00
Will Miao 2ccfbaf073 fix(trigger-words): auto-commit pending input on save/blur to prevent data loss, see #785
- Auto-commit input value when clicking save button
- Auto-commit on blur to handle users clicking outside input
- Fixes issue where users would type a trigger word and click save,
  but the word wasn't added because they didn't press Enter first
- Maintains backward compatibility with existing comma-based workflows
2026-01-28 14:34:34 +08:00
Will Miao dd89aa49c1 feat: Add HTML and attribute escaping for trigger words and class tokens to prevent XSS vulnerabilities, along with new frontend tests. Fixes #732 2025-12-23 08:47:15 +08:00
Will Miao 675d49e4ce feat(security): escape HTML attributes and content in model modal, fixes #720
- Import `escapeAttribute` and `escapeHtml` utilities from shared utils
- Remove duplicate `escapeAttribute` function from ModelModal.js
- Apply escaping to file path attributes in model modal and trigger words
- Escape folder path HTML content to prevent XSS vulnerabilities
- Ensure safe handling of user-controlled data in UI components
2025-12-11 18:08:35 +08:00
Will Miao 906d00106d feat(trigger-words): increase maximum word limit from 30 to 100, fixes #660 2025-11-15 08:19:53 +08:00
Will Miao bdc86ddf15 Refactor API endpoints to use '/api/lm/' prefix
- Updated all relevant routes in `stats_routes.py` and `update_routes.py` to include the new '/api/lm/' prefix for consistency.
- Modified API endpoint configurations in `apiConfig.js` to reflect the new structure, ensuring all CRUD and bulk operations are correctly routed.
- Adjusted fetch calls in various components and managers to utilize the updated API paths, including recipe, model, and example image operations.
- Ensured all instances of the old API paths were replaced with the new '/api/lm/' prefix across the codebase for uniformity and to prevent broken links.
2025-09-18 14:50:40 +08:00
Will Miao b2428f607c feat(localization): add trigger words functionality with localization support for UI elements and messages 2025-08-31 15:13:12 +08:00
Will Miao e60a579b85 feat(localization): enhance toast messages for API actions and model management with i18n support
refactor(localization): update toast messages in various components and managers for better user feedback
2025-08-31 12:25:08 +08:00
Will Miao 342a722991 feat: refactor model API structure to support specific model types with dedicated API clients for Checkpoints, LoRAs, and Embeddings
refactor: consolidate model API client creation into a factory function for better maintainability
feat: implement move operations for LoRAs and handle unsupported operations for Checkpoints and Embeddings
2025-08-04 19:37:53 +08:00
Will Miao a7d9255c2c refactor: Replace direct model metadata API calls with unified model API client 2025-07-25 15:35:16 +08:00
Will Miao fcfc868e57 feat: Move LoRA related components to shared directory for consistency
- Added PresetTags.js to handle LoRA model preset parameter tags.
- Introduced RecipeTab.js for managing recipes associated with LoRA models.
- Created TriggerWords.js to manage trigger word functionality for LoRA models.
- Implemented utility functions in utils.js for general model modal operations.
2025-07-22 16:00:04 +08:00