initial implementation 6.0.0-beta.9
This commit is contained in:
parent
4973770c1c
commit
ebea457b01
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,3 +1,19 @@
|
|||
## 6.0.0-beta.9
|
||||
|
||||
- Added `headers`, `otherLikelyURLs` arguments on `ChromeSafariBrowser.open` method for Android
|
||||
- Added `onNavigationEvent`, `onServiceConnected`, `onRelationshipValidationResult` events on `ChromeSafariBrowser` for Android
|
||||
- Added `mayLaunchUrl`, `launchUrl`, `updateActionButton`, `validateRelationship` methods on `ChromeSafariBrowser` for Android
|
||||
- Added `didLoadSuccessfully` optional argument on `ChromeSafariBrowser.onCompletedInitialLoad` event for iOS
|
||||
- Added `onInitialLoadDidRedirect`, `onWillOpenInBrowser` events on `ChromeSafariBrowser` for iOS
|
||||
- Added `clearWebsiteData`, `prewarmConnections`, `invalidatePrewarmingToken` static methods on `ChromeSafariBrowser` for iOS
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- `ChromeSafariBrowser.onCompletedInitialLoad` event has an optional argument
|
||||
|
||||
## 6.0.0-beta.8
|
||||
|
||||
|
||||
## 6.0.0-beta.7
|
||||
|
||||
- Updated Android hybrid composition implementation
|
||||
|
|
|
@ -5,11 +5,6 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class ActionBroadcastReceiver extends BroadcastReceiver {
|
||||
protected static final String LOG_TAG = "ActionBroadcastReceiver";
|
||||
public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID";
|
||||
|
@ -27,7 +22,7 @@ public class ActionBroadcastReceiver extends BroadcastReceiver {
|
|||
|
||||
ChromeCustomTabsActivity browser = ChromeSafariBrowserManager.browsers.get(viewId);
|
||||
if (browser != null && browser.channelDelegate != null) {
|
||||
browser.channelDelegate.onChromeSafariBrowserItemActionPerform(id, url, title);
|
||||
browser.channelDelegate.onItemActionPerform(id, url, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.os.Bundle;
|
|||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
||||
import androidx.browser.customtabs.CustomTabsCallback;
|
||||
|
@ -20,7 +21,6 @@ import androidx.browser.customtabs.CustomTabsService;
|
|||
import androidx.browser.customtabs.CustomTabsSession;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebViewManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.CustomTabsActionButton;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.CustomTabsMenuItem;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
|
||||
|
@ -44,11 +44,16 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
@Nullable
|
||||
public CustomTabsSession customTabsSession;
|
||||
protected final int CHROME_CUSTOM_TAB_REQUEST_CODE = 100;
|
||||
protected boolean onChromeSafariBrowserOpened = false;
|
||||
protected boolean onChromeSafariBrowserCompletedInitialLoad = false;
|
||||
protected boolean onOpened = false;
|
||||
protected boolean onCompletedInitialLoad = false;
|
||||
@Nullable
|
||||
public ChromeSafariBrowserManager manager;
|
||||
@Nullable
|
||||
public String initialUrl;
|
||||
@Nullable
|
||||
public List<String> initialOtherLikelyURLs;
|
||||
@Nullable
|
||||
public Map<String, String> initialHeaders;
|
||||
public List<CustomTabsMenuItem> menuItems = new ArrayList<>();
|
||||
@Nullable
|
||||
public CustomTabsActionButton actionButton;
|
||||
|
@ -69,7 +74,7 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
|
||||
String managerId = b.getString("managerId");
|
||||
manager = ChromeSafariBrowserManager.shared.get(managerId);
|
||||
if (manager == null || manager.plugin == null|| manager.plugin.messenger == null) return;
|
||||
if (manager == null || manager.plugin == null || manager.plugin.messenger == null) return;
|
||||
|
||||
ChromeSafariBrowserManager.browsers.put(id, this);
|
||||
|
||||
|
@ -77,6 +82,8 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
channelDelegate = new ChromeCustomTabsChannelDelegate(this, channel);
|
||||
|
||||
initialUrl = b.getString("url");
|
||||
initialHeaders = (Map<String, String>) b.getSerializable("headers");
|
||||
initialOtherLikelyURLs = b.getStringArrayList("otherLikelyURLs");
|
||||
|
||||
customSettings = new ChromeCustomTabsSettings();
|
||||
customSettings.parse((HashMap<String, Object>) b.getSerializable("settings"));
|
||||
|
@ -92,6 +99,9 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
@Override
|
||||
public void onCustomTabsConnected() {
|
||||
customTabsConnected();
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.onServiceConnected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,49 +114,49 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
customTabActivityHelper.setCustomTabsCallback(new CustomTabsCallback() {
|
||||
@Override
|
||||
public void onNavigationEvent(int navigationEvent, Bundle extras) {
|
||||
if (navigationEvent == TAB_SHOWN && !onChromeSafariBrowserOpened) {
|
||||
onChromeSafariBrowserOpened = true;
|
||||
if (navigationEvent == TAB_SHOWN && !onOpened) {
|
||||
onOpened = true;
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.onChromeSafariBrowserOpened();
|
||||
channelDelegate.onOpened();
|
||||
}
|
||||
}
|
||||
|
||||
if (navigationEvent == NAVIGATION_FINISHED && !onChromeSafariBrowserCompletedInitialLoad) {
|
||||
onChromeSafariBrowserCompletedInitialLoad = true;
|
||||
if (navigationEvent == NAVIGATION_FINISHED && !onCompletedInitialLoad) {
|
||||
onCompletedInitialLoad = true;
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.onChromeSafariBrowserCompletedInitialLoad();
|
||||
channelDelegate.onCompletedInitialLoad();
|
||||
}
|
||||
}
|
||||
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.onNavigationEvent(navigationEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extraCallback(String callbackName, Bundle args) {
|
||||
|
||||
}
|
||||
public void extraCallback(@NonNull String callbackName, Bundle args) {}
|
||||
|
||||
@Override
|
||||
public void onMessageChannelReady(Bundle extras) {
|
||||
|
||||
}
|
||||
public void onMessageChannelReady(Bundle extras) {}
|
||||
|
||||
@Override
|
||||
public void onPostMessage(String message, Bundle extras) {
|
||||
|
||||
}
|
||||
public void onPostMessage(@NonNull String message, Bundle extras) {}
|
||||
|
||||
@Override
|
||||
public void onRelationshipValidationResult(@CustomTabsService.Relation int relation, Uri requestedOrigin,
|
||||
public void onRelationshipValidationResult(@CustomTabsService.Relation int relation,
|
||||
@NonNull Uri requestedOrigin,
|
||||
boolean result, Bundle extras) {
|
||||
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.onRelationshipValidationResult(relation, requestedOrigin, result);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void customTabsConnected() {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
Uri uri = Uri.parse(initialUrl);
|
||||
customTabActivityHelper.mayLaunchUrl(uri, null, null);
|
||||
|
||||
public void launchUrl(@NonNull String url,
|
||||
@Nullable Map<String, String> headers,
|
||||
@Nullable List<String> otherLikelyURLs) {
|
||||
Uri uri = mayLaunchUrl(url, headers, otherLikelyURLs);
|
||||
builder = new CustomTabsIntent.Builder(customTabsSession);
|
||||
prepareCustomTabs();
|
||||
|
||||
|
@ -156,7 +166,39 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
CustomTabActivityHelper.openCustomTab(this, customTabsIntent, uri, CHROME_CUSTOM_TAB_REQUEST_CODE);
|
||||
}
|
||||
|
||||
public Uri mayLaunchUrl(@NonNull String url,
|
||||
@Nullable Map<String, String> headers,
|
||||
@Nullable List<String> otherLikelyURLs) {
|
||||
Uri uri = Uri.parse(url);
|
||||
Bundle bundleHeaders = new Bundle();
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
bundleHeaders.putString(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
List<Bundle> bundleOtherLikelyURLs = new ArrayList<>();
|
||||
if (otherLikelyURLs != null) {
|
||||
for (String otherLikelyURL : otherLikelyURLs) {
|
||||
Bundle bundleOtherLikelyURL = new Bundle();
|
||||
bundleOtherLikelyURL.putString(CustomTabsService.KEY_URL, otherLikelyURL);
|
||||
}
|
||||
}
|
||||
customTabActivityHelper.mayLaunchUrl(uri, bundleHeaders, bundleOtherLikelyURLs);
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void customTabsConnected() {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
if (initialUrl != null) {
|
||||
launchUrl(initialUrl, initialHeaders, initialOtherLikelyURLs);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareCustomTabs() {
|
||||
if (builder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (customSettings.addDefaultShareMenuItem != null) {
|
||||
builder.setShareState(customSettings.addDefaultShareMenuItem ?
|
||||
CustomTabsIntent.SHARE_STATE_ON : CustomTabsIntent.SHARE_STATE_OFF);
|
||||
|
@ -203,6 +245,20 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
CustomTabsHelper.addKeepAliveExtra(this, customTabsIntent.intent);
|
||||
}
|
||||
|
||||
public void updateActionButton(@NonNull byte[] icon, @NonNull String description) {
|
||||
if (customTabsSession == null || actionButton == null) {
|
||||
return;
|
||||
}
|
||||
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
|
||||
bitmapOptions.inMutable = true;
|
||||
Bitmap bmp = BitmapFactory.decodeByteArray(
|
||||
icon, 0, icon.length, bitmapOptions
|
||||
);
|
||||
customTabsSession.setActionButton(bmp, description);
|
||||
actionButton.setIcon(icon);
|
||||
actionButton.setDescription(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
@ -265,7 +321,7 @@ public class ChromeCustomTabsActivity extends Activity implements Disposable {
|
|||
customTabsSession = null;
|
||||
finish();
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.onChromeSafariBrowserClosed();
|
||||
channelDelegate.onClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.CustomTabsActionButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
|
@ -28,6 +30,56 @@ public class ChromeCustomTabsChannelDelegate extends ChannelDelegateImpl {
|
|||
@Override
|
||||
public void onMethodCall(@NonNull final MethodCall call, @NonNull final MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
case "launchUrl":
|
||||
if (chromeCustomTabsActivity != null) {
|
||||
String url = (String) call.argument("url");
|
||||
if (url != null) {
|
||||
Map<String, String> headers = (Map<String, String>) call.argument("headers");
|
||||
List<String> otherLikelyURLs = (List<String>) call.argument("otherLikelyURLs");
|
||||
chromeCustomTabsActivity.launchUrl(url, headers, otherLikelyURLs);
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "mayLaunchUrl":
|
||||
if (chromeCustomTabsActivity != null) {
|
||||
String url = (String) call.argument("url");
|
||||
if (url != null) {
|
||||
Map<String, String> headers = (Map<String, String>) call.argument("headers");
|
||||
List<String> otherLikelyURLs = (List<String>) call.argument("otherLikelyURLs");
|
||||
chromeCustomTabsActivity.mayLaunchUrl(url, headers, otherLikelyURLs);
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "updateActionButton":
|
||||
if (chromeCustomTabsActivity != null) {
|
||||
byte[] icon = (byte[]) call.argument("icon");
|
||||
String description = (String) call.argument("description");
|
||||
chromeCustomTabsActivity.updateActionButton(icon, description);
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "validateRelationship":
|
||||
if (chromeCustomTabsActivity != null && chromeCustomTabsActivity.customTabsSession != null) {
|
||||
Integer relation = (Integer) call.argument("relation");
|
||||
String origin = (String) call.argument("origin");
|
||||
chromeCustomTabsActivity.customTabsSession.validateRelationship(relation, Uri.parse(origin), null);
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "close":
|
||||
if (chromeCustomTabsActivity != null) {
|
||||
chromeCustomTabsActivity.onStop();
|
||||
|
@ -54,35 +106,60 @@ public class ChromeCustomTabsChannelDelegate extends ChannelDelegateImpl {
|
|||
}
|
||||
}
|
||||
|
||||
public void onChromeSafariBrowserOpened() {
|
||||
public void onServiceConnected() {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
channel.invokeMethod("onChromeSafariBrowserOpened", obj);
|
||||
channel.invokeMethod("onServiceConnected", obj);
|
||||
}
|
||||
|
||||
public void onChromeSafariBrowserCompletedInitialLoad() {
|
||||
public void onOpened() {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
channel.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", obj);
|
||||
channel.invokeMethod("onOpened", obj);
|
||||
}
|
||||
|
||||
public void onChromeSafariBrowserClosed() {
|
||||
public void onCompletedInitialLoad() {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
channel.invokeMethod("onChromeSafariBrowserClosed", obj);
|
||||
channel.invokeMethod("onCompletedInitialLoad", obj);
|
||||
}
|
||||
|
||||
public void onChromeSafariBrowserItemActionPerform(int id, String url, String title) {
|
||||
public void onNavigationEvent(int navigationEvent) {;
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("navigationEvent", navigationEvent);
|
||||
channel.invokeMethod("onNavigationEvent", obj);
|
||||
}
|
||||
|
||||
public void onClosed() {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
channel.invokeMethod("onClosed", obj);
|
||||
}
|
||||
|
||||
public void onItemActionPerform(int id, String url, String title) {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("id", id);
|
||||
obj.put("url", url);
|
||||
obj.put("title", title);
|
||||
channel.invokeMethod("onChromeSafariBrowserItemActionPerform", obj);
|
||||
channel.invokeMethod("onItemActionPerform", obj);
|
||||
}
|
||||
|
||||
public void onRelationshipValidationResult(int relation, @NonNull Uri requestedOrigin, boolean result) {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) return;
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("relation", relation);
|
||||
obj.put("requestedOrigin", requestedOrigin.toString());
|
||||
obj.put("result", result);
|
||||
channel.invokeMethod("onRelationshipValidationResult", obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -92,8 +92,10 @@ public class ChromeCustomTabsSettings implements ISettings<ChromeCustomTabsActiv
|
|||
boolean isSticky = (boolean) displayModeMap.get("isSticky");
|
||||
int layoutInDisplayCutoutMode = (int) displayModeMap.get("displayCutoutMode");
|
||||
displayMode = new TrustedWebActivityDisplayMode.ImmersiveMode(isSticky, layoutInDisplayCutoutMode);
|
||||
break;
|
||||
case "DEFAULT_MODE":
|
||||
displayMode = new TrustedWebActivityDisplayMode.DefaultMode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.Headless
|
|||
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -46,10 +47,12 @@ public class ChromeSafariBrowserManager extends ChannelDelegateImpl {
|
|||
case "open":
|
||||
if (plugin != null && plugin.activity != null) {
|
||||
String url = (String) call.argument("url");
|
||||
HashMap<String, Object> headers = (HashMap<String, Object>) call.argument("headers");
|
||||
ArrayList<String> otherLikelyURLs = (ArrayList<String>) call.argument("otherLikelyURLs");
|
||||
HashMap<String, Object> settings = (HashMap<String, Object>) call.argument("settings");
|
||||
HashMap<String, Object> actionButton = (HashMap<String, Object>) call.argument("actionButton");
|
||||
List<HashMap<String, Object>> menuItemList = (List<HashMap<String, Object>>) call.argument("menuItemList");
|
||||
open(plugin.activity, viewId, url, settings, actionButton, menuItemList, result);
|
||||
open(plugin.activity, viewId, url, headers, otherLikelyURLs, settings, actionButton, menuItemList, result);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
|
@ -66,8 +69,9 @@ public class ChromeSafariBrowserManager extends ChannelDelegateImpl {
|
|||
}
|
||||
}
|
||||
|
||||
public void open(Activity activity, String viewId, String url, HashMap<String, Object> settings,
|
||||
HashMap<String, Object> actionButton,
|
||||
public void open(Activity activity, String viewId, @Nullable String url, @Nullable HashMap<String, Object> headers,
|
||||
@Nullable ArrayList<String> otherLikelyURLs,
|
||||
HashMap<String, Object> settings, HashMap<String, Object> actionButton,
|
||||
List<HashMap<String, Object>> menuItemList, MethodChannel.Result result) {
|
||||
|
||||
Intent intent = null;
|
||||
|
@ -76,6 +80,8 @@ public class ChromeSafariBrowserManager extends ChannelDelegateImpl {
|
|||
extras.putBoolean("isData", false);
|
||||
extras.putString("id", viewId);
|
||||
extras.putString("managerId", this.id);
|
||||
extras.putSerializable("headers", headers);
|
||||
extras.putSerializable("otherLikelyURLs", otherLikelyURLs);
|
||||
extras.putSerializable("settings", settings);
|
||||
extras.putSerializable("actionButton", (Serializable) actionButton);
|
||||
extras.putSerializable("menuItemList", (Serializable) menuItemList);
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.pm.PackageManager;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.browser.customtabs.CustomTabsCallback;
|
||||
import androidx.browser.customtabs.CustomTabsClient;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
|
@ -68,6 +69,7 @@ public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
|||
*
|
||||
* @return a CustomTabsSession.
|
||||
*/
|
||||
@Nullable
|
||||
public CustomTabsSession getSession() {
|
||||
if (mClient == null) {
|
||||
mCustomTabsSession = null;
|
||||
|
|
|
@ -3,13 +3,20 @@ package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
|||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.browser.customtabs.CustomTabsService;
|
||||
import androidx.browser.trusted.TrustedWebActivityIntent;
|
||||
import androidx.browser.trusted.TrustedWebActivityIntentBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TrustedWebActivity extends ChromeCustomTabsActivity {
|
||||
|
||||
|
@ -18,11 +25,14 @@ public class TrustedWebActivity extends ChromeCustomTabsActivity {
|
|||
public TrustedWebActivityIntentBuilder builder;
|
||||
|
||||
@Override
|
||||
public void customTabsConnected() {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
Uri uri = Uri.parse(initialUrl);
|
||||
customTabActivityHelper.mayLaunchUrl(uri, null, null);
|
||||
public void launchUrl(@NonNull String url,
|
||||
@Nullable Map<String, String> headers,
|
||||
@Nullable List<String> otherLikelyURLs) {
|
||||
if (customTabsSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = mayLaunchUrl(url, headers, otherLikelyURLs);
|
||||
builder = new TrustedWebActivityIntentBuilder(uri);
|
||||
prepareCustomTabs();
|
||||
|
||||
|
@ -32,6 +42,15 @@ public class TrustedWebActivity extends ChromeCustomTabsActivity {
|
|||
CustomTabActivityHelper.openCustomTab(this, trustedWebActivityIntent, uri, CHROME_CUSTOM_TAB_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customTabsConnected() {
|
||||
customTabsSession = customTabActivityHelper.getSession();
|
||||
if (initialUrl != null) {
|
||||
launchUrl(initialUrl, initialHeaders, initialOtherLikelyURLs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void prepareCustomTabs() {
|
||||
if (customSettings.toolbarBackgroundColor != null && !customSettings.toolbarBackgroundColor.isEmpty()) {
|
||||
CustomTabColorSchemeParams.Builder defaultColorSchemeBuilder = new CustomTabColorSchemeParams.Builder();
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/3.3.5"
|
||||
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
|
||||
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||
export "FLUTTER_TARGET=lib/main.dart"
|
||||
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
|
||||
export "FLUTTER_BUILD_DIR=build"
|
||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||
export "FLUTTER_BUILD_NUMBER=1"
|
||||
export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
||||
export "PACKAGE_CONFIG=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/.dart_tool/package_config.json"
|
||||
|
|
|
@ -11,7 +11,7 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser {
|
|||
}
|
||||
|
||||
@override
|
||||
void onCompletedInitialLoad() {
|
||||
void onCompletedInitialLoad(didLoadSuccessfully) {
|
||||
print("ChromeSafari browser initial load completed");
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
|||
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_chromesafaribrowser"
|
||||
static var registrar: FlutterPluginRegistrar?
|
||||
static var browsers: [String: SafariViewController?] = [:]
|
||||
@available(iOS 15.0, *)
|
||||
static var prewarmingTokens: [String: SFSafariViewController.PrewarmingToken?] = [:]
|
||||
|
||||
init(registrar: FlutterPluginRegistrar) {
|
||||
super.init(channel: FlutterMethodChannel(name: ChromeSafariBrowserManager.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
|
||||
|
@ -40,6 +42,44 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
|||
result(false)
|
||||
}
|
||||
break
|
||||
case "clearWebsiteData":
|
||||
if #available(iOS 16.0, *) {
|
||||
SFSafariViewController.DataStore.default.clearWebsiteData {
|
||||
result(true)
|
||||
}
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
case "prewarmConnections":
|
||||
if #available(iOS 15.0, *) {
|
||||
let stringURLs = arguments!["URLs"] as! [String]
|
||||
var URLs: [URL] = []
|
||||
for stringURL in stringURLs {
|
||||
if let url = URL(string: stringURL) {
|
||||
URLs.append(url)
|
||||
}
|
||||
}
|
||||
let prewarmingToken = SFSafariViewController.prewarmConnections(to: URLs)
|
||||
let prewarmingTokenId = NSUUID().uuidString
|
||||
ChromeSafariBrowserManager.prewarmingTokens[prewarmingTokenId] = prewarmingToken
|
||||
result([
|
||||
"id": prewarmingTokenId
|
||||
])
|
||||
} else {
|
||||
result(nil)
|
||||
}
|
||||
case "invalidatePrewarmingToken":
|
||||
if #available(iOS 15.0, *) {
|
||||
let prewarmingToken = arguments!["prewarmingToken"] as! [String:Any?]
|
||||
if let prewarmingTokenId = prewarmingToken["id"] as? String,
|
||||
let prewarmingToken = ChromeSafariBrowserManager.prewarmingTokens[prewarmingTokenId] {
|
||||
prewarmingToken?.invalidate()
|
||||
ChromeSafariBrowserManager.prewarmingTokens[prewarmingTokenId] = nil
|
||||
}
|
||||
result(true)
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
|
@ -95,6 +135,12 @@ public class ChromeSafariBrowserManager: ChannelDelegate {
|
|||
browser?.dispose()
|
||||
}
|
||||
ChromeSafariBrowserManager.browsers.removeAll()
|
||||
if #available(iOS 15.0, *) {
|
||||
ChromeSafariBrowserManager.prewarmingTokens.values.forEach { (prewarmingToken: SFSafariViewController.PrewarmingToken?) in
|
||||
prewarmingToken?.invalidate()
|
||||
}
|
||||
ChromeSafariBrowserManager.prewarmingTokens.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
|
@ -48,6 +48,6 @@ class CustomUIActivity : UIActivity {
|
|||
|
||||
override func perform() {
|
||||
let browser = ChromeSafariBrowserManager.browsers[viewId]
|
||||
browser??.channelDelegate?.onChromeSafariBrowserMenuItemActionPerform(id: id, url: url, title: title)
|
||||
browser??.channelDelegate?.onItemActionPerform(id: id, url: url, title: title)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,12 +42,12 @@ public class SafariViewController: SFSafariViewController, SFSafariViewControlle
|
|||
public override func viewWillAppear(_ animated: Bool) {
|
||||
// prepareSafariBrowser()
|
||||
super.viewWillAppear(animated)
|
||||
channelDelegate?.onChromeSafariBrowserOpened()
|
||||
channelDelegate?.onOpened()
|
||||
}
|
||||
|
||||
public override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
channelDelegate?.onChromeSafariBrowserClosed()
|
||||
channelDelegate?.onClosed()
|
||||
self.dispose()
|
||||
}
|
||||
|
||||
|
@ -87,12 +87,7 @@ public class SafariViewController: SFSafariViewController, SFSafariViewControlle
|
|||
|
||||
public func safariViewController(_ controller: SFSafariViewController,
|
||||
didCompleteInitialLoad didLoadSuccessfully: Bool) {
|
||||
if didLoadSuccessfully {
|
||||
channelDelegate?.onChromeSafariBrowserCompletedInitialLoad()
|
||||
}
|
||||
else {
|
||||
print("Cant load successfully the 'SafariViewController'.")
|
||||
}
|
||||
channelDelegate?.onCompletedInitialLoad(didLoadSuccessfully: didLoadSuccessfully)
|
||||
}
|
||||
|
||||
public func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] {
|
||||
|
@ -103,18 +98,14 @@ public class SafariViewController: SFSafariViewController, SFSafariViewControlle
|
|||
}
|
||||
return uiActivities
|
||||
}
|
||||
//
|
||||
// public func safariViewController(_ controller: SFSafariViewController, excludedActivityTypesFor URL: URL, title: String?) -> [UIActivity.ActivityType] {
|
||||
// print("excludedActivityTypesFor")
|
||||
// print(URL)
|
||||
// print(title)
|
||||
// return []
|
||||
// }
|
||||
//
|
||||
// public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL) {
|
||||
// print("initialLoadDidRedirectTo")
|
||||
// print(URL)
|
||||
// }
|
||||
|
||||
public func safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo url: URL) {
|
||||
channelDelegate?.onInitialLoadDidRedirect(url: url)
|
||||
}
|
||||
|
||||
public func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController) {
|
||||
channelDelegate?.onWillOpenInBrowser()
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
channelDelegate?.dispose()
|
||||
|
|
|
@ -31,28 +31,42 @@ public class SafariViewControllerChannelDelegate : ChannelDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
public func onChromeSafariBrowserOpened() {
|
||||
public func onOpened() {
|
||||
let arguments: [String: Any?] = [:]
|
||||
channel?.invokeMethod("onChromeSafariBrowserOpened", arguments: arguments)
|
||||
channel?.invokeMethod("onOpened", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onChromeSafariBrowserCompletedInitialLoad() {
|
||||
let arguments: [String: Any?] = [:]
|
||||
channel?.invokeMethod("onChromeSafariBrowserCompletedInitialLoad", arguments: arguments)
|
||||
public func onCompletedInitialLoad(didLoadSuccessfully: Bool) {
|
||||
let arguments: [String: Any?] = [
|
||||
"didLoadSuccessfully": didLoadSuccessfully
|
||||
]
|
||||
channel?.invokeMethod("onCompletedInitialLoad", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onChromeSafariBrowserClosed() {
|
||||
let arguments: [String: Any?] = [:]
|
||||
channel?.invokeMethod("onChromeSafariBrowserClosed", arguments: arguments)
|
||||
public func onInitialLoadDidRedirect(url: URL) {
|
||||
let arguments: [String: Any?] = [
|
||||
"url": url.absoluteString
|
||||
]
|
||||
channel?.invokeMethod("onInitialLoadDidRedirect", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onChromeSafariBrowserMenuItemActionPerform(id: Int64, url: URL, title: String?) {
|
||||
public func onWillOpenInBrowser() {
|
||||
let arguments: [String: Any?] = [:]
|
||||
channel?.invokeMethod("onWillOpenInBrowser", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onClosed() {
|
||||
let arguments: [String: Any?] = [:]
|
||||
channel?.invokeMethod("onClosed", arguments: arguments)
|
||||
}
|
||||
|
||||
public func onItemActionPerform(id: Int64, url: URL, title: String?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"id": id,
|
||||
"url": url.absoluteString,
|
||||
"title": title,
|
||||
]
|
||||
channel?.invokeMethod("onChromeSafariBrowserMenuItemActionPerform", arguments: arguments)
|
||||
channel?.invokeMethod("onItemActionPerform", arguments: arguments)
|
||||
}
|
||||
|
||||
public override func dispose() {
|
||||
|
|
|
@ -4,6 +4,9 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import '../types/custom_tabs_navigation_event_type.dart';
|
||||
import '../types/custom_tabs_relation_type.dart';
|
||||
import '../types/prewarming_token.dart';
|
||||
import '../util.dart';
|
||||
import '../debug_logging_settings.dart';
|
||||
|
||||
|
@ -41,7 +44,7 @@ class ChromeSafariBrowserNotOpenedException implements Exception {
|
|||
///(you can read more about it here: https://developers.google.com/web/android/custom-tabs/best-practices#applications_targeting_android_11_api_level_30_or_above).
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- Android
|
||||
///- iOS
|
||||
class ChromeSafariBrowser {
|
||||
///Debug settings.
|
||||
|
@ -85,17 +88,43 @@ class ChromeSafariBrowser {
|
|||
_debugLog(call.method, call.arguments);
|
||||
|
||||
switch (call.method) {
|
||||
case "onChromeSafariBrowserOpened":
|
||||
case "onServiceConnected":
|
||||
onServiceConnected();
|
||||
break;
|
||||
case "onOpened":
|
||||
onOpened();
|
||||
break;
|
||||
case "onChromeSafariBrowserCompletedInitialLoad":
|
||||
onCompletedInitialLoad();
|
||||
case "onCompletedInitialLoad":
|
||||
final bool? didLoadSuccessfully = call.arguments["didLoadSuccessfully"];
|
||||
onCompletedInitialLoad(didLoadSuccessfully);
|
||||
break;
|
||||
case "onChromeSafariBrowserClosed":
|
||||
case "onInitialLoadDidRedirect":
|
||||
final String? url = call.arguments["url"];
|
||||
final Uri? uri = url != null ? Uri.tryParse(url) : null;
|
||||
onInitialLoadDidRedirect(uri);
|
||||
break;
|
||||
case "onNavigationEvent":
|
||||
final navigationEvent = CustomTabsNavigationEventType.fromNativeValue(
|
||||
call.arguments["navigationEvent"]);
|
||||
onNavigationEvent(navigationEvent);
|
||||
break;
|
||||
case "onRelationshipValidationResult":
|
||||
final relation =
|
||||
CustomTabsRelationType.fromNativeValue(call.arguments["relation"]);
|
||||
final requestedOrigin = call.arguments["requestedOrigin"] != null
|
||||
? Uri.tryParse(call.arguments["requestedOrigin"])
|
||||
: null;
|
||||
final bool result = call.arguments["result"];
|
||||
onRelationshipValidationResult(relation, requestedOrigin, result);
|
||||
break;
|
||||
case "onWillOpenInBrowser":
|
||||
onWillOpenInBrowser();
|
||||
break;
|
||||
case "onClosed":
|
||||
onClosed();
|
||||
this._isOpened = false;
|
||||
break;
|
||||
case "onChromeSafariBrowserItemActionPerform":
|
||||
case "onItemActionPerform":
|
||||
String url = call.arguments["url"];
|
||||
String title = call.arguments["title"];
|
||||
int id = call.arguments["id"].toInt();
|
||||
|
@ -112,25 +141,38 @@ class ChromeSafariBrowser {
|
|||
|
||||
///Opens the [ChromeSafariBrowser] instance with an [url].
|
||||
///
|
||||
///[url]: The [url] to load. On iOS, the [url] must use the `http` or `https` scheme.
|
||||
///[url] - The [url] to load. On iOS, the [url] is required and must use the `http` or `https` scheme.
|
||||
///
|
||||
///[options]: Options for the [ChromeSafariBrowser].
|
||||
///[headers] - extra request headers. Supported only on Android.
|
||||
///
|
||||
///[settings]: Settings for the [ChromeSafariBrowser].
|
||||
///[otherLikelyURLs] - Other likely destinations, sorted in decreasing likelihood order. Supported only on Android.
|
||||
///
|
||||
///[options] - Options for the [ChromeSafariBrowser].
|
||||
///
|
||||
///[settings] - Settings for the [ChromeSafariBrowser].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
Future<void> open(
|
||||
{required Uri url,
|
||||
{Uri? url,
|
||||
Map<String, String>? headers,
|
||||
List<Uri>? otherLikelyURLs,
|
||||
@Deprecated('Use settings instead')
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
ChromeSafariBrowserClassOptions? options,
|
||||
ChromeSafariBrowserSettings? settings}) async {
|
||||
assert(url.toString().isNotEmpty);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
if (!kIsWeb &&
|
||||
(defaultTargetPlatform == TargetPlatform.iOS ||
|
||||
defaultTargetPlatform == TargetPlatform.macOS)) {
|
||||
assert(['http', 'https'].contains(url.scheme),
|
||||
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.iOS) {
|
||||
assert(url != null, 'The specified URL must not be null on iOS.');
|
||||
assert(['http', 'https'].contains(url!.scheme),
|
||||
'The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported on iOS.');
|
||||
}
|
||||
if (url != null) {
|
||||
assert(url.toString().isNotEmpty, 'The specified URL must not be empty.');
|
||||
}
|
||||
this.throwIsAlreadyOpened(message: url != null ? 'Cannot open $url!' : '');
|
||||
|
||||
this._isOpened = true;
|
||||
|
||||
List<Map<String, dynamic>> menuItemList = [];
|
||||
_menuItems.forEach((key, value) {
|
||||
|
@ -143,15 +185,87 @@ class ChromeSafariBrowser {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('id', () => id);
|
||||
args.putIfAbsent('url', () => url.toString());
|
||||
args.putIfAbsent('url', () => url?.toString());
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('otherLikelyURLs',
|
||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||
args.putIfAbsent('settings', () => initialSettings);
|
||||
args.putIfAbsent('actionButton', () => _actionButton?.toMap());
|
||||
args.putIfAbsent('menuItemList', () => menuItemList);
|
||||
await _sharedChannel.invokeMethod('open', args);
|
||||
this._isOpened = true;
|
||||
}
|
||||
|
||||
///Tells the browser to launch with [url].
|
||||
///
|
||||
///[url] - initial url.
|
||||
///
|
||||
///[headers] - extra request headers.
|
||||
///
|
||||
///[otherLikelyURLs] - Other likely destinations, sorted in decreasing likelihood order.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
Future<void> launchUrl(
|
||||
{required Uri url,
|
||||
Map<String, String>? headers,
|
||||
List<Uri>? otherLikelyURLs}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url.toString());
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('otherLikelyURLs',
|
||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||
await _channel.invokeMethod("launchUrl", args);
|
||||
}
|
||||
|
||||
///Tells the browser of a likely future navigation to a URL.
|
||||
///The most likely URL has to be specified first.
|
||||
///Optionally, a list of other likely URLs can be provided.
|
||||
///They are treated as less likely than the first one, and have to be sorted in decreasing priority order.
|
||||
///These additional URLs may be ignored. All previous calls to this method will be deprioritized.
|
||||
///
|
||||
///[url] - Most likely URL, may be null if otherLikelyBundles is provided.
|
||||
///
|
||||
///[headers] - extra request headers.
|
||||
///
|
||||
///[otherLikelyURLs] - Other likely destinations, sorted in decreasing likelihood order.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android ([Official API - CustomTabsSession.mayLaunchUrl](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession#mayLaunchUrl(android.net.Uri,android.os.Bundle,java.util.List%3Candroid.os.Bundle%3E)))
|
||||
Future<void> mayLaunchUrl(
|
||||
{Uri? url,
|
||||
Map<String, String>? headers,
|
||||
List<Uri>? otherLikelyURLs}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('url', () => url?.toString());
|
||||
args.putIfAbsent('headers', () => headers);
|
||||
args.putIfAbsent('otherLikelyURLs',
|
||||
() => otherLikelyURLs?.map((e) => e.toString()).toList());
|
||||
await _channel.invokeMethod("mayLaunchUrl", args);
|
||||
}
|
||||
|
||||
///Requests to validate a relationship between the application and an origin.
|
||||
///
|
||||
///See [here](https://developers.google.com/digital-asset-links/v1/getting-started) for documentation about Digital Asset Links.
|
||||
///This methods requests the browser to verify a relation with the calling application, to grant the associated rights.
|
||||
///
|
||||
///If this method returns `true`, the validation result will be provided through [onRelationshipValidationResult].
|
||||
///Otherwise the request didn't succeed.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android ([Official API - CustomTabsSession.validateRelationship](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession#validateRelationship(int,android.net.Uri,android.os.Bundle)))
|
||||
Future<void> validateRelationship(
|
||||
{required CustomTabsRelationType relation, required Uri origin}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('relation', () => relation.toNativeValue());
|
||||
args.putIfAbsent('origin', () => origin.toString());
|
||||
await _channel.invokeMethod("validateRelationship", args);
|
||||
}
|
||||
|
||||
///Closes the [ChromeSafariBrowser] instance.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
Future<void> close() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod("close", args);
|
||||
|
@ -162,14 +276,34 @@ class ChromeSafariBrowser {
|
|||
///**NOTE**: Not available in a Trusted Web Activity.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android ([Official API - CustomTabsIntent.Builder.setActionButton ](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setActionButton(android.graphics.Bitmap,%20java.lang.String,%20android.app.PendingIntent,%20boolean)))
|
||||
///- Android ([Official API - CustomTabsIntent.Builder.setActionButton](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder#setActionButton(android.graphics.Bitmap,%20java.lang.String,%20android.app.PendingIntent,%20boolean)))
|
||||
void setActionButton(ChromeSafariBrowserActionButton actionButton) {
|
||||
this._actionButton = actionButton;
|
||||
}
|
||||
|
||||
///Updates the [ChromeSafariBrowserActionButton.icon] and [ChromeSafariBrowserActionButton.description].
|
||||
///
|
||||
///**NOTE**: Not available in a Trusted Web Activity.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android ([Official API - CustomTabsSession.setActionButton](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsSession#setActionButton(android.graphics.Bitmap,java.lang.String)))
|
||||
Future<void> updateActionButton(
|
||||
{required Uint8List icon, required String description}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('icon', () => icon);
|
||||
args.putIfAbsent('description', () => description);
|
||||
await _channel.invokeMethod("updateActionButton", args);
|
||||
_actionButton?.icon = icon;
|
||||
_actionButton?.description = description;
|
||||
}
|
||||
|
||||
///Adds a [ChromeSafariBrowserMenuItem] to the menu.
|
||||
///
|
||||
///**NOTE**: Not available in an Android Trusted Web Activity.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
void addMenuItem(ChromeSafariBrowserMenuItem menuItem) {
|
||||
this._menuItems[menuItem.id] = menuItem;
|
||||
}
|
||||
|
@ -177,6 +311,10 @@ class ChromeSafariBrowser {
|
|||
///Adds a list of [ChromeSafariBrowserMenuItem] to the menu.
|
||||
///
|
||||
///**NOTE**: Not available in an Android Trusted Web Activity.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
void addMenuItems(List<ChromeSafariBrowserMenuItem> menuItems) {
|
||||
menuItems.forEach((menuItem) {
|
||||
this._menuItems[menuItem.id] = menuItem;
|
||||
|
@ -186,21 +324,135 @@ class ChromeSafariBrowser {
|
|||
///On Android, returns `true` if Chrome Custom Tabs is available.
|
||||
///On iOS, returns `true` if SFSafariViewController is available.
|
||||
///Otherwise returns `false`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
static Future<bool> isAvailable() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _sharedChannel.invokeMethod("isAvailable", args);
|
||||
}
|
||||
|
||||
///Event fires when the [ChromeSafariBrowser] is opened.
|
||||
///Clear associated website data accrued from browsing activity within your app.
|
||||
///This includes all local storage, cached resources, and cookies.
|
||||
///
|
||||
///**NOTE for iOS**: available on iOS 16.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - SFSafariViewController.DataStore.clearWebsiteData](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/datastore/3981117-clearwebsitedata))
|
||||
static Future<void> clearWebsiteData() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _sharedChannel.invokeMethod("clearWebsiteData", args);
|
||||
}
|
||||
|
||||
///Prewarms a connection to each URL. SFSafariViewController will automatically use a
|
||||
///prewarmed connection if possible when loading its initial URL.
|
||||
///
|
||||
///Returns a token object that corresponds to the requested URLs. You must keep a strong
|
||||
///reference to this token as long as you expect the prewarmed connections to remain open. If the same
|
||||
///server is requested in multiple calls to this method, all of the corresponding tokens must be
|
||||
///invalidated or released to end the prewarmed connection to that server.
|
||||
///
|
||||
///This method uses a best-effort approach to prewarming connections, but may delay
|
||||
///or drop requests based on the volume of requests made by your app. Use this method when you expect
|
||||
///to present the browser soon. Many HTTP servers time out connections after a few minutes.
|
||||
///After a timeout, prewarming delivers less performance benefit.
|
||||
///
|
||||
///[URLs] - the URLs of servers that the browser should prewarm connections to.
|
||||
///Only supports URLs with `http://` or `https://` schemes.
|
||||
///
|
||||
///**NOTE for iOS**: available on iOS 15.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - SFSafariViewController.prewarmConnections](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/3752133-prewarmconnections))
|
||||
static Future<PrewarmingToken?> prewarmConnections(List<Uri> URLs) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('URLs', () => URLs.map((e) => e.toString()).toList());
|
||||
Map<String, dynamic>? result =
|
||||
(await _sharedChannel.invokeMethod("prewarmConnections", args))
|
||||
?.cast<String, dynamic>();
|
||||
return PrewarmingToken.fromMap(result);
|
||||
}
|
||||
|
||||
///Ends all prewarmed connections associated with the token, except for connections that are also kept alive by other tokens.
|
||||
///
|
||||
///**NOTE for iOS**: available on iOS 15.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - SFSafariViewController.prewarmConnections](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/3752133-prewarmconnections))
|
||||
static Future<void> invalidatePrewarmingToken(PrewarmingToken prewarmingToken) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('prewarmingToken', () => prewarmingToken.toMap());
|
||||
await _sharedChannel.invokeMethod("invalidatePrewarmingToken", args);
|
||||
}
|
||||
|
||||
///Event fired when the when connecting from Android Custom Tabs Service.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
void onServiceConnected() {}
|
||||
|
||||
///Event fired when the [ChromeSafariBrowser] is opened.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
void onOpened() {}
|
||||
|
||||
///Event fires when the initial URL load is complete.
|
||||
void onCompletedInitialLoad() {}
|
||||
///Event fired when the initial URL load is complete.
|
||||
///
|
||||
///[didLoadSuccessfully] - `true` if loading completed successfully; otherwise, `false`. Supported only on iOS.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS ([Official API - SFSafariViewControllerDelegate.safariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontrollerdelegate/1621215-safariviewcontroller))
|
||||
void onCompletedInitialLoad(bool? didLoadSuccessfully) {}
|
||||
|
||||
///Event fires when the [ChromeSafariBrowser] is closed.
|
||||
///Event fired when the initial URL load is complete.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - SFSafariViewControllerDelegate.safariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontrollerdelegate/2923545-safariviewcontroller))
|
||||
void onInitialLoadDidRedirect(Uri? url) {}
|
||||
|
||||
///Event fired when a navigation event happens.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android ([Official API - CustomTabsCallback.onNavigationEvent](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsCallback#onNavigationEvent(int,android.os.Bundle)))
|
||||
void onNavigationEvent(CustomTabsNavigationEventType? navigationEvent) {}
|
||||
|
||||
///Event fired when a relationship validation result is available.
|
||||
///
|
||||
///[relation] - Relation for which the result is available. Value previously passed to [validateRelationship].
|
||||
///
|
||||
///[requestedOrigin] - Origin requested. Value previously passed to [validateRelationship].
|
||||
///
|
||||
///[result] - Whether the relation was validated.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android ([Official API - CustomTabsCallback.onRelationshipValidationResult](https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsCallback#onRelationshipValidationResult(int,android.net.Uri,boolean,android.os.Bundle)))
|
||||
void onRelationshipValidationResult(
|
||||
CustomTabsRelationType? relation, Uri? requestedOrigin, bool result) {}
|
||||
|
||||
///Event fired when the user opens the current page in the default browser by tapping the toolbar button.
|
||||
///
|
||||
///**NOTE for iOS**: available on iOS 14.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - SFSafariViewControllerDelegate.safariViewControllerWillOpenInBrowser](https://developer.apple.com/documentation/safariservices/sfsafariviewcontrollerdelegate/3650426-safariviewcontrollerwillopeninbr))
|
||||
void onWillOpenInBrowser() {}
|
||||
|
||||
///Event fired when the [ChromeSafariBrowser] is closed.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
void onClosed() {}
|
||||
|
||||
///Returns `true` if the [ChromeSafariBrowser] instance is opened, otherwise `false`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
bool isOpened() {
|
||||
return this._isOpened;
|
||||
}
|
||||
|
@ -225,6 +477,9 @@ class ChromeSafariBrowser {
|
|||
///Class that represents a custom action button for a [ChromeSafariBrowser] instance.
|
||||
///
|
||||
///**NOTE**: Not available in an Android Trusted Web Activity.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
class ChromeSafariBrowserActionButton {
|
||||
///The action button id. It should be different from the [ChromeSafariBrowserMenuItem.id].
|
||||
int id;
|
||||
|
@ -270,6 +525,10 @@ class ChromeSafariBrowserActionButton {
|
|||
///Class that represents a custom menu item for a [ChromeSafariBrowser] instance.
|
||||
///
|
||||
///**NOTE**: Not available in an Android Trusted Web Activity.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android
|
||||
///- iOS
|
||||
class ChromeSafariBrowserMenuItem {
|
||||
///The menu item id. It should be different from [ChromeSafariBrowserActionButton.id].
|
||||
int id;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
|
||||
import '../chrome_safari_browser/chrome_safari_browser.dart';
|
||||
|
||||
part 'custom_tabs_navigation_event_type.g.dart';
|
||||
|
||||
///The type corresponding to the navigation event of [ChromeSafariBrowser.onNavigationEvent].
|
||||
@ExchangeableEnum()
|
||||
class CustomTabsNavigationEventType_ {
|
||||
// ignore: unused_field
|
||||
final int _value;
|
||||
|
||||
// ignore: unused_field
|
||||
final int? _nativeValue = null;
|
||||
|
||||
const CustomTabsNavigationEventType_._internal(this._value);
|
||||
|
||||
///Sent when the tab has started loading a page.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 1)])
|
||||
static const STARTED = const CustomTabsNavigationEventType_._internal(1);
|
||||
|
||||
///Sent when the tab has finished loading a page.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 2)])
|
||||
static const FINISHED = const CustomTabsNavigationEventType_._internal(2);
|
||||
|
||||
///Sent when the tab couldn't finish loading due to a failure.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 3)])
|
||||
static const FAILED = const CustomTabsNavigationEventType_._internal(3);
|
||||
|
||||
///Sent when loading was aborted by a user action before it finishes like clicking on a link or refreshing the page.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 4)])
|
||||
static const ABORTED = const CustomTabsNavigationEventType_._internal(4);
|
||||
|
||||
///Sent when the tab becomes visible.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 5)])
|
||||
static const TAB_SHOWN = const CustomTabsNavigationEventType_._internal(5);
|
||||
|
||||
///Sent when the tab becomes hidden.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 6)])
|
||||
static const TAB_HIDDEN = const CustomTabsNavigationEventType_._internal(6);
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'custom_tabs_navigation_event_type.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// ExchangeableEnumGenerator
|
||||
// **************************************************************************
|
||||
|
||||
///The type corresponding to the navigation event of [ChromeSafariBrowser.onNavigationEvent].
|
||||
class CustomTabsNavigationEventType {
|
||||
final int _value;
|
||||
final int? _nativeValue;
|
||||
const CustomTabsNavigationEventType._internal(this._value, this._nativeValue);
|
||||
// ignore: unused_element
|
||||
factory CustomTabsNavigationEventType._internalMultiPlatform(
|
||||
int value, Function nativeValue) =>
|
||||
CustomTabsNavigationEventType._internal(value, nativeValue());
|
||||
|
||||
///Sent when the tab has started loading a page.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final STARTED =
|
||||
CustomTabsNavigationEventType._internalMultiPlatform(1, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Sent when the tab has finished loading a page.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final FINISHED =
|
||||
CustomTabsNavigationEventType._internalMultiPlatform(2, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Sent when the tab couldn't finish loading due to a failure.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final FAILED =
|
||||
CustomTabsNavigationEventType._internalMultiPlatform(3, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 3;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Sent when loading was aborted by a user action before it finishes like clicking on a link or refreshing the page.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final ABORTED =
|
||||
CustomTabsNavigationEventType._internalMultiPlatform(4, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Sent when the tab becomes visible.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final TAB_SHOWN =
|
||||
CustomTabsNavigationEventType._internalMultiPlatform(5, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Sent when the tab becomes hidden.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final TAB_HIDDEN =
|
||||
CustomTabsNavigationEventType._internalMultiPlatform(6, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Set of all values of [CustomTabsNavigationEventType].
|
||||
static final Set<CustomTabsNavigationEventType> values = [
|
||||
CustomTabsNavigationEventType.STARTED,
|
||||
CustomTabsNavigationEventType.FINISHED,
|
||||
CustomTabsNavigationEventType.FAILED,
|
||||
CustomTabsNavigationEventType.ABORTED,
|
||||
CustomTabsNavigationEventType.TAB_SHOWN,
|
||||
CustomTabsNavigationEventType.TAB_HIDDEN,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [CustomTabsNavigationEventType] instance from [int] value.
|
||||
static CustomTabsNavigationEventType? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return CustomTabsNavigationEventType.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets a possible [CustomTabsNavigationEventType] instance from a native value.
|
||||
static CustomTabsNavigationEventType? fromNativeValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return CustomTabsNavigationEventType.values
|
||||
.firstWhere((element) => element.toNativeValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
///Gets [int?] native value.
|
||||
int? toNativeValue() => _nativeValue;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return 'STARTED';
|
||||
case 2:
|
||||
return 'FINISHED';
|
||||
case 3:
|
||||
return 'FAILED';
|
||||
case 4:
|
||||
return 'ABORTED';
|
||||
case 5:
|
||||
return 'TAB_SHOWN';
|
||||
case 6:
|
||||
return 'TAB_HIDDEN';
|
||||
}
|
||||
return _value.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
|
||||
|
||||
part 'custom_tabs_relation_type.g.dart';
|
||||
|
||||
///Custom Tabs relation for which the result is available.
|
||||
@ExchangeableEnum()
|
||||
class CustomTabsRelationType_ {
|
||||
// ignore: unused_field
|
||||
final int _value;
|
||||
|
||||
// ignore: unused_field
|
||||
final int? _nativeValue = null;
|
||||
|
||||
const CustomTabsRelationType_._internal(this._value);
|
||||
|
||||
///For App -> Web transitions, requests the app to use the declared origin to be used as origin for the client app in the web APIs context.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 1)])
|
||||
static const USE_AS_ORIGIN = const CustomTabsRelationType_._internal(1);
|
||||
|
||||
///Requests the ability to handle all URLs from a given origin.
|
||||
@EnumSupportedPlatforms(platforms: [EnumAndroidPlatform(value: 2)])
|
||||
static const HANDLE_ALL_URLS = const CustomTabsRelationType_._internal(2);
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'custom_tabs_relation_type.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// ExchangeableEnumGenerator
|
||||
// **************************************************************************
|
||||
|
||||
///Custom Tabs relation for which the result is available.
|
||||
class CustomTabsRelationType {
|
||||
final int _value;
|
||||
final int? _nativeValue;
|
||||
const CustomTabsRelationType._internal(this._value, this._nativeValue);
|
||||
// ignore: unused_element
|
||||
factory CustomTabsRelationType._internalMultiPlatform(
|
||||
int value, Function nativeValue) =>
|
||||
CustomTabsRelationType._internal(value, nativeValue());
|
||||
|
||||
///For App -> Web transitions, requests the app to use the declared origin to be used as origin for the client app in the web APIs context.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final USE_AS_ORIGIN =
|
||||
CustomTabsRelationType._internalMultiPlatform(1, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Requests the ability to handle all URLs from a given origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
static final HANDLE_ALL_URLS =
|
||||
CustomTabsRelationType._internalMultiPlatform(2, () {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
///Set of all values of [CustomTabsRelationType].
|
||||
static final Set<CustomTabsRelationType> values = [
|
||||
CustomTabsRelationType.USE_AS_ORIGIN,
|
||||
CustomTabsRelationType.HANDLE_ALL_URLS,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [CustomTabsRelationType] instance from [int] value.
|
||||
static CustomTabsRelationType? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return CustomTabsRelationType.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets a possible [CustomTabsRelationType] instance from a native value.
|
||||
static CustomTabsRelationType? fromNativeValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return CustomTabsRelationType.values
|
||||
.firstWhere((element) => element.toNativeValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
///Gets [int?] native value.
|
||||
int? toNativeValue() => _nativeValue;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return 'USE_AS_ORIGIN';
|
||||
case 2:
|
||||
return 'HANDLE_ALL_URLS';
|
||||
}
|
||||
return _value.toString();
|
||||
}
|
||||
}
|
|
@ -215,3 +215,6 @@ export 'printer.dart' show Printer;
|
|||
export 'window_type.dart' show WindowType;
|
||||
export 'window_style_mask.dart' show WindowStyleMask;
|
||||
export 'window_titlebar_separator_style.dart' show WindowTitlebarSeparatorStyle;
|
||||
export 'custom_tabs_navigation_event_type.dart' show CustomTabsNavigationEventType;
|
||||
export 'custom_tabs_relation_type.dart' show CustomTabsRelationType;
|
||||
export 'prewarming_token.dart' show PrewarmingToken;
|
|
@ -0,0 +1,14 @@
|
|||
import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart';
|
||||
|
||||
import '../chrome_safari_browser/chrome_safari_browser.dart';
|
||||
|
||||
part 'prewarming_token.g.dart';
|
||||
|
||||
///Class that represents the Prewarming Token returned by [ChromeSafariBrowser.prewarmConnections].
|
||||
@ExchangeableObject()
|
||||
class PrewarmingToken_ {
|
||||
///Prewarming Token id.
|
||||
final String id;
|
||||
|
||||
PrewarmingToken_({required this.id});
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'prewarming_token.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// ExchangeableObjectGenerator
|
||||
// **************************************************************************
|
||||
|
||||
///Class that represents the Prewarming Token returned by [ChromeSafariBrowser.prewarmConnections].
|
||||
class PrewarmingToken {
|
||||
///Prewarming Token id.
|
||||
final String id;
|
||||
PrewarmingToken({required this.id});
|
||||
|
||||
///Gets a possible [PrewarmingToken] instance from a [Map] value.
|
||||
static PrewarmingToken? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
final instance = PrewarmingToken(
|
||||
id: map['id'],
|
||||
);
|
||||
return instance;
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"id": id,
|
||||
};
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toJson() {
|
||||
return toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PrewarmingToken{id: $id}';
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_inappwebview
|
||||
description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
|
||||
version: 6.0.0-beta.7
|
||||
version: 6.0.0-beta.9
|
||||
homepage: https://inappwebview.dev/
|
||||
repository: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||
issue_tracker: https://github.com/pichillilorenzo/flutter_inappwebview/issues
|
||||
|
|
Loading…
Reference in New Issue