mirror of
https://github.com/flutter/packages.git
synced 2025-06-30 23:03:11 +08:00
[google_sign_in_web] Migrate to pkg:web. (#5612)
This PR updates `google_sign_in_web` to: * Use the latest `google_identity_services_web` and `http` * Use `package:web` This should allow the package to compile to WASM. ## Issues * Fixes https://github.com/flutter/flutter/issues/139169 * Needed to https://github.com/flutter/flutter/issues/139170 ## Tests * All tests should pass (ran locally) * Demo app compiled to WASM: https://dit-gis-test.web.app
This commit is contained in:
@ -1,3 +1,8 @@
|
|||||||
|
## 0.12.3
|
||||||
|
|
||||||
|
* Migrates to `package:web`.
|
||||||
|
* Updates minimum supported SDK version to Flutter 3.16.0/Dart 3.2.0.
|
||||||
|
|
||||||
## 0.12.2+1
|
## 0.12.2+1
|
||||||
|
|
||||||
* Re-publishes `0.12.2` with a small fix to the CodeClient initialization.
|
* Re-publishes `0.12.2` with a small fix to the CodeClient initialization.
|
||||||
|
@ -9,8 +9,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:google_sign_in_web/src/flexible_size_html_element_view.dart';
|
import 'package:google_sign_in_web/src/flexible_size_html_element_view.dart';
|
||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
import 'package:web/web.dart' as web;
|
||||||
import 'src/dom.dart';
|
|
||||||
|
|
||||||
/// Used to keep track of the number of HtmlElementView factories the test has registered.
|
/// Used to keep track of the number of HtmlElementView factories the test has registered.
|
||||||
int widgetFactoryNumber = 0;
|
int widgetFactoryNumber = 0;
|
||||||
@ -54,7 +53,8 @@ void main() {
|
|||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
const Size childSize = Size(300, 40);
|
const Size childSize = Size(300, 40);
|
||||||
|
|
||||||
final DomHtmlElement resizable = document.createElement('div');
|
final web.HTMLDivElement resizable =
|
||||||
|
web.document.createElement('div') as web.HTMLDivElement;
|
||||||
resize(resizable, childSize);
|
resize(resizable, childSize);
|
||||||
|
|
||||||
final Element element = await pumpResizableWidget(
|
final Element element = await pumpResizableWidget(
|
||||||
@ -73,7 +73,8 @@ void main() {
|
|||||||
const Size initialSize = Size(160, 100);
|
const Size initialSize = Size(160, 100);
|
||||||
const Size newSize = Size(300, 40);
|
const Size newSize = Size(300, 40);
|
||||||
|
|
||||||
final DomHtmlElement resizable = document.createElement('div');
|
final web.HTMLDivElement resizable =
|
||||||
|
web.document.createElement('div') as web.HTMLDivElement;
|
||||||
resize(resizable, newSize);
|
resize(resizable, newSize);
|
||||||
|
|
||||||
final Element element = await pumpResizableWidget(
|
final Element element = await pumpResizableWidget(
|
||||||
@ -94,7 +95,8 @@ void main() {
|
|||||||
final Size expandedSize = initialSize * 2;
|
final Size expandedSize = initialSize * 2;
|
||||||
final Size contractedSize = initialSize / 2;
|
final Size contractedSize = initialSize / 2;
|
||||||
|
|
||||||
final DomHtmlElement resizable = document.createElement('div')
|
final web.HTMLDivElement resizable = web.document.createElement('div')
|
||||||
|
as web.HTMLDivElement
|
||||||
..setAttribute(
|
..setAttribute(
|
||||||
'style', 'width: 100%; height: 100%; background: #fabada;');
|
'style', 'width: 100%; height: 100%; background: #fabada;');
|
||||||
|
|
||||||
@ -160,7 +162,8 @@ class ResizableFromJs extends StatelessWidget {
|
|||||||
ui_web.platformViewRegistry.registerViewFactory(
|
ui_web.platformViewRegistry.registerViewFactory(
|
||||||
'resizable_from_js_$instanceId',
|
'resizable_from_js_$instanceId',
|
||||||
(int viewId) {
|
(int viewId) {
|
||||||
final DomHtmlElement element = document.createElement('div');
|
final web.HTMLDivElement element =
|
||||||
|
web.document.createElement('div') as web.HTMLDivElement;
|
||||||
element.setAttribute('style',
|
element.setAttribute('style',
|
||||||
'width: 100%; height: 100%; overflow: hidden; background: red;');
|
'width: 100%; height: 100%; overflow: hidden; background: red;');
|
||||||
element.id = 'test_element_$viewId';
|
element.id = 'test_element_$viewId';
|
||||||
@ -191,16 +194,16 @@ class ResizableFromJs extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resizes `resizable` to `size`.
|
/// Resizes `resizable` to `size`.
|
||||||
void resize(DomHtmlElement resizable, Size size) {
|
void resize(web.HTMLElement resizable, Size size) {
|
||||||
resizable.setAttribute('style',
|
resizable.setAttribute('style',
|
||||||
'width: ${size.width}px; height: ${size.height}px; background: #fabada');
|
'width: ${size.width}px; height: ${size.height}px; background: #fabada');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a function that can be used to inject `element` in `onPlatformViewCreated` callbacks.
|
/// Returns a function that can be used to inject `element` in `onPlatformViewCreated` callbacks.
|
||||||
void Function(int) injectElement(DomHtmlElement element) {
|
void Function(int) injectElement(web.HTMLElement element) {
|
||||||
return (int viewId) {
|
return (int viewId) {
|
||||||
final DomHtmlElement root =
|
final web.Element? root =
|
||||||
document.querySelector('#test_element_$viewId')!;
|
web.document.querySelector('#test_element_$viewId');
|
||||||
root.appendChild(element);
|
root!.appendChild(element);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ import 'package:google_sign_in_web/src/people.dart';
|
|||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
import 'package:mockito/annotations.dart';
|
import 'package:mockito/annotations.dart';
|
||||||
import 'package:mockito/mockito.dart' as mockito;
|
import 'package:mockito/mockito.dart' as mockito;
|
||||||
|
import 'package:web/web.dart' as web;
|
||||||
|
|
||||||
import 'google_sign_in_web_test.mocks.dart';
|
import 'google_sign_in_web_test.mocks.dart';
|
||||||
import 'src/dom.dart';
|
|
||||||
import 'src/person.dart';
|
import 'src/person.dart';
|
||||||
|
|
||||||
// Mock GisSdkClient so we can simulate any response from the JS side.
|
// Mock GisSdkClient so we can simulate any response from the JS side.
|
||||||
@ -36,12 +36,12 @@ void main() {
|
|||||||
expect(plugin.autoDetectedClientId, isNull);
|
expect(plugin.autoDetectedClientId, isNull);
|
||||||
|
|
||||||
// Add it to the test page now, and try again
|
// Add it to the test page now, and try again
|
||||||
final DomHtmlMetaElement meta =
|
final web.HTMLMetaElement meta =
|
||||||
document.createElement('meta') as DomHtmlMetaElement
|
web.document.createElement('meta') as web.HTMLMetaElement
|
||||||
..name = clientIdMetaName
|
..name = clientIdMetaName
|
||||||
..content = expectedClientId;
|
..content = expectedClientId;
|
||||||
|
|
||||||
document.head.appendChild(meta);
|
web.document.head!.appendChild(meta);
|
||||||
|
|
||||||
final GoogleSignInPlugin another = GoogleSignInPlugin(
|
final GoogleSignInPlugin another = GoogleSignInPlugin(
|
||||||
debugOverrideLoader: true,
|
debugOverrideLoader: true,
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
/*
|
|
||||||
// DOM shim. This file contains everything we need from the DOM API written as
|
|
||||||
// @staticInterop, so we don't need dart:html
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/
|
|
||||||
//
|
|
||||||
// (To be replaced by `package:web`)
|
|
||||||
*/
|
|
||||||
|
|
||||||
import 'package:js/js.dart';
|
|
||||||
|
|
||||||
/// Document interface
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
abstract class DomHtmlDocument {}
|
|
||||||
|
|
||||||
/// Some methods of document
|
|
||||||
extension DomHtmlDocumentExtension on DomHtmlDocument {
|
|
||||||
/// document.head
|
|
||||||
external DomHtmlElement get head;
|
|
||||||
|
|
||||||
/// document.createElement
|
|
||||||
external DomHtmlElement createElement(String tagName);
|
|
||||||
|
|
||||||
/// document.querySelector
|
|
||||||
external DomHtmlElement? querySelector(String selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An instance of an HTMLElement
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
abstract class DomHtmlElement {}
|
|
||||||
|
|
||||||
/// (Some) methods of HtmlElement
|
|
||||||
extension DomHtmlElementExtension on DomHtmlElement {
|
|
||||||
external String get id;
|
|
||||||
external set id(String id);
|
|
||||||
external set innerText(String innerText);
|
|
||||||
external String? getAttribute(String attributeName);
|
|
||||||
|
|
||||||
/// Node.appendChild
|
|
||||||
external DomHtmlElement appendChild(DomHtmlElement child);
|
|
||||||
|
|
||||||
/// Element.setAttribute
|
|
||||||
external void setAttribute(String name, Object value);
|
|
||||||
|
|
||||||
/// Element.remove
|
|
||||||
external void remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An instance of an HTMLMetaElement
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
abstract class DomHtmlMetaElement extends DomHtmlElement {}
|
|
||||||
|
|
||||||
/// Some methods exclusive of Script elements
|
|
||||||
extension DomHtmlMetaElementExtension on DomHtmlMetaElement {
|
|
||||||
external set name(String name);
|
|
||||||
external set content(String content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getters
|
|
||||||
|
|
||||||
/// window.document
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
external DomHtmlDocument get document;
|
|
@ -2,9 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:js/js_util.dart' as js_util;
|
import 'dart:js_interop';
|
||||||
|
|
||||||
/// Converts a [data] object into a JS Object of type `T`.
|
/// Converts a [data] object into a JS Object of type `T`.
|
||||||
T jsifyAs<T>(Map<String, Object?> data) {
|
T jsifyAs<T>(Map<String, Object?> data) {
|
||||||
return js_util.jsify(data) as T;
|
return data.jsify() as T;
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ name: google_sign_in_web_integration_tests
|
|||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.1.0 <4.0.0"
|
sdk: ">=3.2.0 <4.0.0"
|
||||||
flutter: ">=3.13.0"
|
flutter: ">=3.16.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
google_identity_services_web: ^0.2.1
|
google_identity_services_web: ^0.3.0
|
||||||
google_sign_in_platform_interface: ^2.4.0
|
google_sign_in_platform_interface: ^2.4.0
|
||||||
google_sign_in_web:
|
google_sign_in_web:
|
||||||
path: ../
|
path: ../
|
||||||
@ -21,8 +21,8 @@ dev_dependencies:
|
|||||||
http: ">=0.13.0 <2.0.0"
|
http: ">=0.13.0 <2.0.0"
|
||||||
integration_test:
|
integration_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
js: ^0.6.3
|
|
||||||
mockito: 5.4.3
|
mockito: 5.4.3
|
||||||
|
web: ">=0.3.0 <0.5.0"
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:html' as html;
|
import 'dart:js_interop';
|
||||||
import 'dart:ui_web' as ui_web;
|
import 'dart:ui_web' as ui_web;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart' show visibleForTesting, kDebugMode;
|
import 'package:flutter/foundation.dart' show visibleForTesting, kDebugMode;
|
||||||
@ -13,9 +13,9 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||||
import 'package:google_identity_services_web/loader.dart' as loader;
|
import 'package:google_identity_services_web/loader.dart' as loader;
|
||||||
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
||||||
|
import 'package:web/web.dart' as web;
|
||||||
|
|
||||||
import 'src/button_configuration.dart' show GSIButtonConfiguration;
|
import 'src/button_configuration.dart' show GSIButtonConfiguration;
|
||||||
import 'src/dom.dart';
|
|
||||||
import 'src/flexible_size_html_element_view.dart';
|
import 'src/flexible_size_html_element_view.dart';
|
||||||
import 'src/gis_client.dart';
|
import 'src/gis_client.dart';
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class GoogleSignInPlugin extends GoogleSignInPlatform {
|
|||||||
}) : _gisSdkClient = debugOverrideGisSdkClient,
|
}) : _gisSdkClient = debugOverrideGisSdkClient,
|
||||||
_userDataController = debugOverrideUserDataController ??
|
_userDataController = debugOverrideUserDataController ??
|
||||||
StreamController<GoogleSignInUserData?>.broadcast() {
|
StreamController<GoogleSignInUserData?>.broadcast() {
|
||||||
autoDetectedClientId = html
|
autoDetectedClientId = web.document
|
||||||
.querySelector(clientIdMetaSelector)
|
.querySelector(clientIdMetaSelector)
|
||||||
?.getAttribute(clientIdAttributeName);
|
?.getAttribute(clientIdAttributeName);
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ class GoogleSignInPlugin extends GoogleSignInPlatform {
|
|||||||
ui_web.platformViewRegistry.registerViewFactory(
|
ui_web.platformViewRegistry.registerViewFactory(
|
||||||
'gsi_login_button',
|
'gsi_login_button',
|
||||||
(int viewId) {
|
(int viewId) {
|
||||||
final DomElement element = createDomElement('div');
|
final web.Element element = web.document.createElement('div');
|
||||||
element.setAttribute('style',
|
element.setAttribute('style',
|
||||||
'width: 100%; height: 100%; overflow: hidden; display: flex; flex-wrap: wrap; align-content: center; justify-content: center;');
|
'width: 100%; height: 100%; overflow: hidden; display: flex; flex-wrap: wrap; align-content: center; justify-content: center;');
|
||||||
element.id = 'sign_in_button_$viewId';
|
element.id = 'sign_in_button_$viewId';
|
||||||
@ -196,8 +196,8 @@ class GoogleSignInPlugin extends GoogleSignInPlatform {
|
|||||||
return FlexHtmlElementView(
|
return FlexHtmlElementView(
|
||||||
viewType: 'gsi_login_button',
|
viewType: 'gsi_login_button',
|
||||||
onPlatformViewCreated: (int viewId) {
|
onPlatformViewCreated: (int viewId) {
|
||||||
final DomElement? element =
|
final web.Element? element =
|
||||||
domDocument.querySelector('#sign_in_button_$viewId');
|
web.document.querySelector('#sign_in_button_$viewId');
|
||||||
assert(element != null,
|
assert(element != null,
|
||||||
'Cannot render GSI button. DOM is not ready!');
|
'Cannot render GSI button. DOM is not ready!');
|
||||||
_gisClient.renderButton(element!, config);
|
_gisClient.renderButton(element!, config);
|
||||||
@ -219,10 +219,11 @@ class GoogleSignInPlugin extends GoogleSignInPlatform {
|
|||||||
@override
|
@override
|
||||||
Future<GoogleSignInUserData?> signIn() async {
|
Future<GoogleSignInUserData?> signIn() async {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
domConsole.warn(
|
web.console.warn(
|
||||||
"The `signIn` method is discouraged on the web because it can't reliably provide an `idToken`.\n"
|
"The `signIn` method is discouraged on the web because it can't reliably provide an `idToken`.\n"
|
||||||
'Use `signInSilently` and `renderButton` to authenticate your users instead.\n'
|
'Use `signInSilently` and `renderButton` to authenticate your users instead.\n'
|
||||||
'Read more: https://pub.dev/packages/google_sign_in_web');
|
'Read more: https://pub.dev/packages/google_sign_in_web'
|
||||||
|
.toJS);
|
||||||
}
|
}
|
||||||
await initialized;
|
await initialized;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:google_identity_services_web/id.dart' as id;
|
import 'package:google_identity_services_web/id.dart' as id;
|
||||||
import 'package:js/js_util.dart' as js_util;
|
|
||||||
|
|
||||||
/// Converts user-facing `GisButtonConfiguration` into the JS-Interop `id.GsiButtonConfiguration`.
|
/// Converts user-facing `GisButtonConfiguration` into the JS-Interop `id.GsiButtonConfiguration`.
|
||||||
id.GsiButtonConfiguration? convertButtonConfiguration(
|
id.GsiButtonConfiguration? convertButtonConfiguration(
|
||||||
@ -12,17 +11,16 @@ id.GsiButtonConfiguration? convertButtonConfiguration(
|
|||||||
if (config == null) {
|
if (config == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return js_util.jsify(<String, Object?>{
|
return id.GsiButtonConfiguration(
|
||||||
if (config.type != null) 'type': _idType[config.type],
|
type: _idType[config.type],
|
||||||
if (config.theme != null) 'theme': _idTheme[config.theme],
|
theme: _idTheme[config.theme],
|
||||||
if (config.size != null) 'size': _idSize[config.size],
|
size: _idSize[config.size],
|
||||||
if (config.text != null) 'text': _idText[config.text],
|
text: _idText[config.text],
|
||||||
if (config.shape != null) 'shape': _idShape[config.shape],
|
shape: _idShape[config.shape],
|
||||||
if (config.logoAlignment != null)
|
logo_alignment: _idLogoAlignment[config.logoAlignment],
|
||||||
'logo_alignment': _idLogoAlignment[config.logoAlignment],
|
width: config.minimumWidth,
|
||||||
if (config.minimumWidth != null) 'width': config.minimumWidth,
|
locale: config.locale,
|
||||||
if (config.locale != null) 'locale': config.locale,
|
);
|
||||||
}) as id.GsiButtonConfiguration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A class to configure the Google Sign-In Button for web.
|
/// A class to configure the Google Sign-In Button for web.
|
||||||
|
@ -1,211 +0,0 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// ignore_for_file: public_member_api_docs
|
|
||||||
|
|
||||||
import 'package:js/js.dart';
|
|
||||||
import 'package:js/js_util.dart' as js_util;
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomConsole {}
|
|
||||||
|
|
||||||
extension DomConsoleExtension on DomConsole {
|
|
||||||
void debug(String message, [List<Object?>? more]) =>
|
|
||||||
js_util.callMethod(this, 'debug', <Object?>[message, ...?more]);
|
|
||||||
void info(String message, [List<Object?>? more]) =>
|
|
||||||
js_util.callMethod(this, 'info', <Object?>[message, ...?more]);
|
|
||||||
void warn(String message, [List<Object?>? more]) =>
|
|
||||||
js_util.callMethod(this, 'warn', <Object?>[message, ...?more]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomWindow {}
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomDocument {}
|
|
||||||
|
|
||||||
extension DomDocumentExtension on DomDocument {
|
|
||||||
external DomElement? querySelector(String selectors);
|
|
||||||
DomElement createElement(String name, [Object? options]) =>
|
|
||||||
js_util.callMethod(this, 'createElement',
|
|
||||||
<Object>[name, if (options != null) options]) as DomElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomElement {}
|
|
||||||
|
|
||||||
extension DomElementExtension on DomElement {
|
|
||||||
external String get id;
|
|
||||||
external set id(String id);
|
|
||||||
external String? getAttribute(String attributeName);
|
|
||||||
external void remove();
|
|
||||||
external void setAttribute(String name, Object value);
|
|
||||||
external void removeAttribute(String name);
|
|
||||||
external set tabIndex(double? value);
|
|
||||||
external double? get tabIndex;
|
|
||||||
external set className(String value);
|
|
||||||
external String get className;
|
|
||||||
external bool hasAttribute(String name);
|
|
||||||
external DomElement? get firstChild;
|
|
||||||
external DomElement? querySelector(String selectors);
|
|
||||||
external String get tagName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JS('window')
|
|
||||||
external DomWindow get domWindow;
|
|
||||||
|
|
||||||
@JS('document')
|
|
||||||
external DomDocument get domDocument;
|
|
||||||
|
|
||||||
@JS('console')
|
|
||||||
external DomConsole get domConsole;
|
|
||||||
|
|
||||||
DomElement createDomElement(String tag) => domDocument.createElement(tag);
|
|
||||||
|
|
||||||
/// DOM Observers: Mutation and Size
|
|
||||||
typedef DomMutationCallbackFn = void Function(
|
|
||||||
List<DomMutationRecord> mutation, DomMutationObserver observer);
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomMutationObserver {}
|
|
||||||
|
|
||||||
DomMutationObserver createDomMutationObserver(DomMutationCallbackFn fn) =>
|
|
||||||
domCallConstructorString('MutationObserver', <Object>[
|
|
||||||
allowInterop(
|
|
||||||
(List<dynamic> mutations, DomMutationObserver observer) {
|
|
||||||
fn(mutations.cast<DomMutationRecord>(), observer);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
])! as DomMutationObserver;
|
|
||||||
|
|
||||||
extension DomMutationObserverExtension on DomMutationObserver {
|
|
||||||
external void disconnect();
|
|
||||||
void observe(DomElement target,
|
|
||||||
{bool? childList,
|
|
||||||
bool? attributes,
|
|
||||||
bool? subtree,
|
|
||||||
List<String>? attributeFilter}) {
|
|
||||||
final Map<String, dynamic> options = <String, dynamic>{
|
|
||||||
if (childList != null) 'childList': childList,
|
|
||||||
if (attributes != null) 'attributes': attributes,
|
|
||||||
if (subtree != null) 'subtree': subtree,
|
|
||||||
if (attributeFilter != null) 'attributeFilter': attributeFilter
|
|
||||||
};
|
|
||||||
return js_util
|
|
||||||
.callMethod(this, 'observe', <Object?>[target, js_util.jsify(options)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomMutationRecord {}
|
|
||||||
|
|
||||||
extension DomMutationRecordExtension on DomMutationRecord {
|
|
||||||
external List<DomElement>? get addedNodes;
|
|
||||||
external List<DomElement>? get removedNodes;
|
|
||||||
external String? get attributeName;
|
|
||||||
external String? get type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ResizeObserver JS binding.
|
|
||||||
///
|
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
abstract class DomResizeObserver {}
|
|
||||||
|
|
||||||
/// Creates a DomResizeObserver with a callback.
|
|
||||||
///
|
|
||||||
/// Internally converts the `List<dynamic>` of entries into the expected
|
|
||||||
/// `List<DomResizeObserverEntry>`
|
|
||||||
DomResizeObserver? createDomResizeObserver(DomResizeObserverCallbackFn fn) {
|
|
||||||
return domCallConstructorString('ResizeObserver', <Object?>[
|
|
||||||
allowInterop((List<dynamic> entries, DomResizeObserver observer) {
|
|
||||||
fn(entries.cast<DomResizeObserverEntry>(), observer);
|
|
||||||
}),
|
|
||||||
]) as DomResizeObserver?;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ResizeObserver instance methods.
|
|
||||||
///
|
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#instance_methods
|
|
||||||
extension DomResizeObserverExtension on DomResizeObserver {
|
|
||||||
external void disconnect();
|
|
||||||
external void observe(DomElement target,
|
|
||||||
[DomResizeObserverObserveOptions options]);
|
|
||||||
external void unobserve(DomElement target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Options object passed to the `observe` method of a [DomResizeObserver].
|
|
||||||
///
|
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#parameters
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
@anonymous
|
|
||||||
abstract class DomResizeObserverObserveOptions {
|
|
||||||
external factory DomResizeObserverObserveOptions({
|
|
||||||
String box,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type of the function used to create a Resize Observer.
|
|
||||||
typedef DomResizeObserverCallbackFn = void Function(
|
|
||||||
List<DomResizeObserverEntry> entries, DomResizeObserver observer);
|
|
||||||
|
|
||||||
/// The object passed to the [DomResizeObserverCallbackFn], which allows access to the new dimensions of the observed element.
|
|
||||||
///
|
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
abstract class DomResizeObserverEntry {}
|
|
||||||
|
|
||||||
/// ResizeObserverEntry instance properties.
|
|
||||||
///
|
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry#instance_properties
|
|
||||||
extension DomResizeObserverEntryExtension on DomResizeObserverEntry {
|
|
||||||
/// A DOMRectReadOnly object containing the new size of the observed element when the callback is run.
|
|
||||||
///
|
|
||||||
/// Note that this is better supported than the above two properties, but it
|
|
||||||
/// is left over from an earlier implementation of the Resize Observer API, is
|
|
||||||
/// still included in the spec for web compat reasons, and may be deprecated
|
|
||||||
/// in future versions.
|
|
||||||
external DomRectReadOnly get contentRect;
|
|
||||||
external DomElement get target;
|
|
||||||
// Some more future getters:
|
|
||||||
//
|
|
||||||
// borderBoxSize
|
|
||||||
// contentBoxSize
|
|
||||||
// devicePixelContentBoxSize
|
|
||||||
}
|
|
||||||
|
|
||||||
@JS()
|
|
||||||
@staticInterop
|
|
||||||
class DomRectReadOnly {}
|
|
||||||
|
|
||||||
extension DomRectReadOnlyExtension on DomRectReadOnly {
|
|
||||||
external double get x;
|
|
||||||
external double get y;
|
|
||||||
external double get width;
|
|
||||||
external double get height;
|
|
||||||
external double get top;
|
|
||||||
external double get right;
|
|
||||||
external double get bottom;
|
|
||||||
external double get left;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object? domGetConstructor(String constructorName) =>
|
|
||||||
js_util.getProperty(domWindow, constructorName);
|
|
||||||
|
|
||||||
T? domCallConstructorString<T>(String constructorName, List<Object?> args) {
|
|
||||||
final Object? constructor = domGetConstructor(constructorName);
|
|
||||||
if (constructor == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return js_util.callConstructor<T>(constructor, args);
|
|
||||||
}
|
|
@ -1,11 +1,11 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
import 'dart:js_interop';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:web/web.dart' as web;
|
||||||
import 'dom.dart';
|
|
||||||
|
|
||||||
/// An HTMLElementView widget that resizes with its contents.
|
/// An HTMLElementView widget that resizes with its contents.
|
||||||
class FlexHtmlElementView extends StatefulWidget {
|
class FlexHtmlElementView extends StatefulWidget {
|
||||||
@ -37,12 +37,12 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
|
|||||||
/// Watches for changes being made to the DOM tree.
|
/// Watches for changes being made to the DOM tree.
|
||||||
///
|
///
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
|
/// See: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
|
||||||
DomMutationObserver? _mutationObserver;
|
web.MutationObserver? _mutationObserver;
|
||||||
|
|
||||||
/// Reports changes to the dimensions of an Element's content box.
|
/// Reports changes to the dimensions of an Element's content box.
|
||||||
///
|
///
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API
|
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API
|
||||||
DomResizeObserver? _resizeObserver;
|
web.ResizeObserver? _resizeObserver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -55,8 +55,13 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
|
|||||||
/// Update the state with the new `size`, if needed.
|
/// Update the state with the new `size`, if needed.
|
||||||
void _doResize(Size size) {
|
void _doResize(Size size) {
|
||||||
if (size != _lastReportedSize) {
|
if (size != _lastReportedSize) {
|
||||||
domConsole.debug(
|
final String log = <Object?>[
|
||||||
'Resizing', <Object>[widget.viewType, size.width, size.height]);
|
'Resizing: ',
|
||||||
|
widget.viewType,
|
||||||
|
size.width,
|
||||||
|
size.height
|
||||||
|
].join(' ');
|
||||||
|
web.console.debug(log.toJS);
|
||||||
setState(() {
|
setState(() {
|
||||||
_lastReportedSize = size;
|
_lastReportedSize = size;
|
||||||
});
|
});
|
||||||
@ -65,12 +70,13 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
|
|||||||
|
|
||||||
/// The function called whenever an observed resize occurs.
|
/// The function called whenever an observed resize occurs.
|
||||||
void _onResizeEntries(
|
void _onResizeEntries(
|
||||||
List<DomResizeObserverEntry> resizes,
|
JSArray resizes,
|
||||||
DomResizeObserver observer,
|
web.ResizeObserver observer,
|
||||||
) {
|
) {
|
||||||
final DomRectReadOnly rect = resizes.last.contentRect;
|
final web.DOMRectReadOnly rect =
|
||||||
|
resizes.toDart.cast<web.ResizeObserverEntry>().last.contentRect;
|
||||||
if (rect.width > 0 && rect.height > 0) {
|
if (rect.width > 0 && rect.height > 0) {
|
||||||
_doResize(Size(rect.width, rect.height));
|
_doResize(Size(rect.width.toDouble(), rect.height.toDouble()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,31 +85,35 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
|
|||||||
/// When mutations are received, this function attaches a Resize Observer to
|
/// When mutations are received, this function attaches a Resize Observer to
|
||||||
/// the first child of the mutation, which will drive
|
/// the first child of the mutation, which will drive
|
||||||
void _onMutationRecords(
|
void _onMutationRecords(
|
||||||
List<DomMutationRecord> mutations,
|
JSArray mutations,
|
||||||
DomMutationObserver observer,
|
web.MutationObserver observer,
|
||||||
) {
|
) {
|
||||||
for (final DomMutationRecord mutation in mutations) {
|
mutations.toDart
|
||||||
if (mutation.addedNodes != null) {
|
.cast<web.MutationRecord>()
|
||||||
final DomElement? element = _locateSizeProvider(mutation.addedNodes!);
|
.forEach((web.MutationRecord mutation) {
|
||||||
|
if (mutation.addedNodes.length > 0) {
|
||||||
|
final web.Element? element = _locateSizeProvider(mutation.addedNodes);
|
||||||
if (element != null) {
|
if (element != null) {
|
||||||
_resizeObserver = createDomResizeObserver(_onResizeEntries);
|
_resizeObserver = web.ResizeObserver(_onResizeEntries.toJS);
|
||||||
_resizeObserver?.observe(element);
|
_resizeObserver?.observe(element);
|
||||||
// Stop looking at other mutations
|
// Stop looking at other mutations
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers a MutationObserver on the root element of the HtmlElementView.
|
/// Registers a MutationObserver on the root element of the HtmlElementView.
|
||||||
void _registerListeners(DomElement? root) {
|
void _registerListeners(web.Element? root) {
|
||||||
assert(root != null, 'DOM is not ready for the FlexHtmlElementView');
|
assert(root != null, 'DOM is not ready for the FlexHtmlElementView');
|
||||||
_mutationObserver = createDomMutationObserver(_onMutationRecords);
|
_mutationObserver = web.MutationObserver(_onMutationRecords.toJS);
|
||||||
// Monitor the size of the child element, whenever it's created...
|
// Monitor the size of the child element, whenever it's created...
|
||||||
_mutationObserver!.observe(
|
_mutationObserver!.observe(
|
||||||
root!,
|
root!,
|
||||||
childList: true,
|
web.MutationObserverInit(
|
||||||
|
childList: true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,14 +137,14 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
|
|||||||
///
|
///
|
||||||
/// The `elements` list should contain a single element: the only child of the
|
/// The `elements` list should contain a single element: the only child of the
|
||||||
/// element returned by `_locatePlatformViewRoot`.
|
/// element returned by `_locatePlatformViewRoot`.
|
||||||
DomElement? _locateSizeProvider(List<DomElement> elements) {
|
web.Element? _locateSizeProvider(web.NodeList elements) {
|
||||||
return elements.first;
|
return elements.item(0) as web.Element?;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the root element of a platform view by its `viewId`.
|
/// Finds the root element of a platform view by its `viewId`.
|
||||||
///
|
///
|
||||||
/// This element matches the one returned by the registered platform view factory.
|
/// This element matches the one returned by the registered platform view factory.
|
||||||
DomElement? _locatePlatformViewRoot(int viewId) {
|
web.Element? _locatePlatformViewRoot(int viewId) {
|
||||||
return domDocument
|
return web.document
|
||||||
.querySelector('flt-platform-view[slot\$="-$viewId"] :first-child');
|
.querySelector('flt-platform-view[slot\$="-$viewId"] :first-child');
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,16 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:js_interop';
|
||||||
|
|
||||||
// TODO(dit): Split `id` and `oauth2` "services" for mocking. https://github.com/flutter/flutter/issues/120657
|
// TODO(dit): Split `id` and `oauth2` "services" for mocking. https://github.com/flutter/flutter/issues/120657
|
||||||
import 'package:google_identity_services_web/id.dart';
|
import 'package:google_identity_services_web/id.dart';
|
||||||
import 'package:google_identity_services_web/oauth2.dart';
|
import 'package:google_identity_services_web/oauth2.dart';
|
||||||
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
||||||
// ignore: unnecessary_import
|
import 'package:web/web.dart' as web;
|
||||||
import 'package:js/js.dart';
|
|
||||||
import 'package:js/js_util.dart';
|
|
||||||
|
|
||||||
import 'button_configuration.dart'
|
import 'button_configuration.dart'
|
||||||
show GSIButtonConfiguration, convertButtonConfiguration;
|
show GSIButtonConfiguration, convertButtonConfiguration;
|
||||||
import 'dom.dart';
|
|
||||||
import 'people.dart' as people;
|
import 'people.dart' as people;
|
||||||
import 'utils.dart' as utils;
|
import 'utils.dart' as utils;
|
||||||
|
|
||||||
@ -65,7 +63,9 @@ class GisSdkClient {
|
|||||||
|
|
||||||
void _logIfEnabled(String message, [List<Object?>? more]) {
|
void _logIfEnabled(String message, [List<Object?>? more]) {
|
||||||
if (_loggingEnabled) {
|
if (_loggingEnabled) {
|
||||||
domConsole.info('[google_sign_in_web] $message', more);
|
final String log =
|
||||||
|
<Object?>['[google_sign_in_web]', message, ...?more].join(' ');
|
||||||
|
web.console.info(log.toJS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ class GisSdkClient {
|
|||||||
_tokenResponses.stream.listen((TokenResponse response) {
|
_tokenResponses.stream.listen((TokenResponse response) {
|
||||||
_lastTokenResponse = response;
|
_lastTokenResponse = response;
|
||||||
_lastTokenResponseExpiration =
|
_lastTokenResponseExpiration =
|
||||||
DateTime.now().add(Duration(seconds: response.expires_in));
|
DateTime.now().add(Duration(seconds: response.expires_in!));
|
||||||
}, onError: (Object error) {
|
}, onError: (Object error) {
|
||||||
_logIfEnabled('Error on TokenResponse:', <Object>[error.toString()]);
|
_logIfEnabled('Error on TokenResponse:', <Object>[error.toString()]);
|
||||||
_lastTokenResponse = null;
|
_lastTokenResponse = null;
|
||||||
@ -130,7 +130,7 @@ class GisSdkClient {
|
|||||||
// Initialize `id` for the silent-sign in code.
|
// Initialize `id` for the silent-sign in code.
|
||||||
final IdConfiguration idConfig = IdConfiguration(
|
final IdConfiguration idConfig = IdConfiguration(
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
callback: allowInterop(onResponse),
|
callback: onResponse,
|
||||||
cancel_on_tap_outside: false,
|
cancel_on_tap_outside: false,
|
||||||
auto_select: true, // Attempt to sign-in silently.
|
auto_select: true, // Attempt to sign-in silently.
|
||||||
hd: hostedDomain,
|
hd: hostedDomain,
|
||||||
@ -161,12 +161,14 @@ class GisSdkClient {
|
|||||||
// Create a Token Client for authorization calls.
|
// Create a Token Client for authorization calls.
|
||||||
final TokenClientConfig tokenConfig = TokenClientConfig(
|
final TokenClientConfig tokenConfig = TokenClientConfig(
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
hosted_domain: hostedDomain,
|
hd: hostedDomain,
|
||||||
callback: allowInterop(_onTokenResponse),
|
callback: _onTokenResponse,
|
||||||
error_callback: allowInterop(_onTokenError),
|
error_callback: _onTokenError,
|
||||||
// `scope` will be modified by the `signIn` method, in case we need to
|
// This is here only to satisfy the initialization of the JS TokenClient.
|
||||||
// backfill user Profile info.
|
// In reality, `scope` is always overridden when calling `requestScopes`
|
||||||
scope: ' ',
|
// (or the deprecated `signIn`) through an [OverridableTokenClientConfig]
|
||||||
|
// object.
|
||||||
|
scope: <String>[' '], // Fake (but non-empty) list of scopes.
|
||||||
);
|
);
|
||||||
return oauth2.initTokenClient(tokenConfig);
|
return oauth2.initTokenClient(tokenConfig);
|
||||||
}
|
}
|
||||||
@ -187,9 +189,9 @@ class GisSdkClient {
|
|||||||
// Token clients have an additional `error_callback` for miscellaneous
|
// Token clients have an additional `error_callback` for miscellaneous
|
||||||
// errors, like "popup couldn't open" or "popup closed by user".
|
// errors, like "popup couldn't open" or "popup closed by user".
|
||||||
void _onTokenError(Object? error) {
|
void _onTokenError(Object? error) {
|
||||||
// This is handled in a funky (js_interop) way because of:
|
if (error != null) {
|
||||||
// https://github.com/dart-lang/sdk/issues/50899
|
_tokenResponses.addError((error as GoogleIdentityServicesError).type);
|
||||||
_tokenResponses.addError(getProperty(error!, 'type'));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a `oauth2.CodeClient` used for authorization (scope) requests.
|
// Creates a `oauth2.CodeClient` used for authorization (scope) requests.
|
||||||
@ -203,10 +205,10 @@ class GisSdkClient {
|
|||||||
// Create a Token Client for authorization calls.
|
// Create a Token Client for authorization calls.
|
||||||
final CodeClientConfig codeConfig = CodeClientConfig(
|
final CodeClientConfig codeConfig = CodeClientConfig(
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
hosted_domain: hostedDomain,
|
hd: hostedDomain,
|
||||||
callback: allowInterop(_onCodeResponse),
|
callback: _onCodeResponse,
|
||||||
error_callback: allowInterop(_onCodeError),
|
error_callback: _onCodeError,
|
||||||
scope: scopes.join(' '),
|
scope: scopes,
|
||||||
select_account: true,
|
select_account: true,
|
||||||
ux_mode: UxMode.popup,
|
ux_mode: UxMode.popup,
|
||||||
);
|
);
|
||||||
@ -222,7 +224,9 @@ class GisSdkClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onCodeError(Object? error) {
|
void _onCodeError(Object? error) {
|
||||||
_codeResponses.addError(getProperty(error!, 'type'));
|
if (error != null) {
|
||||||
|
_codeResponses.addError((error as GoogleIdentityServicesError).type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to sign-in the user using the OneTap UX flow.
|
/// Attempts to sign-in the user using the OneTap UX flow.
|
||||||
@ -238,9 +242,9 @@ class GisSdkClient {
|
|||||||
// Ask the SDK to render the OneClick sign-in.
|
// Ask the SDK to render the OneClick sign-in.
|
||||||
//
|
//
|
||||||
// And also handle its "moments".
|
// And also handle its "moments".
|
||||||
id.prompt(allowInterop((PromptMomentNotification moment) {
|
id.prompt((PromptMomentNotification moment) {
|
||||||
_onPromptMoment(moment, userDataCompleter);
|
_onPromptMoment(moment, userDataCompleter);
|
||||||
}));
|
});
|
||||||
|
|
||||||
return userDataCompleter.future;
|
return userDataCompleter.future;
|
||||||
}
|
}
|
||||||
@ -287,7 +291,7 @@ class GisSdkClient {
|
|||||||
Object parent,
|
Object parent,
|
||||||
GSIButtonConfiguration options,
|
GSIButtonConfiguration options,
|
||||||
) async {
|
) async {
|
||||||
return id.renderButton(parent, convertButtonConfiguration(options)!);
|
return id.renderButton(parent, convertButtonConfiguration(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Requests a server auth code per:
|
/// Requests a server auth code per:
|
||||||
@ -318,11 +322,10 @@ class GisSdkClient {
|
|||||||
'Use `renderButton` instead. See: https://pub.dev/packages/google_sign_in_web#migrating-to-v011-and-v012-google-identity-services')
|
'Use `renderButton` instead. See: https://pub.dev/packages/google_sign_in_web#migrating-to-v011-and-v012-google-identity-services')
|
||||||
Future<GoogleSignInUserData?> signIn() async {
|
Future<GoogleSignInUserData?> signIn() async {
|
||||||
// Warn users that this method will be removed.
|
// Warn users that this method will be removed.
|
||||||
domConsole.warn(
|
web.console.warn(
|
||||||
'The google_sign_in plugin `signIn` method is deprecated on the web, and will be removed in Q2 2024. Please use `renderButton` instead. See: ',
|
'The google_sign_in plugin `signIn` method is deprecated on the web, and will be removed in Q2 2024. Please use `renderButton` instead. See: '
|
||||||
<String>[
|
'https://pub.dev/packages/google_sign_in_web#migrating-to-v011-and-v012-google-identity-services'
|
||||||
'https://pub.dev/packages/google_sign_in_web#migrating-to-v011-and-v012-google-identity-services'
|
.toJS);
|
||||||
]);
|
|
||||||
// If we already know the user, use their `email` as a `hint`, so they don't
|
// If we already know the user, use their `email` as a `hint`, so they don't
|
||||||
// have to pick their user again in the Authorization popup.
|
// have to pick their user again in the Authorization popup.
|
||||||
final GoogleSignInUserData? knownUser =
|
final GoogleSignInUserData? knownUser =
|
||||||
@ -331,14 +334,14 @@ class GisSdkClient {
|
|||||||
// user activation.
|
// user activation.
|
||||||
_tokenClient.requestAccessToken(OverridableTokenClientConfig(
|
_tokenClient.requestAccessToken(OverridableTokenClientConfig(
|
||||||
prompt: knownUser == null ? 'select_account' : '',
|
prompt: knownUser == null ? 'select_account' : '',
|
||||||
hint: knownUser?.email,
|
login_hint: knownUser?.email,
|
||||||
scope: <String>[
|
scope: <String>[
|
||||||
..._initialScopes,
|
..._initialScopes,
|
||||||
// If the user hasn't gone through the auth process,
|
// If the user hasn't gone through the auth process,
|
||||||
// the plugin will attempt to `requestUserData` after,
|
// the plugin will attempt to `requestUserData` after,
|
||||||
// so we need extra scopes to retrieve that info.
|
// so we need extra scopes to retrieve that info.
|
||||||
if (_lastCredentialResponse == null) ...people.scopes,
|
if (_lastCredentialResponse == null) ...people.scopes,
|
||||||
].join(' '),
|
],
|
||||||
));
|
));
|
||||||
|
|
||||||
await _tokenResponses.stream.first;
|
await _tokenResponses.stream.first;
|
||||||
@ -384,7 +387,7 @@ class GisSdkClient {
|
|||||||
/// Revokes the current authorization and authentication.
|
/// Revokes the current authorization and authentication.
|
||||||
Future<void> disconnect() async {
|
Future<void> disconnect() async {
|
||||||
if (_lastTokenResponse != null) {
|
if (_lastTokenResponse != null) {
|
||||||
oauth2.revoke(_lastTokenResponse!.access_token);
|
oauth2.revoke(_lastTokenResponse!.access_token!);
|
||||||
}
|
}
|
||||||
await signOut();
|
await signOut();
|
||||||
}
|
}
|
||||||
@ -431,8 +434,8 @@ class GisSdkClient {
|
|||||||
|
|
||||||
_tokenClient.requestAccessToken(OverridableTokenClientConfig(
|
_tokenClient.requestAccessToken(OverridableTokenClientConfig(
|
||||||
prompt: knownUser == null ? 'select_account' : '',
|
prompt: knownUser == null ? 'select_account' : '',
|
||||||
hint: knownUser?.email,
|
login_hint: knownUser?.email,
|
||||||
scope: scopes.join(' '),
|
scope: scopes,
|
||||||
include_granted_scopes: true,
|
include_granted_scopes: true,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@ description: Flutter plugin for Google Sign-In, a secure authentication system
|
|||||||
for signing in with a Google account on Android, iOS and Web.
|
for signing in with a Google account on Android, iOS and Web.
|
||||||
repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_web
|
repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_web
|
||||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22
|
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22
|
||||||
version: 0.12.2+1
|
version: 0.12.3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.1.0 <4.0.0"
|
sdk: ">=3.2.0 <4.0.0"
|
||||||
flutter: ">=3.13.0"
|
flutter: ">=3.16.0"
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
plugin:
|
plugin:
|
||||||
@ -22,10 +22,10 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
google_identity_services_web: ^0.2.2
|
google_identity_services_web: ^0.3.0
|
||||||
google_sign_in_platform_interface: ^2.4.0
|
google_sign_in_platform_interface: ^2.4.0
|
||||||
http: ">=0.13.0 <2.0.0"
|
http: ">=0.13.0 <2.0.0"
|
||||||
js: ^0.6.3
|
web: ">=0.3.0 <0.5.0"
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -9,8 +9,5 @@
|
|||||||
# NOTE: camera_android is semi-excluded via special casing in the repo tools.
|
# NOTE: camera_android is semi-excluded via special casing in the repo tools.
|
||||||
# See create_all_packages_app_command.dart.
|
# See create_all_packages_app_command.dart.
|
||||||
|
|
||||||
# Excluded until the google_sign_in_web package updates
|
|
||||||
- google_identity_services_web
|
|
||||||
|
|
||||||
# This is a permament entry, as it should never be a direct app dependency.
|
# This is a permament entry, as it should never be a direct app dependency.
|
||||||
- plugin_platform_interface
|
- plugin_platform_interface
|
||||||
|
Reference in New Issue
Block a user