From f15851b8f1650efb8c0a0a8f1463a2120345cdd1 Mon Sep 17 00:00:00 2001 From: HuangRed Date: Fri, 23 Aug 2024 08:54:05 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=BD=91=E9=A1=B5?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0onLoad=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/twitter_login.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index 55f711e..e847792 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -173,7 +173,7 @@ class TwitterLogin { } } - Future loginV2({bool forceLogin = false}) async { + Future loginV2({bool forceLogin = false, void Function()? onLoad}) async { String? resultURI; RequestToken requestToken; try { @@ -253,6 +253,7 @@ class TwitterLogin { throw const CanceledByUserException(); } + onLoad?.call(); final token = await AccessToken.getAccessToken( apiKey, apiSecretKey, From b4b55d5ed501ebcf7d043a5cd0191cff0783d4cf Mon Sep 17 00:00:00 2001 From: HuangRed Date: Wed, 18 Sep 2024 09:20:43 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E7=9A=84=E7=99=BB=E5=BD=95=E4=BA=A4=E4=BA=92=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/main.dart | 110 ++++++++++---------- lib/entity/auth_result.dart | 21 ++-- lib/src/twitter_login.dart | 196 ++---------------------------------- 3 files changed, 70 insertions(+), 257 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index e6e364c..8dd8108 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:twitter_login/twitter_login.dart'; + void main() { runApp(MyApp()); @@ -73,77 +73,77 @@ class _MyAppState extends State { /// Use Twitter API v1.1 Future login() async { - final twitterLogin = TwitterLogin( - /// Consumer API keys - apiKey: apiKey, + // final twitterLogin = TwitterLogin( + // /// Consumer API keys + // // apiKey: apiKey, - /// Consumer API Secret keys - apiSecretKey: apiSecretKey, + // /// Consumer API Secret keys + // // apiSecretKey: apiSecretKey, - /// Registered Callback URLs in TwitterApp - /// Android is a deeplink - /// iOS is a URLScheme - redirectURI: 'example://', - ); + // /// Registered Callback URLs in TwitterApp + // /// Android is a deeplink + // /// iOS is a URLScheme + // redirectURI: 'example://', + // ); /// Forces the user to enter their credentials /// to ensure the correct users account is authorized. /// If you want to implement Twitter account switching, set [force_login] to true /// login(forceLogin: true); - final authResult = await twitterLogin.login(); - switch (authResult.status) { - case TwitterLoginStatus.loggedIn: - // success - print('====== Login success ======'); - print(authResult.authToken); - print(authResult.authTokenSecret); - break; - case TwitterLoginStatus.cancelledByUser: - // cancel - print('====== Login cancel ======'); - break; - case TwitterLoginStatus.error: - case null: - // error - print('====== Login error ======'); - break; - } + // final authResult = await twitterLogin.login(); + // switch (authResult.status) { + // case TwitterLoginStatus.loggedIn: + // // success + // print('====== Login success ======'); + // print(authResult.authToken); + // print(authResult.authTokenSecret); + // break; + // case TwitterLoginStatus.cancelledByUser: + // // cancel + // print('====== Login cancel ======'); + // break; + // case TwitterLoginStatus.error: + // case null: + // // error + // print('====== Login error ======'); + // break; + // } } /// Use Twitter API v2. Future loginV2() async { - final twitterLogin = TwitterLogin( - /// Consumer API keys - apiKey: apiKey, + // final twitterLogin = TwitterLogin( + // /// Consumer API keys + // //apiKey: apiKey, - /// Consumer API Secret keys - apiSecretKey: apiSecretKey, + // /// Consumer API Secret keys + // // apiSecretKey: apiSecretKey, - /// Registered Callback URLs in TwitterApp - /// Android is a deeplink - /// iOS is a URLScheme - redirectURI: 'example://', - ); + // /// Registered Callback URLs in TwitterApp + // /// Android is a deeplink + // /// iOS is a URLScheme + // redirectURI: 'example://', + // ); /// Forces the user to enter their credentials /// to ensure the correct users account is authorized. /// If you want to implement Twitter account switching, set [force_login] to true /// login(forceLogin: true); - final authResult = await twitterLogin.loginV2(); - switch (authResult.status) { - case TwitterLoginStatus.loggedIn: - // success - print('====== Login success ======'); - break; - case TwitterLoginStatus.cancelledByUser: - // cancel - print('====== Login cancel ======'); - break; - case TwitterLoginStatus.error: - case null: - // error - print('====== Login error ======'); - break; - } + // final authResult = await twitterLogin.loginV2(); + // switch (authResult.status) { + // case TwitterLoginStatus.loggedIn: + // // success + // print('====== Login success ======'); + // break; + // case TwitterLoginStatus.cancelledByUser: + // // cancel + // print('====== Login cancel ======'); + // break; + // case TwitterLoginStatus.error: + // case null: + // // error + // print('====== Login error ======'); + // break; + // } } } diff --git a/lib/entity/auth_result.dart b/lib/entity/auth_result.dart index 7a8782a..1c86196 100644 --- a/lib/entity/auth_result.dart +++ b/lib/entity/auth_result.dart @@ -1,29 +1,26 @@ import 'dart:core'; -import 'package:twitter_login/entity/user.dart'; import 'package:twitter_login/src/twitter_login.dart'; /// The result when the Twitter login flow has completed. /// The login methods always return an instance of this class. class AuthResult { - /// constructor AuthResult({ String? authToken, - String? authTokenSecret, + String? authVerifier, required TwitterLoginStatus status, String? errorMessage, - User? user, }) : _authToken = authToken, - _authTokenSecret = authTokenSecret, + _authVerifier = authVerifier, _status = status, - _errorMessage = errorMessage, - _user = user; + _errorMessage = errorMessage; + /// The access token for using the Twitter APIs final String? _authToken; - //// The access token secret for using the Twitter APIs - final String? _authTokenSecret; + /// The access token secret for using the Twitter APIs + final String? _authVerifier; /// The status after a Twitter login flow has completed final TwitterLoginStatus? _status; @@ -31,12 +28,8 @@ class AuthResult { /// The error message when the log in flow completed with an error final String? _errorMessage; - /// Twitter Account user Info. - final User? _user; - String? get authToken => _authToken; - String? get authTokenSecret => _authTokenSecret; + String? get authVerifier => _authVerifier; TwitterLoginStatus? get status => _status; String? get errorMessage => _errorMessage; - User? get user => _user; } diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index e847792..72ce73b 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -1,12 +1,9 @@ import 'dart:async'; import 'dart:io'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:twitter_login/entity/auth_result.dart'; -import 'package:twitter_login/entity/user.dart'; -import 'package:twitter_login/schemes/access_token.dart'; -import 'package:twitter_login/schemes/request_token.dart'; + import 'package:twitter_login/src/auth_browser.dart'; import 'package:twitter_login/src/exception.dart'; @@ -26,17 +23,9 @@ enum TwitterLoginStatus { class TwitterLogin { /// constructor TwitterLogin({ - required this.apiKey, - required this.apiSecretKey, required this.redirectURI, }); - /// Consumer API key - final String apiKey; - - /// Consumer API secret key - final String apiSecretKey; - /// Callback URL final String redirectURI; @@ -44,25 +33,9 @@ class TwitterLogin { static const _eventChannel = EventChannel('twitter_login/event'); static final Stream _eventStream = _eventChannel.receiveBroadcastStream(); - /// Logs the user - /// Forces the user to enter their credentials to ensure the correct users account is authorized. - Future login({bool forceLogin = false}) async { + ///使用更安全的登录交互方式 + Future loginV3({required String oauthToken, void Function()? onLoad}) async { String? resultURI; - RequestToken requestToken; - try { - requestToken = await RequestToken.getRequestToken( - apiKey, - apiSecretKey, - redirectURI, - forceLogin, - ); - } on Exception { - throw PlatformException( - code: '400', - message: 'Failed to generate request token.', - details: 'Please check your APIKey or APISecret.', - ); - } final uri = Uri.parse(redirectURI); final completer = Completer(); @@ -89,140 +62,15 @@ class TwitterLogin { }, ); - try { - if (Platform.isIOS || Platform.isMacOS) { - /// Login to Twitter account with SFAuthenticationSession or ASWebAuthenticationSession. - resultURI = await authBrowser.doAuth(requestToken.authorizeURI, uri.scheme); - } else if (Platform.isAndroid) { - // Login to Twitter account with chrome_custom_tabs. - final success = await authBrowser.open(requestToken.authorizeURI, uri.scheme); - if (!success) { - throw PlatformException( - code: '200', - message: 'Could not open browser, probably caused by unavailable custom tabs.', - ); - } - resultURI = await completer.future; - await subscribe.cancel(); - } else { - throw PlatformException( - code: '100', - message: 'Not supported by this os.', - ); - } - - // The user closed the browser. - if (resultURI?.isEmpty ?? true) { - throw const CanceledByUserException(); - } - - final queries = Uri.splitQueryString(Uri.parse(resultURI!).query); - if (queries['error'] != null) { - throw Exception('Error Response: ${queries['error']}'); - } - - // The user cancelled the login flow. - if (queries['denied'] != null) { - throw const CanceledByUserException(); - } - - final token = await AccessToken.getAccessToken( - apiKey, - apiSecretKey, - queries, - ); - - if ((token.authToken?.isEmpty ?? true) || (token.authTokenSecret?.isEmpty ?? true)) { - return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, - status: TwitterLoginStatus.error, - errorMessage: 'Failed', - ); - } - - User? user; - - try { - user = await User.getUserData( - apiKey, - apiSecretKey, - token.authToken!, - token.authTokenSecret!, - ); - } on Exception { - debugPrint('The rate limit may have been reached or the API may be restricted.'); - } - - return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, - status: TwitterLoginStatus.loggedIn, - user: user, - ); - } on CanceledByUserException { - return AuthResult( - status: TwitterLoginStatus.cancelledByUser, - errorMessage: 'The user cancelled the login flow.', - ); - } catch (error) { - return AuthResult( - status: TwitterLoginStatus.error, - errorMessage: error.toString(), - ); - } - } - - Future loginV2({bool forceLogin = false, void Function()? onLoad}) async { - String? resultURI; - RequestToken requestToken; - try { - requestToken = await RequestToken.getRequestToken( - apiKey, - apiSecretKey, - redirectURI, - forceLogin, - ); - } on Exception { - throw PlatformException( - code: '400', - message: 'Failed to generate request token.', - details: 'Please check your APIKey or APISecret.', - ); - } - - final uri = Uri.parse(redirectURI); - final completer = Completer(); - late StreamSubscription subscribe; - - if (Platform.isAndroid) { - await _channel.invokeMethod('setScheme', uri.scheme); - subscribe = _eventStream.listen((data) async { - if (data['type'] == 'url') { - if (!completer.isCompleted) { - completer.complete(data['url']?.toString()); - } else { - throw const CanceledByUserException(); - } - } - }); - } - - final authBrowser = AuthBrowser( - onClose: () { - if (!completer.isCompleted) { - completer.complete(null); - } - }, - ); + final authorizeURI = 'https://api.twitter.com/oauth/authorize?oauth_token==$oauthToken'; try { if (Platform.isIOS || Platform.isMacOS) { /// Login to Twitter account with SFAuthenticationSession or ASWebAuthenticationSession. - resultURI = await authBrowser.doAuth(requestToken.authorizeURI, uri.scheme); + resultURI = await authBrowser.doAuth(authorizeURI, uri.scheme); } else if (Platform.isAndroid) { // Login to Twitter account with chrome_custom_tabs. - final success = await authBrowser.open(requestToken.authorizeURI, uri.scheme); + final success = await authBrowser.open(authorizeURI, uri.scheme); if (!success) { throw PlatformException( code: '200', @@ -254,39 +102,11 @@ class TwitterLogin { } onLoad?.call(); - final token = await AccessToken.getAccessToken( - apiKey, - apiSecretKey, - queries, - ); - - if ((token.authToken?.isEmpty ?? true) || (token.authTokenSecret?.isEmpty ?? true)) { - return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, - status: TwitterLoginStatus.error, - errorMessage: 'Failed', - ); - } - - User? user; - try { - user = await User.getUserDataV2( - apiKey, - apiSecretKey, - token.authToken!, - token.authTokenSecret!, - token.userId!, - ); - } on Exception { - debugPrint('The rate limit may have been reached or the API may be restricted.'); - } return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, + authToken: queries['oauth_token'], + authVerifier: queries['oauth_verifier'], status: TwitterLoginStatus.loggedIn, - user: user, ); } on CanceledByUserException { return AuthResult( From 04df49e175339a6ddd7102df86dcd723572c17d3 Mon Sep 17 00:00:00 2001 From: HuangRed Date: Wed, 18 Sep 2024 09:30:38 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/twitter_login.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index 72ce73b..9c7987a 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -34,7 +34,7 @@ class TwitterLogin { static final Stream _eventStream = _eventChannel.receiveBroadcastStream(); ///使用更安全的登录交互方式 - Future loginV3({required String oauthToken, void Function()? onLoad}) async { + Future login({required String oauthToken}) async { String? resultURI; final uri = Uri.parse(redirectURI); @@ -101,8 +101,6 @@ class TwitterLogin { throw const CanceledByUserException(); } - onLoad?.call(); - return AuthResult( authToken: queries['oauth_token'], authVerifier: queries['oauth_verifier'], From 446adf046d67b35684b078d11699281651e4d54b Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Jul 2026 14:59:20 +1000 Subject: [PATCH 4/4] Refactor Twitter login plugin for Swift (#4) Refactor Twitter login plugin to use Swift implementation and update podspec configurations --- .gitignore | 4 +- ios/Classes/TwitterLoginPlugin.h | 4 -- ios/Classes/TwitterLoginPlugin.m | 15 ----- ios/twitter_login.podspec | 7 +-- ios/twitter_login/Package.swift | 23 ++++++++ .../SwiftTwitterLoginPlugin.swift | 55 +++++++++++-------- lib/src/twitter_login.dart | 8 +-- macos/twitter_login.podspec | 4 +- macos/twitter_login/Package.swift | 23 ++++++++ .../twitter_login}/TwitterLoginPlugin.swift | 22 ++++---- pubspec.yaml | 2 +- 11 files changed, 99 insertions(+), 68 deletions(-) delete mode 100644 ios/Classes/TwitterLoginPlugin.h delete mode 100644 ios/Classes/TwitterLoginPlugin.m create mode 100644 ios/twitter_login/Package.swift rename ios/{Classes => twitter_login/Sources/twitter_login}/SwiftTwitterLoginPlugin.swift (65%) create mode 100644 macos/twitter_login/Package.swift rename macos/{Classes => twitter_login/Sources/twitter_login}/TwitterLoginPlugin.swift (92%) diff --git a/.gitignore b/.gitignore index 59d25c2..809bcea 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ .packages .pub/ .dart_tool/ +.build/ +.swiftpm/ pubspec.lock Podfile @@ -41,4 +43,4 @@ build/ .project .classpath -.settings \ No newline at end of file +.settings diff --git a/ios/Classes/TwitterLoginPlugin.h b/ios/Classes/TwitterLoginPlugin.h deleted file mode 100644 index 29cfc9d..0000000 --- a/ios/Classes/TwitterLoginPlugin.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface TwitterLoginPlugin : NSObject -@end diff --git a/ios/Classes/TwitterLoginPlugin.m b/ios/Classes/TwitterLoginPlugin.m deleted file mode 100644 index 854434c..0000000 --- a/ios/Classes/TwitterLoginPlugin.m +++ /dev/null @@ -1,15 +0,0 @@ -#import "TwitterLoginPlugin.h" -#if __has_include() -#import -#else -// Support project import fallback if the generated compatibility header -// is not copied when this plugin is created as a library. -// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 -#import "twitter_login-Swift.h" -#endif - -@implementation TwitterLoginPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftTwitterLoginPlugin registerWithRegistrar:registrar]; -} -@end diff --git a/ios/twitter_login.podspec b/ios/twitter_login.podspec index bd0c511..90ec8cf 100644 --- a/ios/twitter_login.podspec +++ b/ios/twitter_login.podspec @@ -13,11 +13,10 @@ Flutter Twitter Login Plugin s.license = { :file => '../LICENSE' } s.author = { 'Your Company' => 'email@example.com' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*' + s.source_files = 'twitter_login/Sources/twitter_login/**/*.swift' s.dependency 'Flutter' - s.platform = :ios, '8.0' + s.platform = :ios, '12.0' - # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } s.swift_version = '5.0' end diff --git a/ios/twitter_login/Package.swift b/ios/twitter_login/Package.swift new file mode 100644 index 0000000..c9f06b8 --- /dev/null +++ b/ios/twitter_login/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "twitter_login", + platforms: [ + .iOS("12.0") + ], + products: [ + .library(name: "twitter-login", targets: ["twitter_login"]) + ], + dependencies: [ + .package(name: "FlutterFramework", path: "../FlutterFramework") + ], + targets: [ + .target( + name: "twitter_login", + dependencies: [ + .product(name: "FlutterFramework", package: "FlutterFramework") + ] + ) + ] +) diff --git a/ios/Classes/SwiftTwitterLoginPlugin.swift b/ios/twitter_login/Sources/twitter_login/SwiftTwitterLoginPlugin.swift similarity index 65% rename from ios/Classes/SwiftTwitterLoginPlugin.swift rename to ios/twitter_login/Sources/twitter_login/SwiftTwitterLoginPlugin.swift index f2e3068..5f2389c 100644 --- a/ios/Classes/SwiftTwitterLoginPlugin.swift +++ b/ios/twitter_login/Sources/twitter_login/SwiftTwitterLoginPlugin.swift @@ -3,8 +3,8 @@ import UIKit import SafariServices import AuthenticationServices -public class SwiftTwitterLoginPlugin: NSObject, FlutterPlugin, ASWebAuthenticationPresentationContextProviding { - var session: Any? = nil +public class SwiftTwitterLoginPlugin: NSObject, FlutterPlugin, ASWebAuthenticationPresentationContextProviding { + var session: Any? public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel( @@ -17,61 +17,68 @@ public class SwiftTwitterLoginPlugin: NSObject, FlutterPlugin, ASWebAuthenticati public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { - case "authentication": - authentication(call, result: result) - default: - result(nil) - return + case "authentication": + authentication(call, result: result) + default: + result(nil) } } public func authentication(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - let args = call.arguments as! NSDictionary - let url = args["url"] as! String + guard + let args = call.arguments as? NSDictionary, + let urlString = args["url"] as? String, + let url = URL(string: urlString) + else { + result(nil) + return + } let urlScheme = args["redirectURL"] as? String - - // iOS12以降 + if #available(iOS 12.0, *) { var authSession: ASWebAuthenticationSession? authSession = ASWebAuthenticationSession( - url: URL(string: url)!, + url: url, callbackURLScheme: urlScheme ) { url, error in result(url?.absoluteString) - authSession!.cancel() + authSession?.cancel() self.session = nil } self.session = authSession if #available(iOS 13.0, *) { authSession?.presentationContextProvider = self } - if !authSession!.start() { - // TODO: failed + if authSession?.start() != true { + result(nil) } - // iOS11のみ } else if #available(iOS 11.0, *) { var authSession: SFAuthenticationSession? authSession = SFAuthenticationSession( - url: URL(string: url)!, + url: url, callbackURLScheme: urlScheme ) { url, error in result(url?.absoluteString) - authSession!.cancel() + authSession?.cancel() self.session = nil } self.session = authSession - if !authSession!.start() { - // TODO: failed + if authSession?.start() != true { + result(nil) } } else { - // iOS10以前は未対応 result("") - return } } - + @available(iOS 12.0, *) public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { - return UIApplication.shared.delegate!.window!! + if #available(iOS 13.0, *) { + return UIApplication.shared.connectedScenes + .compactMap { $0 as? UIWindowScene } + .flatMap { $0.windows } + .first { $0.isKeyWindow } ?? UIWindow() + } + return UIApplication.shared.keyWindow ?? UIWindow() } } diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index 9c7987a..a216387 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -34,7 +34,7 @@ class TwitterLogin { static final Stream _eventStream = _eventChannel.receiveBroadcastStream(); ///使用更安全的登录交互方式 - Future login({required String oauthToken}) async { + Future login({required String oauthToken, required String oauthUrl}) async { String? resultURI; final uri = Uri.parse(redirectURI); @@ -62,15 +62,13 @@ class TwitterLogin { }, ); - final authorizeURI = 'https://api.twitter.com/oauth/authorize?oauth_token==$oauthToken'; - try { if (Platform.isIOS || Platform.isMacOS) { /// Login to Twitter account with SFAuthenticationSession or ASWebAuthenticationSession. - resultURI = await authBrowser.doAuth(authorizeURI, uri.scheme); + resultURI = await authBrowser.doAuth(oauthUrl, uri.scheme); } else if (Platform.isAndroid) { // Login to Twitter account with chrome_custom_tabs. - final success = await authBrowser.open(authorizeURI, uri.scheme); + final success = await authBrowser.open(oauthUrl, uri.scheme); if (!success) { throw PlatformException( code: '200', diff --git a/macos/twitter_login.podspec b/macos/twitter_login.podspec index b3cb347..7a6a2e2 100644 --- a/macos/twitter_login.podspec +++ b/macos/twitter_login.podspec @@ -13,10 +13,10 @@ Flutter Twitter Login Plugin s.license = { :file => '../LICENSE' } s.author = { 'Your Company' => 'email@example.com' } s.source = { :path => '.' } - s.source_files = '**/*' + s.source_files = 'twitter_login/Sources/twitter_login/**/*.swift' s.dependency 'FlutterMacOS' - s.platform = :osx, '10.11' + s.platform = :osx, '10.15' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } s.swift_version = '5.0' end diff --git a/macos/twitter_login/Package.swift b/macos/twitter_login/Package.swift new file mode 100644 index 0000000..5d14f67 --- /dev/null +++ b/macos/twitter_login/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "twitter_login", + platforms: [ + .macOS("10.15") + ], + products: [ + .library(name: "twitter-login", targets: ["twitter_login"]) + ], + dependencies: [ + .package(name: "FlutterFramework", path: "../FlutterFramework") + ], + targets: [ + .target( + name: "twitter_login", + dependencies: [ + .product(name: "FlutterFramework", package: "FlutterFramework") + ] + ) + ] +) diff --git a/macos/Classes/TwitterLoginPlugin.swift b/macos/twitter_login/Sources/twitter_login/TwitterLoginPlugin.swift similarity index 92% rename from macos/Classes/TwitterLoginPlugin.swift rename to macos/twitter_login/Sources/twitter_login/TwitterLoginPlugin.swift index 21dc618..9567432 100644 --- a/macos/Classes/TwitterLoginPlugin.swift +++ b/macos/twitter_login/Sources/twitter_login/TwitterLoginPlugin.swift @@ -6,19 +6,19 @@ import AuthenticationServices public class TwitterLoginPlugin: NSObject, FlutterPlugin, ASWebAuthenticationPresentationContextProviding { var session: Any? = nil - + @available(macOS 10.15, *) public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { return NSApplication.shared.mainWindow! } - + public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "twitter_login/auth_browser", binaryMessenger: registrar.messenger) let instance = TwitterLoginPlugin() registrar.addMethodCallDelegate(instance, channel: channel) } - - + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "authentication": @@ -33,15 +33,15 @@ public class TwitterLoginPlugin: NSObject, FlutterPlugin, ASWebAuthenticationPre return } } - - + + @available(macOS 10.15, *) //required by XCode or fail to compile public func authentication(_ call: FlutterMethodCall, result: @escaping FlutterResult) { let args = call.arguments as! NSDictionary let url = args["url"] as! String let urlScheme = args["redirectURL"] as? String - - + + var authSession: ASWebAuthenticationSession? authSession = ASWebAuthenticationSession( url: URL(string: url)!, @@ -52,13 +52,11 @@ public class TwitterLoginPlugin: NSObject, FlutterPlugin, ASWebAuthenticationPre self.session = nil } self.session = authSession - if #available(iOS 13.0, *) { - authSession?.presentationContextProvider = self - } + authSession?.presentationContextProvider = self if !authSession!.start() { // TODO: failed result(nil) } - + } } diff --git a/pubspec.yaml b/pubspec.yaml index c88e91c..4f7d658 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -27,6 +27,6 @@ flutter: package: com.maru.twitter_login pluginClass: TwitterLoginPlugin ios: - pluginClass: TwitterLoginPlugin + pluginClass: SwiftTwitterLoginPlugin macos: pluginClass: TwitterLoginPlugin