Skip to content

Commit 1567102

Browse files
committed
Added support for responsiveness and updated readme
1 parent 3ac8ae0 commit 1567102

File tree

5 files changed

+335
-202
lines changed

5 files changed

+335
-202
lines changed

README.md

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ This is a UI/UX concept app for creative exploration and experimentation.
1616

1717
## 📥 Download Links
1818

19-
| Platform | Download Link |
20-
|-------------|----------------------------------------------------------------|
21-
| **Web** | [Open in Browser](https://mdrconsole.srinivasa.dev/) |
19+
| Platform | Download Link |
20+
|-------------|-----------------------------------------------------------------------------------------------------------------------------|
21+
| **Web** | [Open in Browser](https://mdrconsole.srinivasa.dev/) |
2222
| **Windows** | [Download Windows App](https://raw.githubusercontent.com/srinivasa-dev/severance-mdr-console/main/downloads/MDRConsole.exe) |
23-
| **macOS** | [Download macOS App](https://raw.githubusercontent.com/srinivasa-dev/severance-mdr-console/main/downloads/MDRConsole.dmg) |
23+
| **macOS** | [Download macOS App](https://raw.githubusercontent.com/srinivasa-dev/severance-mdr-console/main/downloads/MDRConsole.dmg) |
2424

2525
---
2626

@@ -49,15 +49,19 @@ This is a UI/UX concept app for creative exploration and experimentation.
4949
## 📁 Project Structure
5050
```bash
5151
lib/
52-
├── main.dart # App entry point and platform handling
53-
├── ui_theme.dart # Global styles, fonts, and colors
54-
├── splash_screen.dart # Initial splash screen widget
52+
├── main.dart # App entry point and platform handling
53+
├── ui_theme.dart # Global styles, fonts, and colors
54+
├── splash_screen.dart # Initial splash screen widget
5555
├── screens/
56-
│ └── severance_home.dart # Main home screen containing MDR interface
56+
│ └── severance_home.dart # Main home screen containing MDR interface
5757
└── widgets/
58-
├── bin_target.dart # Widget for displaying and interacting with bin targets
59-
├── animated_hover_digit.dart # Animated numeric display on hover
60-
├── custom_divider.dart # Custom divider with styling
58+
├── bin_target.dart # Widget for displaying and interacting with
59+
bin targets
60+
├── animated_hover_digit.dart # Animated numeric display on hover
61+
├── custom_divider.dart # Custom divider with styling
62+
├── utils/
63+
└── global_scale.dart # Contains the ScaleFactorProvider class for
64+
screen size adjustments
6165
```
6266

6367
### 🔍 File Details
@@ -83,6 +87,10 @@ lib/
8387
- **widgets/custom_divider.dart**
8488
A stylized divider line widget used for separating UI sections.
8589

90+
- **utils/global_scale.dart**
91+
This file contains the `ScaleFactorProvider` class, which calculates and applies a scale factor based on the device’s screen width.
92+
It helps ensure that the UI remains proportionate and readable across different screen sizes by dynamically adjusting the size of UI elements.
93+
8694
---
8795

8896
### 🖱️ Custom Cursor Implementation
@@ -142,6 +150,30 @@ This code ensures that the custom cursor is set when the app launches on macOS,
142150

143151
---
144152

153+
## ⚙️ Scale Factor Adjustment
154+
155+
To ensure the app's UI adapts across different screen sizes, the `ScaleFactorProvider` class provides dynamic scaling of UI elements based on the device's screen width. This allows for a consistent user experience on various devices, from small screens to larger displays.
156+
157+
### How it Works
158+
159+
1. **Scale Factor Calculation**
160+
The `updateScaleFactor` method takes the current screen width and assigns an appropriate scale factor:
161+
- Smaller screens have a reduced scale factor.
162+
- Larger screens use a scale factor closer to `1.0` (no scaling).
163+
164+
This method helps ensure that the UI remains usable and well-proportioned on all devices.
165+
166+
2. **Scaling Values**
167+
The `scaleValue` method multiplies the provided value by the current scale factor, ensuring that dimensions and spacing are adjusted accordingly.
168+
169+
Example usage in the app:
170+
```dart
171+
ScaleFactorProvider.updateScaleFactor(context);
172+
double scaledValue = ScaleFactorProvider.scaleValue(originalValue);
173+
```
174+
175+
---
176+
145177
## ▶️ Getting Started
146178

147179
### Prerequisites
@@ -156,7 +188,7 @@ This code ensures that the custom cursor is set when the app launches on macOS,
156188
git clone https://github.com/srinivasa-dev/severance-mdr-console.git
157189
cd severance-mdr-console
158190
flutter pub get
159-
flutter run -d windows # or chrome, macos, etc.
191+
flutter run -d windows # or chrome, macos.
160192
```
161193

162194
---

lib/screens/severance_home.dart

Lines changed: 82 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:macrodata_refinement/widgets/footer.dart';
66
import 'package:url_launcher/url_launcher.dart';
77

88
import '../ui_theme.dart';
9+
import '../utils/global_scale.dart';
910
import '../widgets/animated_hover_digit.dart';
1011
import '../widgets/bin_target.dart';
1112

@@ -17,10 +18,8 @@ class SeveranceHomePage extends StatefulWidget {
1718
}
1819

1920
class _SeveranceHomePageState extends State<SeveranceHomePage> {
20-
final List<List<int>> grid = List.generate(
21-
20,
22-
(_) => List.generate(20, (_) => Random().nextInt(10)),
23-
);
21+
int _crossAxisCount = 20;
22+
List<List<int>> grid = [];
2423

2524
final Map<int, int> binProgress = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0};
2625

@@ -36,15 +35,35 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
3635
List<GlobalKey> _binKeys = List.generate(5, (j) => GlobalKey());
3736
Map<int, GlobalKey> gridKeys = {};
3837

38+
late double scaleFactor;
39+
3940
@override
4041
void initState() {
41-
// Initialize
42+
grid = List.generate(
43+
_crossAxisCount,
44+
(_) => List.generate(_crossAxisCount, (_) => Random().nextInt(10)),
45+
);
46+
4247
for (int i = 0; i < 400; i++) {
4348
gridKeys[i] = GlobalKey();
4449
}
50+
scaleFactor = ScaleFactorProvider.scaleFactor;
4551
super.initState();
4652
}
4753

54+
@override
55+
void didChangeDependencies() {
56+
super.didChangeDependencies();
57+
// Update the scale factor when the screen size or orientation changes
58+
ScaleFactorProvider.updateScaleFactor(context);
59+
scaleFactor = ScaleFactorProvider.scaleFactor;
60+
_crossAxisCount = scaleFactor <= 0.8 ? 10 : 20;
61+
grid = List.generate(
62+
_crossAxisCount,
63+
(_) => List.generate(_crossAxisCount, (_) => Random().nextInt(10)),
64+
);
65+
}
66+
4867
void _addAnimatedDigitOverlay(Offset start, Offset end, int value) {
4968
final overlay = Overlay.of(context);
5069
final entry = OverlayEntry(
@@ -83,25 +102,28 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
83102
Stack(
84103
children: [
85104
Positioned(
86-
right: 25.0,
105+
right: 25.0 * scaleFactor,
87106
top: 0,
88107
bottom: 0,
89108
child: Transform.scale(
90-
scale: 0.6,
109+
scale: 0.6 * scaleFactor,
91110
child: Image.asset(
92111
'assets/lumon-logo.png',
93112
color: UITheme.themeColor,
94113
),
95114
),
96115
),
97116
Container(
98-
margin: const EdgeInsets.symmetric(
99-
vertical: 18.0,
100-
horizontal: 60.0,
117+
margin: EdgeInsets.symmetric(
118+
vertical: 18.0 * scaleFactor,
119+
horizontal: 60.0 * scaleFactor,
101120
),
102-
padding: const EdgeInsets.symmetric(horizontal: 6.0),
121+
padding: EdgeInsets.symmetric(horizontal: 6.0 * scaleFactor),
103122
decoration: BoxDecoration(
104-
border: Border.all(color: UITheme.themeColor, width: 2.0),
123+
border: Border.all(
124+
color: UITheme.themeColor,
125+
width: 2.0 * scaleFactor,
126+
),
105127
),
106128
child: Row(
107129
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -118,15 +140,18 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
118140
},
119141
child: Text(
120142
'Nivasael',
121-
style: UITheme.uiFont(20, fontWeight: FontWeight.w700),
143+
style: UITheme.uiFont(
144+
20.0 * scaleFactor,
145+
fontWeight: FontWeight.w700,
146+
),
122147
),
123148
),
124149
Padding(
125-
padding: const EdgeInsets.only(right: 100.0),
150+
padding: EdgeInsets.only(right: 100.0 * scaleFactor),
126151
child: Text(
127152
'$totalProgress% Complete',
128153
style: UITheme.uiFont(
129-
20,
154+
20.0 * scaleFactor,
130155
color: Colors.transparent,
131156
fontWeight: FontWeight.w600,
132157
).copyWith(
@@ -144,20 +169,20 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
144169
],
145170
),
146171
CustomDivider(),
147-
CustomDivider(height: 10.0),
172+
CustomDivider(height: 10.0 * scaleFactor),
148173
Expanded(
149174
child: GridView.builder(
150175
itemCount: grid.length * grid[0].length,
151-
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
152-
crossAxisCount: 20,
153-
mainAxisSpacing: 4,
154-
crossAxisSpacing: 4,
155-
childAspectRatio: 0.8,
176+
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
177+
crossAxisCount: _crossAxisCount,
178+
mainAxisSpacing: 4 * scaleFactor,
179+
crossAxisSpacing: 4 * scaleFactor,
180+
childAspectRatio: 0.8 * scaleFactor,
156181
),
157182
padding: EdgeInsets.zero,
158183
itemBuilder: (context, index) {
159-
int row = index ~/ 20;
160-
int col = index % 20;
184+
int row = index ~/ _crossAxisCount;
185+
int col = index % _crossAxisCount;
161186
int val = grid[row][col];
162187

163188
bool isHovered = false;
@@ -172,36 +197,38 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
172197

173198
return GestureDetector(
174199
onTap: () {
175-
if (isHovered) {
176-
// Mark the entire region as active when tapped
177-
setState(() {
200+
// Mark the entire region as active when tapped
201+
setState(() {
202+
hoveredRow = row;
203+
hoveredCol = col;
204+
205+
for (int r = hoveredRow! - 1; r <= hoveredRow! + 1; r++) {
178206
for (
179-
int r = hoveredRow! - 1;
180-
r <= hoveredRow! + 1;
181-
r++
207+
int c = hoveredCol! - 1;
208+
c <= hoveredCol! + 1;
209+
c++
182210
) {
183-
for (
184-
int c = hoveredCol! - 1;
185-
c <= hoveredCol! + 1;
186-
c++
187-
) {
188-
if (r >= 0 && r < 20 && c >= 0 && c < 20) {
189-
int activeIndex = r * 20 + c;
190-
activeIndices.add(
191-
activeIndex,
192-
); // Add the index to the active set
193-
}
211+
if (r >= 0 &&
212+
r < _crossAxisCount &&
213+
c >= 0 &&
214+
c < _crossAxisCount) {
215+
int activeIndex = r * _crossAxisCount + c;
216+
activeIndices.add(
217+
activeIndex,
218+
); // Add the index to the active set
194219
}
195220
}
196-
});
197-
}
221+
}
222+
});
198223
},
199224
child: Container(
200-
key: gridKeys[row * 20 + col],
225+
key: gridKeys[row * _crossAxisCount + col],
201226
child: AnimatedHoverDigit(
202227
value: val,
203228
isHovering: isHovered,
204-
isActive: activeIndices.contains(row * 20 + col),
229+
isActive: activeIndices.contains(
230+
row * _crossAxisCount + col,
231+
),
205232
onHoverChange: (hovering) {
206233
setState(() {
207234
if (hovering) {
@@ -220,7 +247,7 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
220247
),
221248
),
222249
CustomDivider(),
223-
CustomDivider(height: 6.0),
250+
CustomDivider(height: 6.0 * scaleFactor),
224251
Row(
225252
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
226253
children: List.generate(5, (i) {
@@ -252,7 +279,8 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
252279
_addAnimatedDigitOverlay(
253280
start,
254281
end,
255-
grid[index ~/ 20][index % 20],
282+
grid[index ~/ _crossAxisCount][index %
283+
_crossAxisCount],
256284
);
257285
}
258286
}
@@ -269,6 +297,8 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
269297
// Move the active indices out of view
270298
activeIndices
271299
.clear(); // Optionally, clear after animation
300+
hoveredRow = null;
301+
hoveredCol = null;
272302
});
273303
});
274304

@@ -287,9 +317,12 @@ class _SeveranceHomePageState extends State<SeveranceHomePage> {
287317
);
288318
}),
289319
),
290-
CustomDivider(height: 4.0, thickness: 2.0),
291-
Footer(),
292-
SizedBox(height: 5.0),
320+
CustomDivider(
321+
height: 4.0 * scaleFactor,
322+
thickness: 2.0 * scaleFactor,
323+
),
324+
Footer(scaleFactor: scaleFactor),
325+
SizedBox(height: 5.0 * scaleFactor),
293326
],
294327
),
295328
);

lib/utils/global_scale.dart

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,24 @@ class ScaleFactorProvider {
99
static void updateScaleFactor(BuildContext context) {
1010
double screenWidth = MediaQuery.of(context).size.width;
1111

12-
if (screenWidth < 400) {
12+
if (screenWidth < 320) {
13+
_scaleFactor = 0.45;
14+
} else if (screenWidth < 360) {
1315
_scaleFactor = 0.5;
14-
} else if (screenWidth < 600) {
16+
} else if (screenWidth < 400) {
17+
_scaleFactor = 0.6;
18+
} else if (screenWidth < 480) {
1519
_scaleFactor = 0.7;
16-
} else if (screenWidth < 700) {
20+
} else if (screenWidth < 540) {
21+
_scaleFactor = 0.75;
22+
} else if (screenWidth < 600) {
23+
_scaleFactor = 0.8;
24+
} else if (screenWidth < 680) {
1725
_scaleFactor = 0.85;
26+
} else if (screenWidth < 760) {
27+
_scaleFactor = 0.9;
28+
} else if (screenWidth < 840) {
29+
_scaleFactor = 0.95;
1830
} else {
1931
_scaleFactor = 1.0;
2032
}

0 commit comments

Comments
 (0)