build: Android's built-in Kotlin, the three plugins applying KGP themselves patched in third_party/
AGP 9 compiles Kotlin itself (android.builtInKotlin=true in every app), and warns that applying the Kotlin Gradle Plugin will soon fail. flutter_web_auth_2 5.1.0, keyboard_height_plugin 0.3.0 and flutter_tts 4.2.5 still apply it unconditionally, so their pub releases are copied into third_party/ with only their android/build.gradle changed, and the root overrides them by path (third_party/README.md says when to drop each). The servers' images copy third_party/, as pub refuses an override whose path is missing. third_party/ isn't our own code: left out of the analysis and the format check. All four apps' APKs build without the warning. A Kotlin daemon's session file that slipped into Train's android/ goes, and every app's android/.gitignore keeps .kotlin/ out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
396e010949
commit
438ce20dbf
12 changed files with 8440 additions and 23 deletions
96
third_party/flutter_web_auth_2/lib/flutter_web_auth_2.dart
vendored
Normal file
96
third_party/flutter_web_auth_2/lib/flutter_web_auth_2.dart
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_web_auth_2/src/options.dart';
|
||||
import 'package:flutter_web_auth_2/src/platform/platform_is.dart';
|
||||
import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart';
|
||||
|
||||
export 'src/options.dart';
|
||||
export 'src/unsupported.dart'
|
||||
if (dart.library.io) 'src/linows.dart'
|
||||
if (dart.library.js_interop) 'src/web.dart';
|
||||
|
||||
class _OnAppLifecycleResumeObserver extends WidgetsBindingObserver {
|
||||
_OnAppLifecycleResumeObserver(this.onResumed);
|
||||
|
||||
final Future<void> Function() onResumed;
|
||||
|
||||
@override
|
||||
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
await onResumed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides all the functions you - as a user - should access.
|
||||
class FlutterWebAuth2 {
|
||||
static final RegExp _schemeRegExp = RegExp(r'^[a-z][a-z\d+.-]*$');
|
||||
|
||||
static FlutterWebAuth2Platform get _platform =>
|
||||
FlutterWebAuth2Platform.instance;
|
||||
|
||||
static final _OnAppLifecycleResumeObserver _resumedObserver =
|
||||
_OnAppLifecycleResumeObserver(_cleanUpDanglingCalls);
|
||||
|
||||
static void _assertCallbackScheme(String callbackUrlScheme) {
|
||||
if ((PlatformIs.web || (!PlatformIs.windows && !PlatformIs.linux)) &&
|
||||
!_schemeRegExp.hasMatch(callbackUrlScheme)) {
|
||||
throw ArgumentError.value(
|
||||
callbackUrlScheme,
|
||||
'callbackUrlScheme',
|
||||
'must be a valid URL scheme',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ask the user to authenticate to the specified web service.
|
||||
///
|
||||
/// The page pointed to by [url] will be loaded and displayed to the user.
|
||||
/// From the page, the user can authenticate herself and grant access to the
|
||||
/// app. On completion, the service will send a callback URL with an
|
||||
/// authentication token, and this URL will be result of the returned
|
||||
/// [Future].
|
||||
///
|
||||
/// [callbackUrlScheme] should be a string specifying the scheme of the URL
|
||||
/// that the page will redirect to upon successful authentication.
|
||||
/// If it is `https`, you also need to specify
|
||||
/// [FlutterWebAuth2Options.httpsHost] and [FlutterWebAuth2Options.httpsPath]
|
||||
/// on Apple devices running iOS >= 17.4 or macOS >= 14.4. This allows for
|
||||
/// easy integration of Universal links.
|
||||
///
|
||||
/// [options] can be used to specify either both general and
|
||||
/// platform-specific settings.
|
||||
static Future<String> authenticate({
|
||||
required String url,
|
||||
required String callbackUrlScheme,
|
||||
FlutterWebAuth2Options options = const FlutterWebAuth2Options(),
|
||||
}) async {
|
||||
assert(
|
||||
!(kIsWeb && options.debugOrigin != null && !kDebugMode),
|
||||
'Do not use debugOrigin in production',
|
||||
);
|
||||
|
||||
_assertCallbackScheme(callbackUrlScheme);
|
||||
|
||||
WidgetsBinding.instance.removeObserver(
|
||||
_resumedObserver,
|
||||
); // safety measure so we never add this observer twice
|
||||
WidgetsBinding.instance.addObserver(_resumedObserver);
|
||||
return _platform.authenticate(
|
||||
url: url,
|
||||
callbackUrlScheme: callbackUrlScheme,
|
||||
options: options.toJson(),
|
||||
);
|
||||
}
|
||||
|
||||
/// The plugin may need to store the resulting callbacks in order to pass
|
||||
/// the result back to the caller of `authenticate`. But if that result never
|
||||
/// comes the callback will dangle around forever. This can be called to
|
||||
/// terminate all `authenticate` calls with an error.
|
||||
static Future<void> _cleanUpDanglingCalls() async {
|
||||
await _platform.clearAllDanglingCalls();
|
||||
WidgetsBinding.instance.removeObserver(_resumedObserver);
|
||||
}
|
||||
}
|
||||
44
third_party/flutter_web_auth_2/lib/src/linows.dart
vendored
Normal file
44
third_party/flutter_web_auth_2/lib/src/linows.dart
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||
import 'package:flutter_web_auth_2/src/server.dart';
|
||||
import 'package:flutter_web_auth_2/src/webview.dart';
|
||||
import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart';
|
||||
|
||||
/// Implements the plugin interface for Linux and Windows (Linows).
|
||||
class FlutterWebAuth2LinowsPlugin extends FlutterWebAuth2Platform {
|
||||
final FlutterWebAuth2Platform _webviewImpl = FlutterWebAuth2WebViewPlugin();
|
||||
final FlutterWebAuth2Platform _serverImpl = FlutterWebAuth2ServerPlugin();
|
||||
|
||||
/// Registers the Linows super-implementation.
|
||||
static void registerWith() {
|
||||
FlutterWebAuth2Platform.instance = FlutterWebAuth2LinowsPlugin();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> authenticate({
|
||||
required String url,
|
||||
required String callbackUrlScheme,
|
||||
required Map<String, dynamic> options,
|
||||
}) async {
|
||||
final parsedOptions = FlutterWebAuth2Options.fromJson(options);
|
||||
if (parsedOptions.useWebview) {
|
||||
return _webviewImpl.authenticate(
|
||||
url: url,
|
||||
callbackUrlScheme: callbackUrlScheme,
|
||||
options: options,
|
||||
);
|
||||
}
|
||||
return _serverImpl.authenticate(
|
||||
url: url,
|
||||
callbackUrlScheme: callbackUrlScheme,
|
||||
options: options,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearAllDanglingCalls() async {
|
||||
await _serverImpl.clearAllDanglingCalls();
|
||||
await _webviewImpl.clearAllDanglingCalls();
|
||||
}
|
||||
}
|
||||
1
third_party/flutter_web_auth_2/lib/src/macos.dart
vendored
Normal file
1
third_party/flutter_web_auth_2/lib/src/macos.dart
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
// MacOS just needs the MethodChannel implementation
|
||||
183
third_party/flutter_web_auth_2/lib/src/options.dart
vendored
Normal file
183
third_party/flutter_web_auth_2/lib/src/options.dart
vendored
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/// Default intent flags for opening the custom tabs intent on Android.
|
||||
const defaultIntentFlags = 0;
|
||||
|
||||
/// "Ephemeral" intent flags for opening the custom tabs intent on Android.
|
||||
@Deprecated('Use [preferEphemeral]')
|
||||
const ephemeralIntentFlags = defaultIntentFlags | 1 << 30;
|
||||
|
||||
/// Default HTML code that generates a nice callback page.
|
||||
const _defaultLandingPage = '''
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Access Granted</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
html, body { margin: 0; padding: 0; }
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
|
||||
}
|
||||
|
||||
#text {
|
||||
padding: 2em;
|
||||
text-align: center;
|
||||
font-size: 2rem;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
window.close()
|
||||
}, 1);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div id="text">This page should automatically close.
|
||||
You may also close this page manually now.</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
''';
|
||||
|
||||
/// Provides configuration options for calls to `authenticate`.
|
||||
class FlutterWebAuth2Options {
|
||||
/// Construct an instance and specify the wanted options.
|
||||
const FlutterWebAuth2Options({
|
||||
bool? preferEphemeral,
|
||||
this.debugOrigin,
|
||||
int? intentFlags,
|
||||
this.windowName,
|
||||
int? timeout,
|
||||
String? landingPageHtml,
|
||||
bool? silentAuth,
|
||||
bool? useWebview,
|
||||
this.httpsHost,
|
||||
this.httpsPath,
|
||||
this.customTabsPackageOrder,
|
||||
}) : preferEphemeral = preferEphemeral ?? false,
|
||||
intentFlags = intentFlags ?? defaultIntentFlags,
|
||||
timeout = timeout ?? 5 * 60,
|
||||
landingPageHtml = landingPageHtml ?? _defaultLandingPage,
|
||||
silentAuth = silentAuth ?? false,
|
||||
useWebview = useWebview ?? true;
|
||||
|
||||
/// Construct an instance from JSON format.
|
||||
FlutterWebAuth2Options.fromJson(Map<String, dynamic> json)
|
||||
: this(
|
||||
preferEphemeral: json['preferEphemeral'],
|
||||
debugOrigin: json['debugOrigin'],
|
||||
intentFlags: json['intentFlags'],
|
||||
windowName: json['windowName'],
|
||||
timeout: json['timeout'],
|
||||
landingPageHtml: json['landingPageHtml'],
|
||||
silentAuth: json['silentAuth'],
|
||||
useWebview: json['useWebview'],
|
||||
httpsHost: json['httpsHost'],
|
||||
httpsPath: json['httpsPath'],
|
||||
customTabsPackageOrder: json['customTabsPackageOrder'],
|
||||
);
|
||||
|
||||
/// **Only has an effect on iOS, Android and macOS!**
|
||||
/// If this is `true`, an ephemeral web browser session
|
||||
/// will be used where possible.
|
||||
final bool preferEphemeral;
|
||||
|
||||
/// **Only has an effect on Web!**
|
||||
/// Can be used to override the origin of the redirect URL.
|
||||
/// This is useful for cases where the redirect URL is not on the same
|
||||
/// domain (e.g. local testing).
|
||||
final String? debugOrigin;
|
||||
|
||||
/// **Only has an effect on Android!**
|
||||
/// Can be used to configure the intent flags for the custom tabs intent.
|
||||
/// Possible values can be found
|
||||
/// [here](https://developer.android.com/reference/android/content/Intent#setFlags(int))
|
||||
/// or by using the flags from the `Flag` class from
|
||||
/// [android_intent_plus](https://pub.dev/packages/android_intent_plus).
|
||||
final int intentFlags;
|
||||
|
||||
/// **Only has an effect on Web!**
|
||||
/// Can be used to pass a window name for the URL open call.
|
||||
/// See [here](https://www.w3schools.com/jsref/met_win_open.asp) for
|
||||
/// possible parameter values.
|
||||
final String? windowName;
|
||||
|
||||
/// **Only has an effect on Linux, Web, and Windows!**
|
||||
/// Can be used to specify a timeout in seconds when the authentication shall
|
||||
/// be deemed unsuccessful. An error will be thrown in order to abort the
|
||||
/// authentication process.
|
||||
final int timeout;
|
||||
|
||||
/// **Only has an effect on Linux and Windows with [useWebview] = `false`!**
|
||||
/// Can be used to customise the landing page which tells the user that the
|
||||
/// authentication was successful. It is the literal HTML source code which
|
||||
/// will be displayed using a `HttpServer`.
|
||||
final String landingPageHtml;
|
||||
|
||||
/// **Only has an effect on Web!**
|
||||
/// When set to `true`, the authentication URL will be loaded in a hidden
|
||||
/// `iframe` instead of opening a new window or tab. This is primarily used
|
||||
/// for silent authentication processes where a full-page redirect is not
|
||||
/// desirable. It allows for a seamless user experience by performing the
|
||||
/// authentication in the background. This approach is useful for token
|
||||
/// refreshes or for maintaining user sessions without explicit user
|
||||
/// interaction. IT IS YOUR RESPONSIBILITY TO MAKE SURE THAT THE URL IS SANE
|
||||
/// AND DOES NOT CAUSE ANY HARM. IFRAMES CAN BE EXPLOITED IN MANY WAYS BY
|
||||
/// MALICIOUS ATTACKERS!
|
||||
final bool silentAuth;
|
||||
|
||||
/// **Only has an effect on Linux and Windows!**
|
||||
/// When set to `true`, use the new Webview implementation.
|
||||
/// When set to `false`, the old approach using an internal server is being
|
||||
/// used in order to fetch the HTTP result. When using the internal server,
|
||||
/// please keep in mind that you cannot choose any callback URL scheme, as
|
||||
/// described in https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/25
|
||||
final bool useWebview;
|
||||
|
||||
/// **Only has an effect on Android, iOS, Linux, macOS, and Windows!**
|
||||
/// String specifying the **host** of the URL that the page will redirect to
|
||||
/// upon successful authentication (callback URL).
|
||||
/// When `callbackUrlScheme` is `https`, this **must** be specified on
|
||||
/// Android and Apple devices running iOS >= 17.4 or macOS >= 14.4.
|
||||
/// On Linux and Windows, this is used when `useWebview == true` in order to
|
||||
/// compare with the host of the callback URL (no matter which scheme!).
|
||||
final String? httpsHost;
|
||||
|
||||
/// **Only has an effect on Android, iOS, Linux, macOS, and Windows!**
|
||||
/// String specifying the **path** of the URL that the page will redirect to
|
||||
/// upon successful authentication (callback URL).
|
||||
/// When `callbackUrlScheme` is `https`, this **must** be specified on
|
||||
/// Android and Apple devices running iOS >= 17.4 or macOS >= 14.4.
|
||||
/// On Linux and Windows, this is used when `useWebview == true` in order to
|
||||
/// compare with the path of the callback URL (no matter which scheme!).
|
||||
final String? httpsPath;
|
||||
|
||||
/// **Only has an effect on Android!**
|
||||
/// Sets the Android browser priority for opening custom tabs.
|
||||
/// Needs to be a list of packages providing a custom tabs
|
||||
/// service. If a browser is not installed, the next on the list
|
||||
/// is tested etc.
|
||||
final List<String>? customTabsPackageOrder;
|
||||
|
||||
/// Convert this instance to JSON format.
|
||||
Map<String, dynamic> toJson() => {
|
||||
'preferEphemeral': preferEphemeral,
|
||||
'debugOrigin': debugOrigin,
|
||||
'intentFlags': intentFlags,
|
||||
'windowName': windowName,
|
||||
'timeout': timeout,
|
||||
'landingPageHtml': landingPageHtml,
|
||||
'silentAuth': silentAuth,
|
||||
'useWebview': useWebview,
|
||||
'customTabsPackageOrder': customTabsPackageOrder,
|
||||
'httpsHost': httpsHost,
|
||||
'httpsPath': httpsPath,
|
||||
};
|
||||
}
|
||||
73
third_party/flutter_web_auth_2/lib/src/platform/platform_is.dart
vendored
Normal file
73
third_party/flutter_web_auth_2/lib/src/platform/platform_is.dart
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// Adapted from https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8
|
||||
|
||||
import 'package:flutter_web_auth_2/src/platform/universal_platform_none.dart'
|
||||
if (dart.library.io) 'package:flutter_web_auth_2/src/platform/universal_platform_vm.dart'
|
||||
if (dart.library.js_interop) 'package:flutter_web_auth_2/src/platform/universal_platform_web.dart';
|
||||
|
||||
/// A universal platform checker.
|
||||
///
|
||||
/// Can be used to check active physical Flutter platform on all platforms.
|
||||
///
|
||||
/// To check what host platform the app is running on use:
|
||||
///
|
||||
/// * PlatformIs.android
|
||||
/// * PlatformIs.iOS
|
||||
/// * PlatformIs.macOS
|
||||
/// * PlatformIs.windows
|
||||
/// * PlatformIs.linux
|
||||
/// * PlatformIs.fuchsia
|
||||
///
|
||||
/// To check the device type use:
|
||||
///
|
||||
/// * PlatformIs.mobile (Android or iOS)
|
||||
/// * PlatformIs.desktop (Windows, macOS or Linux)
|
||||
///
|
||||
/// Currently Fuchsia is not considered mobile nor desktop, even if it
|
||||
/// might be so in the future.
|
||||
///
|
||||
/// To check if the Flutter application is running on Web you can use:
|
||||
///
|
||||
/// * PlatformIs.web
|
||||
///
|
||||
/// Alternatively the Flutter foundation compile time constant kIsWeb also
|
||||
/// works well for that.
|
||||
///
|
||||
/// The platform checks are supported independently on web. You can use
|
||||
/// PlatformIs windows, iOS, macOS, Android and Linux to check what the host
|
||||
/// platform is when you are running a Flutter Web application.
|
||||
///
|
||||
/// Checking if we are running on a Fuchsia host in a Web browser, is not yet
|
||||
/// fully supported. If running in a Web browser on Fuchsia, PlatformIs.web
|
||||
/// will be true, but PlatformIs.fuchsia will be false. Future versions, when
|
||||
/// Fuchsia is released, may fix this.
|
||||
class PlatformIs {
|
||||
PlatformIs._();
|
||||
|
||||
/// Is Web?
|
||||
static bool get web => UniversalPlatform.web;
|
||||
|
||||
/// Is macOS?
|
||||
static bool get macOS => UniversalPlatform.macOS;
|
||||
|
||||
/// Is Windows?
|
||||
static bool get windows => UniversalPlatform.windows;
|
||||
|
||||
/// Is Linux?
|
||||
static bool get linux => UniversalPlatform.linux;
|
||||
|
||||
/// Is Android?
|
||||
static bool get android => UniversalPlatform.android;
|
||||
|
||||
/// Is iOS?
|
||||
static bool get iOS => UniversalPlatform.iOS;
|
||||
|
||||
/// Is Fuchsia?
|
||||
static bool get fuchsia => UniversalPlatform.fuchsia;
|
||||
|
||||
/// Is Mobile?
|
||||
static bool get mobile => PlatformIs.iOS || PlatformIs.android;
|
||||
|
||||
/// Is Desktop?
|
||||
static bool get desktop =>
|
||||
PlatformIs.macOS || PlatformIs.windows || PlatformIs.linux;
|
||||
}
|
||||
33
third_party/flutter_web_auth_2/lib/src/platform/universal_platform_none.dart
vendored
Normal file
33
third_party/flutter_web_auth_2/lib/src/platform/universal_platform_none.dart
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Adapted from https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8
|
||||
|
||||
// NOTE:
|
||||
// Never import this library directly in the application. The PlatformIs
|
||||
// class and library uses conditional imports to only import this file on
|
||||
// VM platform builds.
|
||||
|
||||
/// UniversalPlatform for just a "none" implementation when the platform
|
||||
/// cannot be identified for some reason.
|
||||
class UniversalPlatform {
|
||||
UniversalPlatform._();
|
||||
|
||||
/// Is Web?
|
||||
static bool get web => false;
|
||||
|
||||
/// Is macOS?
|
||||
static bool get macOS => false;
|
||||
|
||||
/// Is Windows?
|
||||
static bool get windows => false;
|
||||
|
||||
/// Is Linux?
|
||||
static bool get linux => false;
|
||||
|
||||
/// Is Android?
|
||||
static bool get android => false;
|
||||
|
||||
/// Is iOS?
|
||||
static bool get iOS => false;
|
||||
|
||||
/// Is Fuchsia?
|
||||
static bool get fuchsia => false;
|
||||
}
|
||||
37
third_party/flutter_web_auth_2/lib/src/platform/universal_platform_vm.dart
vendored
Normal file
37
third_party/flutter_web_auth_2/lib/src/platform/universal_platform_vm.dart
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Adapted from https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
// NOTE:
|
||||
// Never import this library directly in the application. The PlatformIs
|
||||
// class and library uses conditional imports to only import this file on
|
||||
// VM platform builds.
|
||||
|
||||
/// UniversalPlatform for Flutter VM builds.
|
||||
///
|
||||
/// We are using Dart VM builds, so we use dart:io Platform to
|
||||
/// get the current platform.
|
||||
class UniversalPlatform {
|
||||
UniversalPlatform._();
|
||||
|
||||
/// Is Web?
|
||||
static bool get web => false;
|
||||
|
||||
/// Is macOS?
|
||||
static bool get macOS => Platform.isMacOS;
|
||||
|
||||
/// Is Windows?
|
||||
static bool get windows => Platform.isWindows;
|
||||
|
||||
/// Is Linux?
|
||||
static bool get linux => Platform.isLinux;
|
||||
|
||||
/// Is Android?
|
||||
static bool get android => Platform.isAndroid;
|
||||
|
||||
/// Is iOS?
|
||||
static bool get iOS => Platform.isIOS;
|
||||
|
||||
/// Is Fuchsia?
|
||||
static bool get fuchsia => Platform.isFuchsia;
|
||||
}
|
||||
57
third_party/flutter_web_auth_2/lib/src/platform/universal_platform_web.dart
vendored
Normal file
57
third_party/flutter_web_auth_2/lib/src/platform/universal_platform_web.dart
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Adapted from https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8
|
||||
|
||||
// ignore: avoid_web_libraries_in_flutter
|
||||
import 'package:web/web.dart';
|
||||
|
||||
// NOTE:
|
||||
// Never import this library directly in the application. The PlatformIs
|
||||
// class and library uses conditional imports to only import this file on
|
||||
// Web platform builds.
|
||||
|
||||
final Navigator _nav = window.navigator;
|
||||
|
||||
/// UniversalPlatform for Flutter WEB build.
|
||||
///
|
||||
/// We can use dart:html Navigator to get the current platform.
|
||||
///
|
||||
/// This function is borrowed, with minor modifications, from GetX utils library
|
||||
/// with MIT license.
|
||||
/// Credits for it belong to its author Jonny Borges https://github.com/jonataslaw
|
||||
/// https://github.com/jonataslaw/getx/blob/master/lib/get_utils/src/platform/platform_web.dart
|
||||
///
|
||||
class UniversalPlatform {
|
||||
UniversalPlatform._();
|
||||
|
||||
/// Is Web?
|
||||
static bool get web => true;
|
||||
|
||||
/// Is macOS?
|
||||
static bool get macOS => _nav.appVersion.contains('Mac OS') && !iOS;
|
||||
|
||||
/// Is Windows?
|
||||
static bool get windows => _nav.appVersion.contains('Win');
|
||||
|
||||
/// Is Linux?
|
||||
static bool get linux =>
|
||||
(_nav.appVersion.contains('Linux') || _nav.appVersion.contains('x11')) &&
|
||||
!android;
|
||||
|
||||
/// Is Android?
|
||||
/// Source: https://developer.chrome.com/multidevice/user-agent
|
||||
static bool get android => _nav.appVersion.contains('Android ');
|
||||
|
||||
/// Is iOS?
|
||||
/// maxTouchPoints is needed to separate iPad iOS13 vs new MacOS
|
||||
static bool get iOS =>
|
||||
_hasMatch(_nav.platform, '/iPad|iPhone|iPod/') ||
|
||||
(_nav.platform == 'MacIntel' && _nav.maxTouchPoints > 1);
|
||||
|
||||
/// Is Fuchsia?
|
||||
/// Theoretically we could be in a Web browser on Fuchsia too, but
|
||||
/// we have no info on how to get that info yet, so we return false.
|
||||
static bool get fuchsia => false;
|
||||
}
|
||||
|
||||
bool _hasMatch(String? value, String pattern) =>
|
||||
// ignore: avoid_bool_literals_in_conditional_expressions
|
||||
(value == null) ? false : RegExp(pattern).hasMatch(value);
|
||||
71
third_party/flutter_web_auth_2/lib/src/server.dart
vendored
Normal file
71
third_party/flutter_web_auth_2/lib/src/server.dart
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||
import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:window_to_front/window_to_front.dart';
|
||||
|
||||
/// Implements the plugin interface using an internal server (currently used by
|
||||
/// Windows and Linux).
|
||||
class FlutterWebAuth2ServerPlugin extends FlutterWebAuth2Platform {
|
||||
HttpServer? _server;
|
||||
Timer? _authTimeout;
|
||||
|
||||
@override
|
||||
Future<String> authenticate({
|
||||
required String url,
|
||||
required String callbackUrlScheme,
|
||||
required Map<String, dynamic> options,
|
||||
}) async {
|
||||
final parsedOptions = FlutterWebAuth2Options.fromJson(options);
|
||||
|
||||
// Validate callback url
|
||||
final callbackUri = Uri.parse(callbackUrlScheme);
|
||||
|
||||
if (callbackUri.scheme != 'http' ||
|
||||
(callbackUri.host != 'localhost' && callbackUri.host != '127.0.0.1') ||
|
||||
!callbackUri.hasPort) {
|
||||
throw ArgumentError(
|
||||
'Callback url scheme must start with http://localhost:{port}',
|
||||
);
|
||||
}
|
||||
|
||||
await _server?.close(force: true);
|
||||
|
||||
_server = await HttpServer.bind('127.0.0.1', callbackUri.port);
|
||||
String? result;
|
||||
|
||||
_authTimeout?.cancel();
|
||||
_authTimeout = Timer(Duration(seconds: parsedOptions.timeout), () {
|
||||
_server?.close();
|
||||
});
|
||||
|
||||
await launchUrl(Uri.parse(url));
|
||||
|
||||
await _server!.listen((req) async {
|
||||
req.response.headers.add('Content-Type', 'text/html');
|
||||
req.response.write(parsedOptions.landingPageHtml);
|
||||
await req.response.close();
|
||||
|
||||
result = req.requestedUri.toString();
|
||||
await _server?.close();
|
||||
_server = null;
|
||||
}).asFuture();
|
||||
|
||||
await _server?.close(force: true);
|
||||
_authTimeout?.cancel();
|
||||
|
||||
if (result != null) {
|
||||
await WindowToFront.activate();
|
||||
return result!;
|
||||
}
|
||||
throw PlatformException(message: 'User canceled login', code: 'CANCELED');
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearAllDanglingCalls() async {
|
||||
await _server?.close(force: true);
|
||||
}
|
||||
}
|
||||
31
third_party/flutter_web_auth_2/lib/src/unsupported.dart
vendored
Normal file
31
third_party/flutter_web_auth_2/lib/src/unsupported.dart
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart';
|
||||
|
||||
/// Implements the plugin interface for unsupported platforms (just throws
|
||||
/// errors).
|
||||
class FlutterWebAuth2UnsupportedPlugin extends FlutterWebAuth2Platform {
|
||||
/// Registers the unsupported implementation.
|
||||
static void registerWith() {
|
||||
FlutterWebAuth2Platform.instance = FlutterWebAuth2UnsupportedPlugin();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> authenticate({
|
||||
required String url,
|
||||
required String callbackUrlScheme,
|
||||
required Map<String, dynamic> options,
|
||||
}) async {
|
||||
throw PlatformException(
|
||||
message: 'Platform either unsupported or unrecognised.',
|
||||
code: 'UNSUPPORTED',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future clearAllDanglingCalls() async {
|
||||
throw PlatformException(
|
||||
message: 'Platform either unsupported or unrecognised.',
|
||||
code: 'UNSUPPORTED',
|
||||
);
|
||||
}
|
||||
}
|
||||
183
third_party/flutter_web_auth_2/lib/src/web.dart
vendored
Normal file
183
third_party/flutter_web_auth_2/lib/src/web.dart
vendored
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:js_interop';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_web_auth_2/src/options.dart';
|
||||
import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:web/web.dart';
|
||||
|
||||
/// Implements the plugin interface using iframes (for silent authentication)
|
||||
/// and through an event listener system (for usual authentication).
|
||||
class FlutterWebAuth2WebPlugin extends FlutterWebAuth2Platform {
|
||||
/// Registers the web implementation.
|
||||
static void registerWith(Registrar registrar) {
|
||||
final channel = MethodChannel(
|
||||
'flutter_web_auth_2',
|
||||
const StandardMethodCodec(),
|
||||
registrar,
|
||||
);
|
||||
final instance = FlutterWebAuth2WebPlugin();
|
||||
channel.setMethodCallHandler(instance._handleMethodCall);
|
||||
FlutterWebAuth2Platform.instance = instance;
|
||||
}
|
||||
|
||||
Future<dynamic> _handleMethodCall(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case 'authenticate':
|
||||
final url = call.arguments['url'].toString();
|
||||
return authenticate(
|
||||
url: url,
|
||||
callbackUrlScheme: '',
|
||||
options: call.arguments['options'],
|
||||
);
|
||||
case 'cleanUpDanglingCalls':
|
||||
return clearAllDanglingCalls();
|
||||
default:
|
||||
throw PlatformException(
|
||||
code: 'Unimplemented',
|
||||
details: "The flutter_web_auth_2 plugin for web doesn't implement "
|
||||
"the method '${call.method}'",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> authenticate({
|
||||
required String url,
|
||||
required String callbackUrlScheme,
|
||||
required Map<String, dynamic> options,
|
||||
}) async {
|
||||
final parsedOptions = FlutterWebAuth2Options.fromJson(options);
|
||||
|
||||
if (parsedOptions.silentAuth) {
|
||||
final authIframe = (document.createElement('iframe') as HTMLIFrameElement)
|
||||
..src = url
|
||||
..style.display = 'none';
|
||||
|
||||
document.body?.append(authIframe);
|
||||
|
||||
final completer = Completer<String>();
|
||||
StreamSubscription? messageSubscription;
|
||||
Timer? responseTimeoutTimer;
|
||||
|
||||
messageSubscription = window.onMessage.listen((messageEvent) {
|
||||
if (messageEvent.origin ==
|
||||
(parsedOptions.debugOrigin ?? Uri.base.origin)) {
|
||||
final data = messageEvent.data.dartify();
|
||||
final authMessage =
|
||||
data != null && data is Map ? data['flutter-web-auth-2'] : null;
|
||||
if (authMessage is String) {
|
||||
authIframe.remove();
|
||||
completer.complete(authMessage);
|
||||
responseTimeoutTimer?.cancel();
|
||||
messageSubscription?.cancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add a timeout for the iframe response
|
||||
responseTimeoutTimer =
|
||||
Timer(Duration(seconds: parsedOptions.timeout), () {
|
||||
authIframe.remove();
|
||||
messageSubscription?.cancel();
|
||||
completer.completeError(
|
||||
PlatformException(
|
||||
code: 'timeout',
|
||||
message: 'Timeout waiting for the iframe response',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
await launchUrl(
|
||||
Uri.parse(url),
|
||||
webOnlyWindowName: parsedOptions.windowName,
|
||||
);
|
||||
|
||||
// Remove the old record if it exists
|
||||
const storageKey = 'flutter-web-auth-2';
|
||||
window.localStorage.removeItem(storageKey);
|
||||
Timer? lsTimer;
|
||||
StreamSubscription? messageSubscription;
|
||||
final completer = Completer<String>();
|
||||
try {
|
||||
// Periodically check for the callback value in local storage.
|
||||
// If it exists, return it. If not, check the timeout.
|
||||
// If the timeout has passed, throw an exception.
|
||||
lsTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
final flutterWebAuthMessage = window.localStorage.getItem(storageKey);
|
||||
if (flutterWebAuthMessage != null) {
|
||||
completer.complete(flutterWebAuthMessage);
|
||||
window.localStorage.removeItem(storageKey);
|
||||
messageSubscription?.cancel();
|
||||
timer.cancel();
|
||||
} else if (timer.tick >= parsedOptions.timeout) {
|
||||
messageSubscription?.cancel();
|
||||
timer.cancel();
|
||||
completer.completeError(
|
||||
PlatformException(
|
||||
code: 'error',
|
||||
message: 'Timeout waiting for callback value',
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Traditional window.opener method of listening for the redirect
|
||||
messageSubscription = window.onMessage.listen(
|
||||
(messageEvent) {
|
||||
if (messageEvent.origin ==
|
||||
(parsedOptions.debugOrigin ?? Uri.base.origin)) {
|
||||
final data = messageEvent.data.dartify();
|
||||
final flutterWebAuthMessage =
|
||||
data != null && data is Map ? data['flutter-web-auth-2'] : null;
|
||||
if (flutterWebAuthMessage is String) {
|
||||
lsTimer?.cancel();
|
||||
messageSubscription?.cancel();
|
||||
completer.complete(flutterWebAuthMessage);
|
||||
}
|
||||
}
|
||||
|
||||
final appleOrigin = Uri(scheme: 'https', host: 'appleid.apple.com');
|
||||
if (messageEvent.origin == appleOrigin.toString()) {
|
||||
try {
|
||||
final data = jsonDecode(messageEvent.data.toString());
|
||||
if (data['method'] == 'oauthDone') {
|
||||
final appleAuth =
|
||||
data['data']['authorization'] as Map<String, dynamic>?;
|
||||
if (appleAuth != null) {
|
||||
final appleAuthQuery = Uri(queryParameters: appleAuth).query;
|
||||
lsTimer?.cancel();
|
||||
messageSubscription?.cancel();
|
||||
completer.complete(
|
||||
appleOrigin.replace(fragment: appleAuthQuery).toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
} on FormatException {
|
||||
// ignore exception
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (error) {
|
||||
lsTimer?.cancel();
|
||||
messageSubscription?.cancel();
|
||||
throw error;
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
lsTimer?.cancel();
|
||||
completer.completeError(e);
|
||||
}
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearAllDanglingCalls() async {}
|
||||
}
|
||||
83
third_party/flutter_web_auth_2/lib/src/webview.dart
vendored
Normal file
83
third_party/flutter_web_auth_2/lib/src/webview.dart
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||
import 'package:flutter_web_auth_2_platform_interface/flutter_web_auth_2_platform_interface.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
/// Implements the plugin interface using the Webview interface (currently used
|
||||
/// by Windows and Linux).
|
||||
class FlutterWebAuth2WebViewPlugin extends FlutterWebAuth2Platform {
|
||||
bool _authenticated = false;
|
||||
Webview? _webview;
|
||||
|
||||
@override
|
||||
Future<String> authenticate({
|
||||
required String url,
|
||||
required String callbackUrlScheme,
|
||||
required Map<String, dynamic> options,
|
||||
}) async {
|
||||
if (!await WebviewWindow.isWebviewAvailable()) {
|
||||
// Microsoft's WebView2 must be installed for this to work
|
||||
throw StateError('Webview is not available');
|
||||
}
|
||||
|
||||
final parsedOptions = FlutterWebAuth2Options.fromJson(options);
|
||||
|
||||
// Reset
|
||||
_authenticated = false;
|
||||
_webview?.close();
|
||||
|
||||
final c = Completer<String>();
|
||||
_webview = await WebviewWindow.create(
|
||||
configuration: CreateConfiguration(
|
||||
windowHeight: 720,
|
||||
windowWidth: 1280,
|
||||
title: 'Authenticate',
|
||||
titleBarTopPadding: 0,
|
||||
userDataFolderWindows: (await getTemporaryDirectory()).path,
|
||||
),
|
||||
);
|
||||
_webview!.setOnUrlRequestCallback((url) {
|
||||
final uri = Uri.parse(url);
|
||||
if (uri.scheme != callbackUrlScheme ||
|
||||
(parsedOptions.httpsHost != null &&
|
||||
uri.host != parsedOptions.httpsHost) ||
|
||||
(parsedOptions.httpsPath != null &&
|
||||
uri.path != parsedOptions.httpsPath)) {
|
||||
return true;
|
||||
}
|
||||
_authenticated = true;
|
||||
_webview?.close();
|
||||
/**
|
||||
* Not setting the webview to null will cause a crash if the
|
||||
* application tries to open another webview
|
||||
*/
|
||||
_webview = null;
|
||||
c.complete(url);
|
||||
return true;
|
||||
});
|
||||
unawaited(
|
||||
_webview!.onClose.whenComplete(
|
||||
() {
|
||||
/**
|
||||
* Not setting the webview to null will cause a crash if the
|
||||
* application tries to open another webview
|
||||
*/
|
||||
_webview = null;
|
||||
if (!_authenticated) {
|
||||
c.completeError(
|
||||
PlatformException(code: 'CANCELED', message: 'User canceled'),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
_webview!.launch(url);
|
||||
return c.future;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearAllDanglingCalls() async {}
|
||||
}
|
||||
Loading…
Reference in a new issue