Jonny Borges
Committed by GitHub

Merge pull request #2048 from parmarravi/master

Added Circular reveal Transition
No preview for this file type
@@ -328,7 +328,7 @@ Text(controller.textFromApi); @@ -328,7 +328,7 @@ Text(controller.textFromApi);
328 328
329 ### 종속성 관리에 대한 자세한 내용 329 ### 종속성 관리에 대한 자세한 내용
330 330
331 -**종속성 관리에 대한 더 제사한 사항은 [여기](./documentation/kr_KO/dependency_management.md)에 있습니다.** 331 +**종속성 관리에 대한 더 자세한 사항은 [여기](./documentation/kr_KO/dependency_management.md)에 있습니다.**
332 332
333 # 기능들 333 # 기능들
334 334
@@ -1092,6 +1092,73 @@ class SettingsService extends GetxService { @@ -1092,6 +1092,73 @@ class SettingsService extends GetxService {
1092 따라서 앱 실행중 절대로 유지되어야 하는 클래스 인스턴스가 필요하면 1092 따라서 앱 실행중 절대로 유지되어야 하는 클래스 인스턴스가 필요하면
1093 `GetxService`를 사용하세요. 1093 `GetxService`를 사용하세요.
1094 1094
  1095 +### 테스트
  1096 +
  1097 +당신은 당신의 컨트롤러들을 생성주기를 포함하여 다른 어떤 클래스처럼 테스트할 수 있습니다 :
  1098 +
  1099 +```dart
  1100 +class Controller extends GetxController {
  1101 + @override
  1102 + void onInit() {
  1103 + super.onInit();
  1104 + //name2로 값 변경
  1105 + name.value = 'name2';
  1106 + }
  1107 +
  1108 + @override
  1109 + void onClose() {
  1110 + name.value = '';
  1111 + super.onClose();
  1112 + }
  1113 +
  1114 + final name = 'name1'.obs;
  1115 +
  1116 + void changeName() => name.value = 'name3';
  1117 +}
  1118 +
  1119 +void main() {
  1120 + test('''
  1121 +Test the state of the reactive variable "name" across all of its lifecycles''',
  1122 + () {
  1123 + /// 당신은 생성주기를 제외하고 컨트롤러를 테스트할 수 있습니다,
  1124 + /// 그러나 당신이 사용하지 않는다면 추천되지 않습니다
  1125 + /// GetX 종속성 주입
  1126 + final controller = Controller();
  1127 + expect(controller.name.value, 'name1');
  1128 +
  1129 + /// 당신이 그것을 사용한다면, 당신은 모든 것을 테스트할 수 있습니다,
  1130 + /// 각각의 생성주기 이후 어플리케이션의 상태를 포함하여.
  1131 + Get.put(controller); // onInit was called
  1132 + expect(controller.name.value, 'name2');
  1133 +
  1134 + /// 당신의 함수를 테스트하세요
  1135 + controller.changeName();
  1136 + expect(controller.name.value, 'name3');
  1137 +
  1138 + /// onClose 호출됨
  1139 + Get.delete<Controller>();
  1140 +
  1141 + expect(controller.name.value, '');
  1142 + });
  1143 +}
  1144 +```
  1145 +
  1146 +#### 팁들
  1147 +
  1148 +##### Mockito 또는 mocktail
  1149 +당신이 당신의 GetxController/GetxService를 모킹하려고 한다면, 당신은 GetxController를 extend 하고, Mock과 mixin 하라, 그렇게 되면
  1150 +
  1151 +```dart
  1152 +class NotificationServiceMock extends GetxService with Mock implements NotificationService {}
  1153 +```
  1154 +
  1155 +##### Get.reset() 사용하기
  1156 +당신이 위젯 또는 테스트 그룹을 테스트하고 있다면, 당신의 테스트의 마지막 또는 해제 때 당신의 이전 테스트에서 모든 설정을 리셋하기 위해 Get.rest을 사용하십시오
  1157 +
  1158 +##### Get.testMode
  1159 +당신이 당신의 컨트롤러에서 당신의 네비게이션을 사용하고 있다면, 당신의 메인의 시작에 `Get.testMode = true` 를 사용하십시오.
  1160 +
  1161 +
1095 # 2.0의 주요 변경점 1162 # 2.0의 주요 변경점
1096 1163
1097 1- Rx 타입들: 1164 1- Rx 타입들:
@@ -115,6 +115,7 @@ class GetConnect extends GetConnectInterface { @@ -115,6 +115,7 @@ class GetConnect extends GetConnectInterface {
115 Decoder? defaultDecoder; 115 Decoder? defaultDecoder;
116 Duration timeout; 116 Duration timeout;
117 List<TrustedCertificate>? trustedCertificates; 117 List<TrustedCertificate>? trustedCertificates;
  118 + String Function(Uri url)? findProxy;
118 GetHttpClient? _httpClient; 119 GetHttpClient? _httpClient;
119 List<GetSocket>? _sockets; 120 List<GetSocket>? _sockets;
120 bool withCredentials; 121 bool withCredentials;
@@ -134,6 +135,7 @@ class GetConnect extends GetConnectInterface { @@ -134,6 +135,7 @@ class GetConnect extends GetConnectInterface {
134 baseUrl: baseUrl, 135 baseUrl: baseUrl,
135 trustedCertificates: trustedCertificates, 136 trustedCertificates: trustedCertificates,
136 withCredentials: withCredentials, 137 withCredentials: withCredentials,
  138 + findProxy: findProxy
137 ); 139 );
138 140
139 @override 141 @override
@@ -39,6 +39,8 @@ class GetHttpClient { @@ -39,6 +39,8 @@ class GetHttpClient {
39 39
40 final GetModifier _modifier; 40 final GetModifier _modifier;
41 41
  42 + String Function(Uri url)? findProxy;
  43 +
42 GetHttpClient({ 44 GetHttpClient({
43 this.userAgent = 'getx-client', 45 this.userAgent = 'getx-client',
44 this.timeout = const Duration(seconds: 8), 46 this.timeout = const Duration(seconds: 8),
@@ -50,10 +52,12 @@ class GetHttpClient { @@ -50,10 +52,12 @@ class GetHttpClient {
50 this.baseUrl, 52 this.baseUrl,
51 List<TrustedCertificate>? trustedCertificates, 53 List<TrustedCertificate>? trustedCertificates,
52 bool withCredentials = false, 54 bool withCredentials = false,
  55 + String Function(Uri url)? findProxy,
53 }) : _httpClient = HttpRequestImpl( 56 }) : _httpClient = HttpRequestImpl(
54 allowAutoSignedCert: allowAutoSignedCert, 57 allowAutoSignedCert: allowAutoSignedCert,
55 trustedCertificates: trustedCertificates, 58 trustedCertificates: trustedCertificates,
56 withCredentials: withCredentials, 59 withCredentials: withCredentials,
  60 + findProxy: findProxy,
57 ), 61 ),
58 _modifier = GetModifier(); 62 _modifier = GetModifier();
59 63
@@ -195,7 +199,6 @@ class GetHttpClient { @@ -195,7 +199,6 @@ class GetHttpClient {
195 int requestNumber = 1, 199 int requestNumber = 1,
196 Map<String, String>? headers, 200 Map<String, String>? headers,
197 }) async { 201 }) async {
198 - try {  
199 var request = await handler(); 202 var request = await handler();
200 203
201 headers?.forEach((key, value) { 204 headers?.forEach((key, value) {
@@ -206,6 +209,7 @@ class GetHttpClient { @@ -206,6 +209,7 @@ class GetHttpClient {
206 final newRequest = await _modifier.modifyRequest<T>(request); 209 final newRequest = await _modifier.modifyRequest<T>(request);
207 210
208 _httpClient.timeout = timeout; 211 _httpClient.timeout = timeout;
  212 + try {
209 var response = await _httpClient.send<T>(newRequest); 213 var response = await _httpClient.send<T>(newRequest);
210 214
211 final newResponse = 215 final newResponse =
@@ -242,7 +246,7 @@ class GetHttpClient { @@ -242,7 +246,7 @@ class GetHttpClient {
242 throw GetHttpException(err.toString()); 246 throw GetHttpException(err.toString());
243 } else { 247 } else {
244 return Response<T>( 248 return Response<T>(
245 - request: null, 249 + request: newRequest,
246 headers: null, 250 headers: null,
247 statusCode: null, 251 statusCode: null,
248 body: null, 252 body: null,
@@ -268,6 +272,8 @@ class GetHttpClient { @@ -268,6 +272,8 @@ class GetHttpClient {
268 headers: headers, 272 headers: headers,
269 decoder: decoder ?? (defaultDecoder as Decoder<T>?), 273 decoder: decoder ?? (defaultDecoder as Decoder<T>?),
270 contentLength: 0, 274 contentLength: 0,
  275 + followRedirects: followRedirects,
  276 + maxRedirects: maxRedirects,
271 )); 277 ));
272 } 278 }
273 279
@@ -17,6 +17,7 @@ class HttpRequestImpl extends HttpRequestBase { @@ -17,6 +17,7 @@ class HttpRequestImpl extends HttpRequestBase {
17 bool allowAutoSignedCert = true, 17 bool allowAutoSignedCert = true,
18 List<TrustedCertificate>? trustedCertificates, 18 List<TrustedCertificate>? trustedCertificates,
19 bool withCredentials = false, 19 bool withCredentials = false,
  20 + String Function(Uri url)? findProxy,
20 }) { 21 }) {
21 _httpClient = io.HttpClient(); 22 _httpClient = io.HttpClient();
22 if (trustedCertificates != null) { 23 if (trustedCertificates != null) {
@@ -29,6 +30,7 @@ class HttpRequestImpl extends HttpRequestBase { @@ -29,6 +30,7 @@ class HttpRequestImpl extends HttpRequestBase {
29 30
30 _httpClient = io.HttpClient(context: _securityContext); 31 _httpClient = io.HttpClient(context: _securityContext);
31 _httpClient!.badCertificateCallback = (_, __, ___) => allowAutoSignedCert; 32 _httpClient!.badCertificateCallback = (_, __, ___) => allowAutoSignedCert;
  33 + _httpClient!.findProxy = findProxy;
32 } 34 }
33 35
34 @override 36 @override
@@ -8,6 +8,7 @@ class HttpRequestImpl extends HttpRequestBase { @@ -8,6 +8,7 @@ class HttpRequestImpl extends HttpRequestBase {
8 bool allowAutoSignedCert = true, 8 bool allowAutoSignedCert = true,
9 List<TrustedCertificate>? trustedCertificates, 9 List<TrustedCertificate>? trustedCertificates,
10 bool withCredentials = false, 10 bool withCredentials = false,
  11 + String Function(Uri url)? findProxy,
11 }); 12 });
12 @override 13 @override
13 void close() {} 14 void close() {}
@@ -239,7 +239,7 @@ class GetInstance { @@ -239,7 +239,7 @@ class GetInstance {
239 final newKey = key ?? _getKey(S, tag); 239 final newKey = key ?? _getKey(S, tag);
240 if (_singl.containsKey(newKey)) { 240 if (_singl.containsKey(newKey)) {
241 final dep = _singl[newKey]; 241 final dep = _singl[newKey];
242 - if (dep != null) { 242 + if (dep != null && !dep.permanent) {
243 dep.isDirty = true; 243 dep.isDirty = true;
244 } 244 }
245 } 245 }
1 import 'package:flutter/cupertino.dart'; 1 import 'package:flutter/cupertino.dart';
2 import 'package:flutter/foundation.dart'; 2 import 'package:flutter/foundation.dart';
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
  4 +
4 import '../../../get_core/get_core.dart'; 5 import '../../../get_core/get_core.dart';
5 import '../../../get_instance/get_instance.dart'; 6 import '../../../get_instance/get_instance.dart';
6 import '../../../get_state_manager/get_state_manager.dart'; 7 import '../../../get_state_manager/get_state_manager.dart';
@@ -9,6 +10,59 @@ import '../../get_navigation.dart'; @@ -9,6 +10,59 @@ import '../../get_navigation.dart';
9 import 'root_controller.dart'; 10 import 'root_controller.dart';
10 11
11 class GetCupertinoApp extends StatelessWidget { 12 class GetCupertinoApp extends StatelessWidget {
  13 + final GlobalKey<NavigatorState>? navigatorKey;
  14 +
  15 + final Widget? home;
  16 + final Map<String, WidgetBuilder>? routes;
  17 + final String? initialRoute;
  18 + final RouteFactory? onGenerateRoute;
  19 + final InitialRouteListFactory? onGenerateInitialRoutes;
  20 + final RouteFactory? onUnknownRoute;
  21 + final List<NavigatorObserver>? navigatorObservers;
  22 + final TransitionBuilder? builder;
  23 + final String title;
  24 + final GenerateAppTitle? onGenerateTitle;
  25 + final CustomTransition? customTransition;
  26 + final Color? color;
  27 + final Map<String, Map<String, String>>? translationsKeys;
  28 + final Translations? translations;
  29 + final TextDirection? textDirection;
  30 + final Locale? locale;
  31 + final Locale? fallbackLocale;
  32 + final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;
  33 + final LocaleListResolutionCallback? localeListResolutionCallback;
  34 + final LocaleResolutionCallback? localeResolutionCallback;
  35 + final Iterable<Locale> supportedLocales;
  36 + final bool showPerformanceOverlay;
  37 + final bool checkerboardRasterCacheImages;
  38 + final bool checkerboardOffscreenLayers;
  39 + final bool showSemanticsDebugger;
  40 + final bool debugShowCheckedModeBanner;
  41 + final Map<LogicalKeySet, Intent>? shortcuts;
  42 + final ThemeData? highContrastTheme;
  43 + final ThemeData? highContrastDarkTheme;
  44 + final Map<Type, Action<Intent>>? actions;
  45 + final Function(Routing?)? routingCallback;
  46 + final Transition? defaultTransition;
  47 + final bool? opaqueRoute;
  48 + final VoidCallback? onInit;
  49 + final VoidCallback? onReady;
  50 + final VoidCallback? onDispose;
  51 + final bool? enableLog;
  52 + final LogWriterCallback? logWriterCallback;
  53 + final bool? popGesture;
  54 + final SmartManagement smartManagement;
  55 + final Bindings? initialBinding;
  56 + final Duration? transitionDuration;
  57 + final bool? defaultGlobalState;
  58 + final List<GetPage>? getPages;
  59 + final GetPage? unknownRoute;
  60 + final RouteInformationProvider? routeInformationProvider;
  61 + final RouteInformationParser<Object>? routeInformationParser;
  62 + final RouterDelegate<Object>? routerDelegate;
  63 + final BackButtonDispatcher? backButtonDispatcher;
  64 + final CupertinoThemeData? theme;
  65 + final bool useInheritedMediaQuery;
12 const GetCupertinoApp({ 66 const GetCupertinoApp({
13 Key? key, 67 Key? key,
14 this.theme, 68 this.theme,
@@ -46,6 +100,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -46,6 +100,7 @@ class GetCupertinoApp extends StatelessWidget {
46 this.shortcuts, 100 this.shortcuts,
47 this.smartManagement = SmartManagement.full, 101 this.smartManagement = SmartManagement.full,
48 this.initialBinding, 102 this.initialBinding,
  103 + this.useInheritedMediaQuery = false,
49 this.unknownRoute, 104 this.unknownRoute,
50 this.routingCallback, 105 this.routingCallback,
51 this.defaultTransition, 106 this.defaultTransition,
@@ -66,58 +121,6 @@ class GetCupertinoApp extends StatelessWidget { @@ -66,58 +121,6 @@ class GetCupertinoApp extends StatelessWidget {
66 backButtonDispatcher = null, 121 backButtonDispatcher = null,
67 super(key: key); 122 super(key: key);
68 123
69 - final GlobalKey<NavigatorState>? navigatorKey;  
70 - final Widget? home;  
71 - final Map<String, WidgetBuilder>? routes;  
72 - final String? initialRoute;  
73 - final RouteFactory? onGenerateRoute;  
74 - final InitialRouteListFactory? onGenerateInitialRoutes;  
75 - final RouteFactory? onUnknownRoute;  
76 - final List<NavigatorObserver>? navigatorObservers;  
77 - final TransitionBuilder? builder;  
78 - final String title;  
79 - final GenerateAppTitle? onGenerateTitle;  
80 - final CustomTransition? customTransition;  
81 - final Color? color;  
82 - final Map<String, Map<String, String>>? translationsKeys;  
83 - final Translations? translations;  
84 - final TextDirection? textDirection;  
85 - final Locale? locale;  
86 - final Locale? fallbackLocale;  
87 - final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;  
88 - final LocaleListResolutionCallback? localeListResolutionCallback;  
89 - final LocaleResolutionCallback? localeResolutionCallback;  
90 - final Iterable<Locale> supportedLocales;  
91 - final bool showPerformanceOverlay;  
92 - final bool checkerboardRasterCacheImages;  
93 - final bool checkerboardOffscreenLayers;  
94 - final bool showSemanticsDebugger;  
95 - final bool debugShowCheckedModeBanner;  
96 - final Map<LogicalKeySet, Intent>? shortcuts;  
97 - final ThemeData? highContrastTheme;  
98 - final ThemeData? highContrastDarkTheme;  
99 - final Map<Type, Action<Intent>>? actions;  
100 - final Function(Routing?)? routingCallback;  
101 - final Transition? defaultTransition;  
102 - final bool? opaqueRoute;  
103 - final VoidCallback? onInit;  
104 - final VoidCallback? onReady;  
105 - final VoidCallback? onDispose;  
106 - final bool? enableLog;  
107 - final LogWriterCallback? logWriterCallback;  
108 - final bool? popGesture;  
109 - final SmartManagement smartManagement;  
110 - final Bindings? initialBinding;  
111 - final Duration? transitionDuration;  
112 - final bool? defaultGlobalState;  
113 - final List<GetPage>? getPages;  
114 - final GetPage? unknownRoute;  
115 - final RouteInformationProvider? routeInformationProvider;  
116 - final RouteInformationParser<Object>? routeInformationParser;  
117 - final RouterDelegate<Object>? routerDelegate;  
118 - final BackButtonDispatcher? backButtonDispatcher;  
119 - final CupertinoThemeData? theme;  
120 -  
121 GetCupertinoApp.router({ 124 GetCupertinoApp.router({
122 Key? key, 125 Key? key,
123 this.theme, 126 this.theme,
@@ -128,6 +131,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -128,6 +131,7 @@ class GetCupertinoApp extends StatelessWidget {
128 this.builder, 131 this.builder,
129 this.title = '', 132 this.title = '',
130 this.onGenerateTitle, 133 this.onGenerateTitle,
  134 + this.useInheritedMediaQuery = false,
131 this.color, 135 this.color,
132 this.highContrastTheme, 136 this.highContrastTheme,
133 this.highContrastDarkTheme, 137 this.highContrastDarkTheme,
@@ -183,31 +187,6 @@ class GetCupertinoApp extends StatelessWidget { @@ -183,31 +187,6 @@ class GetCupertinoApp extends StatelessWidget {
183 Get.routeInformationParser = routeInformationParser; 187 Get.routeInformationParser = routeInformationParser;
184 } 188 }
185 189
186 - Route<dynamic> generator(RouteSettings settings) {  
187 - return PageRedirect(settings: settings, unknownRoute: unknownRoute).page();  
188 - }  
189 -  
190 - List<Route<dynamic>> initialRoutesGenerate(String name) {  
191 - return [  
192 - PageRedirect(  
193 - settings: RouteSettings(name: name),  
194 - unknownRoute: unknownRoute,  
195 - ).page()  
196 - ];  
197 - }  
198 -  
199 - Widget defaultBuilder(BuildContext context, Widget? child) {  
200 - return Directionality(  
201 - textDirection: textDirection ??  
202 - (rtlLanguages.contains(Get.locale?.languageCode)  
203 - ? TextDirection.rtl  
204 - : TextDirection.ltr),  
205 - child: builder == null  
206 - ? (child ?? Material())  
207 - : builder!(context, child ?? Material()),  
208 - );  
209 - }  
210 -  
211 @override 190 @override
212 Widget build(BuildContext context) => GetBuilder<GetMaterialController>( 191 Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
213 init: Get.rootController, 192 init: Get.rootController,
@@ -271,6 +250,7 @@ class GetCupertinoApp extends StatelessWidget { @@ -271,6 +250,7 @@ class GetCupertinoApp extends StatelessWidget {
271 showSemanticsDebugger: showSemanticsDebugger, 250 showSemanticsDebugger: showSemanticsDebugger,
272 debugShowCheckedModeBanner: debugShowCheckedModeBanner, 251 debugShowCheckedModeBanner: debugShowCheckedModeBanner,
273 shortcuts: shortcuts, 252 shortcuts: shortcuts,
  253 + useInheritedMediaQuery: useInheritedMediaQuery,
274 ) 254 )
275 : CupertinoApp( 255 : CupertinoApp(
276 key: _.unikey, 256 key: _.unikey,
@@ -310,7 +290,33 @@ class GetCupertinoApp extends StatelessWidget { @@ -310,7 +290,33 @@ class GetCupertinoApp extends StatelessWidget {
310 showSemanticsDebugger: showSemanticsDebugger, 290 showSemanticsDebugger: showSemanticsDebugger,
311 debugShowCheckedModeBanner: debugShowCheckedModeBanner, 291 debugShowCheckedModeBanner: debugShowCheckedModeBanner,
312 shortcuts: shortcuts, 292 shortcuts: shortcuts,
  293 + useInheritedMediaQuery: useInheritedMediaQuery,
313 // actions: actions, 294 // actions: actions,
314 ), 295 ),
315 ); 296 );
  297 +
  298 + Widget defaultBuilder(BuildContext context, Widget? child) {
  299 + return Directionality(
  300 + textDirection: textDirection ??
  301 + (rtlLanguages.contains(Get.locale?.languageCode)
  302 + ? TextDirection.rtl
  303 + : TextDirection.ltr),
  304 + child: builder == null
  305 + ? (child ?? Material())
  306 + : builder!(context, child ?? Material()),
  307 + );
  308 + }
  309 +
  310 + Route<dynamic> generator(RouteSettings settings) {
  311 + return PageRedirect(settings: settings, unknownRoute: unknownRoute).page();
  312 + }
  313 +
  314 + List<Route<dynamic>> initialRoutesGenerate(String name) {
  315 + return [
  316 + PageRedirect(
  317 + settings: RouteSettings(name: name),
  318 + unknownRoute: unknownRoute,
  319 + ).page()
  320 + ];
  321 + }
316 } 322 }
@@ -67,6 +67,7 @@ class GetMaterialApp extends StatelessWidget { @@ -67,6 +67,7 @@ class GetMaterialApp extends StatelessWidget {
67 final RouteInformationParser<Object>? routeInformationParser; 67 final RouteInformationParser<Object>? routeInformationParser;
68 final RouterDelegate<Object>? routerDelegate; 68 final RouterDelegate<Object>? routerDelegate;
69 final BackButtonDispatcher? backButtonDispatcher; 69 final BackButtonDispatcher? backButtonDispatcher;
  70 + final bool useInheritedMediaQuery;
70 const GetMaterialApp({ 71 const GetMaterialApp({
71 Key? key, 72 Key? key,
72 this.navigatorKey, 73 this.navigatorKey,
@@ -78,6 +79,7 @@ class GetMaterialApp extends StatelessWidget { @@ -78,6 +79,7 @@ class GetMaterialApp extends StatelessWidget {
78 this.onGenerateRoute, 79 this.onGenerateRoute,
79 this.onGenerateInitialRoutes, 80 this.onGenerateInitialRoutes,
80 this.onUnknownRoute, 81 this.onUnknownRoute,
  82 + this.useInheritedMediaQuery = false,
81 List<NavigatorObserver> this.navigatorObservers = 83 List<NavigatorObserver> this.navigatorObservers =
82 const <NavigatorObserver>[], 84 const <NavigatorObserver>[],
83 this.builder, 85 this.builder,
@@ -142,6 +144,7 @@ class GetMaterialApp extends StatelessWidget { @@ -142,6 +144,7 @@ class GetMaterialApp extends StatelessWidget {
142 this.color, 144 this.color,
143 this.theme, 145 this.theme,
144 this.darkTheme, 146 this.darkTheme,
  147 + this.useInheritedMediaQuery = false,
145 this.highContrastTheme, 148 this.highContrastTheme,
146 this.highContrastDarkTheme, 149 this.highContrastDarkTheme,
147 this.themeMode = ThemeMode.system, 150 this.themeMode = ThemeMode.system,
@@ -271,6 +274,7 @@ class GetMaterialApp extends StatelessWidget { @@ -271,6 +274,7 @@ class GetMaterialApp extends StatelessWidget {
271 debugShowCheckedModeBanner: debugShowCheckedModeBanner, 274 debugShowCheckedModeBanner: debugShowCheckedModeBanner,
272 shortcuts: shortcuts, 275 shortcuts: shortcuts,
273 scrollBehavior: scrollBehavior, 276 scrollBehavior: scrollBehavior,
  277 + useInheritedMediaQuery: useInheritedMediaQuery,
274 ) 278 )
275 : MaterialApp( 279 : MaterialApp(
276 key: _.unikey, 280 key: _.unikey,
@@ -317,6 +321,7 @@ class GetMaterialApp extends StatelessWidget { @@ -317,6 +321,7 @@ class GetMaterialApp extends StatelessWidget {
317 debugShowCheckedModeBanner: debugShowCheckedModeBanner, 321 debugShowCheckedModeBanner: debugShowCheckedModeBanner,
318 shortcuts: shortcuts, 322 shortcuts: shortcuts,
319 scrollBehavior: scrollBehavior, 323 scrollBehavior: scrollBehavior,
  324 + useInheritedMediaQuery: useInheritedMediaQuery,
320 // actions: actions, 325 // actions: actions,
321 ), 326 ),
322 ); 327 );
  1 +import 'dart:math' show sqrt, max;
  2 +import 'dart:ui' show lerpDouble;
  3 +
  4 +import 'package:flutter/material.dart';
  5 +
  6 +class CircularRevealClipper extends CustomClipper<Path> {
  7 + final double fraction;
  8 + final Alignment? centerAlignment;
  9 + final Offset? centerOffset;
  10 + final double? minRadius;
  11 + final double? maxRadius;
  12 +
  13 + CircularRevealClipper({
  14 + required this.fraction,
  15 + this.centerAlignment,
  16 + this.centerOffset,
  17 + this.minRadius,
  18 + this.maxRadius,
  19 + });
  20 +
  21 + @override
  22 + Path getClip(Size size) {
  23 + final Offset center = this.centerAlignment?.alongSize(size) ??
  24 + this.centerOffset ??
  25 + Offset(size.width / 2, size.height / 2);
  26 + final minRadius = this.minRadius ?? 0;
  27 + final maxRadius = this.maxRadius ?? calcMaxRadius(size, center);
  28 +
  29 + return Path()
  30 + ..addOval(
  31 + Rect.fromCircle(
  32 + center: center,
  33 + radius: lerpDouble(minRadius, maxRadius, fraction)!,
  34 + ),
  35 + );
  36 + }
  37 +
  38 + @override
  39 + bool shouldReclip(CustomClipper<Path> oldClipper) => true;
  40 +
  41 + static double calcMaxRadius(Size size, Offset center) {
  42 + final w = max(center.dx, size.width - center.dx);
  43 + final h = max(center.dy, size.height - center.dy);
  44 + return sqrt(w * w + h * h);
  45 + }
  46 +}
  47 +
@@ -184,3 +184,26 @@ class SizeTransitions { @@ -184,3 +184,26 @@ class SizeTransitions {
184 ); 184 );
185 } 185 }
186 } 186 }
  187 +
  188 +
  189 +class CircularRevealTransition {
  190 + Widget buildTransitions(
  191 + BuildContext context,
  192 + Curve? curve,
  193 + Alignment? alignment,
  194 + Animation<double> animation,
  195 + Animation<double> secondaryAnimation,
  196 + Widget child) {
  197 + return ClipPath(
  198 + clipper: CircularRevealClipper(
  199 + fraction: animation.value,
  200 + centerAlignment: Alignment.center,
  201 + centerOffset: Offset.zero,
  202 + minRadius: 0,
  203 + maxRadius: 800,
  204 + ),
  205 + child: child,
  206 + );
  207 + }
  208 +}
  209 +
@@ -619,6 +619,22 @@ Cannot read the previousTitle for a route that has not yet been installed''', @@ -619,6 +619,22 @@ Cannot read the previousTitle for a route that has not yet been installed''',
619 onStartPopGesture: () => _startPopGesture<T>(route), 619 onStartPopGesture: () => _startPopGesture<T>(route),
620 child: child) 620 child: child)
621 : child); 621 : child);
  622 +
  623 + case Transition.ciruclarReveal:
  624 + return CircularRevealTransition().buildTransitions(
  625 + context,
  626 + route.curve,
  627 + route.alignment,
  628 + animation,
  629 + secondaryAnimation,
  630 + route.popGesture ?? Get.defaultPopGesture
  631 + ? CupertinoBackGestureDetector<T>(
  632 + gestureWidth: route.gestureWidth?.call(context) ??
  633 + _kBackGestureWidth,
  634 + enabledCallback: () => _isPopGestureEnabled<T>(route),
  635 + onStartPopGesture: () => _startPopGesture<T>(route),
  636 + child: child)
  637 + : child);
622 638
623 default: 639 default:
624 if (Get.customTransition != null) { 640 if (Get.customTransition != null) {
@@ -67,6 +67,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> { @@ -67,6 +67,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> {
67 } 67 }
68 68
69 bool firstRebuild = true; 69 bool firstRebuild = true;
  70 + bool sentToStream = false;
70 71
71 /// Same as `toString()` but using a getter. 72 /// Same as `toString()` but using a getter.
72 String get string => value.toString(); 73 String get string => value.toString();
@@ -96,10 +97,11 @@ mixin RxObjectMixin<T> on NotifyManager<T> { @@ -96,10 +97,11 @@ mixin RxObjectMixin<T> on NotifyManager<T> {
96 /// Widget, only if it's different from the previous value. 97 /// Widget, only if it's different from the previous value.
97 set value(T val) { 98 set value(T val) {
98 if (subject.isClosed) return; 99 if (subject.isClosed) return;
  100 + sentToStream = false;
99 if (_value == val && !firstRebuild) return; 101 if (_value == val && !firstRebuild) return;
100 firstRebuild = false; 102 firstRebuild = false;
101 _value = val; 103 _value = val;
102 - 104 + sentToStream = true;
103 subject.add(_value); 105 subject.add(_value);
104 } 106 }
105 107
@@ -254,7 +256,7 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { @@ -254,7 +256,7 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> {
254 value = v; 256 value = v;
255 // If it's not the first rebuild, the listeners have been called already 257 // If it's not the first rebuild, the listeners have been called already
256 // So we won't call them again. 258 // So we won't call them again.
257 - if (!firstRebuild) { 259 + if (!firstRebuild && !sentToStream) {
258 subject.add(v); 260 subject.add(v);
259 } 261 }
260 } 262 }
@@ -36,13 +36,13 @@ mixin GetSingleTickerProviderStateMixin on GetxController @@ -36,13 +36,13 @@ mixin GetSingleTickerProviderStateMixin on GetxController
36 if (_ticker == null) return true; 36 if (_ticker == null) return true;
37 throw FlutterError.fromParts(<DiagnosticsNode>[ 37 throw FlutterError.fromParts(<DiagnosticsNode>[
38 ErrorSummary( 38 ErrorSummary(
39 - '$runtimeType is a SingleTickerProviderStateMixin but multiple tickers were created.'), 39 + '$runtimeType is a GetSingleTickerProviderStateMixin but multiple tickers were created.'),
40 ErrorDescription( 40 ErrorDescription(
41 - 'A SingleTickerProviderStateMixin can only be used as a TickerProvider once.'), 41 + 'A GetSingleTickerProviderStateMixin can only be used as a TickerProvider once.'),
42 ErrorHint( 42 ErrorHint(
43 'If a State is used for multiple AnimationController objects, or if it is passed to other ' 43 'If a State is used for multiple AnimationController objects, or if it is passed to other '
44 'objects and those objects might use it more than one time in total, then instead of ' 44 'objects and those objects might use it more than one time in total, then instead of '
45 - 'mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin.', 45 + 'mixing in a GetSingleTickerProviderStateMixin, use a regular GetTickerProviderStateMixin.',
46 ), 46 ),
47 ]); 47 ]);
48 }()); 48 }());
@@ -66,7 +66,7 @@ mixin GetSingleTickerProviderStateMixin on GetxController @@ -66,7 +66,7 @@ mixin GetSingleTickerProviderStateMixin on GetxController
66 throw FlutterError.fromParts(<DiagnosticsNode>[ 66 throw FlutterError.fromParts(<DiagnosticsNode>[
67 ErrorSummary('$this was disposed with an active Ticker.'), 67 ErrorSummary('$this was disposed with an active Ticker.'),
68 ErrorDescription( 68 ErrorDescription(
69 - '$runtimeType created a Ticker via its SingleTickerProviderStateMixin, but at the time ' 69 + '$runtimeType created a Ticker via its GetSingleTickerProviderStateMixin, but at the time '
70 'dispose() was called on the mixin, that Ticker was still active. The Ticker must ' 70 'dispose() was called on the mixin, that Ticker was still active. The Ticker must '
71 'be disposed before calling super.dispose().', 71 'be disposed before calling super.dispose().',
72 ), 72 ),
@@ -82,6 +82,99 @@ mixin GetSingleTickerProviderStateMixin on GetxController @@ -82,6 +82,99 @@ mixin GetSingleTickerProviderStateMixin on GetxController
82 } 82 }
83 } 83 }
84 84
  85 +/// Used like `TickerProviderMixin` but only with Get Controllers.
  86 +/// Simplifies multiple AnimationController creation inside GetxController.
  87 +///
  88 +/// Example:
  89 +///```
  90 +///class SplashController extends GetxController with
  91 +/// GetTickerProviderStateMixin {
  92 +/// AnimationController first_controller;
  93 +/// AnimationController second_controller;
  94 +///
  95 +/// @override
  96 +/// void onInit() {
  97 +/// final duration = const Duration(seconds: 2);
  98 +/// first_controller =
  99 +/// AnimationController.unbounded(duration: duration, vsync: this);
  100 +/// second_controller =
  101 +/// AnimationController.unbounded(duration: duration, vsync: this);
  102 +/// first_controller.repeat();
  103 +/// first_controller.addListener(() =>
  104 +/// print("Animation Controller value: ${first_controller.value}"));
  105 +/// second_controller.addListener(() =>
  106 +/// print("Animation Controller value: ${second_controller.value}"));
  107 +/// }
  108 +/// ...
  109 +/// ```
  110 +mixin GetTickerProviderStateMixin on GetxController implements TickerProvider {
  111 + Set<Ticker>? _tickers;
  112 +
  113 + @override
  114 + Ticker createTicker(TickerCallback onTick) {
  115 + _tickers ??= <_WidgetTicker>{};
  116 + final result = _WidgetTicker(onTick, this, debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null);
  117 + _tickers!.add(result);
  118 + return result;
  119 + }
  120 +
  121 + void _removeTicker(_WidgetTicker ticker) {
  122 + assert(_tickers != null);
  123 + assert(_tickers!.contains(ticker));
  124 + _tickers!.remove(ticker);
  125 + }
  126 +
  127 + void didChangeDependencies(BuildContext context) {
  128 + final muted = !TickerMode.of(context);
  129 + if (_tickers != null) {
  130 + for (final ticker in _tickers!) {
  131 + ticker.muted = muted;
  132 + }
  133 + }
  134 + }
  135 +
  136 + @override
  137 + void onClose() {
  138 + assert(() {
  139 + if (_tickers != null) {
  140 + for (final ticker in _tickers!) {
  141 + if (ticker.isActive) {
  142 + throw FlutterError.fromParts(<DiagnosticsNode>[
  143 + ErrorSummary('$this was disposed with an active Ticker.'),
  144 + ErrorDescription(
  145 + '$runtimeType created a Ticker via its GetTickerProviderStateMixin, but at the time '
  146 + 'dispose() was called on the mixin, that Ticker was still active. All Tickers must '
  147 + 'be disposed before calling super.dispose().',
  148 + ),
  149 + ErrorHint(
  150 + 'Tickers used by AnimationControllers '
  151 + 'should be disposed by calling dispose() on the AnimationController itself. '
  152 + 'Otherwise, the ticker will leak.',
  153 + ),
  154 + ticker.describeForError('The offending ticker was'),
  155 + ]);
  156 + }
  157 + }
  158 + }
  159 + return true;
  160 + }());
  161 + super.onClose();
  162 + }
  163 +
  164 +}
  165 +
  166 +class _WidgetTicker extends Ticker {
  167 + _WidgetTicker(TickerCallback onTick, this._creator, { String? debugLabel }) : super(onTick, debugLabel: debugLabel);
  168 +
  169 + final GetTickerProviderStateMixin _creator;
  170 +
  171 + @override
  172 + void dispose() {
  173 + _creator._removeTicker(this);
  174 + super.dispose();
  175 + }
  176 +}
  177 +
85 @Deprecated('use GetSingleTickerProviderStateMixin') 178 @Deprecated('use GetSingleTickerProviderStateMixin')
86 179
87 /// Used like `SingleTickerProviderMixin` but only with Get Controllers. 180 /// Used like `SingleTickerProviderMixin` but only with Get Controllers.
@@ -69,13 +69,13 @@ extension Trans on String { @@ -69,13 +69,13 @@ extension Trans on String {
69 final translationsWithNoCountry = Get.translations 69 final translationsWithNoCountry = Get.translations
70 .map((key, value) => MapEntry(key.split("_").first, value)); 70 .map((key, value) => MapEntry(key.split("_").first, value));
71 final containsKey = 71 final containsKey =
72 - translationsWithNoCountry.containsKey(Get.locale!.languageCode); 72 + translationsWithNoCountry.containsKey(Get.locale!.languageCode.split("_").first);
73 73
74 if (!containsKey) { 74 if (!containsKey) {
75 return null; 75 return null;
76 } 76 }
77 77
78 - return translationsWithNoCountry[Get.locale!.languageCode]; 78 + return translationsWithNoCountry[Get.locale!.languageCode.split("_").first];
79 } 79 }
80 80
81 String get tr { 81 String get tr {
@@ -125,7 +125,7 @@ void main() { @@ -125,7 +125,7 @@ void main() {
125 reactiveInteger.trigger(3); 125 reactiveInteger.trigger(3);
126 // then repeat twice 126 // then repeat twice
127 reactiveInteger.trigger(3); 127 reactiveInteger.trigger(3);
128 - reactiveInteger.trigger(3); 128 + reactiveInteger.trigger(1);
129 129
130 await Future.delayed(Duration(milliseconds: 100)); 130 await Future.delayed(Duration(milliseconds: 100));
131 expect(3, timesCalled); 131 expect(3, timesCalled);