Merge branch 'master' of git://github.com/jonataslaw/getx
Showing
39 changed files
with
413 additions
and
133 deletions
No preview for this file type
| @@ -23,7 +23,7 @@ jobs: | @@ -23,7 +23,7 @@ jobs: | ||
| 23 | # https://github.com/marketplace/actions/flutter-action | 23 | # https://github.com/marketplace/actions/flutter-action | 
| 24 | - uses: subosito/flutter-action@v1 | 24 | - uses: subosito/flutter-action@v1 | 
| 25 | with: | 25 | with: | 
| 26 | - flutter-version: "2.2.3" | 26 | + flutter-version: "2.8.0" | 
| 27 | channel: "stable" | 27 | channel: "stable" | 
| 28 | - run: flutter pub get | 28 | - run: flutter pub get | 
| 29 | #- run: flutter analyze | 29 | #- run: flutter analyze | 
| 1 | -## [4.5.1] - Big Update | 1 | +## [4.6.1] | 
| 2 | +Fix GetConnect on Flutter web | ||
| 3 | + | ||
| 4 | +## [4.6.0] | ||
| 5 | +Add useInheritedMediaQuery to GetMaterialApp and GetCupertinoApp (@davidhole) | ||
| 6 | +Add Circular reveal Transition (@parmarravi) | ||
| 7 | +Add request to failed response (@heftekharm) | ||
| 8 | +Fix internationalization with only country code (@codercengiz) | ||
| 9 | +Add GetTickerProviderStateMixin when multiple AnimationController objects are used (@NatsuOnFire) | ||
| 10 | +Add the followRedirects and maxRedirects fields to the Request object (@wei53881) | ||
| 11 | +Fix to rx.trigger fires twice (@gslender) | ||
| 12 | +Add proxy setting support to GetConnect (@jtans) | ||
| 13 | +Fix markAsDirty used on permanent controllers (@zenalex) | ||
| 14 | +Update Korean readme (@dumbokim) | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +## [4.5.1] | ||
| 2 | Fix Snackbar when it have action and icon the same time | 18 | Fix Snackbar when it have action and icon the same time | 
| 3 | 19 | ||
| 4 | ## [4.5.0] - Big Update | 20 | ## [4.5.0] - Big Update | 
| 5 | -To have a context-free, page-agnostic snackbar, we used OverlayRoute to display a partial route. | 21 | +To have a page-agnostic snackbar, we used OverlayRoute to display a partial route. | 
| 6 | However this had several problems: | 22 | However this had several problems: | 
| 7 | 23 | ||
| 8 | 1: There was no possibility to close the page without closing the snackbar | 24 | 1: There was no possibility to close the page without closing the snackbar | 
| @@ -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 타입들: | 
| 1 | -class Logger { | 1 | +mixin Logger { | 
| 2 | // Sample of abstract logging function | 2 | // Sample of abstract logging function | 
| 3 | static void write(String text, {bool isError = false}) { | 3 | static void write(String text, {bool isError = false}) { | 
| 4 | Future.microtask(() => print('** $text. isError: [$isError]')); | 4 | Future.microtask(() => print('** $text. isError: [$isError]')); | 
| @@ -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,7 +135,7 @@ class GetConnect extends GetConnectInterface { | @@ -134,7 +135,7 @@ class GetConnect extends GetConnectInterface { | ||
| 134 | baseUrl: baseUrl, | 135 | baseUrl: baseUrl, | 
| 135 | trustedCertificates: trustedCertificates, | 136 | trustedCertificates: trustedCertificates, | 
| 136 | withCredentials: withCredentials, | 137 | withCredentials: withCredentials, | 
| 137 | - ); | 138 | + findProxy: findProxy); | 
| 138 | 139 | ||
| 139 | @override | 140 | @override | 
| 140 | Future<Response<T>> get<T>( | 141 | Future<Response<T>> get<T>( | 
| @@ -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 | 
| @@ -14,6 +14,7 @@ class HttpRequestImpl implements HttpRequestBase { | @@ -14,6 +14,7 @@ class HttpRequestImpl implements HttpRequestBase { | ||
| 14 | bool allowAutoSignedCert = true, | 14 | bool allowAutoSignedCert = true, | 
| 15 | List<TrustedCertificate>? trustedCertificates, | 15 | List<TrustedCertificate>? trustedCertificates, | 
| 16 | this.withCredentials = false, | 16 | this.withCredentials = false, | 
| 17 | + String Function(Uri url)? findProxy, | ||
| 17 | }); | 18 | }); | 
| 18 | 19 | ||
| 19 | /// The currently active XHRs. | 20 | /// The currently active XHRs. | 
| @@ -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() {} | 
| @@ -232,7 +232,7 @@ class GetInstance { | @@ -232,7 +232,7 @@ class GetInstance { | ||
| 232 | final newKey = key ?? _getKey(S, tag); | 232 | final newKey = key ?? _getKey(S, tag); | 
| 233 | if (_singl.containsKey(newKey)) { | 233 | if (_singl.containsKey(newKey)) { | 
| 234 | final dep = _singl[newKey]; | 234 | final dep = _singl[newKey]; | 
| 235 | - if (dep != null) { | 235 | + if (dep != null && !dep.permanent) { | 
| 236 | dep.isDirty = true; | 236 | dep.isDirty = true; | 
| 237 | } | 237 | } | 
| 238 | } | 238 | } | 
| @@ -9,9 +9,6 @@ import '../../get_utils/get_utils.dart'; | @@ -9,9 +9,6 @@ import '../../get_utils/get_utils.dart'; | ||
| 9 | import '../get_navigation.dart'; | 9 | import '../get_navigation.dart'; | 
| 10 | import 'dialog/dialog_route.dart'; | 10 | import 'dialog/dialog_route.dart'; | 
| 11 | import 'root/parse_route.dart'; | 11 | import 'root/parse_route.dart'; | 
| 12 | -import 'root/root_controller.dart'; | ||
| 13 | -import 'routes/transitions_type.dart'; | ||
| 14 | -import 'snackbar/snackbar_controller.dart'; | ||
| 15 | 12 | ||
| 16 | /// It replaces the Flutter Navigator, but needs no context. | 13 | /// It replaces the Flutter Navigator, but needs no context. | 
| 17 | /// You can to use navigator.push(YourRoute()) rather | 14 | /// You can to use navigator.push(YourRoute()) rather | 
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | 2 | ||
| 3 | import '../../../get.dart'; | 3 | import '../../../get.dart'; | 
| 4 | -import 'get_navigator.dart'; | ||
| 5 | -import 'get_router_delegate.dart'; | ||
| 6 | 4 | ||
| 7 | class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> | 5 | class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> | 
| 8 | extends StatefulWidget { | 6 | extends StatefulWidget { | 
| 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'; | 
| 7 | import '../../../get_utils/get_utils.dart'; | 8 | import '../../../get_utils/get_utils.dart'; | 
| 8 | import '../../get_navigation.dart'; | 9 | import '../../get_navigation.dart'; | 
| 9 | -import 'root_controller.dart'; | ||
| 10 | 10 | ||
| 11 | class GetCupertinoApp extends StatelessWidget { | 11 | class GetCupertinoApp extends StatelessWidget { | 
| 12 | + final GlobalKey<NavigatorState>? navigatorKey; | ||
| 13 | + | ||
| 14 | + final Widget? home; | ||
| 15 | + final Map<String, WidgetBuilder>? routes; | ||
| 16 | + final String? initialRoute; | ||
| 17 | + final RouteFactory? onGenerateRoute; | ||
| 18 | + final InitialRouteListFactory? onGenerateInitialRoutes; | ||
| 19 | + final RouteFactory? onUnknownRoute; | ||
| 20 | + final List<NavigatorObserver>? navigatorObservers; | ||
| 21 | + final TransitionBuilder? builder; | ||
| 22 | + final String title; | ||
| 23 | + final GenerateAppTitle? onGenerateTitle; | ||
| 24 | + final CustomTransition? customTransition; | ||
| 25 | + final Color? color; | ||
| 26 | + final Map<String, Map<String, String>>? translationsKeys; | ||
| 27 | + final Translations? translations; | ||
| 28 | + final TextDirection? textDirection; | ||
| 29 | + final Locale? locale; | ||
| 30 | + final Locale? fallbackLocale; | ||
| 31 | + final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates; | ||
| 32 | + final LocaleListResolutionCallback? localeListResolutionCallback; | ||
| 33 | + final LocaleResolutionCallback? localeResolutionCallback; | ||
| 34 | + final Iterable<Locale> supportedLocales; | ||
| 35 | + final bool showPerformanceOverlay; | ||
| 36 | + final bool checkerboardRasterCacheImages; | ||
| 37 | + final bool checkerboardOffscreenLayers; | ||
| 38 | + final bool showSemanticsDebugger; | ||
| 39 | + final bool debugShowCheckedModeBanner; | ||
| 40 | + final Map<LogicalKeySet, Intent>? shortcuts; | ||
| 41 | + final ThemeData? highContrastTheme; | ||
| 42 | + final ThemeData? highContrastDarkTheme; | ||
| 43 | + final Map<Type, Action<Intent>>? actions; | ||
| 44 | + final Function(Routing?)? routingCallback; | ||
| 45 | + final Transition? defaultTransition; | ||
| 46 | + final bool? opaqueRoute; | ||
| 47 | + final VoidCallback? onInit; | ||
| 48 | + final VoidCallback? onReady; | ||
| 49 | + final VoidCallback? onDispose; | ||
| 50 | + final bool? enableLog; | ||
| 51 | + final LogWriterCallback? logWriterCallback; | ||
| 52 | + final bool? popGesture; | ||
| 53 | + final SmartManagement smartManagement; | ||
| 54 | + final Bindings? initialBinding; | ||
| 55 | + final Duration? transitionDuration; | ||
| 56 | + final bool? defaultGlobalState; | ||
| 57 | + final List<GetPage>? getPages; | ||
| 58 | + final GetPage? unknownRoute; | ||
| 59 | + final RouteInformationProvider? routeInformationProvider; | ||
| 60 | + final RouteInformationParser<Object>? routeInformationParser; | ||
| 61 | + final RouterDelegate<Object>? routerDelegate; | ||
| 62 | + final BackButtonDispatcher? backButtonDispatcher; | ||
| 63 | + final CupertinoThemeData? theme; | ||
| 64 | + final bool useInheritedMediaQuery; | ||
| 12 | const GetCupertinoApp({ | 65 | const GetCupertinoApp({ | 
| 13 | Key? key, | 66 | Key? key, | 
| 14 | this.theme, | 67 | this.theme, | 
| @@ -46,6 +99,7 @@ class GetCupertinoApp extends StatelessWidget { | @@ -46,6 +99,7 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 46 | this.shortcuts, | 99 | this.shortcuts, | 
| 47 | this.smartManagement = SmartManagement.full, | 100 | this.smartManagement = SmartManagement.full, | 
| 48 | this.initialBinding, | 101 | this.initialBinding, | 
| 102 | + this.useInheritedMediaQuery = false, | ||
| 49 | this.unknownRoute, | 103 | this.unknownRoute, | 
| 50 | this.routingCallback, | 104 | this.routingCallback, | 
| 51 | this.defaultTransition, | 105 | this.defaultTransition, | 
| @@ -66,58 +120,6 @@ class GetCupertinoApp extends StatelessWidget { | @@ -66,58 +120,6 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 66 | backButtonDispatcher = null, | 120 | backButtonDispatcher = null, | 
| 67 | super(key: key); | 121 | super(key: key); | 
| 68 | 122 | ||
| 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({ | 123 | GetCupertinoApp.router({ | 
| 122 | Key? key, | 124 | Key? key, | 
| 123 | this.theme, | 125 | this.theme, | 
| @@ -128,6 +130,7 @@ class GetCupertinoApp extends StatelessWidget { | @@ -128,6 +130,7 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 128 | this.builder, | 130 | this.builder, | 
| 129 | this.title = '', | 131 | this.title = '', | 
| 130 | this.onGenerateTitle, | 132 | this.onGenerateTitle, | 
| 133 | + this.useInheritedMediaQuery = false, | ||
| 131 | this.color, | 134 | this.color, | 
| 132 | this.highContrastTheme, | 135 | this.highContrastTheme, | 
| 133 | this.highContrastDarkTheme, | 136 | this.highContrastDarkTheme, | 
| @@ -183,31 +186,6 @@ class GetCupertinoApp extends StatelessWidget { | @@ -183,31 +186,6 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 183 | Get.routeInformationParser = routeInformationParser; | 186 | Get.routeInformationParser = routeInformationParser; | 
| 184 | } | 187 | } | 
| 185 | 188 | ||
| 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 | 189 | @override | 
| 212 | Widget build(BuildContext context) => GetBuilder<GetMaterialController>( | 190 | Widget build(BuildContext context) => GetBuilder<GetMaterialController>( | 
| 213 | init: Get.rootController, | 191 | init: Get.rootController, | 
| @@ -271,6 +249,7 @@ class GetCupertinoApp extends StatelessWidget { | @@ -271,6 +249,7 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 271 | showSemanticsDebugger: showSemanticsDebugger, | 249 | showSemanticsDebugger: showSemanticsDebugger, | 
| 272 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 250 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 
| 273 | shortcuts: shortcuts, | 251 | shortcuts: shortcuts, | 
| 252 | + useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 274 | ) | 253 | ) | 
| 275 | : CupertinoApp( | 254 | : CupertinoApp( | 
| 276 | key: _.unikey, | 255 | key: _.unikey, | 
| @@ -310,7 +289,33 @@ class GetCupertinoApp extends StatelessWidget { | @@ -310,7 +289,33 @@ class GetCupertinoApp extends StatelessWidget { | ||
| 310 | showSemanticsDebugger: showSemanticsDebugger, | 289 | showSemanticsDebugger: showSemanticsDebugger, | 
| 311 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 290 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 
| 312 | shortcuts: shortcuts, | 291 | shortcuts: shortcuts, | 
| 292 | + useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 313 | // actions: actions, | 293 | // actions: actions, | 
| 314 | ), | 294 | ), | 
| 315 | ); | 295 | ); | 
| 296 | + | ||
| 297 | + Widget defaultBuilder(BuildContext context, Widget? child) { | ||
| 298 | + return Directionality( | ||
| 299 | + textDirection: textDirection ?? | ||
| 300 | + (rtlLanguages.contains(Get.locale?.languageCode) | ||
| 301 | + ? TextDirection.rtl | ||
| 302 | + : TextDirection.ltr), | ||
| 303 | + child: builder == null | ||
| 304 | + ? (child ?? Material()) | ||
| 305 | + : builder!(context, child ?? Material()), | ||
| 306 | + ); | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + Route<dynamic> generator(RouteSettings settings) { | ||
| 310 | + return PageRedirect(settings: settings, unknownRoute: unknownRoute).page(); | ||
| 311 | + } | ||
| 312 | + | ||
| 313 | + List<Route<dynamic>> initialRoutesGenerate(String name) { | ||
| 314 | + return [ | ||
| 315 | + PageRedirect( | ||
| 316 | + settings: RouteSettings(name: name), | ||
| 317 | + unknownRoute: unknownRoute, | ||
| 318 | + ).page() | ||
| 319 | + ]; | ||
| 320 | + } | ||
| 316 | } | 321 | } | 
| 1 | -import 'package:flutter/cupertino.dart'; | ||
| 2 | import 'package:flutter/foundation.dart'; | 1 | import 'package:flutter/foundation.dart'; | 
| 3 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; | 
| 4 | 3 | ||
| @@ -7,7 +6,6 @@ import '../../../get_instance/get_instance.dart'; | @@ -7,7 +6,6 @@ import '../../../get_instance/get_instance.dart'; | ||
| 7 | import '../../../get_state_manager/get_state_manager.dart'; | 6 | import '../../../get_state_manager/get_state_manager.dart'; | 
| 8 | import '../../../get_utils/get_utils.dart'; | 7 | import '../../../get_utils/get_utils.dart'; | 
| 9 | import '../../get_navigation.dart'; | 8 | import '../../get_navigation.dart'; | 
| 10 | -import 'root_controller.dart'; | ||
| 11 | 9 | ||
| 12 | class GetMaterialApp extends StatelessWidget { | 10 | class GetMaterialApp extends StatelessWidget { | 
| 13 | final GlobalKey<NavigatorState>? navigatorKey; | 11 | final GlobalKey<NavigatorState>? navigatorKey; | 
| @@ -67,6 +65,7 @@ class GetMaterialApp extends StatelessWidget { | @@ -67,6 +65,7 @@ class GetMaterialApp extends StatelessWidget { | ||
| 67 | final RouteInformationParser<Object>? routeInformationParser; | 65 | final RouteInformationParser<Object>? routeInformationParser; | 
| 68 | final RouterDelegate<Object>? routerDelegate; | 66 | final RouterDelegate<Object>? routerDelegate; | 
| 69 | final BackButtonDispatcher? backButtonDispatcher; | 67 | final BackButtonDispatcher? backButtonDispatcher; | 
| 68 | + final bool useInheritedMediaQuery; | ||
| 70 | const GetMaterialApp({ | 69 | const GetMaterialApp({ | 
| 71 | Key? key, | 70 | Key? key, | 
| 72 | this.navigatorKey, | 71 | this.navigatorKey, | 
| @@ -78,6 +77,7 @@ class GetMaterialApp extends StatelessWidget { | @@ -78,6 +77,7 @@ class GetMaterialApp extends StatelessWidget { | ||
| 78 | this.onGenerateRoute, | 77 | this.onGenerateRoute, | 
| 79 | this.onGenerateInitialRoutes, | 78 | this.onGenerateInitialRoutes, | 
| 80 | this.onUnknownRoute, | 79 | this.onUnknownRoute, | 
| 80 | + this.useInheritedMediaQuery = false, | ||
| 81 | List<NavigatorObserver> this.navigatorObservers = | 81 | List<NavigatorObserver> this.navigatorObservers = | 
| 82 | const <NavigatorObserver>[], | 82 | const <NavigatorObserver>[], | 
| 83 | this.builder, | 83 | this.builder, | 
| @@ -142,6 +142,7 @@ class GetMaterialApp extends StatelessWidget { | @@ -142,6 +142,7 @@ class GetMaterialApp extends StatelessWidget { | ||
| 142 | this.color, | 142 | this.color, | 
| 143 | this.theme, | 143 | this.theme, | 
| 144 | this.darkTheme, | 144 | this.darkTheme, | 
| 145 | + this.useInheritedMediaQuery = false, | ||
| 145 | this.highContrastTheme, | 146 | this.highContrastTheme, | 
| 146 | this.highContrastDarkTheme, | 147 | this.highContrastDarkTheme, | 
| 147 | this.themeMode = ThemeMode.system, | 148 | this.themeMode = ThemeMode.system, | 
| @@ -271,6 +272,7 @@ class GetMaterialApp extends StatelessWidget { | @@ -271,6 +272,7 @@ class GetMaterialApp extends StatelessWidget { | ||
| 271 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 272 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 
| 272 | shortcuts: shortcuts, | 273 | shortcuts: shortcuts, | 
| 273 | scrollBehavior: scrollBehavior, | 274 | scrollBehavior: scrollBehavior, | 
| 275 | + useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 274 | ) | 276 | ) | 
| 275 | : MaterialApp( | 277 | : MaterialApp( | 
| 276 | key: _.unikey, | 278 | key: _.unikey, | 
| @@ -317,6 +319,7 @@ class GetMaterialApp extends StatelessWidget { | @@ -317,6 +319,7 @@ class GetMaterialApp extends StatelessWidget { | ||
| 317 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 319 | debugShowCheckedModeBanner: debugShowCheckedModeBanner, | 
| 318 | shortcuts: shortcuts, | 320 | shortcuts: shortcuts, | 
| 319 | scrollBehavior: scrollBehavior, | 321 | scrollBehavior: scrollBehavior, | 
| 322 | + useInheritedMediaQuery: useInheritedMediaQuery, | ||
| 320 | // actions: actions, | 323 | // actions: actions, | 
| 321 | ), | 324 | ), | 
| 322 | ); | 325 | ); | 
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | 2 | ||
| 3 | import '../../../get.dart'; | 3 | import '../../../get.dart'; | 
| 4 | -import '../../../get_state_manager/get_state_manager.dart'; | ||
| 5 | -import '../../../get_utils/get_utils.dart'; | ||
| 6 | -import '../routes/custom_transition.dart'; | ||
| 7 | -import '../routes/observers/route_observer.dart'; | ||
| 8 | -import '../routes/transitions_type.dart'; | ||
| 9 | 4 | ||
| 10 | class GetMaterialController extends SuperController { | 5 | class GetMaterialController extends SuperController { | 
| 11 | bool testMode = false; | 6 | bool testMode = false; | 
| 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 center = centerAlignment?.alongSize(size) ?? | ||
| 24 | + 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 | +} | 
| @@ -2,10 +2,7 @@ import 'package:flutter/material.dart'; | @@ -2,10 +2,7 @@ import 'package:flutter/material.dart'; | ||
| 2 | 2 | ||
| 3 | import '../../../get.dart'; | 3 | import '../../../get.dart'; | 
| 4 | import '../router_report.dart'; | 4 | import '../router_report.dart'; | 
| 5 | -import 'custom_transition.dart'; | ||
| 6 | import 'get_transition_mixin.dart'; | 5 | import 'get_transition_mixin.dart'; | 
| 7 | -import 'route_middleware.dart'; | ||
| 8 | -import 'transitions_type.dart'; | ||
| 9 | 6 | ||
| 10 | mixin PageRouteReportMixin<T> on Route<T> { | 7 | mixin PageRouteReportMixin<T> on Route<T> { | 
| 11 | @override | 8 | @override | 
| 1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; | 
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; | 
| 3 | 3 | ||
| 4 | +import 'circular_reveal_clipper.dart'; | ||
| 5 | + | ||
| 4 | class LeftToRightFadeTransition { | 6 | class LeftToRightFadeTransition { | 
| 5 | Widget buildTransitions( | 7 | Widget buildTransitions( | 
| 6 | BuildContext context, | 8 | BuildContext context, | 
| @@ -184,3 +186,24 @@ class SizeTransitions { | @@ -184,3 +186,24 @@ class SizeTransitions { | ||
| 184 | ); | 186 | ); | 
| 185 | } | 187 | } | 
| 186 | } | 188 | } | 
| 189 | + | ||
| 190 | +class CircularRevealTransition { | ||
| 191 | + Widget buildTransitions( | ||
| 192 | + BuildContext context, | ||
| 193 | + Curve? curve, | ||
| 194 | + Alignment? alignment, | ||
| 195 | + Animation<double> animation, | ||
| 196 | + Animation<double> secondaryAnimation, | ||
| 197 | + Widget child) { | ||
| 198 | + return ClipPath( | ||
| 199 | + clipper: CircularRevealClipper( | ||
| 200 | + fraction: animation.value, | ||
| 201 | + centerAlignment: Alignment.center, | ||
| 202 | + centerOffset: Offset.zero, | ||
| 203 | + minRadius: 0, | ||
| 204 | + maxRadius: 800, | ||
| 205 | + ), | ||
| 206 | + child: child, | ||
| 207 | + ); | ||
| 208 | + } | ||
| 209 | +} | 
| 1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; | 
| 2 | -import 'package:flutter/foundation.dart'; | ||
| 3 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; | 
| 4 | -import 'package:flutter/widgets.dart'; | ||
| 5 | 3 | ||
| 6 | import '../../../get_core/src/get_main.dart'; | 4 | import '../../../get_core/src/get_main.dart'; | 
| 7 | import '../../../get_instance/get_instance.dart'; | 5 | import '../../../get_instance/get_instance.dart'; | 
| 8 | import '../../get_navigation.dart'; | 6 | import '../../get_navigation.dart'; | 
| 9 | -import 'custom_transition.dart'; | ||
| 10 | -import 'transitions_type.dart'; | ||
| 11 | 7 | ||
| 12 | class GetPage<T> extends Page<T> { | 8 | class GetPage<T> extends Page<T> { | 
| 13 | final GetPageBuilder page; | 9 | final GetPageBuilder page; | 
| @@ -8,7 +8,6 @@ import 'package:flutter/material.dart'; | @@ -8,7 +8,6 @@ import 'package:flutter/material.dart'; | ||
| 8 | 8 | ||
| 9 | import '../../../get.dart'; | 9 | import '../../../get.dart'; | 
| 10 | import 'default_transitions.dart'; | 10 | import 'default_transitions.dart'; | 
| 11 | -import 'transitions_type.dart'; | ||
| 12 | 11 | ||
| 13 | const double _kBackGestureWidth = 20.0; | 12 | const double _kBackGestureWidth = 20.0; | 
| 14 | const int _kMaxDroppedSwipePageForwardAnimationTime = | 13 | const int _kMaxDroppedSwipePageForwardAnimationTime = | 
| @@ -620,6 +619,22 @@ Cannot read the previousTitle for a route that has not yet been installed''', | @@ -620,6 +619,22 @@ Cannot read the previousTitle for a route that has not yet been installed''', | ||
| 620 | child: child) | 619 | child: child) | 
| 621 | : child); | 620 | : child); | 
| 622 | 621 | ||
| 622 | + case Transition.circularReveal: | ||
| 623 | + return CircularRevealTransition().buildTransitions( | ||
| 624 | + context, | ||
| 625 | + route.curve, | ||
| 626 | + route.alignment, | ||
| 627 | + animation, | ||
| 628 | + secondaryAnimation, | ||
| 629 | + route.popGesture ?? Get.defaultPopGesture | ||
| 630 | + ? CupertinoBackGestureDetector<T>( | ||
| 631 | + gestureWidth: route.gestureWidth?.call(context) ?? | ||
| 632 | + _kBackGestureWidth, | ||
| 633 | + enabledCallback: () => _isPopGestureEnabled<T>(route), | ||
| 634 | + onStartPopGesture: () => _startPopGesture<T>(route), | ||
| 635 | + child: child) | ||
| 636 | + : child); | ||
| 637 | + | ||
| 623 | default: | 638 | default: | 
| 624 | if (Get.customTransition != null) { | 639 | if (Get.customTransition != null) { | 
| 625 | return Get.customTransition!.buildTransition(context, route.curve, | 640 | return Get.customTransition!.buildTransition(context, route.curve, | 
| @@ -5,7 +5,6 @@ import '../../../../instance_manager.dart'; | @@ -5,7 +5,6 @@ import '../../../../instance_manager.dart'; | ||
| 5 | import '../../../get_navigation.dart'; | 5 | import '../../../get_navigation.dart'; | 
| 6 | import '../../dialog/dialog_route.dart'; | 6 | import '../../dialog/dialog_route.dart'; | 
| 7 | import '../../router_report.dart'; | 7 | import '../../router_report.dart'; | 
| 8 | -import '../default_route.dart'; | ||
| 9 | 8 | ||
| 10 | /// Extracts the name of a route based on it's instance type | 9 | /// Extracts the name of a route based on it's instance type | 
| 11 | /// or null if not possible. | 10 | /// or null if not possible. | 
| @@ -17,7 +17,8 @@ enum Transition { | @@ -17,7 +17,8 @@ enum Transition { | ||
| 17 | cupertino, | 17 | cupertino, | 
| 18 | cupertinoDialog, | 18 | cupertinoDialog, | 
| 19 | size, | 19 | size, | 
| 20 | - native | 20 | + circularReveal, | 
| 21 | + native, | ||
| 21 | } | 22 | } | 
| 22 | 23 | ||
| 23 | typedef GetPageBuilder = Widget Function(); | 24 | typedef GetPageBuilder = Widget Function(); | 
| @@ -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,100 @@ mixin GetSingleTickerProviderStateMixin on GetxController | @@ -82,6 +82,100 @@ 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, | ||
| 117 | + debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null); | ||
| 118 | + _tickers!.add(result); | ||
| 119 | + return result; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + void _removeTicker(_WidgetTicker ticker) { | ||
| 123 | + assert(_tickers != null); | ||
| 124 | + assert(_tickers!.contains(ticker)); | ||
| 125 | + _tickers!.remove(ticker); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + void didChangeDependencies(BuildContext context) { | ||
| 129 | + final muted = !TickerMode.of(context); | ||
| 130 | + if (_tickers != null) { | ||
| 131 | + for (final ticker in _tickers!) { | ||
| 132 | + ticker.muted = muted; | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + @override | ||
| 138 | + void onClose() { | ||
| 139 | + assert(() { | ||
| 140 | + if (_tickers != null) { | ||
| 141 | + for (final ticker in _tickers!) { | ||
| 142 | + if (ticker.isActive) { | ||
| 143 | + throw FlutterError.fromParts(<DiagnosticsNode>[ | ||
| 144 | + ErrorSummary('$this was disposed with an active Ticker.'), | ||
| 145 | + ErrorDescription( | ||
| 146 | + '$runtimeType created a Ticker via its GetTickerProviderStateMixin, but at the time ' | ||
| 147 | + 'dispose() was called on the mixin, that Ticker was still active. All Tickers must ' | ||
| 148 | + 'be disposed before calling super.dispose().', | ||
| 149 | + ), | ||
| 150 | + ErrorHint( | ||
| 151 | + 'Tickers used by AnimationControllers ' | ||
| 152 | + 'should be disposed by calling dispose() on the AnimationController itself. ' | ||
| 153 | + 'Otherwise, the ticker will leak.', | ||
| 154 | + ), | ||
| 155 | + ticker.describeForError('The offending ticker was'), | ||
| 156 | + ]); | ||
| 157 | + } | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | + return true; | ||
| 161 | + }()); | ||
| 162 | + super.onClose(); | ||
| 163 | + } | ||
| 164 | +} | ||
| 165 | + | ||
| 166 | +class _WidgetTicker extends Ticker { | ||
| 167 | + _WidgetTicker(TickerCallback onTick, this._creator, {String? debugLabel}) | ||
| 168 | + : super(onTick, debugLabel: debugLabel); | ||
| 169 | + | ||
| 170 | + final GetTickerProviderStateMixin _creator; | ||
| 171 | + | ||
| 172 | + @override | ||
| 173 | + void dispose() { | ||
| 174 | + _creator._removeTicker(this); | ||
| 175 | + super.dispose(); | ||
| 176 | + } | ||
| 177 | +} | ||
| 178 | + | ||
| 85 | @Deprecated('use GetSingleTickerProviderStateMixin') | 179 | @Deprecated('use GetSingleTickerProviderStateMixin') | 
| 86 | 180 | ||
| 87 | /// Used like `SingleTickerProviderMixin` but only with Get Controllers. | 181 | /// Used like `SingleTickerProviderMixin` but only with Get Controllers. | 
| 1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; | 
| 2 | 2 | ||
| 3 | import '../../../get.dart'; | 3 | import '../../../get.dart'; | 
| 4 | -import 'get_view.dart'; | ||
| 5 | 4 | ||
| 6 | mixin GetResponsiveMixin on Widget { | 5 | mixin GetResponsiveMixin on Widget { | 
| 7 | ResponsiveScreen get screen; | 6 | ResponsiveScreen get screen; | 
| 1 | import 'dart:collection'; | 1 | import 'dart:collection'; | 
| 2 | -import 'package:flutter/foundation.dart'; | 2 | + | 
| 3 | import 'package:flutter/widgets.dart'; | 3 | import 'package:flutter/widgets.dart'; | 
| 4 | 4 | ||
| 5 | // This callback remove the listener on addListener function | 5 | // This callback remove the listener on addListener function | 
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | + | ||
| 2 | import '../../get_state_manager.dart'; | 3 | import '../../get_state_manager.dart'; | 
| 3 | -import 'get_state.dart'; | ||
| 4 | 4 | ||
| 5 | class MixinBuilder<T extends GetxController> extends StatelessWidget { | 5 | class MixinBuilder<T extends GetxController> extends StatelessWidget { | 
| 6 | @required | 6 | @required | 
| 1 | import 'package:collection/collection.dart'; | 1 | import 'package:collection/collection.dart'; | 
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; | 
| 3 | -import 'package:flutter/widgets.dart'; | ||
| 4 | 3 | ||
| 5 | extension ContextExtensionss on BuildContext { | 4 | extension ContextExtensionss on BuildContext { | 
| 6 | /// The same of [MediaQuery.of(context).size] | 5 | /// The same of [MediaQuery.of(context).size] | 
| @@ -68,14 +68,14 @@ extension Trans on String { | @@ -68,14 +68,14 @@ extension Trans on String { | ||
| 68 | Map<String, String>? get _getSimilarLanguageTranslation { | 68 | Map<String, String>? get _getSimilarLanguageTranslation { | 
| 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 = | ||
| 72 | - translationsWithNoCountry.containsKey(Get.locale!.languageCode); | 71 | + final containsKey = translationsWithNoCountry | 
| 72 | + .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 { | 
| 1 | name: get | 1 | name: get | 
| 2 | description: Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX. | 2 | description: Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX. | 
| 3 | -version: 4.5.1 | 3 | +version: 4.6.1 | 
| 4 | homepage: https://github.com/jonataslaw/getx | 4 | homepage: https://github.com/jonataslaw/getx | 
| 5 | 5 | ||
| 6 | environment: | 6 | environment: | 
| 1 | +// ignore_for_file: avoid_classes_with_only_static_members | ||
| 2 | + | ||
| 1 | import 'package:flutter_test/flutter_test.dart'; | 3 | import 'package:flutter_test/flutter_test.dart'; | 
| 2 | import 'package:get/get.dart'; | 4 | import 'package:get/get.dart'; | 
| 3 | 5 | ||
| @@ -146,8 +148,8 @@ void main() { | @@ -146,8 +148,8 @@ void main() { | ||
| 146 | Get.create<Service>(() => Api()); | 148 | Get.create<Service>(() => Api()); | 
| 147 | final ct1 = Get.find<Service>(); | 149 | final ct1 = Get.find<Service>(); | 
| 148 | final ct2 = Get.find<Service>(); | 150 | final ct2 = Get.find<Service>(); | 
| 149 | - expect(ct1 is Service, true); | ||
| 150 | - expect(ct2 is Service, true); | 151 | + // expect(ct1 is Service, true); | 
| 152 | + // expect(ct2 is Service, true); | ||
| 151 | expect(ct1 == ct2, false); | 153 | expect(ct1 == ct2, false); | 
| 152 | Get.reset(); | 154 | Get.reset(); | 
| 153 | }); | 155 | }); | 
| @@ -336,7 +336,10 @@ void main() { | @@ -336,7 +336,10 @@ void main() { | ||
| 336 | 336 | ||
| 337 | testWidgets("Get.back navigates back", (tester) async { | 337 | testWidgets("Get.back navigates back", (tester) async { | 
| 338 | await tester.pumpWidget( | 338 | await tester.pumpWidget( | 
| 339 | - Wrapper(child: FirstScreen()), | 339 | + Wrapper( | 
| 340 | + child: FirstScreen(), | ||
| 341 | + defaultTransition: Transition.circularReveal, | ||
| 342 | + ), | ||
| 340 | ); | 343 | ); | 
| 341 | 344 | ||
| 342 | Get.to(SecondScreen()); | 345 | Get.to(SecondScreen()); | 
| 1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; | 
| 2 | -import 'package:flutter/material.dart'; | ||
| 3 | import 'package:flutter_test/flutter_test.dart'; | 2 | import 'package:flutter_test/flutter_test.dart'; | 
| 4 | import 'package:get/get.dart'; | 3 | import 'package:get/get.dart'; | 
| 5 | 4 | 
| @@ -114,6 +114,23 @@ void main() { | @@ -114,6 +114,23 @@ void main() { | ||
| 114 | expect(1, timesCalled); | 114 | expect(1, timesCalled); | 
| 115 | }); | 115 | }); | 
| 116 | 116 | ||
| 117 | + test('Rx different value will call the listener when `trigger`', () async { | ||
| 118 | + var reactiveInteger = RxInt(0); | ||
| 119 | + var timesCalled = 0; | ||
| 120 | + reactiveInteger.listen((newInt) { | ||
| 121 | + timesCalled++; | ||
| 122 | + }); | ||
| 123 | + | ||
| 124 | + // we call 3 | ||
| 125 | + reactiveInteger.trigger(1); | ||
| 126 | + // then repeat twice | ||
| 127 | + reactiveInteger.trigger(2); | ||
| 128 | + reactiveInteger.trigger(3); | ||
| 129 | + | ||
| 130 | + await Future.delayed(Duration(milliseconds: 100)); | ||
| 131 | + expect(3, timesCalled); | ||
| 132 | + }); | ||
| 133 | + | ||
| 117 | test('Rx same value will call the listener when `trigger`', () async { | 134 | test('Rx same value will call the listener when `trigger`', () async { | 
| 118 | var reactiveInteger = RxInt(2); | 135 | var reactiveInteger = RxInt(2); | 
| 119 | var timesCalled = 0; | 136 | var timesCalled = 0; | 
| @@ -126,9 +143,10 @@ void main() { | @@ -126,9 +143,10 @@ void main() { | ||
| 126 | // then repeat twice | 143 | // then repeat twice | 
| 127 | reactiveInteger.trigger(3); | 144 | reactiveInteger.trigger(3); | 
| 128 | reactiveInteger.trigger(3); | 145 | reactiveInteger.trigger(3); | 
| 146 | + reactiveInteger.trigger(1); | ||
| 129 | 147 | ||
| 130 | await Future.delayed(Duration(milliseconds: 100)); | 148 | await Future.delayed(Duration(milliseconds: 100)); | 
| 131 | - expect(3, timesCalled); | 149 | + expect(4, timesCalled); | 
| 132 | }); | 150 | }); | 
| 133 | 151 | ||
| 134 | test('Rx String with non null values', () async { | 152 | test('Rx String with non null values', () async { | 
- 
Please register or login to post a comment