Closed jtkeyva closed 3 years ago
Hi JT,
I'm not the owner of this repo, but normally convert to null safety is very simple.
Do you need help?
Hi @fabiohxcx that's very generous of you! I tried doing it with another repo and I had to revert back and have been intimidated since. Sure, help would be great! What can I do now? Thanks
Any help or guidance greatly appreciated. These are the packages in my project (some in this repo) that I rely on that are not yet NULL Safe so it's kinda tricky and not sure what to do:
simple_gravatar - looks like it’s updated as of github? fireflutter - requested merge_map - requested esys_flutter_share (don’t need) flutter_widgets - broken down into smaller packages that each support null safety flutter_hsvcolor_picker story_painter -reqeusted fast_color_picker - requested control_pad - requested simple_timer - requested cupertino_rounded_corners - requested
I will work on this in the next day for this repo. It shouldn’t be too difficult if all the packages it relies on are already ported. If not I will need to wait until they are. I know getx is ported, I will check the rest.
Dear @jtkeyva,
I thought you were talking about converting your code to null safety and not about dependencies.
It's possible to use packages that are not yet NULL Safe, but several problems can happen.
Because depending on the package the Null value is necessary for the logic.
For example, you are using a package for search in list, and the logic consider that if String comes null we have to return all items and if String is Empty return an empty list.
The best way is wait for the update from package creators. Otherwise you would have to enter the in each repo package to check the logic.
@delay awesome!
@fabiohxcx thank you. yeah, i'm kinda stuck because a handful of packages are still not safe although i have requested so I suppose I just wait. on another note, i have not upgraded flutter because i can't run my projects. have you had luck running null sound (or whatever it is ha)?
@jtkeyva I still never tried to clone a repo null safety, but I created some projects for test, including null safety packages and ran very well.
Null Safe is just a tool to help developers avoid null exceptions.
The default is everything not to be null.
But there will always be cases where the var need to be null.
Por example an API response:
String? name = json['name']
, there's no way to escape.
or set a default in case of null:
String name = json[ 'name'] ?? 'no name';
Really depends on your logic and context.
There are a lot of tutorials about this subject.
Hope I have helped you
@jtkeyva just another tip.
I you need to work on projects and each of the project uses different flutter versions (some null safe and others not), fvm
can help you.
I spent some time working on this today and it is more involved than I thought it would be. I have made changes to pretty much every file but there are some underlying changes I need to make to the loader and the localization package is not outputting null safe generated code. I manually edited it but is what I really need to do is to make some code which will use getX localization instead of this package but that is more involved since I still want to use a spreadsheet for the translations. Also firebase hasn't made their analytics package null safe yet.
Dear @delay
I was able to convert the Loader
code into null safe.
below is the code, I changed a few names, but it's almost the same code from you:
It worked perfectly.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../theme/colors.dart';
final _loadKey = GlobalKey(debugLabel: 'overlay_parent');
final _modalBarrierDefaultColor = warmGrey.withOpacity(0.7);
late OverlayEntry _loaderEntry;
bool _loaderShown = false;
Widget? _loadingIndicator;
class GlobalLoading extends StatelessWidget {
final Widget child;
final Widget? loader;
const GlobalLoading({Key? key, this.loader, required this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
// BackButtonInterceptor.init();
_loadingIndicator = loader;
return SizedBox(
key: _loadKey,
child: child,
);
}
}
OverlayState? get _overlayState {
final context = _loadKey.currentContext;
if (context == null) return null;
NavigatorState? navigator;
void visitor(Element element) {
if (navigator != null) return;
if (element.widget is Navigator) {
navigator = (element as StatefulElement).state as NavigatorState;
} else {
element.visitChildElements(visitor);
}
}
// ignore: unused_element
context.visitChildElements(visitor);
assert(navigator != null, '''unable to show overlay''');
return navigator!.overlay;
}
/// To handle a loader for the application
Future<void> showLoadingIndicator({bool isModal = true, Color? modalColor, double size = 30}) async {
try {
debugPrint('Showing loading overlay');
final _child = Center(
child: SizedBox(
width: size,
height: size,
child: _loadingIndicator ?? CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Colors.black)),
),
);
await _showOverlay(
child: isModal
? Stack(
children: <Widget>[
ModalBarrier(
dismissible: false,
color: modalColor ?? _modalBarrierDefaultColor,
),
_child
],
)
: _child,
);
} catch (err) {
debugPrint('Exception showing loading overlay\n${err.toString()}');
rethrow;
}
}
Future<void> hideLoadingIndicator() async {
try {
debugPrint('Hiding loading overlay');
await _hideOverlay();
} catch (err) {
debugPrint('Exception hiding loading overlay');
rethrow;
}
}
Future<void> _showOverlay({required Widget child}) async {
try {
final overlay = _overlayState;
if (_loaderShown) {
debugPrint('An overlay is already showing');
return Future.value(false);
}
final overlayEntry = OverlayEntry(
builder: (context) => child,
);
overlay!.insert(overlayEntry);
_loaderEntry = overlayEntry;
_loaderShown = true;
} catch (err) {
debugPrint('Exception inserting loading overlay\n${err.toString()}');
rethrow;
}
}
Future<void> _hideOverlay() async {
try {
_loaderEntry.remove();
_loaderShown = false;
} catch (err) {
debugPrint('Exception removing loading overlay\n${err.toString()}');
rethrow;
}
}
@fabiohxcx thank you so much! a great help @delay thank you for chipping away at it! i wish i could be more help
Just to let you know, I am still working on this. I am making progress. I have made a small command-line dart app that generates a translation file of the getX localization class and switched to using getX internationalization code. This let me get around using the flutter_sheet_localization package which isn't outputting null safe code. I am still working through some problems with firebase not initializing properly with null safe active. Hopefully I will figure out the remaining problems so I can get the update released. Thanks for your patience!
If you need help. let mt know!
I'm using firebase and it's working properly.
the only difference I noticed, when you try to get a unavailable field it throws an exception ex: doc.get('name')
Thanks @fabiohxcx, I finally got it updated to null safety and the new translation system in place. There is one part of the code I got working but not in the way I would have liked. I had to change my validator code from:
validator: Validator(labels).email,
to:
validator: (value) {
String pattern =
r'^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z]+';
RegExp regex = RegExp(pattern);
if (!regex.hasMatch(value!))
return 'validator.email'.tr;
else
return null;
},
I couldn't figure that one out and got tired of messing with it but if you have validators similar to the old way of calling that, I would love to see how you did it.
This new version makes use of GetX translation instead of flutter_sheet_localization. In order to use the new system it still generates part of the code. So on the command line go to the /lib/helpers directory and then type:
dart update_localizations.dart
This will generate the localization.g.dart file in the lib/helpers directory which getX needs to handle the translations. I prefer handling my translations for the app in google sheets. The generated translation file for this small app is around 500 lines so it would be a pain to handle this by hand.
Let me know if you find any bugs! @jtkeyva
Dear @delay
try to to something like this
validator: (email) => Validator.email(email),
GetX has some helper funcion like:
GetUtils.isEmail(email)
so I think your function could be:
static String? email(String? email) {
if (email == null) {
return 'Error Message';
}
if (!GetUtils.isEmail(email)) {
return 'Error Message';
}
return null;
}
Or: if (email == null || !GetUtils.isEmail(email)) { return 'Error'; }
I tried this:
validator: Validator.email,
And it worked as well
Ok thanks! I will try these suggestions! I didn't know about those utils in getX. It seems to have everything!
thank you so much @delay great work!
@delay i added some old code and tried to "dart migrate" and got this:
Analyzing project... [--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------/]Bad state: Error: package has unmigrated dependencies.
Before migrating your package, we recommend ensuring that every library it imports (either directly or indirectly) has been migrated to null safety, so that you will be able to run your unit tests in sound null checking mode. You are currently importing the following non-null-safe libraries:
package:myapp/constants/app_routes.dart package:myapp/constants/app_themes.dart package:myapp/constants/constants.dart package:myapp/constants/globals.dart package:myapp/controllers/auth_controller.dart package:myapp/controllers/controllers.dart package:myapp/controllers/language_controller.dart package:myapp/controllers/theme_controller.dart package:myapp/helpers/gravatar.dart package:myapp/helpers/helpers.dart package:myapp/helpers/localization.g.dart package:myapp/helpers/validator.dart package:myapp/models/menu_option_model.dart package:myapp/models/models.dart package:myapp/models/user_model.dart package:myapp/ui/auth/reset_password_ui.dart package:myapp/ui/auth/sign_in_ui.dart package:myapp/ui/auth/sign_up_ui.dart package:myapp/ui/auth/update_profile_ui.dart package:myapp/ui/components/avatar.dart package:myapp/ui/components/components.dart package:myapp/ui/components/dropdown_picker.dart package:myapp/ui/components/dropdown_picker_with_icon.dart package:myapp/ui/components/form_input_field.dart package:myapp/ui/components/form_input_field_with_icon.dart package:myapp/ui/components/form_vertical_spacing.dart package:myapp/ui/components/label_button.dart package:myapp/ui/components/loading.dart package:myapp/ui/components/logo_graphic_header.dart package:myapp/ui/components/primary_button.dart package:myapp/ui/components/segmented_selector.dart package:myapp/ui/google_place.dart package:myapp/ui/home_ui.dart package:myapp/ui/settings_ui.dart package:myapp/ui/ui.dart
Please upgrade the packages containing these libraries to null safe versions
before continuing. To see what null safe package versions are available, run
the following command: dart pub outdated --mode=null-safety
.
To skip this check and try to migrate anyway, re-run with the flag
--skip-import-check
.
➜ myapp git:(master) ✗ dart migrate --skip-import-check Migrating /Users/jt/keyva/radmaps/dev/app/v1/myapp
See https://dart.dev/go/null-safety-migration for a migration guide.
Analyzing project... [--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------/]Warning: package has unmigrated dependencies.
Continuing due to the presence of --skip-import-check
. To see a complete
list of the unmigrated dependencies, re-run without the --skip-import-check
flag.
157 analysis issues found:
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:58:54 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:61:14 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:68:42 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:70:61 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:75:48 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:76:72 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:107:36 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:108:38 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:119:29 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:120:31 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:120:38 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:124:51 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:131:61 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:147:27 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:149:75 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/auth_controller.dart:206:64 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/language_controller.dart:38:9 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/language_controller.dart:55:33 • (experiment_not_enabled)
error • Unexpected text 'late' at lib/controllers/theme_controller.dart:12:3 • (unexpected_token)
error • This requires the 'non-nullable' language feature to be enabled at lib/controllers/theme_controller.dart:44:34 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/helpers/gravatar.dart:37:8 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/helpers/gravatar.dart:38:18 • (experiment_not_enabled)
error • This requires the 'non-nullable' language feature to be enabled at lib/helpers/gravatar.dart:41:19 • (experiment_not_enabled)
error • Undefined class 'required' at lib/helpers/update_localizations.dart:136:5 • (undefined_class)
error • The parameter type 'dynamic' is incompatible with the field type 'String' at lib/helpers/update_localizations.dart:136:5 • (field_initializing_formal_not_assignable)
error • Undefined class 'required' at lib/helpers/update_localizations.dart:137:5 • (undefined_class)
error • The parameter type 'dynamic' is incompatible with the field type 'List
The migration tool didn't start, due to analysis errors.
We recommend fixing the analysis issues before running dart migrate
.
Alternatively, you can run dart migrate --ignore-errors
, but you might
get erroneous migration suggestions.
More information: https://dart.dev/go/null-safety-migration
Sorry, I was trying to migrate code that I dropped into your code. I migrated it separately and all good!
Any plans to update to support Null Safety? Thanks