Skip to content

Commit 0c5d60b

Browse files
Merge pull request #4 from muhammadkamel/fix/media-query-fallback
Fix/media query fallback
2 parents 6566f37 + 026f036 commit 0c5d60b

27 files changed

Lines changed: 2741 additions & 38 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,4 @@ coverage/
8282
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
8383
!/dev/ci/**/Gemfile.lock
8484

85+
.agent/rules/

CHANGELOG.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,89 @@
44

55
All notable changes to this project will be documented in this file.
66

7+
## [1.4.0] - 2025-12-23
8+
9+
### Added
10+
11+
- **InheritedWidget-Based Scope**: Introduced `ScreenUtilPlusScope` for efficient, targeted rebuilds
12+
13+
- New `autoRebuild` parameter in `ScreenUtilPlusInit` (defaults to `true` for backward compatibility)
14+
- When `autoRebuild: false`, only widgets that explicitly depend on `ScreenUtilPlusScope` rebuild
15+
- Significantly improves performance by avoiding unnecessary tree-wide rebuilds
16+
- Accessible via `ScreenUtilPlus.of(context)` or `context.su`
17+
18+
- **Context-Aware Extensions**: New `ResponsiveSizeContext` extension on `BuildContext`
19+
20+
- `context.w(value)` - Scale width
21+
- `context.h(value)` - Scale height
22+
- `context.r(value)` - Scale radius
23+
- `context.sp(value)` - Scale font size
24+
- `context.spMin(value)` - Scale font size with minimum
25+
- `context.dg(value)` - Scale diagonal
26+
- `context.dm(value)` - Scale diameter
27+
- `context.verticalSpace(value)` - Create vertical spacing
28+
- `context.horizontalSpace(value)` - Create horizontal spacing
29+
- `context.edgeInsets(...)` - Create scaled EdgeInsets
30+
- `context.borderRadius(...)` - Create scaled BorderRadius
31+
- These extensions work efficiently with `autoRebuild: false` by registering InheritedWidget dependencies
32+
33+
- **Example App Enhancements**:
34+
35+
- New `ScopeDemoPage` showcasing `ScreenUtilPlusScope` features and performance benefits
36+
- Interactive demo comparing rebuild behavior with `autoRebuild` on/off
37+
- Visual demonstrations of context-aware extensions
38+
39+
- **Comprehensive Test Coverage**:
40+
- Added 25+ new tests across 6 new test files
41+
- Achieved **99.2% code coverage** (1574/1586 lines) with **619 total tests**
42+
- New test files:
43+
- `screen_util_plus_scope_test.dart` - InheritedWidget functionality
44+
- `responsive_size_context_test.dart` - Context-aware extensions
45+
- `context_extension_test.dart` - Context extension methods
46+
- `adaptive_text_style_test.dart` - Adaptive text styles including xxl breakpoint
47+
- `screen_util_plus_desktop_test.dart` - Desktop platform support
48+
- `screen_util_plus_edge_cases_test.dart` - Edge case scenarios
49+
50+
### Changed
51+
52+
- **Simplified Context Extension**: Refactored `mediaQueryData` getter in `ScreenUtilContextExtension`
53+
54+
- Removed unreachable `View.maybeOf` fallback for cleaner code
55+
- Now simply returns `MediaQuery.maybeOf(this)`
56+
- Achieved 100% test coverage for this file
57+
58+
- **R-Widgets Enhancement**: Updated `RContainer` and `RText` to be context-aware
59+
60+
- Now use `context.su` to register InheritedWidget dependencies
61+
- Benefit from efficient rebuilds when `autoRebuild: false`
62+
63+
- **Code Quality Improvements**:
64+
- Removed unused imports across multiple files
65+
- Added explicit braces to single-line if statements for better readability
66+
- Improved code formatting and consistency
67+
68+
### Performance
69+
70+
- **Rebuild Optimization**: With `autoRebuild: false`, only widgets that explicitly use:
71+
72+
- `ScreenUtilPlus.of(context)` or `context.su`
73+
- Context-aware extensions (`context.w()`, `context.h()`, etc.)
74+
- R-widgets (`RContainer`, `RText`, etc.)
75+
76+
will rebuild when screen metrics change, significantly reducing unnecessary rebuilds
77+
78+
### Migration Guide
79+
80+
For existing users, no changes are required. The default behavior (`autoRebuild: true`) maintains backward compatibility.
81+
82+
To opt into the new performance optimizations:
83+
84+
1. Set `autoRebuild: false` in `ScreenUtilPlusInit`
85+
2. Use context-aware extensions (`context.w()`) instead of num extensions (`100.w`)
86+
3. Or use R-widgets (`RContainer`, `RText`) which are already context-aware
87+
88+
See the new `ScopeDemoPage` in the example app for a complete demonstration.
89+
790
## [1.3.1] - 2025-12-10
891

992
### Changed

README.md

Lines changed: 134 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,23 @@
1313
## ✨ Features
1414

1515
- 📱 **Responsive Scaling**: Automatic scaling of width, height, font size, and more
16-
- 🎯 **CSS-like Breakpoints**: Media query-style breakpoints (Bootstrap, Tailwind, Material Design)
16+
-**InheritedWidget-Based Scope**: Efficient, targeted rebuilds with `ScreenUtilPlusScope`
17+
- 🎯 **Context-Aware Extensions**: New `context.w()`, `context.h()`, `context.sp()` for optimal performance
18+
- 🎨 **CSS-like Breakpoints**: Media query-style breakpoints (Bootstrap, Tailwind, Material Design)
1719
- 📐 **SwiftUI-like Size Classes**: Compact/Regular size classes for adaptive layouts
18-
- 🎨 **Adaptive Widgets**: Breakpoint-aware containers, text, and builders
19-
- 🚀 **Performance Optimized**: Intelligent rebuild detection with Equatable
20+
- 🧩 **Adaptive Widgets**: Breakpoint-aware containers, text, and builders
21+
- 🚀 **Performance Optimized**: Intelligent rebuild detection with optional `autoRebuild: false`
2022
- 🎭 **Responsive Theme**: Automatic text style scaling in themes
2123
- 📦 **Zero Configuration**: Works out of the box with sensible defaults
22-
- 🧪 **Well Tested**: 98.3% code coverage with 500+ tests
24+
- 🧪 **Well Tested**: 99.2% code coverage with 619 tests
2325

2426
## 📦 Installation
2527

2628
Add this to your package's `pubspec.yaml` file:
2729

2830
```yaml
2931
dependencies:
30-
flutter_screenutil_plus: ^1.2.0
32+
flutter_screenutil_plus: ^1.4.0
3133
```
3234
3335
Then run:
@@ -83,6 +85,106 @@ Container(
8385
)
8486
```
8587

88+
### 2. Use Responsive Extensions
89+
90+
```dart
91+
Container(
92+
width: 100.w, // Responsive width
93+
height: 50.h, // Responsive height
94+
padding: EdgeInsets.all(16.r), // Responsive padding
95+
child: Text(
96+
'Hello World',
97+
style: TextStyle(fontSize: 16.sp), // Responsive font
98+
),
99+
)
100+
```
101+
102+
### 3. **NEW in v1.4.0**: Context-Aware Extensions (Recommended)
103+
104+
For better performance with `autoRebuild: false`, use context-aware extensions:
105+
106+
```dart
107+
Container(
108+
width: context.w(100), // Context-aware width
109+
height: context.h(50), // Context-aware height
110+
padding: context.edgeInsets(all: 16), // Context-aware padding
111+
child: Text(
112+
'Hello World',
113+
style: TextStyle(fontSize: context.sp(16)), // Context-aware font
114+
),
115+
)
116+
```
117+
118+
## 🚀 Performance Optimization (v1.4.0)
119+
120+
### InheritedWidget-Based Scope
121+
122+
Version 1.4.0 introduces `ScreenUtilPlusScope` for efficient, targeted rebuilds:
123+
124+
```dart
125+
ScreenUtilPlusInit(
126+
designSize: const Size(360, 690),
127+
autoRebuild: false, // 🎯 NEW: Disable automatic tree-wide rebuilds
128+
builder: (context, child) {
129+
return MaterialApp(
130+
home: child,
131+
);
132+
},
133+
child: HomePage(),
134+
)
135+
```
136+
137+
**Benefits of `autoRebuild: false`:**
138+
139+
-**Significantly faster** - Only widgets that need responsive values rebuild
140+
- 🎯 **Targeted updates** - Only widgets using `context.w()`, `context.su`, or R-widgets rebuild
141+
- 🔄 **Backward compatible** - Defaults to `true` for existing apps
142+
143+
### Context-Aware Extensions
144+
145+
When using `autoRebuild: false`, use context-aware extensions for optimal performance:
146+
147+
```dart
148+
// ✅ Recommended with autoRebuild: false
149+
context.w(100) // Scale width
150+
context.h(50) // Scale height
151+
context.r(20) // Scale radius
152+
context.sp(16) // Scale font size
153+
context.spMin(12) // Scale font with minimum
154+
context.dg(100) // Scale diagonal
155+
context.dm(100) // Scale diameter
156+
157+
// Spacing helpers
158+
context.verticalSpace(20) // Vertical spacing
159+
context.horizontalSpace(20) // Horizontal spacing
160+
161+
// Complex values
162+
context.edgeInsets(all: 16) // Scaled EdgeInsets
163+
context.edgeInsets( // Custom EdgeInsets
164+
horizontal: 16,
165+
vertical: 8,
166+
)
167+
context.borderRadius(all: 12) // Scaled BorderRadius
168+
169+
// Access ScreenUtilPlus instance
170+
final su = context.su; // Get ScreenUtilPlus instance
171+
```
172+
173+
### Migration to Context-Aware Extensions
174+
175+
```dart
176+
// ❌ Old way (still works, but rebuilds entire tree)
177+
Container(width: 100.w, height: 50.h)
178+
179+
// ✅ New way (efficient with autoRebuild: false)
180+
Container(width: context.w(100), height: context.h(50))
181+
```
182+
183+
**When to use each:**
184+
185+
- **`autoRebuild: true`** (default): Use `.w`, `.h`, `.sp` extensions - simpler syntax
186+
- **`autoRebuild: false`**: Use `context.w()`, `context.h()`, `context.sp()` - better performance
187+
86188
## 📚 Core Features
87189

88190
### Responsive Extensions
@@ -393,6 +495,7 @@ ScreenUtilPlusInit(
393495
| Property | Type | Default Value | Description |
394496
| ----------------- | ---------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
395497
| designSize | Size | Size(360,690) | The size of the device screen in the design draft, in dp |
498+
| autoRebuild | bool | true | **NEW in v1.4.0**: When false, only widgets using context-aware extensions or `context.su` rebuild on screen changes (improves performance) |
396499
| builder | Function | null | Return widget that uses the library in a property (ex: MaterialApp's theme) |
397500
| child | Widget | null | A part of builder that its dependencies/properties don't use the library |
398501
| rebuildFactor | RebuildFactor | RebuildFactors.size | Function that takes old and new screen metrics and returns whether to rebuild or not when changes occur. See [RebuildFactors](#rebuild-factors) |
@@ -529,15 +632,32 @@ switch (deviceType) {
529632

530633
#### Context Extensions
531634

532-
| Extension | Description | Example |
533-
| ---------------------- | ----------------------------- | ------------------------------------------------- |
534-
| `context.breakpoint` | Current breakpoint | `context.breakpoint` |
535-
| `context.isAtLeast()` | Check if at least breakpoint | `context.isAtLeast(Breakpoint.md)` |
536-
| `context.isLessThan()` | Check if less than breakpoint | `context.isLessThan(Breakpoint.lg)` |
537-
| `context.isBetween()` | Check if between breakpoints | `context.isBetween(Breakpoint.sm, Breakpoint.lg)` |
538-
| `context.sizeClasses` | Get size classes | `context.sizeClasses` |
539-
| `context.adaptive()` | Get AdaptiveValues | `context.adaptive()` |
540-
| `context.responsive()` | Get ResponsiveQuery | `context.responsive()` |
635+
| Extension | Description | Example |
636+
| --------------------------- | ----------------------------- | ------------------------------------------------- |
637+
| **Context-Aware (v1.4.0)** | | |
638+
| `context.w(value)` | Scale width | `context.w(100)` |
639+
| `context.h(value)` | Scale height | `context.h(50)` |
640+
| `context.r(value)` | Scale radius | `context.r(20)` |
641+
| `context.sp(value)` | Scale font size | `context.sp(16)` |
642+
| `context.spMin(value)` | Scale font with minimum | `context.spMin(12)` |
643+
| `context.dg(value)` | Scale diagonal | `context.dg(100)` |
644+
| `context.dm(value)` | Scale diameter | `context.dm(100)` |
645+
| `context.verticalSpace()` | Create vertical spacing | `context.verticalSpace(20)` |
646+
| `context.horizontalSpace()` | Create horizontal spacing | `context.horizontalSpace(20)` |
647+
| `context.edgeInsets()` | Create scaled EdgeInsets | `context.edgeInsets(all: 16)` |
648+
| `context.borderRadius()` | Create scaled BorderRadius | `context.borderRadius(all: 12)` |
649+
| `context.su` | Get ScreenUtilPlus instance | `context.su` |
650+
| **Breakpoints** | | |
651+
| `context.breakpoint` | Current breakpoint | `context.breakpoint` |
652+
| `context.isAtLeast()` | Check if at least breakpoint | `context.isAtLeast(Breakpoint.md)` |
653+
| `context.isLessThan()` | Check if less than breakpoint | `context.isLessThan(Breakpoint.lg)` |
654+
| `context.isBetween()` | Check if between breakpoints | `context.isBetween(Breakpoint.sm, Breakpoint.lg)` |
655+
| **Size Classes** | | |
656+
| `context.sizeClasses` | Get size classes | `context.sizeClasses` |
657+
| **Utilities** | | |
658+
| `context.adaptive()` | Get AdaptiveValues | `context.adaptive()` |
659+
| `context.responsive()` | Get ResponsiveQuery | `context.responsive()` |
660+
| `context.mediaQueryData` | Get MediaQueryData | `context.mediaQueryData` |
541661

542662
#### Widgets
543663

example/lib/home_page.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_screenutil_plus/flutter_screenutil_plus.dart';
3+
import 'package:flutter_screenutil_plus_example/scope_demo_page.dart';
34

45
class HomePage extends StatefulWidget {
56
const HomePage({super.key});
@@ -105,6 +106,30 @@ class _HomePageState extends State<HomePage> {
105106
],
106107
),
107108
),
109+
10.verticalSpace,
110+
SizedBox(
111+
width: double.infinity,
112+
child: ElevatedButton.icon(
113+
onPressed: () {
114+
Navigator.push(
115+
context,
116+
MaterialPageRoute(
117+
builder: (context) => const ScopeDemoPage(),
118+
),
119+
);
120+
},
121+
icon: Icon(Icons.widgets, size: 18.sp),
122+
label: Text(
123+
'View InheritedWidget Demo',
124+
style: TextStyle(fontSize: 14.sp),
125+
),
126+
style: ElevatedButton.styleFrom(
127+
backgroundColor: Colors.purple.shade600,
128+
foregroundColor: Colors.white,
129+
padding: EdgeInsets.symmetric(vertical: 12.h),
130+
),
131+
),
132+
),
108133
],
109134
),
110135
);

example/lib/main.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ class MyApp extends StatelessWidget {
1616
designSize: const Size(360, 690),
1717
minTextAdapt: true,
1818
splitScreenMode: true,
19+
autoRebuild: false,
20+
// NEW: Set autoRebuild to false for better performance
21+
// When false, only widgets using context.su or R-widgets will rebuild
22+
// autoRebuild: false,
1923
// Use builder only if you need to use library outside ScreenUtilPlusInit context
2024
builder: (context, child) {
2125
return MaterialApp(

0 commit comments

Comments
 (0)