11import 'dart:math' as math;
22
33import 'package:flutter/widgets.dart' ;
4+ import 'package:querya_desktop/core/layout/ui_scale.dart' ;
45
56/// Breakpoints and sizes derived from window / overlay size (desktop adaptive UI).
67abstract class WindowLayout {
@@ -18,6 +19,36 @@ abstract class WindowLayout {
1819 return (screenHeight * 0.04 ).clamp (12.0 , 40.0 );
1920 }
2021
22+ /// Scaled [BoxConstraints] for modal dialogs (respects [QueryaUiScaleScope] ).
23+ static BoxConstraints dialogConstraints (
24+ BuildContext context, {
25+ double ? maxWidth,
26+ double ? minWidth,
27+ double ? maxHeight,
28+ double ? minHeight,
29+ }) {
30+ return BoxConstraints (
31+ maxWidth: maxWidth != null ? context.scaled (maxWidth) : double .infinity,
32+ minWidth: minWidth != null ? context.scaled (minWidth) : 0 ,
33+ maxHeight: maxHeight != null ? context.scaled (maxHeight) : double .infinity,
34+ minHeight: minHeight != null ? context.scaled (minHeight) : 0 ,
35+ );
36+ }
37+
38+ /// Fits a base dialog dimension into the viewport, then applies UI scale.
39+ static double scaledDialogExtent (
40+ BuildContext context, {
41+ required double screenExtent,
42+ required double insetTotal,
43+ required double baseMax,
44+ required double baseMin,
45+ double viewportFactor = 1.0 ,
46+ }) {
47+ final available = math.max (0.0 , screenExtent - insetTotal);
48+ final base = math.min (baseMax, math.max (baseMin, available * viewportFactor));
49+ return math.min (context.scaled (base ), available);
50+ }
51+
2152 /// Use for [Dialog.insetPadding] / modal margins on small windows.
2253 static EdgeInsets dialogSymmetricInsets (BuildContext context) {
2354 final mq = MediaQuery .sizeOf (context);
@@ -28,15 +59,30 @@ abstract class WindowLayout {
2859 }
2960
3061 /// "Select database" and similar pickers.
31- static double newConnectionDialogMaxWidth (double screenWidth) {
32- final inset = dialogHorizontalInset (screenWidth) * 2 ;
33- return math.min (740 , math.max (280.0 , screenWidth - inset));
62+ static double newConnectionDialogMaxWidth (BuildContext context) {
63+ final mq = MediaQuery .sizeOf (context);
64+ final inset = dialogHorizontalInset (mq.width) * 2 ;
65+ return scaledDialogExtent (
66+ context,
67+ screenExtent: mq.width,
68+ insetTotal: inset,
69+ baseMax: 740 ,
70+ baseMin: 280 ,
71+ viewportFactor: 1.0 ,
72+ );
3473 }
3574
36- static double newConnectionDialogHeight (double screenHeight) {
37- final inset = dialogVerticalInset (screenHeight) * 2 ;
38- final h = screenHeight - inset;
39- return math.min (580 , math.max (320.0 , h * 0.78 ));
75+ static double newConnectionDialogHeight (BuildContext context) {
76+ final mq = MediaQuery .sizeOf (context);
77+ final inset = dialogVerticalInset (mq.height) * 2 ;
78+ return scaledDialogExtent (
79+ context,
80+ screenExtent: mq.height,
81+ insetTotal: inset,
82+ baseMax: 580 ,
83+ baseMin: 320 ,
84+ viewportFactor: 0.78 ,
85+ );
4086 }
4187
4288 static double newConnectionSidebarWidth (double dialogWidth) {
@@ -53,12 +99,13 @@ abstract class WindowLayout {
5399 return 1 ;
54100 }
55101
56- static double dbTypeCardHeight (int crossAxisCount) {
57- return switch (crossAxisCount) {
58- 4 => 144 ,
59- 2 => 138 ,
60- _ => 132 ,
102+ static double dbTypeCardHeight (BuildContext context, int crossAxisCount) {
103+ final base = switch (crossAxisCount) {
104+ 4 => 144.0 ,
105+ 2 => 138.0 ,
106+ _ => 132.0 ,
61107 };
108+ return context.scaled (base );
62109 }
63110
64111 /// Empty workspace hero content max width (stays within viewport minus padding).
0 commit comments