Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 112 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
1 change: 1 addition & 0 deletions example/ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -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"
1 change: 1 addition & 0 deletions example/ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -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"
26 changes: 11 additions & 15 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -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());
Expand All @@ -19,22 +18,19 @@ class _MyAppState extends State<MyApp> {

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;
}
});
}

Expand Down
5 changes: 4 additions & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
39 changes: 18 additions & 21 deletions lib/flutter_twitter_login.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -54,9 +51,9 @@ class TwitterLogin {
/// ```
///
/// If the user is not logged in, this returns null.
Future<TwitterSession> get currentSession async {
final Map<dynamic, dynamic> session =
await channel.invokeMethod('getCurrentSession', _keys);
Future<TwitterSession?> get currentSession async {
final session = await channel.invokeMethod<Map<dynamic, dynamic>>(
'getCurrentSession', _keys);

if (session == null) {
return null;
Expand Down Expand Up @@ -101,10 +98,10 @@ class TwitterLogin {
///
/// See the [TwitterLoginResult] class for more documentation.
Future<TwitterLoginResult> authorize() async {
final Map<dynamic, dynamic> result =
await channel.invokeMethod('authorize', _keys);
final result =
await channel.invokeMethod<Map<dynamic, dynamic>>('authorize', _keys);

return new TwitterLoginResult._(result.cast<String, dynamic>());
return new TwitterLoginResult._(result?.cast<String, dynamic>() ?? {});
}

/// Logs the currently logged in user out.
Expand All @@ -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<String, dynamic> map)
: status = _parseStatus(map['status'], map['errorMessage']),
Expand All @@ -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;
}
Expand Down Expand Up @@ -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].
///
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_twitter_login
description: A Flutter plugin for allowing users to authenticate with native Android &amp; iOS Twitter login SDKs.
version: 1.1.0
version: 2.0.0-nullsafety
author: Iiro Krankka <iiro.krankka@gmail.com>
homepage: https://github.com/roughike/flutter_twitter_login

Expand All @@ -18,4 +18,4 @@ flutter:
pluginClass: TwitterLoginPlugin

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
20 changes: 11 additions & 9 deletions test/flutter_twitter_login_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -33,9 +35,9 @@ void main() {
};

final List<MethodCall> log = [];
TwitterLogin sut;
late TwitterLogin sut;

void setMethodCallResponse(Map<String, dynamic> response) {
void setMethodCallResponse(Map<String, dynamic>? response) {
channel.setMockMethodCallHandler((MethodCall methodCall) {
log.add(methodCall);
return new Future.value(response);
Expand All @@ -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));
});

Expand Down Expand Up @@ -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(
Expand All @@ -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',
Expand Down Expand Up @@ -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 {
Expand Down