diff --git a/.gitignore b/.gitignore index 14c7d4c..270e6af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,117 @@ +# Miscellaneous +*.class +*.lock +*.log +*.pyc +*.swp .DS_Store .atom/ -.idea +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.classpath +.project +.settings/ +.vscode/ + +# Flutter repo-specific +/bin/cache/ +/bin/internal/bootstrap.bat +/bin/internal/bootstrap.sh +/bin/mingit/ +/dev/benchmarks/mega_gallery/ +/dev/bots/.recipe_deps +/dev/bots/android_tools/ +/dev/devicelab/ABresults*.json +/dev/docs/doc/ +/dev/docs/flutter.docs.zip +/dev/docs/lib/ +/dev/docs/pubspec.yaml +/dev/integration_tests/**/xcuserdata +/dev/integration_tests/**/Pods +/packages/flutter/coverage/ +version +analysis_benchmark.json + +# packages file containing multi-root paths +.packages.generated + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +**/generated_plugin_registrant.dart .packages +.pub-cache/ .pub/ build/ -ios/.generated/ -packages -pubspec.lock +flutter_*.png +linked_*.ds +unlinked.ds +unlinked_spec.ds + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java +**/android/key.properties +*.jks + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +**/macos/Flutter/GeneratedPluginRegistrant.swift + +# Coverage +coverage/ + +# Symbols +app.*.symbols + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +!/dev/ci/**/Gemfile.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 772c7c2..8ee7d11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.0-nullsafety + +Migrated to null safety. + ## 1.1.0 * Dart 2 support! There should not be any breaking changes. Please do file issues if you have problems. diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index e8efba1..b2f5fae 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1,2 +1,3 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 399e934..88c2914 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1,2 +1,3 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/example/lib/main.dart b/example/lib/main.dart index 5b8437f..b336c76 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_twitter_login/flutter_twitter_login.dart'; void main() => runApp(new MyApp()); @@ -19,22 +18,19 @@ class _MyAppState extends State { void _login() async { final TwitterLoginResult result = await twitterLogin.authorize(); - String newMessage; - - switch (result.status) { - case TwitterLoginStatus.loggedIn: - newMessage = 'Logged in! username: ${result.session.username}'; - break; - case TwitterLoginStatus.cancelledByUser: - newMessage = 'Login cancelled by user.'; - break; - case TwitterLoginStatus.error: - newMessage = 'Login error: ${result.errorMessage}'; - break; - } setState(() { - _message = newMessage; + switch (result.status) { + case TwitterLoginStatus.loggedIn: + _message = 'Logged in! username: ${result.session!.username}'; + break; + case TwitterLoginStatus.cancelledByUser: + _message = 'Login cancelled by user.'; + break; + case TwitterLoginStatus.error: + _message = 'Login error: ${result.errorMessage}'; + break; + } }); } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 5c27df8..910184c 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,6 +1,9 @@ name: flutter_twitter_login_example description: Demonstrates how to use the flutter_twitter_login plugin. +environment: + sdk: ">=2.12.0-0 <3.0.0" + dependencies: flutter: sdk: flutter @@ -55,5 +58,5 @@ flutter: # - asset: fonts/TrajanPro_Bold.ttf # weight: 700 # - # For details regarding fonts from package dependencies, + # For details regarding fonts from package dependencies, # see https://flutter.io/custom-fonts/#from-packages diff --git a/lib/flutter_twitter_login.dart b/lib/flutter_twitter_login.dart index edb66ef..c8fc5dd 100644 --- a/lib/flutter_twitter_login.dart +++ b/lib/flutter_twitter_login.dart @@ -15,13 +15,10 @@ class TwitterLogin { /// apps site at https://apps.twitter.com/, in the "Keys and Access Tokens" /// tab. TwitterLogin({ - @required this.consumerKey, - @required this.consumerSecret, - }) - : assert(consumerKey != null && consumerKey.isNotEmpty, - 'Consumer key may not be null or empty.'), - assert(consumerSecret != null && consumerSecret.isNotEmpty, - 'Consumer secret may not be null or empty.'), + required this.consumerKey, + required this.consumerSecret, + }) : assert(consumerKey.isNotEmpty, 'Consumer key may not be empty.'), + assert(consumerSecret.isNotEmpty, 'Consumer secret may not be empty.'), _keys = { 'consumerKey': consumerKey, 'consumerSecret': consumerSecret, @@ -54,9 +51,9 @@ class TwitterLogin { /// ``` /// /// If the user is not logged in, this returns null. - Future get currentSession async { - final Map session = - await channel.invokeMethod('getCurrentSession', _keys); + Future get currentSession async { + final session = await channel.invokeMethod>( + 'getCurrentSession', _keys); if (session == null) { return null; @@ -101,10 +98,10 @@ class TwitterLogin { /// /// See the [TwitterLoginResult] class for more documentation. Future authorize() async { - final Map result = - await channel.invokeMethod('authorize', _keys); + final result = + await channel.invokeMethod>('authorize', _keys); - return new TwitterLoginResult._(result.cast()); + return new TwitterLoginResult._(result?.cast() ?? {}); } /// Logs the currently logged in user out. @@ -127,11 +124,11 @@ class TwitterLoginResult { /// Only available when the [status] equals [TwitterLoginStatus.loggedIn], /// otherwise null. - final TwitterSession session; + final TwitterSession? session; /// Only available when the [status] equals [TwitterLoginStatus.error] /// otherwise null. - final String errorMessage; + final String? errorMessage; TwitterLoginResult._(Map map) : status = _parseStatus(map['status'], map['errorMessage']), @@ -142,13 +139,13 @@ class TwitterLoginResult { : null, errorMessage = map['errorMessage']; - static TwitterLoginStatus _parseStatus(String status, String errorMessage) { + static TwitterLoginStatus _parseStatus(String? status, String? errorMessage) { switch (status) { case 'loggedIn': return TwitterLoginStatus.loggedIn; case 'error': // Kind of a hack, but the only way of determining this. - if (errorMessage.contains('canceled') || + if (errorMessage!.contains('canceled') || errorMessage.contains('cancelled')) { return TwitterLoginStatus.cancelledByUser; } @@ -181,17 +178,17 @@ enum TwitterLoginStatus { /// the [token] and [secret] are needed for making authenticated Twitter API /// calls. class TwitterSession { - final String secret; - final String token; + final String? secret; + final String? token; /// The user's unique identifier, usually a long series of numbers. - final String userId; + final String? userId; /// The user's Twitter handle. /// /// For example, if you can visit your Twitter profile by typing the URL /// http://twitter.com/hello, your Twitter handle (or username) is "hello". - final String username; + final String? username; /// Constructs a new access token instance from a [Map]. /// diff --git a/pubspec.yaml b/pubspec.yaml index eb42642..29c1d82 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_twitter_login description: A Flutter plugin for allowing users to authenticate with native Android & iOS Twitter login SDKs. -version: 1.1.0 +version: 2.0.0-nullsafety author: Iiro Krankka homepage: https://github.com/roughike/flutter_twitter_login @@ -18,4 +18,4 @@ flutter: pluginClass: TwitterLoginPlugin environment: - sdk: ">=2.0.0-dev.28.0 <3.0.0" \ No newline at end of file + sdk: ">=2.12.0-0 <3.0.0" diff --git a/test/flutter_twitter_login_test.dart b/test/flutter_twitter_login_test.dart index f82b9f2..5ce80f0 100644 --- a/test/flutter_twitter_login_test.dart +++ b/test/flutter_twitter_login_test.dart @@ -5,6 +5,8 @@ import 'package:flutter_twitter_login/flutter_twitter_login.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + group('$TwitterLogin', () { const MethodChannel channel = const MethodChannel( 'com.roughike/flutter_twitter_login', @@ -33,9 +35,9 @@ void main() { }; final List log = []; - TwitterLogin sut; + late TwitterLogin sut; - void setMethodCallResponse(Map response) { + void setMethodCallResponse(Map? response) { channel.setMockMethodCallHandler((MethodCall methodCall) { log.add(methodCall); return new Future.value(response); @@ -58,10 +60,10 @@ void main() { log.clear(); }); - test('can not call constructor with null or empty key or secret', () { - expect(() => new TwitterLogin(consumerKey: null, consumerSecret: null), + test('can not call constructor with empty key or secret', () { + expect(() => new TwitterLogin(consumerKey: 'key', consumerSecret: ''), throwsA(anything)); - expect(() => new TwitterLogin(consumerKey: '', consumerSecret: ''), + expect(() => new TwitterLogin(consumerKey: '', consumerSecret: 'secret'), throwsA(anything)); }); @@ -95,7 +97,7 @@ void main() { test('get currentSession - handles null response gracefully', () async { setMethodCallResponse(null); - final TwitterSession session = await sut.currentSession; + final TwitterSession? session = await sut.currentSession; expect(session, isNull); expect(log, [ isMethodCall( @@ -108,8 +110,8 @@ void main() { test('get currentSession - parses session correctly', () async { setMethodCallResponse(kSessionMap); - final TwitterSession session = await sut.currentSession; - expectSessionParsedCorrectly(session); + final session = await sut.currentSession; + expectSessionParsedCorrectly(session!); expect(log, [ isMethodCall( 'getCurrentSession', @@ -137,7 +139,7 @@ void main() { final TwitterLoginResult result = await sut.authorize(); expect(result.status, TwitterLoginStatus.loggedIn); - expectSessionParsedCorrectly(result.session); + expectSessionParsedCorrectly(result.session!); }); test('authorize - cancelled by user', () async {