diff --git a/.changeset/fix-preview-scaling.md b/.changeset/fix-preview-scaling.md new file mode 100644 index 00000000..c22c744b --- /dev/null +++ b/.changeset/fix-preview-scaling.md @@ -0,0 +1,5 @@ +--- +'@open-codesign/desktop': patch +--- + +Preserve preview artboard scroll bounds at scaled zoom levels to prevent desktop and tablet previews from being clipped. diff --git a/.github/workflows/codex-pr-review.yml b/.github/workflows/codex-pr-review.yml index 5d8b7c28..918a261f 100644 --- a/.github/workflows/codex-pr-review.yml +++ b/.github/workflows/codex-pr-review.yml @@ -121,6 +121,11 @@ jobs: [ -n "$effort" ] || effort="$DEFAULT_EFFORT" [ -n "$effort" ] || effort='high' + fallback_model="$DEFAULT_MODEL" + [ -n "$fallback_model" ] || fallback_model='gpt-5.4' + fallback_effort="$DEFAULT_EFFORT" + [ -n "$fallback_effort" ] || fallback_effort='high' + is_deepseek='false' case "$base_url" in *api.deepseek.com*) @@ -134,6 +139,10 @@ jobs: echo "model=$model" echo "effort=$effort" echo "is_deepseek=$is_deepseek" + echo "fallback_api_key=$DEFAULT_API_KEY" + echo "fallback_base_url=$DEFAULT_BASE_URL" + echo "fallback_model=$fallback_model" + echo "fallback_effort=$fallback_effort" } >> "$GITHUB_OUTPUT" - name: Set up Node.js for DeepSeek review @@ -143,7 +152,9 @@ jobs: node-version: "20" - name: Run DeepSeek for PR Review + id: run_deepseek if: steps.check_bot.outputs.has_review_for_current_head != 'true' && steps.review_config.outputs.is_deepseek == 'true' + continue-on-error: true env: GH_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }} @@ -159,7 +170,7 @@ jobs: - name: Run Codex for PR Review id: run_codex - if: steps.check_bot.outputs.has_review_for_current_head != 'true' && steps.review_config.outputs.is_deepseek != 'true' + if: always() && steps.check_bot.outputs.has_review_for_current_head != 'true' && (steps.review_config.outputs.is_deepseek != 'true' || steps.run_deepseek.outcome == 'failure') uses: openai/codex-action@e0fdf01220eb9a88167c4898839d273e3f2609d1 # v1 env: GH_TOKEN: ${{ github.token }} @@ -169,10 +180,10 @@ jobs: LATEST_BOT_REVIEW_COMMIT: ${{ steps.check_bot.outputs.latest_bot_review_commit }} IS_FOLLOW_UP_REVIEW: ${{ steps.check_bot.outputs.is_follow_up_review }} with: - openai-api-key: ${{ steps.review_config.outputs.api_key }} - responses-api-endpoint: ${{ steps.review_config.outputs.base_url }} - model: ${{ steps.review_config.outputs.model }} - effort: ${{ steps.review_config.outputs.effort }} + openai-api-key: ${{ steps.review_config.outputs.fallback_api_key }} + responses-api-endpoint: ${{ steps.review_config.outputs.fallback_base_url }} + model: ${{ steps.review_config.outputs.fallback_model }} + effort: ${{ steps.review_config.outputs.fallback_effort }} sandbox: danger-full-access safety-strategy: drop-sudo prompt-file: .github/prompts/codex-pr-review.md diff --git a/apps/desktop/src/renderer/src/components/PreviewPane.test.ts b/apps/desktop/src/renderer/src/components/PreviewPane.test.ts index b433f7b1..d2ec2ad3 100644 --- a/apps/desktop/src/renderer/src/components/PreviewPane.test.ts +++ b/apps/desktop/src/renderer/src/components/PreviewPane.test.ts @@ -13,6 +13,7 @@ import { previewArtboardStyle, previewPaneLayoutClasses, previewViewportDimensions, + scaledPreviewFrameStyle, scaleRectForZoom, stablePreviewSourceKey, } from './PreviewPane'; @@ -116,6 +117,15 @@ describe('preview artboard frame', () => { }), ).toBe(100); }); + + it('preserves scaled desktop dimensions as minimum scroll bounds', () => { + expect(scaledPreviewFrameStyle('desktop', 150)).toEqual({ + width: '2160px', + height: '1350px', + minWidth: '2160px', + minHeight: '1350px', + }); + }); }); describe('preview pane welcome state', () => { diff --git a/apps/desktop/src/renderer/src/components/PreviewPane.tsx b/apps/desktop/src/renderer/src/components/PreviewPane.tsx index a7125b39..0fe12b1e 100644 --- a/apps/desktop/src/renderer/src/components/PreviewPane.tsx +++ b/apps/desktop/src/renderer/src/components/PreviewPane.tsx @@ -167,6 +167,18 @@ export function previewArtboardFrameClass(): string { return ARTBOARD_FRAME_CLASS; } +export function scaledPreviewFrameStyle( + viewport: PreviewSlotProps['viewport'], + zoom: number, +): CSSProperties { + const frame = previewViewportDimensions(viewport); + const scale = zoom / 100; + const width = `${Math.round(frame.width * scale)}px`; + const height = `${Math.round(frame.height * scale)}px`; + + return { width, height, minWidth: width, minHeight: height }; +} + function ScaledPreviewFrame({ viewport, zoom, @@ -179,13 +191,7 @@ function ScaledPreviewFrame({ const frame = previewViewportDimensions(viewport); const scale = zoom / 100; return ( -