Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix web stage 'Keep Style' rendering not matching the app#3499

Merged
vassbo merged 1 commit into
ChurchApps:devChurchApps/FreeShow:devfrom
vicholz:cfix-webstage-keepstylevicholz/FreeShow:cfix-webstage-keepstyleCopy head branch name to clipboard
Jul 13, 2026
Merged

Fix web stage 'Keep Style' rendering not matching the app#3499
vassbo merged 1 commit into
ChurchApps:devChurchApps/FreeShow:devfrom
vicholz:cfix-webstage-keepstylevicholz/FreeShow:cfix-webstage-keepstyleCopy head branch name to clipboard

Conversation

@vicholz

@vicholz vicholz commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Branch: cfix-webstage-keepstyle

Commit: 110f19e1 (branched from dev)

Summary

Fixes the web StageShow (browser) rendering of slide text items with "Keep Style" checked not matching the stage layout preview inside FreeShow. The web client's port of the slide-text renderer had drifted from the app's in four ways — original item layout was discarded, font sizes were overridden, the canvas used the wrong resolution, and two behavior options were applied differently.

Divergence (web vs app) Effect Fix
display: contents always appended + item bounds rescaled to the browser window Original item box/position thrown away Ported the app's originalStyle mode
Stage item's font size (default 100px) injected over every text span Slide's real font sizes overridden Keep Style now passes fontSize={0} like the app
Slide canvas used browser window resolution Item coordinates mis-scaled on any non-1080p window Canvas uses the slide's actual resolution
Auto-size keyed to deprecated item.auto; lineCount truncated the current slide Modern shows never auto-sized; text cut off Matches the app: textFit-based, lineCount only for next/previous previews

Deep dive

How "Keep Style" works in the app

A slide_text stage item normally re-renders slide text with stage-defined styling. With Keep Style (keepStyle) checked, the app instead renders the slide's items exactly as they appear on the output — original position, size, and text styling — inside a scaled-down slide-resolution canvas:

<!-- frontend SlideText.svelte (style = keepStyle) -->
<Main let:resolution let:width let:height>
    <Zoomed background="transparent" style={getStyleResolution(resolution, width, height, "fit")} center>
        <Textbox {item} ... isStage originalStyle />
    </Zoomed>
</Main>

The originalStyle flag is the key: the app's Textbox only resets the item's own box when it is not set:

// frontend Textbox.svelte
if (isStage && !originalStyle) {
    currentStyle += "display: contents;"
}

What the web client did instead

The stage server has its own ports of SlideText/Textbox/Zoomed, and the keep-style path had drifted:

  1. Layout discarded — the web Textbox always appended display: contents (dissolving the item's box: position, dimensions, background), and separately rescaled the item's bounds from slide space to the browser window — inside a canvas that already scales:
// server Textbox.svelte (before)
function getCustomStyle(style) {
    style += "display: contents;"     // unconditional
    return style
}
if (autoStage) itemStyle = itemStyle + newSizes   // window-relative rescale
  1. Font size stomped — the text spans appended a font-size override whenever fontSize was truthy, and Stagebox always passed the stage item's font size (default 100px):
<span style="{style ? text.style + (fontSize ? 'font-size: ' + fontSize + 'px;' : '') : ...}">

The app deliberately passes fontSize={0} for slide text ("don't pass fontSize from item style, which is MAX_FONT_SIZE=800").

  1. Wrong canvas resolution — the web Zoomed defaults to dynamicResolution: true, overriding the canvas with window.innerWidth/innerHeight. Item coordinates are defined in slide space (1920×1080), so positions only lined up if the browser happened to be fullscreen 1080p:
// server Zoomed.svelte
let resolution = show?.settings.resolution || { width: 1920, height: 1080 }
if (dynamicResolution) resolution = { width: window.innerWidth, height: window.innerHeight }  // ← the problem
  1. Option semantics — auto-size was keyed to the deprecated item.auto flag instead of textFit (modern shows only set textFit, so they never auto-sized on the web), and the stage "line count" limit was applied to the current slide, where the app only applies it to next/previous slide previews:
// app:  maxLines={Number(slideOffset !== 0 && stageItem.lineCount)}
// web:  maxLines={Number(stageItem.lineCount)}          ← truncated the live slide

The fix

The web Textbox gained the app's originalStyle mode:

export let originalStyle: boolean = false // keep the slide item's own box/position/text styles ("Keep Style")

// keep the item's original bounds when rendering inside a slide-resolution canvas
if (autoStage && !originalStyle) itemStyle = itemStyle + newSizes

function getCustomStyle(style) {
    // reset item styles (as it's set in parent item) - unless keeping the slide item's own layout
    if (!originalStyle) style += "display: contents;"
    return style
}

And the web SlideText keep-style branch now mirrors the app exactly — slide-resolution canvas, original font sizes, textFit-based auto-size, offset-only line limits:

$: slideResolution = (slide as any)?.settings?.resolution || { width: 1920, height: 1080 }

<Zoomed show={{ settings: { resolution: slideResolution } }} dynamicResolution={false}
        style={getStyleResolution(slideResolution, width, height, "fit")} center>
    <Textbox showId={currentSlide.id} {item} originalStyle
             maxLines={Number(slideOffset !== 0 && stageItem.lineCount)}
             autoSize={(item.textFit !== "none" || item.auto) && autoSize}
             fontSize={0} ... />
</Zoomed>

With fontSize={0}, the span override is skipped and the slide's own text styles apply; when auto-size is enabled, the computed size still takes over (same as the app). The Stagebox call site was aligned too (autoSize={item.textFit !== "none" && item.auto !== false}).

Known remaining difference

Auto-sized text uses a simpler measuring algorithm on the web client than the app's, so auto-fitted items can differ by a small font-size margin. Static keep-style items (the common case) now match exactly.

Verification

Stage server bundle builds cleanly; prettier passes; no new svelte-check findings. Rendering parity is best confirmed visually: open the web stage display with a Keep Style layout and compare against the in-app stage preview (hard-refresh the browser — the stage page is PWA-cached).


🤖 Generated with Claude Code

The web StageShow client's slide_text "Keep Style" path had drifted from
the app's renderer, so the browser display didn't match the stage layout
preview in FreeShow:

- The item's original box/position was discarded (display: contents was
  always appended, and item bounds were rescaled to the browser window
  inside the already-scaled slide canvas). Textbox now supports
  originalStyle, keeping the slide item's own layout like the app does.
- Original font sizes were overridden with the stage item's font size
  (default 100px). Keep Style now passes fontSize 0 so the slide's own
  text styles apply, same as the app.
- The slide canvas used the browser window resolution instead of the
  slide resolution, mis-scaling item coordinates on any non-1080p window.
- Auto-size was keyed to the deprecated item.auto flag instead of textFit,
  and the stage line count limit was applied to the current slide instead
  of only to next/previous slide previews.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vassbo
vassbo merged commit e7304ab into ChurchApps:dev Jul 13, 2026
vassbo added a commit that referenced this pull request Jul 16, 2026
* Don't fail license check if offline

* Fixed Flipped Checkbox Logic (#3474)

* Added Conditions button for Output window item #3461

* Fixed output stacking #3469

* Prebuilt Aero Peak Helper #3476

* Applied code changes sent in by Amazing Life Foundation.

* Fix import of pro6 files (#3487)

* Updated the bug report template. Mainly to ask users to check for duplicate bugs and test on the latest stable and beta versions before filling, but also added directions to encourage the users to help figure out if a certain OS or in what version of FreeShow the issue started. (#3507)

* Fix undo/redo media leak and layout corruption in SLIDES history (#3497)

* Fix stage output window lag/freeze and reduce capture overhead (#3498)

* Removed unused Mirror item

* Fix web stage 'Keep Style' rendering not matching the app (#3499)

* Fix audio playlist stopping after one song (#3500)

* Fixed StageShow item size not stretching to large resolutions

* Fixed server not auto starting after toggled back on

* Fixing errors

* Fixed many files loading at once

* Fixed errors

* Fixing errors

* Smarter auto groups #3511

* Remove unused List item

* Fixed Focus mode navigation through duplicated shows #3467

* Fixed template Styles overwrites not working correctly with auto size #3480

* Remove list item remains

* Tweaked Sentry logging init

* Added script to rebuild OPUS propely in case of Not found!

* Toggle to disable PCO auto sync on startup #3490

* Merge improvements #3492

* Internal pasting keeps formatting #3493

* Missing Visual C++ Redistributable Info

* Event item from/to time of day

* Fixed line align updating

* Enhancements

* Fixed text selection sometimes deselected when it should not

* Fixed text selection sometimes deselected when it should not

* Fixed Spotify time jumping

* Enhancements

* Interaction updates

* Tips

* Tweak

* Updated Polish language

* Added syncManager test
- Cloud fixes

* Fixed output stacking sometimes

* Fixed Planning Center shows replaced when also syncing to cloud #2777

* Content provider run timer

* Reduced expand arrows
- Moved some buttons to context menus
- Fixed NDI inputs groups option not showing

* Fixed cloud test casing

* Edit mode tabs

* Unique tab name

* Unique tab name

* Fixed slide zoom in

* Fixed new cloud devices not marking uploads as new

* Added three machine sync test

* Fixed startup sync

* Changed fallback char from | to ?

* Tweak

* Split multiple items in two #3477

* Fixed scripture show verses not splitted in two properly

* Text edit highlighted #3468

* Fixed scroll height

* Highlight dynamic values

* Version update

---------

Co-authored-by: Jeremy Zongker <jeremy@zongker.net>
Co-authored-by: David Myers <david.d.myers@gmail.com>
Co-authored-by: Jonas <32509408+Toaster996@users.noreply.github.com>
Co-authored-by: Frederick Henderson <frederickjh@users.noreply.github.com>
Co-authored-by: Victor <vicholz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.