Render the consolidated user actions menu as a popover trigger and rework the comment and forum-post header layout for symmetric, browser-independent alignment.
Core changes:
- Popover fragment (templates/lite/fragments/popover.html, templates/admin/fragments/popover.html):
- Add is_user_menu flag: user-menu trigger class and bi-menu-button-wide-fill icon
- Wrap items/view/edit/delete menu entries in li for valid list markup
- Comment header (templates/lite/fragments/comment.html, templates/lite/assets/css/theme.css):
- Place the user and editor gear cluster before the post number
Lay out the header on a 1fr auto 1fr grid: fixed-width author column, meta aligned from the left, action cluster on the right
- Forum post (templates/lite/fragments/forum-post.html, templates/lite/assets/css/theme.css):
- Move the user menu into the meta cluster before the post number
Flex the meta bar and drop its fixed height so date and cluster never overlap the post body
- Center the nickname plate with flexbox for consistent cross-browser rendering
- Gear styling (templates/lite/assets/css/theme.css):
- User gear shares the editor gear styling (grey, brand-blue on hover)
Benefits:
- Symmetric, consistent post headers regardless of nickname length
- Valid li/a menu markup in both lite and admin themes
Technical notes:
- Template markup and CSS only; no behavior change
Replace the duplicated action-menu builders (add_menu, getUserMenu and two inline $actionMenu closures) with a single getActionMenu() helper and route comment, forum, private-message and clients menus through it.
Core changes:
- Action-menu helper (core/system.php):
Add getActionMenu(array $items, bool $user = false)
- Wraps each prepared HTML item in list-item and builds the popover
- Editor gear by default, user menu (is_user_menu, _USER) when $user is true
- Remove add_menu() and getUserMenu()
Replace the inline implode(list-item) menu builds in getComments and getVotingView with getActionMenu()
- Comment author menu (core/system.php):
Build the user actions menu (personal/message/profile/site) and pass it as btn_user instead of separate btn_personal/btn_pm/btn_profile/btn_web
- Forum (modules/forum/index.php):
Fold author actions plus quote-reply into the user menu via getActionMenu(..., true); route the editor menu through getActionMenu
- Private messages (core/user.php):
- Remove both $actionMenu closures; use getActionMenu() for every menu
- Build the PM author menu (profile/site) via getActionMenu(..., true)
- Clients (modules/clients/index.php):
- Route the row action menu through getActionMenu(explode('||', ...))
Benefits:
- One menu builder instead of four near-duplicates
- Consistent user-menu contract across all front-end modules
Technical notes:
- Behavior preserved; popover fragment items_html API unchanged
Replace the cache-only getCompressHtml() with a single getOutputHtml() that normalizes the assembled page in setFoot() before echo and before page-cache write, so users always receive processed HTML even when page-cache is off.
Core changes:
- Output normalizer (core/system.php):
Add getOutputHtml(string $html, bool $full = false) replacing getCompressHtml()
- Protect script/style/pre/code/textarea bodies and comments first, exposing
only the opening tag so multiline <script src> tags get normalized too
- Squeeze multiline class lists and multiline tags to a single line
- Keep the template's own indentation; only drop blank lines from false {% if %}
- full=true keeps the legacy maximal-compression path and strips non-IE comments
- Output and cache wiring (core/system.php):
- Echo the readable (full=false) output to the user on every request
Compress (full=true) only the copy written to storage/cache/pages/html when cache_c=1, restoring the original cache-only compression contract
Benefits:
- Heavy parsing runs only on the few multiline matches, not on every tag
- Real homepage normalization measured at ~0.32 ms vs ~4.3 ms for a tokenizer
- view-source has no multiline tags, no multiline class, no giant glued lines
Technical notes:
- storage/cache/templates keeps compiled PHP only; final HTML is never written there
- Output is idempotent; script/style/pre/code/textarea bodies stay byte-for-byte
Behavior change: live echo is now normalized for readability on every request; with cache_c=1 a cache hit still serves compressed HTML while a miss serves readable HTML, matching the previous cache-only compression semantics
This commit refines lite theme layout spacing, rating control presentation, and floating feedback links. It removes the separate contact-block partial now that both layouts render the feedback link directly.
Core changes:
- Theme spacing and controls (theme.css, base.css):
Add a shared grid gap variable and apply it to card and post grids.
- Adjust full-view width and metadata alignment rules.
- Refine rating badges, star hover preview, and mobile metadata stacking.
Update floating idea and feedback tabs to grow from the screen edge.
- Uses sideways writing mode where supported.
- Avoids edge gaps during hover and focus states.
- Lite layouts (app.html, home.html):
- Render the feedback tab directly in both layouts.
- Keep the layout output independent of a separate partial payload.
- Theme foot variables (index.php, contact-block.html):
- Remove contactblock generation from theme foot variables.
- Delete the unused contact-block partial.
Benefits:
- Reduces one template indirection in the lite footer path.
- Improves consistency of grid spacing and floating controls.
- Keeps rating UI states clearer for interactive and static displays.
Technical notes:
- No database or storage changes.
- Template output changes are limited to the lite theme.
- Backward compatible for existing theme data except the removed internal contactblock variable.
This commit unifies rating rendering and voting request handling so star and like controls share one data contract. It also switches live rating actions to POST requests with CSRF headers.
Core changes:
- Rating rendering helper (core/helpers.php):
Collapse duplicate star and like rendering branches into one shared template payload.
- Builds a common vote query and live-state wrapper.
- Provides CSRF token data for live HTMX requests.
- Rating request handler (core/system.php):
Replace repeated module-specific branches with a table and field map.
- Keeps duplicate-vote checks by user, ip, and cookie.
- Persists votes through prepared statements and returns the refreshed rating block.
- Rating fragments (rating-bar.html, rating-like.html):
Use the shared vote_query payload for live interactions.
- Sends votes with hx-post instead of hx-get.
- Adds CSRF headers to live rating containers.
Benefits:
- Removes duplicated rating control rendering logic.
- Makes rating vote handling easier to audit and extend.
- Aligns state-changing rating actions with POST semantics.
Technical notes:
- No database schema changes.
- The template payload for rating controls is updated.
- Backward compatible for existing persisted rating values.
This commit prevents malformed requests and concurrent cache writes from generating PHP warnings or TypeErrors. It keeps pagination and cache writes bounded before they reach runtime-sensitive PHP APIs.
Core changes:
- Search pagination (modules/search/index.php):
Clamp page size and requested page before calculating the array slice offset.
- Prevents oversized numeric input from overflowing into a float offset.
- Passes the normalized page to the pager renderer.
- Forum topic view (modules/forum/index.php):
Clamp requested topic pages to the available page range before building the SQL offset.
- Handles empty result sets before reading the first row.
- Casts category permission fields before calling is_acess().
- Cache writes (core/classes/cache.php):
Use a unique temporary file for atomic cache writes.
- Avoids rename/unlink warnings from concurrent writers sharing one .tmp path.
Benefits:
- Reduces noisy PHP log entries from crawler input.
- Prevents request-level TypeErrors from invalid pagination values.
- Improves reliability of concurrent cache generation.
Technical notes:
- No storage format changes.
- No public API changes.
- Backward compatible behavior for valid requests.
Drop the dropdown feedback form from the footer and link straight to the contact module, removing the per-request captcha and token work behind it.
Core changes:
- Footer block (templates/lite/partials/contact-block.html):
- Replace the dropdown form with a plain link to index.php?name=contact
- Theme hook (templates/lite/index.php):
Stop building the feedback fields, captcha and token in getThemeFootVars(); pass only the label
Benefits:
- Less work per page render (no captcha/token for the footer)
- Smaller markup surface
Technical notes:
The contact page keeps its own form, captcha and token, reachable via the link
- The matching form-only styles are removed in the lite style commit
Bring the frontend theme onto the shared .sl-float / .sl-float-panel contract, give the side tabs a modern vertical-text layout pinned to the left edge, and make the id badge a circle-or-pill.
Core changes:
- Floating popovers (templates/lite/assets/css/theme.css):
Map tip/menu/dropdown panels onto .sl-float-panel with the sl-is-open state and viewport-fixed placement
- Drive click dropdowns through opacity/visibility so they fade in place
- Transition opacity only (not position) so panels no longer slide in or up
- Side tabs (#block-idea / #block-feedback):
Pin both tabs to the left edge, stacked symmetrically around the vertical centre with writing-mode vertical text
On hover slide out to the right with the label; a same-colour left shadow keeps the screen edge covered
- Id badge (.sl-card-id):
Size to the 24px token; min-width plus a pill radius render a circle for a single digit and widen for more
- Footer feedback styles:
Remove the now-unused .sl-block-feedback-form / .sl-bff-* and #block-feedback dropdown rules
Benefits:
- One floating mechanism shared with the admin theme
- Side tabs no longer clipped by the right-hand scrollbar
- Cleaner, token-driven badges and tabs
Technical notes:
- Frontend (lite) theme only
Adopt the .sl-float / .sl-float-panel contract in the admin theme and polish the monitor page: fix the gauge percentage colours, drop the unwanted info-block scroll, align the chart tooltip surface and add jump links from the Software panel.
Core changes:
- Admin theme (templates/admin/assets/css/theme.css):
Collapse the paired .sl-tip / .sl-menu rules onto .sl-float-panel and the sl-is-open state
Server Status: let the % text inherit the gauge colour by dropping the static colour override
- Remove the info-grid overflow-x that forced a vertical scrollbar
- Match the chart tooltip surface to the popover tokens
- Turn the Software items into smooth-scrolling jump links
- Monitor markup (templates/admin/partials/basic-monitor.html):
- Add anchor ids to the Server/PHP/MySQL blocks and link the Software rows
- Monitor module (admin/modules/monitor.php):
- Render the diagnostic cells through the unified popover (icon + value)
- Bump the chart tip corner radius to match the panel
Benefits:
- Consistent floating UI and monitor styling
- Clearer at-a-glance Server Status colours
- Quicker navigation inside the monitor page
Technical notes:
- Admin-only; no behaviour change outside the monitor
Collapse the separate info-tooltip, row-actions and editor-action-menu templates into a single popover fragment per theme and migrate every call site, so all floating popovers share one markup contract built on the .sl-float / .sl-float-panel primitive.
Core changes:
- Unified fragment (templates/{admin,lite}/fragments/popover.html):
Add one popover that renders either a tip (icon + text/dl) or an action menu, selected from the passed keys
- Delete info-tooltip.html, row-actions.html and editor-action-menu.html
- Call sites (core/.php, admin/modules/.php, modules/*/.php):
- Point ~100 getHtmlFrag() calls at the new popover fragment
- Repoint the edit-actions.html and view.html includes
- Frontend markup (templates/lite/fragments + partials):
Tag tip/menu/dropdown hosts with .sl-float and panels with .sl-float-panel; mark click dropdowns with data-sl-float-event="click"
- Drop the now-inert data-sl-toggle-effect attributes from float dropdowns
Benefits:
- One popover contract instead of three near-duplicate fragments
- Behaviour and output-escaping boundaries preserved
- Smaller, easier to reason about template surface
Technical notes:
Tip vs menu is inferred from menu-only keys; raw vs escaped output is unchanged
- No backend or database changes