Skip to content

feat: add custom resolution viewport with positioning options#24

Open
gonzamoiguer wants to merge 4 commits intoinnovation-system:mainfrom
gonzamoiguer:feature/simulated-resolution
Open

feat: add custom resolution viewport with positioning options#24
gonzamoiguer wants to merge 4 commits intoinnovation-system:mainfrom
gonzamoiguer:feature/simulated-resolution

Conversation

@gonzamoiguer
Copy link
Copy Markdown

@gonzamoiguer gonzamoiguer commented Feb 27, 2026

This pr proposes the option to load page inside an iframe with fixed resolution, for those projects and installations where the final user viewport is smaller than the actual physical screen.
Resolves #23

  • Add custom resolution settings (global and per-display)
  • Implement viewport.html with iframe for rendering sites at custom resolutions
  • Add position selector (9 preset positions: top/center/bottom × left/center/right)
  • Update UI with resolution controls and position picker
  • Maintain fullscreen kiosk mode while rendering sites at specified dimensions
  • Support independent resolution configuration for multiple displays

- Add custom resolution settings (global and per-display)
- Implement viewport.html with iframe for rendering sites at custom resolutions
- Add position selector (9 preset positions: top/center/bottom × left/center/right)
- Update UI with resolution controls and position picker
- Maintain fullscreen kiosk mode while rendering sites at specified dimensions
- Support independent resolution configuration for multiple displays
Copy link
Copy Markdown
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also wondering if there is a cleaner way to handle this from electron side

Comment thread package.json Outdated
{
"name": "electron-kiosk",
"version": "0.10.0",
"version": "0.10.1",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do this, this is bumped automatically

Comment thread src/renderer/src/App.vue Outdated
v => !!v || 'Width is required',
v => v >= 320 || 'Minimum width is 320px'
]"
@input="validateForm"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove all @input and @updatemodel-value. Validaiton is lazy

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for rendering configured URLs inside a fixed-size “simulated viewport” (via an iframe wrapper page), enabling pixel-perfect layouts on unconventional downstream/scaled display resolutions while keeping the Electron app itself in fullscreen kiosk mode.

Changes:

  • Introduces global + per-display “Custom Resolution” settings (width/height + 9-position alignment).
  • Adds a new viewport.html renderer entry that embeds the target URL in a sized/positioned iframe.
  • Updates renderer build config to include viewport.html as an additional HTML entry.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/store.js Adds persisted settings fields for custom resolution + positioning (global and per-display).
src/renderer/viewport.html New iframe-based wrapper page that enforces a fixed render size and alignment.
src/renderer/src/App.vue Adds UI controls for configuring custom resolution and redirects to the viewport wrapper when enabled.
electron.vite.config.js Ensures viewport.html is bundled as a renderer entry alongside index.html.
package.json Bumps package version (but release process appears to handle this automatically).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/renderer/src/App.vue Outdated
Comment on lines +509 to +512
// Trigger form validation
if (this.$refs.form) {
this.$refs.form.validate()
}
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateForm() forces immediate form validation and is wired to multiple @input/@change handlers, which defeats Vuetify's lazy validation behavior and can cause noisy UX/perf issues. Remove this method and the event handlers that call it, and rely on the existing submit-time validation (this.$refs.form.validate() in updateSettings).

Suggested change
// Trigger form validation
if (this.$refs.form) {
this.$refs.form.validate()
}
// Intentionally left blank: rely on submit-time validation
// via this.$refs.form.validate() in updateSettings().

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +46
// Get parameters from URL
const params = new URLSearchParams(window.location.search);
const targetUrl = params.get('url');
const width = params.get('width') || '1920';
const height = params.get('height') || '1080';
const position = params.get('position') || 'top-left';

// Set iframe properties
const iframe = document.getElementById('viewport-frame');
iframe.src = targetUrl;
iframe.style.width = width + 'px';
iframe.style.height = height + 'px';

Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

targetUrl, width, and height are taken directly from query params and used to set iframe.src and inline styles without validation. Parse width/height as integers (and clamp to reasonable min/max), and handle missing/invalid url by showing an error state instead of navigating the iframe to null/invalid URLs.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +43
<iframe id="viewport-frame"></iframe>

<script>
// Get parameters from URL
const params = new URLSearchParams(window.location.search);
const targetUrl = params.get('url');
const width = params.get('width') || '1920';
const height = params.get('height') || '1080';
const position = params.get('position') || 'top-left';

// Set iframe properties
const iframe = document.getElementById('viewport-frame');
iframe.src = targetUrl;
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the iframe is not sandboxed, many sites can “break out” of the simulated viewport by setting top.location (or similar frame-busting), which defeats the custom-resolution wrapper. Consider adding an iframe sandbox that blocks top-level navigation (potentially with a configurable allowlist for features like forms/scripts) so the wrapper reliably enforces the viewport.

Copilot uses AI. Check for mistakes.
Comment on lines +64 to +67
// Handle iframe load errors
iframe.onerror = function() {
console.error('Failed to load URL in viewport:', targetUrl);
};
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iframe.onerror generally won’t fire for common iframe load failures (e.g., X-Frame-Options / CSP frame-ancestors blocking, DNS errors). Consider adding a visible fallback UI (and/or a timeout) that informs the user the page couldn’t be embedded, rather than relying on onerror which may never run.

Copilot uses AI. Check for mistakes.
Comment thread package.json Outdated
{
"name": "electron-kiosk",
"version": "0.10.0",
"version": "0.10.1",
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package version is being bumped in this PR, but the repository release process appears to manage versioning automatically. Please revert this change to avoid conflicting with automated version bumps.

Suggested change
"version": "0.10.1",
"version": "0.10.0",

Copilot uses AI. Check for mistakes.
@gonzamoiguer
Copy link
Copy Markdown
Author

You are right about validation, I was having issues under certain circumstances, the update button kept being disabled, but its out the scope of this PR. Undid that to keep it the way it worked.

Specifically, what do you mean with cleaner from the electron side ?

@robertsLando
Copy link
Copy Markdown
Member

Specifically, what do you mean with cleaner from the electron side ?

I mean that maybe you could set viewport and resolution from backend that spawns the window instead, not sure about this just asking if you checked this path

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.

New Feature: Simulated Resolution

3 participants