added PrintJobController to manage print jobs
This commit is contained in:
parent
0a16e1babe
commit
0dd9dfbff6
|
@ -3,6 +3,7 @@
|
|||
- Deprecated old classes/properties/methods to make them eventually compatible with other Platforms and WebView engines.
|
||||
- Added Web support
|
||||
- Added `ProxyController` for Android
|
||||
- Added `PrintJobController` to manage print jobs
|
||||
- Added `WebAuthenticationSession` for iOS
|
||||
- Added `pauseAllMediaPlayback`, `setAllMediaPlaybackSuspended`, `closeAllMediaPresentations`, `requestMediaPlaybackState`, `isInFullscreen`, `getCameraCaptureState`, `setCameraCaptureState`, `getMicrophoneCaptureState`, `setMicrophoneCaptureState` WebView controller methods
|
||||
- Added `underPageBackgroundColor`, `isTextInteractionEnabled`, `isSiteSpecificQuirksModeEnabled`, `upgradeKnownHostsToHTTPS`, `forceDarkStrategy` WebView settings
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ISettings<T> {
|
||||
public ISettings parse(Map<String, Object> settings);
|
||||
public Map<String, Object> toMap();
|
||||
public Map<String, Object> getRealSettings(T obj);
|
||||
@NonNull ISettings<T> parse(@NonNull Map<String, Object> settings);
|
||||
@NonNull Map<String, Object> toMap();
|
||||
@NonNull Map<String, Object> getRealSettings(@NonNull T obj);
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs.ChromeSafariBrowserManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.credential_database.CredentialDatabaseHandler;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.headless_in_app_webview.HeadlessInAppWebViewManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.proxy.ProxyManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.service_worker.ServiceWorkerManager;
|
||||
|
||||
|
@ -27,21 +29,36 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
|||
|
||||
protected static final String LOG_TAG = "InAppWebViewFlutterPL";
|
||||
|
||||
@Nullable
|
||||
public PlatformUtil platformUtil;
|
||||
@Nullable
|
||||
public InAppBrowserManager inAppBrowserManager;
|
||||
@Nullable
|
||||
public HeadlessInAppWebViewManager headlessInAppWebViewManager;
|
||||
@Nullable
|
||||
public ChromeSafariBrowserManager chromeSafariBrowserManager;
|
||||
@Nullable
|
||||
public InAppWebViewStatic inAppWebViewStatic;
|
||||
@Nullable
|
||||
public MyCookieManager myCookieManager;
|
||||
@Nullable
|
||||
public CredentialDatabaseHandler credentialDatabaseHandler;
|
||||
@Nullable
|
||||
public MyWebStorage myWebStorage;
|
||||
@Nullable
|
||||
public ServiceWorkerManager serviceWorkerManager;
|
||||
@Nullable
|
||||
public WebViewFeatureManager webViewFeatureManager;
|
||||
@Nullable
|
||||
public ProxyManager proxyManager;
|
||||
public FlutterWebViewFactory flutterWebViewFactory;
|
||||
@Nullable
|
||||
public PrintJobManager printJobManager;
|
||||
@Nullable
|
||||
public static ValueCallback<Uri> filePathCallbackLegacy;
|
||||
@Nullable
|
||||
public static ValueCallback<Uri[]> filePathCallback;
|
||||
|
||||
public FlutterWebViewFactory flutterWebViewFactory;
|
||||
public Context applicationContext;
|
||||
public PluginRegistry.Registrar registrar;
|
||||
public BinaryMessenger messenger;
|
||||
|
@ -101,10 +118,13 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
|||
}
|
||||
webViewFeatureManager = new WebViewFeatureManager(this);
|
||||
proxyManager = new ProxyManager(this);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
printJobManager = new PrintJobManager();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromEngine(FlutterPluginBinding binding) {
|
||||
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
|
||||
if (platformUtil != null) {
|
||||
platformUtil.dispose();
|
||||
platformUtil = null;
|
||||
|
@ -149,6 +169,10 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
|||
proxyManager.dispose();
|
||||
proxyManager = null;
|
||||
}
|
||||
if (printJobManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
printJobManager.dispose();
|
||||
printJobManager = null;
|
||||
}
|
||||
filePathCallbackLegacy = null;
|
||||
filePathCallback = null;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs;
|
|||
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.browser.trusted.ScreenOrientation;
|
||||
|
@ -35,8 +36,9 @@ public class ChromeCustomTabsSettings implements ISettings<ChromeCustomTabsActiv
|
|||
public TrustedWebActivityDisplayMode displayMode = null;
|
||||
public Integer screenOrientation = ScreenOrientation.DEFAULT;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ChromeCustomTabsSettings parse(Map<String, Object> options) {
|
||||
public ChromeCustomTabsSettings parse(@NonNull Map<String, Object> options) {
|
||||
for (Map.Entry<String, Object> pair : options.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
|
@ -104,6 +106,7 @@ public class ChromeCustomTabsSettings implements ISettings<ChromeCustomTabsActiv
|
|||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> options = new HashMap<>();
|
||||
|
@ -122,8 +125,9 @@ public class ChromeCustomTabsSettings implements ISettings<ChromeCustomTabsActiv
|
|||
return options;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(ChromeCustomTabsActivity chromeCustomTabsActivity) {
|
||||
public Map<String, Object> getRealSettings(@NonNull ChromeCustomTabsActivity chromeCustomTabsActivity) {
|
||||
Map<String, Object> realOptions = toMap();
|
||||
if (chromeCustomTabsActivity != null) {
|
||||
Intent intent = chromeCustomTabsActivity.getIntent();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.in_app_browser;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ISettings;
|
||||
|
@ -26,8 +27,9 @@ public class InAppBrowserSettings implements ISettings<InAppBrowserActivity> {
|
|||
public Boolean allowGoBackWithBackButton = true;
|
||||
public Boolean shouldCloseOnBackButtonPressed = false;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InAppBrowserSettings parse(Map<String, Object> settings) {
|
||||
public InAppBrowserSettings parse(@NonNull Map<String, Object> settings) {
|
||||
for (Map.Entry<String, Object> pair : settings.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
|
@ -72,6 +74,7 @@ public class InAppBrowserSettings implements ISettings<InAppBrowserActivity> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
|
@ -88,12 +91,13 @@ public class InAppBrowserSettings implements ISettings<InAppBrowserActivity> {
|
|||
return settings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(InAppBrowserActivity inAppBrowserActivity) {
|
||||
public Map<String, Object> getRealSettings(@NonNull InAppBrowserActivity inAppBrowserActivity) {
|
||||
Map<String, Object> realSettings = toMap();
|
||||
realSettings.put("hideToolbarTop", !inAppBrowserActivity.actionBar.isShowing());
|
||||
realSettings.put("hideUrlBar", !inAppBrowserActivity.menu.findItem(R.id.menu_search).isVisible());
|
||||
realSettings.put("hideProgressBar", inAppBrowserActivity.progressBar.getMax() == 0);
|
||||
realSettings.put("hideToolbarTop", inAppBrowserActivity.actionBar == null || !inAppBrowserActivity.actionBar.isShowing());
|
||||
realSettings.put("hideUrlBar", inAppBrowserActivity.menu == null || !inAppBrowserActivity.menu.findItem(R.id.menu_search).isVisible());
|
||||
realSettings.put("hideProgressBar", inAppBrowserActivity.progressBar == null || inAppBrowserActivity.progressBar.getMax() == 0);
|
||||
return realSettings;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public class PrintJS {
|
|||
|
||||
public static final String PRINT_JS_SOURCE = "window.print = function() {" +
|
||||
" if (window.top == null || window.top === window) {" +
|
||||
" window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onPrint', window.location.href);" +
|
||||
" window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onPrintRequest', window.location.href);" +
|
||||
" } else {" +
|
||||
" window.top.print();" +
|
||||
" }" +
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.print_job;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.PrintJobInfoExt;
|
||||
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class PrintJobChannelDelegate extends ChannelDelegateImpl {
|
||||
@Nullable
|
||||
private PrintJobController printJobController;
|
||||
|
||||
public PrintJobChannelDelegate(@NonNull PrintJobController printJobController, @NonNull MethodChannel channel) {
|
||||
super(channel);
|
||||
this.printJobController = printJobController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
case "cancel":
|
||||
if (printJobController != null) {
|
||||
printJobController.cancel();
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "restart":
|
||||
if (printJobController != null) {
|
||||
printJobController.restart();
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "getInfo":
|
||||
if (printJobController != null) {
|
||||
PrintJobInfoExt info = printJobController.getInfo();
|
||||
result.success(info != null ? info.toMap() : null);
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "dispose":
|
||||
if (printJobController != null) {
|
||||
printJobController.dispose();
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
printJobController = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.print_job;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.PrintJobInfoExt;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class PrintJobController implements Disposable {
|
||||
protected static final String LOG_TAG = "PrintJob";
|
||||
public static final String METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_printjobcontroller_";
|
||||
|
||||
@NonNull
|
||||
public String id;
|
||||
@Nullable
|
||||
public PrintJobChannelDelegate channelDelegate;
|
||||
@Nullable
|
||||
public android.print.PrintJob job;
|
||||
@Nullable
|
||||
public PrintJobSettings settings;
|
||||
|
||||
public PrintJobController(@NonNull String id, @NonNull android.print.PrintJob job,
|
||||
@Nullable PrintJobSettings settings, @NonNull InAppWebViewFlutterPlugin plugin) {
|
||||
this.id = id;
|
||||
this.job = job;
|
||||
this.settings = settings;
|
||||
final MethodChannel channel = new MethodChannel(plugin.messenger, METHOD_CHANNEL_NAME_PREFIX + id);
|
||||
this.channelDelegate = new PrintJobChannelDelegate(this, channel);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (this.job != null) {
|
||||
this.job.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
if (this.job != null) {
|
||||
this.job.restart();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PrintJobInfoExt getInfo() {
|
||||
if (this.job != null) {
|
||||
return PrintJobInfoExt.fromPrintJobInfo(this.job.getInfo());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void disposeNoCancel() {
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.dispose();
|
||||
channelDelegate = null;
|
||||
}
|
||||
if (PrintJobManager.jobs.containsKey(id)) {
|
||||
PrintJobManager.jobs.put(id, null);
|
||||
}
|
||||
if (job != null) {
|
||||
job = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (channelDelegate != null) {
|
||||
channelDelegate.dispose();
|
||||
channelDelegate = null;
|
||||
}
|
||||
if (PrintJobManager.jobs.containsKey(id)) {
|
||||
PrintJobManager.jobs.put(id, null);
|
||||
}
|
||||
if (job != null) {
|
||||
job.cancel();
|
||||
job = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.pichillilorenzo.flutter_inappwebview.print_job;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class PrintJobManager implements Disposable {
|
||||
protected static final String LOG_TAG = "PrintJobManager";
|
||||
|
||||
public static final Map<String, PrintJobController> jobs = new HashMap<>();
|
||||
|
||||
public PrintJobManager() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
Collection<PrintJobController> printJobControllers = jobs.values();
|
||||
for (PrintJobController job : printJobControllers) {
|
||||
if (job != null) {
|
||||
job.dispose();
|
||||
}
|
||||
}
|
||||
jobs.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.print_job;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ISettings;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.MediaSizeExt;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ResolutionExt;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class PrintJobSettings implements ISettings<PrintJobController> {
|
||||
|
||||
public static final String LOG_TAG = "PrintJobSettings";
|
||||
|
||||
public Boolean handledByClient = false;
|
||||
@Nullable
|
||||
public String jobName;
|
||||
@Nullable
|
||||
public Integer orientation;
|
||||
// @Nullable
|
||||
// public MarginsExt margins;
|
||||
@Nullable
|
||||
public MediaSizeExt mediaSize;
|
||||
@Nullable
|
||||
public Integer colorMode;
|
||||
@Nullable
|
||||
public Integer duplexMode;
|
||||
@Nullable
|
||||
public ResolutionExt resolution;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PrintJobSettings parse(@NonNull Map<String, Object> settings) {
|
||||
for (Map.Entry<String, Object> pair : settings.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case "handledByClient":
|
||||
handledByClient = (Boolean) value;
|
||||
break;
|
||||
case "jobName":
|
||||
jobName = (String) value;
|
||||
break;
|
||||
case "orientation":
|
||||
orientation = (Integer) value;
|
||||
break;
|
||||
// case "margins":
|
||||
// margins = MarginsExt.fromMap((Map<String, Object>) value);
|
||||
// break;
|
||||
case "mediaSize":
|
||||
mediaSize = MediaSizeExt.fromMap((Map<String, Object>) value);
|
||||
break;
|
||||
case "colorMode":
|
||||
colorMode = (Integer) value;
|
||||
break;
|
||||
case "duplexMode":
|
||||
duplexMode = (Integer) value;
|
||||
break;
|
||||
case "resolution":
|
||||
resolution = ResolutionExt.fromMap((Map<String, Object>) value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
settings.put("handledByClient", handledByClient);
|
||||
settings.put("jobName", jobName);
|
||||
settings.put("orientation", orientation);
|
||||
// settings.put("margins", margins != null ? margins.toMap() : null);
|
||||
settings.put("mediaSize", mediaSize != null ? mediaSize.toMap() : null);
|
||||
settings.put("colorMode", colorMode);
|
||||
settings.put("duplexMode", duplexMode);
|
||||
settings.put("resolution", resolution != null ? resolution.toMap() : null);
|
||||
return settings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(@NonNull PrintJobController printJobController) {
|
||||
Map<String, Object> realSettings = toMap();
|
||||
return realSettings;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.proxy;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.webkit.ProxyConfig;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ISettings;
|
||||
|
@ -17,8 +18,9 @@ public class ProxySettings implements ISettings<ProxyConfig> {
|
|||
Boolean bypassSimpleHostnames = null;
|
||||
Boolean removeImplicitRules = null;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ProxySettings parse(Map<String, Object> settings) {
|
||||
public ProxySettings parse(@NonNull Map<String, Object> settings) {
|
||||
for (Map.Entry<String, Object> pair : settings.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
|
@ -55,6 +57,7 @@ public class ProxySettings implements ISettings<ProxyConfig> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> toMap() {
|
||||
List<Map<String, String>> proxyRuleMapList = new ArrayList<>();
|
||||
|
@ -70,8 +73,9 @@ public class ProxySettings implements ISettings<ProxyConfig> {
|
|||
return settings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(ProxyConfig proxyConfig) {
|
||||
public Map<String, Object> getRealSettings(@NonNull ProxyConfig proxyConfig) {
|
||||
Map<String, Object> realSettings = toMap();
|
||||
List<Map<String, String>> proxyRuleMapList = new ArrayList<>();
|
||||
List<ProxyConfig.ProxyRule> proxyRules = proxyConfig.getProxyRules();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.pull_to_refresh;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ISettings;
|
||||
|
@ -22,7 +23,9 @@ public class PullToRefreshSettings implements ISettings<PullToRefreshLayout> {
|
|||
@Nullable
|
||||
public Integer size;
|
||||
|
||||
public PullToRefreshSettings parse(Map<String, Object> settings) {
|
||||
@NonNull
|
||||
@Override
|
||||
public PullToRefreshSettings parse(@NonNull Map<String, Object> settings) {
|
||||
for (Map.Entry<String, Object> pair : settings.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
|
@ -55,6 +58,7 @@ public class PullToRefreshSettings implements ISettings<PullToRefreshLayout> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
settings.put("enabled", enabled);
|
||||
|
@ -66,8 +70,9 @@ public class PullToRefreshSettings implements ISettings<PullToRefreshLayout> {
|
|||
return settings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(PullToRefreshLayout pullToRefreshLayout) {
|
||||
public Map<String, Object> getRealSettings(@NonNull PullToRefreshLayout pullToRefreshLayout) {
|
||||
Map<String, Object> realSettings = toMap();
|
||||
return realSettings;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.os.Build;
|
||||
import android.print.PrintAttributes;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class MarginsExt {
|
||||
private double top;
|
||||
private double right;
|
||||
private double bottom;
|
||||
private double left;
|
||||
|
||||
public MarginsExt() {}
|
||||
|
||||
public MarginsExt(double top, double right, double bottom, double left) {
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MarginsExt fromMargins(@Nullable PrintAttributes.Margins margins) {
|
||||
if (margins == null) {
|
||||
return null;
|
||||
}
|
||||
MarginsExt marginsExt = new MarginsExt();
|
||||
marginsExt.top = milsToPixels(margins.getTopMils());
|
||||
marginsExt.right = milsToPixels(margins.getRightMils());
|
||||
marginsExt.bottom = milsToPixels(margins.getBottomMils());
|
||||
marginsExt.left = milsToPixels(margins.getLeftMils());
|
||||
return marginsExt;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MarginsExt fromMap(@Nullable Map<String, Object> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return new MarginsExt(
|
||||
(double) map.get("top"),
|
||||
(double) map.get("right"),
|
||||
(double) map.get("bottom"),
|
||||
(double) map.get("left"));
|
||||
}
|
||||
|
||||
public PrintAttributes.Margins toMargins() {
|
||||
return new PrintAttributes.Margins(
|
||||
pixelsToMils(left),
|
||||
pixelsToMils(top),
|
||||
pixelsToMils(right),
|
||||
pixelsToMils(bottom)
|
||||
);
|
||||
}
|
||||
|
||||
// from mils to pixels
|
||||
private static double milsToPixels(int mils) {
|
||||
return mils * 0.09600001209449;
|
||||
}
|
||||
|
||||
// from pixels to mils
|
||||
private static int pixelsToMils(double pixels) {
|
||||
return (int) Math.round(pixels * 10.416665354331);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("top", top);
|
||||
obj.put("right", right);
|
||||
obj.put("bottom", bottom);
|
||||
obj.put("left", left);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public double getTop() {
|
||||
return top;
|
||||
}
|
||||
|
||||
public void setTop(double top) {
|
||||
this.top = top;
|
||||
}
|
||||
|
||||
public double getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public void setRight(double right) {
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public double getBottom() {
|
||||
return bottom;
|
||||
}
|
||||
|
||||
public void setBottom(double bottom) {
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public double getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public void setLeft(double left) {
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MarginsExt that = (MarginsExt) o;
|
||||
|
||||
if (Double.compare(that.top, top) != 0) return false;
|
||||
if (Double.compare(that.right, right) != 0) return false;
|
||||
if (Double.compare(that.bottom, bottom) != 0) return false;
|
||||
return Double.compare(that.left, left) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(top);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(right);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(bottom);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(left);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MarginsExt{" +
|
||||
"top=" + top +
|
||||
", right=" + right +
|
||||
", bottom=" + bottom +
|
||||
", left=" + left +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.os.Build;
|
||||
import android.print.PrintAttributes;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class MediaSizeExt {
|
||||
@NonNull
|
||||
private String id;
|
||||
@Nullable
|
||||
private String label;
|
||||
private int widthMils;
|
||||
private int heightMils;
|
||||
|
||||
public MediaSizeExt(@NonNull String id, @Nullable String label, int widthMils, int heightMils) {
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
this.widthMils = widthMils;
|
||||
this.heightMils = heightMils;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MediaSizeExt fromMediaSize(@Nullable PrintAttributes.MediaSize mediaSize) {
|
||||
if (mediaSize == null) {
|
||||
return null;
|
||||
}
|
||||
return new MediaSizeExt(
|
||||
mediaSize.getId(),
|
||||
null,
|
||||
mediaSize.getHeightMils(),
|
||||
mediaSize.getWidthMils()
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MediaSizeExt fromMap(@Nullable Map<String, Object> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
String id = (String) map.get("id");
|
||||
String label = (String) map.get("label");
|
||||
int widthMils = (int) map.get("widthMils");
|
||||
int heightMils = (int) map.get("heightMils");
|
||||
return new MediaSizeExt(id, label, widthMils, heightMils);
|
||||
}
|
||||
|
||||
public PrintAttributes.MediaSize toMediaSize() {
|
||||
return new PrintAttributes.MediaSize(
|
||||
id, "Custom", widthMils, heightMils
|
||||
);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("id", id);
|
||||
obj.put("label", label);
|
||||
obj.put("heightMils", heightMils);
|
||||
obj.put("widthMils", widthMils);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@NonNull String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(@Nullable String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public int getWidthMils() {
|
||||
return widthMils;
|
||||
}
|
||||
|
||||
public void setWidthMils(int widthMils) {
|
||||
this.widthMils = widthMils;
|
||||
}
|
||||
|
||||
public int getHeightMils() {
|
||||
return heightMils;
|
||||
}
|
||||
|
||||
public void setHeightMils(int heightMils) {
|
||||
this.heightMils = heightMils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MediaSizeExt that = (MediaSizeExt) o;
|
||||
|
||||
if (widthMils != that.widthMils) return false;
|
||||
if (heightMils != that.heightMils) return false;
|
||||
if (!id.equals(that.id)) return false;
|
||||
return label != null ? label.equals(that.label) : that.label == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id.hashCode();
|
||||
result = 31 * result + (label != null ? label.hashCode() : 0);
|
||||
result = 31 * result + widthMils;
|
||||
result = 31 * result + heightMils;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MediaSizeExt{" +
|
||||
"id='" + id + '\'' +
|
||||
", label='" + label + '\'' +
|
||||
", widthMils=" + widthMils +
|
||||
", heightMils=" + heightMils +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.os.Build;
|
||||
import android.print.PrintAttributes;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class PrintAttributesExt {
|
||||
private int colorMode;
|
||||
@Nullable
|
||||
private Integer duplex;
|
||||
@Nullable
|
||||
private Integer orientation;
|
||||
@Nullable
|
||||
private MediaSizeExt mediaSize;
|
||||
@Nullable
|
||||
private ResolutionExt resolution;
|
||||
@Nullable
|
||||
private MarginsExt margins;
|
||||
|
||||
@Nullable
|
||||
public static PrintAttributesExt fromPrintAttributes(@Nullable PrintAttributes attributes) {
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
}
|
||||
PrintAttributesExt attributesExt = new PrintAttributesExt();
|
||||
attributesExt.colorMode = attributes.getColorMode();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
attributesExt.duplex = attributes.getDuplexMode();
|
||||
}
|
||||
PrintAttributes.MediaSize mediaSize = attributes.getMediaSize();
|
||||
if (mediaSize != null) {
|
||||
attributesExt.mediaSize = MediaSizeExt.fromMediaSize(mediaSize);
|
||||
attributesExt.orientation = mediaSize.isPortrait() ? 0 : 1;
|
||||
}
|
||||
attributesExt.resolution = ResolutionExt.fromResolution(attributes.getResolution());
|
||||
attributesExt.margins = MarginsExt.fromMargins(attributes.getMinMargins());
|
||||
return attributesExt;
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("colorMode", colorMode);
|
||||
obj.put("duplex", duplex);
|
||||
obj.put("orientation", orientation);
|
||||
obj.put("mediaSize", mediaSize != null ? mediaSize.toMap() : null);
|
||||
obj.put("resolution", resolution != null ? resolution.toMap() : null);
|
||||
obj.put("margins", margins != null ? margins.toMap() : null);
|
||||
return obj;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.os.Build;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintJobInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class PrintJobInfoExt {
|
||||
private int state;
|
||||
private int copies;
|
||||
@Nullable
|
||||
private Integer numberOfPages;
|
||||
private long creationTime;
|
||||
@NonNull
|
||||
private String label;
|
||||
@Nullable
|
||||
private String printerId;
|
||||
@Nullable
|
||||
private PrintAttributesExt attributes;
|
||||
|
||||
@Nullable
|
||||
public static PrintJobInfoExt fromPrintJobInfo(@Nullable PrintJobInfo info) {
|
||||
if (info == null) {
|
||||
return null;
|
||||
}
|
||||
PrintJobInfoExt printJobInfoExt = new PrintJobInfoExt();
|
||||
printJobInfoExt.state = info.getState();
|
||||
printJobInfoExt.copies = info.getCopies();
|
||||
printJobInfoExt.numberOfPages = info.getPages() != null ? info.getPages().length : null;
|
||||
printJobInfoExt.creationTime = info.getCreationTime();
|
||||
printJobInfoExt.label = info.getLabel();
|
||||
printJobInfoExt.printerId = info.getPrinterId() != null ? info.getPrinterId().getLocalId() : null;
|
||||
printJobInfoExt.attributes = PrintAttributesExt.fromPrintAttributes(info.getAttributes());
|
||||
return printJobInfoExt;
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("state", state);
|
||||
obj.put("copies", copies);
|
||||
obj.put("numberOfPages", numberOfPages);
|
||||
obj.put("creationTime", creationTime);
|
||||
obj.put("label", label);
|
||||
obj.put("printerId", printerId);
|
||||
obj.put("attributes", attributes != null ? attributes.toMap() : null);
|
||||
return obj;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.types;
|
||||
|
||||
import android.os.Build;
|
||||
import android.print.PrintAttributes;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public class ResolutionExt {
|
||||
@NonNull
|
||||
private String id;
|
||||
@NonNull
|
||||
private String label;
|
||||
private int verticalDpi;
|
||||
private int horizontalDpi;
|
||||
|
||||
public ResolutionExt(@NonNull String id, @NonNull String label, int verticalDpi, int horizontalDpi) {
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
this.verticalDpi = verticalDpi;
|
||||
this.horizontalDpi = horizontalDpi;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ResolutionExt fromResolution(@Nullable PrintAttributes.Resolution resolution) {
|
||||
if (resolution == null) {
|
||||
return null;
|
||||
}
|
||||
return new ResolutionExt(
|
||||
resolution.getId(),
|
||||
resolution.getLabel(),
|
||||
resolution.getVerticalDpi(),
|
||||
resolution.getHorizontalDpi()
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ResolutionExt fromMap(@Nullable Map<String, Object> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
String id = (String) map.get("id");
|
||||
String label = (String) map.get("label");
|
||||
int verticalDpi = (int) map.get("verticalDpi");
|
||||
int horizontalDpi = (int) map.get("horizontalDpi");
|
||||
return new ResolutionExt(id, label, verticalDpi, horizontalDpi);
|
||||
}
|
||||
|
||||
public PrintAttributes.Resolution toResolution() {
|
||||
return new PrintAttributes.Resolution(
|
||||
id, label, horizontalDpi, verticalDpi
|
||||
);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("id", id);
|
||||
obj.put("label", label);
|
||||
obj.put("verticalDpi", verticalDpi);
|
||||
obj.put("horizontalDpi", horizontalDpi);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@NonNull String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(@NonNull String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public int getVerticalDpi() {
|
||||
return verticalDpi;
|
||||
}
|
||||
|
||||
public void setVerticalDpi(int verticalDpi) {
|
||||
this.verticalDpi = verticalDpi;
|
||||
}
|
||||
|
||||
public int getHorizontalDpi() {
|
||||
return horizontalDpi;
|
||||
}
|
||||
|
||||
public void setHorizontalDpi(int horizontalDpi) {
|
||||
this.horizontalDpi = horizontalDpi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ResolutionExt that = (ResolutionExt) o;
|
||||
|
||||
if (verticalDpi != that.verticalDpi) return false;
|
||||
if (horizontalDpi != that.horizontalDpi) return false;
|
||||
if (!id.equals(that.id)) return false;
|
||||
return label.equals(that.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id.hashCode();
|
||||
result = 31 * result + label.hashCode();
|
||||
result = 31 * result + verticalDpi;
|
||||
result = 31 * result + horizontalDpi;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ResolutionExt{" +
|
||||
"id='" + id + '\'' +
|
||||
", label='" + label + '\'' +
|
||||
", verticalDpi=" + verticalDpi +
|
||||
", horizontalDpi=" + horizontalDpi +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.webview;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.ISettings;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -10,7 +12,9 @@ public class ContextMenuSettings implements ISettings<Object> {
|
|||
|
||||
public Boolean hideDefaultSystemContextMenuItems = false;
|
||||
|
||||
public ContextMenuSettings parse(Map<String, Object> options) {
|
||||
@NonNull
|
||||
@Override
|
||||
public ContextMenuSettings parse(@NonNull Map<String, Object> options) {
|
||||
for (Map.Entry<String, Object> pair : options.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
|
@ -28,14 +32,16 @@ public class ContextMenuSettings implements ISettings<Object> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> options = new HashMap<>();
|
||||
options.put("hideDefaultSystemContextMenuItems", hideDefaultSystemContextMenuItems);
|
||||
return options;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(Object obj) {
|
||||
public Map<String, Object> getRealSettings(@NonNull Object obj) {
|
||||
Map<String, Object> realOptions = toMap();
|
||||
return realOptions;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserDelegate;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobSettings;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ContentWorld;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.HitTestResult;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.URLRequest;
|
||||
|
@ -64,7 +65,8 @@ public interface InAppWebViewInterface {
|
|||
void onResume();
|
||||
void pauseTimers();
|
||||
void resumeTimers();
|
||||
void printCurrentPage();
|
||||
@Nullable
|
||||
String printCurrentPage(@Nullable PrintJobSettings settings);
|
||||
int getContentHeight();
|
||||
void getContentHeight(ValueCallback<Integer> callback);
|
||||
void zoomBy(float zoomFactor);
|
||||
|
|
|
@ -6,11 +6,16 @@ import android.util.Log;
|
|||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobController;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobSettings;
|
||||
import com.pichillilorenzo.flutter_inappwebview.webview.WebViewChannelDelegate;
|
||||
import com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview.InAppWebView;
|
||||
import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.JavaScriptBridgeJS;
|
||||
import com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview.InAppWebViewChromeClient;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
@ -58,8 +63,33 @@ public class JavaScriptBridgeInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
if (handlerName.equals("onPrint") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
inAppWebView.printCurrentPage();
|
||||
if (handlerName.equals("onPrintRequest") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
PrintJobSettings settings = new PrintJobSettings();
|
||||
settings.handledByClient = true;
|
||||
final String printJobId = inAppWebView.printCurrentPage(settings);
|
||||
if (inAppWebView != null && inAppWebView.channelDelegate != null) {
|
||||
inAppWebView.channelDelegate.onPrintRequest(inAppWebView.getUrl(), printJobId, new WebViewChannelDelegate.PrintRequestCallback() {
|
||||
@Override
|
||||
public boolean nonNullSuccess(@NonNull Boolean handledByClient) {
|
||||
return !handledByClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defaultBehaviour(@Nullable Boolean handledByClient) {
|
||||
PrintJobController printJobController = PrintJobManager.jobs.get(printJobId);
|
||||
if (printJobController != null) {
|
||||
printJobController.disposeNoCancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
|
||||
Log.e(LOG_TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : ""));
|
||||
defaultBehaviour(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
} else if (handlerName.equals("callAsyncJavaScript")) {
|
||||
try {
|
||||
JSONArray arguments = new JSONArray(args);
|
||||
|
|
|
@ -15,6 +15,7 @@ import androidx.webkit.WebViewFeature;
|
|||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.in_app_browser.InAppBrowserSettings;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobSettings;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.BaseCallbackResultImpl;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
|
||||
import com.pichillilorenzo.flutter_inappwebview.types.ClientCertChallenge;
|
||||
|
@ -344,9 +345,15 @@ public class WebViewChannelDelegate extends ChannelDelegateImpl {
|
|||
break;
|
||||
case "printCurrentPage":
|
||||
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
webView.printCurrentPage();
|
||||
PrintJobSettings settings = new PrintJobSettings();
|
||||
Map<String, Object> settingsMap = (Map<String, Object>) call.argument("settings");
|
||||
if (settingsMap != null) {
|
||||
settings.parse(settingsMap);
|
||||
}
|
||||
result.success(webView.printCurrentPage(settings));
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
case "getContentHeight":
|
||||
if (webView instanceof InAppWebView) {
|
||||
|
@ -1230,6 +1237,26 @@ public class WebViewChannelDelegate extends ChannelDelegateImpl {
|
|||
channel.invokeMethod("onCallJsHandler", obj, callback);
|
||||
}
|
||||
|
||||
public static class PrintRequestCallback extends BaseCallbackResultImpl<Boolean> {
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean decodeResult(@Nullable Object obj) {
|
||||
return (obj instanceof Boolean) && (boolean) obj;
|
||||
}
|
||||
}
|
||||
|
||||
public void onPrintRequest(String url, String printJobId, @NonNull PrintRequestCallback callback) {
|
||||
MethodChannel channel = getChannel();
|
||||
if (channel == null) {
|
||||
callback.defaultBehaviour(null);
|
||||
return;
|
||||
}
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("url", url);
|
||||
obj.put("printJobId", printJobId);
|
||||
channel.invokeMethod("onPrintRequest", obj, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
|
|
@ -55,6 +55,9 @@ import androidx.webkit.WebViewCompat;
|
|||
import androidx.webkit.WebViewFeature;
|
||||
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobController;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobManager;
|
||||
import com.pichillilorenzo.flutter_inappwebview.print_job.PrintJobSettings;
|
||||
import com.pichillilorenzo.flutter_inappwebview.webview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.R;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
@ -1251,25 +1254,75 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie
|
|||
webSettings.setBuiltInZoomControls(enabled);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public void printCurrentPage() {
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
@Nullable
|
||||
public String printCurrentPage(@Nullable PrintJobSettings settings) {
|
||||
if (plugin != null && plugin.activity != null) {
|
||||
// Get a PrintManager instance
|
||||
PrintManager printManager = (PrintManager) plugin.activity.getSystemService(Context.PRINT_SERVICE);
|
||||
|
||||
if (printManager != null) {
|
||||
String jobName = getTitle() + " Document";
|
||||
PrintAttributes.Builder builder = new PrintAttributes.Builder();
|
||||
|
||||
String jobName = (getTitle() != null ? getTitle() : getUrl()) + " Document";
|
||||
|
||||
if (settings != null) {
|
||||
if (settings.jobName != null && !settings.jobName.isEmpty()) {
|
||||
jobName = settings.jobName;
|
||||
}
|
||||
if (settings.orientation != null) {
|
||||
int orientation = settings.orientation;
|
||||
switch (orientation) {
|
||||
case 0:
|
||||
// PORTRAIT
|
||||
builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_PORTRAIT);
|
||||
break;
|
||||
case 1:
|
||||
// LANDSCAPE
|
||||
builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (settings.margins != null) {
|
||||
// // for some reason, Android doesn't set the margins
|
||||
// builder.setMinMargins(settings.margins.toMargins());
|
||||
// }
|
||||
if (settings.mediaSize != null) {
|
||||
builder.setMediaSize(settings.mediaSize.toMediaSize());
|
||||
}
|
||||
if (settings.colorMode != null) {
|
||||
builder.setColorMode(settings.colorMode);
|
||||
}
|
||||
if (settings.duplexMode != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
builder.setDuplexMode(settings.duplexMode);
|
||||
}
|
||||
if (settings.resolution != null) {
|
||||
builder.setResolution(settings.resolution.toResolution());
|
||||
}
|
||||
}
|
||||
|
||||
// Get a printCurrentPage adapter instance
|
||||
PrintDocumentAdapter printAdapter = createPrintDocumentAdapter(jobName);
|
||||
PrintDocumentAdapter printAdapter;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
printAdapter = createPrintDocumentAdapter(jobName);
|
||||
} else {
|
||||
printAdapter = createPrintDocumentAdapter();
|
||||
}
|
||||
|
||||
// Create a printCurrentPage job with name and adapter instance
|
||||
printManager.print(jobName, printAdapter,
|
||||
new PrintAttributes.Builder().build());
|
||||
android.print.PrintJob job = printManager.print(jobName, printAdapter, builder.build());
|
||||
|
||||
if (settings != null && settings.handledByClient) {
|
||||
String id = UUID.randomUUID().toString();
|
||||
PrintJobController printJobController = new PrintJobController(id, job, settings, plugin);
|
||||
PrintJobManager.jobs.put(printJobController.id, printJobController);
|
||||
return id;
|
||||
}
|
||||
} else {
|
||||
Log.e(LOG_TAG, "No PrintManager available");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.os.Build;
|
|||
import android.view.View;
|
||||
import android.webkit.WebSettings;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.webkit.WebSettingsCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
@ -112,8 +113,9 @@ public class InAppWebViewSettings implements ISettings<InAppWebViewInterface> {
|
|||
@Nullable
|
||||
public String horizontalScrollbarTrackColor;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InAppWebViewSettings parse(Map<String, Object> settings) {
|
||||
public InAppWebViewSettings parse(@NonNull Map<String, Object> settings) {
|
||||
for (Map.Entry<String, Object> pair : settings.entrySet()) {
|
||||
String key = pair.getKey();
|
||||
Object value = pair.getValue();
|
||||
|
@ -374,6 +376,7 @@ public class InAppWebViewSettings implements ISettings<InAppWebViewInterface> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
|
@ -462,8 +465,9 @@ public class InAppWebViewSettings implements ISettings<InAppWebViewInterface> {
|
|||
return settings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Map<String, Object> getRealSettings(InAppWebViewInterface inAppWebView) {
|
||||
public Map<String, Object> getRealSettings(@NonNull InAppWebViewInterface inAppWebView) {
|
||||
Map<String, Object> realSettings = toMap();
|
||||
if (inAppWebView instanceof InAppWebView) {
|
||||
InAppWebView webView = (InAppWebView) inAppWebView;
|
||||
|
|
|
@ -27,7 +27,8 @@ import io.flutter.plugin.common.MethodChannel;
|
|||
public class WebMessageChannel implements Disposable {
|
||||
protected static final String LOG_TAG = "WebMessageChannel";
|
||||
public static final String METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_web_message_channel_";
|
||||
|
||||
|
||||
@NonNull
|
||||
public String id;
|
||||
@Nullable
|
||||
public WebMessageChannelChannelDelegate channelDelegate;
|
||||
|
|
|
@ -30,7 +30,7 @@ public class WebMessageChannelChannelDelegate extends ChannelDelegateImpl {
|
|||
final Integer index = (Integer) call.argument("index");
|
||||
webMessageChannel.setWebMessageCallbackForInAppWebView(index, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "postMessage":
|
||||
|
@ -39,7 +39,7 @@ public class WebMessageChannelChannelDelegate extends ChannelDelegateImpl {
|
|||
Map<String, Object> message = (Map<String, Object>) call.argument("message");
|
||||
webMessageChannel.postMessageForInAppWebView(index, message, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
case "close":
|
||||
|
@ -47,7 +47,7 @@ public class WebMessageChannelChannelDelegate extends ChannelDelegateImpl {
|
|||
Integer index = (Integer) call.argument("index");
|
||||
webMessageChannel.closeForInAppWebView(index, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -31,7 +31,7 @@ public class WebMessageListenerChannelDelegate extends ChannelDelegateImpl {
|
|||
String message = (String) call.argument("message");
|
||||
webMessageListener.postMessageForInAppWebView(message, result);
|
||||
} else {
|
||||
result.success(true);
|
||||
result.success(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -29,8 +29,9 @@ void onPrint() {
|
|||
onLoadStop: (controller, url) async {
|
||||
await controller.evaluateJavascript(source: "window.print();");
|
||||
},
|
||||
onPrint: (controller, url) {
|
||||
onPrintRequest: (controller, url, printJob) async {
|
||||
onPrintCompleter.complete(url?.toString());
|
||||
return false;
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -114,7 +114,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
InAppWebView(
|
||||
key: webViewKey,
|
||||
initialUrlRequest:
|
||||
URLRequest(url: Uri.parse('https://flutter.dev/')),
|
||||
URLRequest(url: Uri.parse('https://github.com/flutter/')),
|
||||
// initialUrlRequest:
|
||||
// URLRequest(url: Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html')),
|
||||
// initialFile: "assets/index.html",
|
||||
|
|
|
@ -14,10 +14,14 @@ public class ISettings<T>: NSObject {
|
|||
super.init()
|
||||
}
|
||||
|
||||
func parse(settings: [String: Any?]) -> ISettings {
|
||||
func parse(settings: [String: Any?]) -> ISettings<T> {
|
||||
for (key, value) in settings {
|
||||
if !(value is NSNull), value != nil, self.responds(to: Selector(key)) {
|
||||
self.setValue(value, forKey: key)
|
||||
if !(value is NSNull), value != nil {
|
||||
if self.responds(to: Selector(key)) {
|
||||
self.setValue(value, forKey: key)
|
||||
} else if self.responds(to: Selector("_" + key)) {
|
||||
self.setValue(value, forKey: "_" + key)
|
||||
}
|
||||
}
|
||||
}
|
||||
return self
|
||||
|
@ -25,15 +29,15 @@ public class ISettings<T>: NSObject {
|
|||
|
||||
func toMap() -> [String: Any?] {
|
||||
var settings: [String: Any?] = [:]
|
||||
var counts = UInt32();
|
||||
let properties = class_copyPropertyList(object_getClass(self), &counts);
|
||||
var counts = UInt32()
|
||||
let properties = class_copyPropertyList(object_getClass(self), &counts)
|
||||
for i in 0..<counts {
|
||||
let property = properties?.advanced(by: Int(i)).pointee;
|
||||
|
||||
let cName = property_getName(property!);
|
||||
let name = String(cString: cName)
|
||||
|
||||
settings[name] = self.value(forKey: name)
|
||||
if let property = properties?.advanced(by: Int(i)).pointee {
|
||||
let cName = property_getName(property)
|
||||
let name = String(cString: cName)
|
||||
let key = !name.hasPrefix("_") ? name : String(name.suffix(from: name.index(name.startIndex, offsetBy: 1)))
|
||||
settings[key] = self.value(forKey: key)
|
||||
}
|
||||
}
|
||||
free(properties)
|
||||
return settings
|
||||
|
|
|
@ -724,7 +724,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
|||
if let with = with {
|
||||
snapshotConfiguration = WKSnapshotConfiguration()
|
||||
if let rect = with["rect"] as? [String: Double] {
|
||||
snapshotConfiguration!.rect = CGRect(x: rect["x"]!, y: rect["y"]!, width: rect["width"]!, height: rect["height"]!)
|
||||
snapshotConfiguration!.rect = CGRect.fromMap(map: rect)
|
||||
}
|
||||
if let snapshotWidth = with["snapshotWidth"] as? Double {
|
||||
snapshotConfiguration!.snapshotWidth = NSNumber(value: snapshotWidth)
|
||||
|
@ -762,7 +762,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
|||
let pdfConfiguration: WKPDFConfiguration = .init()
|
||||
if let configuration = configuration {
|
||||
if let rect = configuration["rect"] as? [String: Double] {
|
||||
pdfConfiguration.rect = CGRect(x: rect["x"]!, y: rect["y"]!, width: rect["width"]!, height: rect["height"]!)
|
||||
pdfConfiguration.rect = CGRect.fromMap(map: rect)
|
||||
}
|
||||
}
|
||||
createPDF(configuration: pdfConfiguration) { (result) in
|
||||
|
@ -2584,9 +2584,29 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
|
|||
} else if message.name == "callHandler" {
|
||||
let body = message.body as! [String: Any?]
|
||||
let handlerName = body["handlerName"] as! String
|
||||
if handlerName == "onPrint" {
|
||||
printCurrentPage(printCompletionHandler: nil)
|
||||
|
||||
if handlerName == "onPrintRequest" {
|
||||
let settings = PrintJobSettings()
|
||||
settings.handledByClient = true
|
||||
if let printJobId = printCurrentPage(settings: settings) {
|
||||
let callback = WebViewChannelDelegate.PrintRequestCallback()
|
||||
callback.nonNullSuccess = { (handledByClient: Bool) in
|
||||
return !handledByClient
|
||||
}
|
||||
callback.defaultBehaviour = { (handledByClient: Bool?) in
|
||||
if let printJob = PrintJobManager.jobs[printJobId] {
|
||||
printJob?.disposeNoDismiss()
|
||||
}
|
||||
}
|
||||
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
|
||||
print(code + ", " + (message ?? ""))
|
||||
callback?.defaultBehaviour(nil)
|
||||
}
|
||||
channelDelegate?.onPrintRequest(url: url, printJobId: printJobId, callback: callback)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let _callHandlerID = body["_callHandlerID"] as! Int64
|
||||
let args = body["args"] as! String
|
||||
|
||||
|
@ -2724,25 +2744,79 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
|
|||
}
|
||||
}
|
||||
|
||||
public func printCurrentPage(printCompletionHandler: ((_ completed: Bool, _ error: Error?) -> Void)?) {
|
||||
public func printCurrentPage(settings: PrintJobSettings? = nil,
|
||||
completionHandler: UIPrintInteractionController.CompletionHandler? = nil) -> String? {
|
||||
var printJobId: String? = nil
|
||||
if let settings = settings, settings.handledByClient {
|
||||
printJobId = NSUUID().uuidString
|
||||
}
|
||||
|
||||
let printController = UIPrintInteractionController.shared
|
||||
let printFormatter = self.viewPrintFormatter()
|
||||
if let settings = settings {
|
||||
if let margins = settings.margins {
|
||||
printFormatter.perPageContentInsets = margins
|
||||
}
|
||||
if let maximumContentHeight = settings.maximumContentHeight {
|
||||
printFormatter.maximumContentHeight = maximumContentHeight
|
||||
}
|
||||
if let maximumContentWidth = settings.maximumContentWidth {
|
||||
printFormatter.maximumContentWidth = maximumContentWidth
|
||||
}
|
||||
}
|
||||
printController.printFormatter = printFormatter
|
||||
|
||||
let completionHandler: UIPrintInteractionController.CompletionHandler = { (printController, completed, error) in
|
||||
if !completed {
|
||||
if let e = error {
|
||||
print("[PRINT] Failed: \(e.localizedDescription)")
|
||||
} else {
|
||||
print("[PRINT] Canceled")
|
||||
printController.printInfo = UIPrintInfo(dictionary: nil)
|
||||
if let printInfo = printController.printInfo {
|
||||
printInfo.jobName = settings?.jobName ?? (title ?? url?.absoluteString ?? "") + " Document"
|
||||
if let settings = settings {
|
||||
if let orientationValue = settings.orientation,
|
||||
let orientation = UIPrintInfo.Orientation.init(rawValue: orientationValue) {
|
||||
printInfo.orientation = orientation
|
||||
}
|
||||
if let duplexModeValue = settings.duplexMode,
|
||||
let duplexMode = UIPrintInfo.Duplex.init(rawValue: duplexModeValue) {
|
||||
printInfo.duplex = duplexMode
|
||||
}
|
||||
if let outputTypeValue = settings.outputType,
|
||||
let outputType = UIPrintInfo.OutputType.init(rawValue: outputTypeValue) {
|
||||
printInfo.outputType = outputType
|
||||
}
|
||||
}
|
||||
if let callback = printCompletionHandler {
|
||||
callback(completed, error)
|
||||
}
|
||||
}
|
||||
|
||||
printController.present(animated: true, completionHandler: completionHandler)
|
||||
// initialize print renderer and set its formatter
|
||||
let printRenderer = CustomUIPrintPageRenderer(numberOfPage: settings?.numberOfPages,
|
||||
forceRenderingQuality: settings?.forceRenderingQuality)
|
||||
printRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
|
||||
if let settings = settings {
|
||||
if let footerHeight = settings.footerHeight {
|
||||
printRenderer.footerHeight = footerHeight
|
||||
}
|
||||
if let headerHeight = settings.headerHeight {
|
||||
printRenderer.headerHeight = headerHeight
|
||||
}
|
||||
}
|
||||
printController.printPageRenderer = printRenderer
|
||||
|
||||
if let settings = settings {
|
||||
printController.showsNumberOfCopies = settings.showsNumberOfCopies
|
||||
printController.showsPaperSelectionForLoadedPapers = settings.showsPaperSelectionForLoadedPapers
|
||||
if #available(iOS 15.0, *) {
|
||||
printController.showsPaperOrientation = settings.showsPaperOrientation
|
||||
}
|
||||
}
|
||||
|
||||
let animated = settings?.animated ?? true
|
||||
if let id = printJobId {
|
||||
let printJob = PrintJobController(id: id, job: printController, settings: settings)
|
||||
PrintJobManager.jobs[id] = printJob
|
||||
printJob.present(animated: animated, completionHandler: completionHandler)
|
||||
} else {
|
||||
printController.present(animated: animated, completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
return printJobId
|
||||
}
|
||||
|
||||
public func getContentHeight() -> Int64 {
|
||||
|
|
|
@ -46,8 +46,8 @@ public class InAppWebViewSettings: ISettings<InAppWebView> {
|
|||
var ignoresViewportScaleLimits = false
|
||||
var allowsInlineMediaPlayback = false
|
||||
var allowsPictureInPictureMediaPlayback = true
|
||||
var isFraudulentWebsiteWarningEnabled = true;
|
||||
var selectionGranularity = 0;
|
||||
var isFraudulentWebsiteWarningEnabled = true
|
||||
var selectionGranularity = 0
|
||||
var dataDetectorTypes: [String] = ["NONE"] // WKDataDetectorTypeNone
|
||||
var preferredContentMode = 0
|
||||
var sharedCookiesEnabled = false
|
||||
|
|
|
@ -273,16 +273,13 @@ public class WebViewChannelDelegate : ChannelDelegate {
|
|||
break
|
||||
case "printCurrentPage":
|
||||
if let webView = webView {
|
||||
webView.printCurrentPage(printCompletionHandler: {(completed, error) in
|
||||
if !completed, let err = error {
|
||||
print(err.localizedDescription)
|
||||
result(false)
|
||||
return
|
||||
}
|
||||
result(true)
|
||||
})
|
||||
let settings = PrintJobSettings()
|
||||
if let settingsMap = arguments!["settings"] as? [String: Any?] {
|
||||
let _ = settings.parse(settings: settingsMap)
|
||||
}
|
||||
result(webView.printCurrentPage(settings: settings))
|
||||
} else {
|
||||
result(false)
|
||||
result(nil)
|
||||
}
|
||||
break
|
||||
case "getContentHeight":
|
||||
|
@ -1054,6 +1051,27 @@ public class WebViewChannelDelegate : ChannelDelegate {
|
|||
channel?.invokeMethod("onMicrophoneCaptureStateChanged", arguments: arguments)
|
||||
}
|
||||
|
||||
public class PrintRequestCallback : BaseCallbackResult<Bool> {
|
||||
override init() {
|
||||
super.init()
|
||||
self.decodeResult = { (obj: Any?) in
|
||||
return obj is Bool && obj as! Bool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func onPrintRequest(url: URL?, printJobId: String?, callback: PrintRequestCallback) {
|
||||
guard let channel = channel else {
|
||||
callback.defaultBehaviour(nil)
|
||||
return
|
||||
}
|
||||
let arguments = [
|
||||
"url": url?.absoluteString,
|
||||
"printJobId": printJobId,
|
||||
]
|
||||
channel.invokeMethod("onPrintRequest", arguments: arguments, callback: callback)
|
||||
}
|
||||
|
||||
public override func dispose() {
|
||||
super.dispose()
|
||||
webView = nil
|
||||
|
|
|
@ -19,6 +19,6 @@ let PRINT_JS_PLUGIN_SCRIPT = PluginScript(
|
|||
|
||||
let PRINT_JS_SOURCE = """
|
||||
window.print = function() {
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler("onPrint", window.location.href);
|
||||
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler("onPrintRequest", window.location.href);
|
||||
}
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// CustomUIPrintPageRenderer.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 10/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class CustomUIPrintPageRenderer : UIPrintPageRenderer {
|
||||
private var _numberOfPages: Int?
|
||||
private var forceRenderingQuality: Int?
|
||||
|
||||
public init(numberOfPage: Int? = nil, forceRenderingQuality: Int? = nil) {
|
||||
super.init()
|
||||
self._numberOfPages = numberOfPage
|
||||
self.forceRenderingQuality = forceRenderingQuality
|
||||
}
|
||||
|
||||
open override var numberOfPages: Int {
|
||||
get {
|
||||
return _numberOfPages ?? super.numberOfPages
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.5, *)
|
||||
open override func currentRenderingQuality(forRequested requestedRenderingQuality: UIPrintRenderingQuality) -> UIPrintRenderingQuality {
|
||||
if let forceRenderingQuality = forceRenderingQuality,
|
||||
let quality = UIPrintRenderingQuality.init(rawValue: forceRenderingQuality) {
|
||||
return quality
|
||||
}
|
||||
return super.currentRenderingQuality(forRequested: requestedRenderingQuality)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// PrintAttributes.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 10/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class PrintAttributes : NSObject {
|
||||
var orientation: UIPrintInfo.Orientation?
|
||||
var duplex: UIPrintInfo.Duplex?
|
||||
var outputType: UIPrintInfo.OutputType?
|
||||
var margins: UIEdgeInsets?
|
||||
var footerHeight: Double?
|
||||
var headerHeight: Double?
|
||||
var paperRect: CGRect?
|
||||
var printableRect: CGRect?
|
||||
var maximumContentHeight: Double?
|
||||
var maximumContentWidth: Double?
|
||||
|
||||
public init(fromPrintJobController: PrintJobController) {
|
||||
super.init()
|
||||
if let printPageRenderer = fromPrintJobController.printPageRenderer {
|
||||
footerHeight = printPageRenderer.footerHeight
|
||||
headerHeight = printPageRenderer.headerHeight
|
||||
paperRect = printPageRenderer.paperRect
|
||||
printableRect = printPageRenderer.printableRect
|
||||
}
|
||||
if let printFormatter = fromPrintJobController.printFormatter {
|
||||
maximumContentHeight = printFormatter.maximumContentHeight
|
||||
maximumContentWidth = printFormatter.maximumContentWidth
|
||||
margins = printFormatter.perPageContentInsets
|
||||
}
|
||||
if let job = fromPrintJobController.job, let printInfo = job.printInfo {
|
||||
orientation = printInfo.orientation
|
||||
duplex = printInfo.duplex
|
||||
outputType = printInfo.outputType
|
||||
}
|
||||
}
|
||||
|
||||
public func toMap () -> [String:Any?] {
|
||||
return [
|
||||
"footerHeight": footerHeight,
|
||||
"headerHeight": headerHeight,
|
||||
"paperRect": paperRect?.toMap(),
|
||||
"printableRect": printableRect?.toMap(),
|
||||
"margins": margins?.toMap(),
|
||||
"maximumContentHeight": maximumContentHeight,
|
||||
"maximumContentWidth": maximumContentWidth,
|
||||
"orientation": orientation?.rawValue,
|
||||
"duplex": duplex?.rawValue,
|
||||
"outputType": outputType?.rawValue
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// PrintJobChannelDelegate.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 09/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class PrintJobChannelDelegate : ChannelDelegate {
|
||||
private weak var printJobController: PrintJobController?
|
||||
|
||||
public init(printJobController: PrintJobController, channel: FlutterMethodChannel) {
|
||||
super.init(channel: channel)
|
||||
self.printJobController = printJobController
|
||||
}
|
||||
|
||||
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
let arguments = call.arguments as? NSDictionary
|
||||
|
||||
switch call.method {
|
||||
case "dismiss":
|
||||
if let job = printJobController?.job {
|
||||
let animated = arguments!["animated"] as! Bool
|
||||
job.dismiss(animated: animated)
|
||||
result(true)
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
break
|
||||
case "getInfo":
|
||||
if let printJobController = printJobController {
|
||||
result(printJobController.getInfo()?.toMap())
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
break
|
||||
case "dispose":
|
||||
if let printJobController = printJobController {
|
||||
printJobController.dispose()
|
||||
result(true)
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func onComplete(completed: Bool, error: Error?) {
|
||||
let arguments: [String: Any?] = [
|
||||
"completed": completed,
|
||||
"error": error?.localizedDescription
|
||||
]
|
||||
channel?.invokeMethod("onComplete", arguments: arguments)
|
||||
}
|
||||
|
||||
public override func dispose() {
|
||||
super.dispose()
|
||||
printJobController = nil
|
||||
}
|
||||
|
||||
deinit {
|
||||
dispose()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
//
|
||||
// PrintJob.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 09/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum PrintJobState: Int {
|
||||
case created = 1
|
||||
case started = 3
|
||||
case completed = 5
|
||||
case failed = 6
|
||||
case canceled = 7
|
||||
}
|
||||
|
||||
public class PrintJobController : NSObject, Disposable, UIPrintInteractionControllerDelegate {
|
||||
static let METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_printjobcontroller_"
|
||||
var id: String
|
||||
var job: UIPrintInteractionController?
|
||||
var settings: PrintJobSettings?
|
||||
var printFormatter: UIPrintFormatter?
|
||||
var printPageRenderer: UIPrintPageRenderer?
|
||||
var channelDelegate: PrintJobChannelDelegate?
|
||||
var state = PrintJobState.created
|
||||
var creationTime = Int64(Date().timeIntervalSince1970 * 1000)
|
||||
|
||||
public init(id: String, job: UIPrintInteractionController? = nil, settings: PrintJobSettings? = nil) {
|
||||
self.id = id
|
||||
super.init()
|
||||
self.job = job
|
||||
self.settings = settings
|
||||
self.printFormatter = job?.printFormatter
|
||||
self.printPageRenderer = job?.printPageRenderer
|
||||
self.job?.delegate = self
|
||||
let channel = FlutterMethodChannel(name: PrintJobController.METHOD_CHANNEL_NAME_PREFIX + id,
|
||||
binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
|
||||
self.channelDelegate = PrintJobChannelDelegate(printJobController: self, channel: channel)
|
||||
}
|
||||
|
||||
public func printInteractionControllerWillStartJob(_ printInteractionController: UIPrintInteractionController) {
|
||||
state = .started
|
||||
}
|
||||
|
||||
public func present(animated: Bool, completionHandler: UIPrintInteractionController.CompletionHandler? = nil) {
|
||||
guard let job = job else {
|
||||
return
|
||||
}
|
||||
|
||||
job.present(animated: animated, completionHandler: { [weak self] (printController, completed, error) in
|
||||
if !completed {
|
||||
if let _ = error {
|
||||
self?.state = .failed
|
||||
} else {
|
||||
self?.state = .canceled
|
||||
}
|
||||
} else {
|
||||
self?.state = .completed
|
||||
}
|
||||
self?.channelDelegate?.onComplete(completed: completed, error: error)
|
||||
if let completionHandler = completionHandler {
|
||||
completionHandler(printController, completed, error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func getInfo() -> PrintJobInfo? {
|
||||
guard let _ = job else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return PrintJobInfo.init(fromPrintJobController: self)
|
||||
}
|
||||
|
||||
public func disposeNoDismiss() {
|
||||
channelDelegate?.dispose()
|
||||
channelDelegate = nil
|
||||
printFormatter = nil
|
||||
printPageRenderer = nil
|
||||
job?.delegate = nil
|
||||
job = nil
|
||||
PrintJobManager.jobs[id] = nil
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
channelDelegate?.dispose()
|
||||
channelDelegate = nil
|
||||
printFormatter = nil
|
||||
printPageRenderer = nil
|
||||
job?.delegate = nil
|
||||
job?.dismiss(animated: false)
|
||||
job = nil
|
||||
PrintJobManager.jobs[id] = nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// PrintJobInfo.swift
|
||||
// flutter_downloader
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 10/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class PrintJobInfo : NSObject {
|
||||
var state: PrintJobState
|
||||
var attributes: PrintAttributes
|
||||
var creationTime: Int64
|
||||
var numberOfPages: Int?
|
||||
var label: String?
|
||||
var printerId: String?
|
||||
|
||||
public init(fromPrintJobController: PrintJobController) {
|
||||
state = fromPrintJobController.state
|
||||
creationTime = fromPrintJobController.creationTime
|
||||
attributes = PrintAttributes.init(fromPrintJobController: fromPrintJobController)
|
||||
super.init()
|
||||
if let printPageRenderer = fromPrintJobController.printPageRenderer {
|
||||
numberOfPages = printPageRenderer.numberOfPages
|
||||
}
|
||||
if let job = fromPrintJobController.job, let printInfo = job.printInfo {
|
||||
label = printInfo.jobName
|
||||
printerId = printInfo.printerID
|
||||
}
|
||||
}
|
||||
|
||||
public func toMap () -> [String:Any?] {
|
||||
return [
|
||||
"state": state.rawValue,
|
||||
"attributes": attributes.toMap(),
|
||||
"copies": nil,
|
||||
"numberOfPages": numberOfPages,
|
||||
"creationTime": creationTime,
|
||||
"label": label,
|
||||
"printerId": printerId
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// PrintJobManager.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 09/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class PrintJobManager: NSObject, Disposable {
|
||||
static var jobs: [String: PrintJobController?] = [:]
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func dispose() {
|
||||
let jobs = PrintJobManager.jobs.values
|
||||
jobs.forEach { (job: PrintJobController?) in
|
||||
job?.dispose()
|
||||
}
|
||||
PrintJobManager.jobs.removeAll()
|
||||
}
|
||||
|
||||
deinit {
|
||||
dispose()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
//
|
||||
// PrintJobSettings.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 09/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers
|
||||
public class PrintJobSettings: ISettings<PrintJobController> {
|
||||
|
||||
public var handledByClient = false
|
||||
public var jobName: String?
|
||||
public var animated = true
|
||||
public var _orientation: NSNumber?
|
||||
public var orientation: Int? {
|
||||
get {
|
||||
return _orientation?.intValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_orientation = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_orientation = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var _numberOfPages: NSNumber?
|
||||
public var numberOfPages: Int? {
|
||||
get {
|
||||
return _numberOfPages?.intValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_numberOfPages = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_numberOfPages = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var _forceRenderingQuality: NSNumber?
|
||||
public var forceRenderingQuality: Int? {
|
||||
get {
|
||||
return _forceRenderingQuality?.intValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_forceRenderingQuality = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_forceRenderingQuality = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var margins: UIEdgeInsets?
|
||||
public var _duplexMode: NSNumber?
|
||||
public var duplexMode: Int? {
|
||||
get {
|
||||
return _duplexMode?.intValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_duplexMode = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_duplexMode = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var _outputType: NSNumber?
|
||||
public var outputType: Int? {
|
||||
get {
|
||||
return _outputType?.intValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_outputType = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_outputType = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var showsNumberOfCopies = true
|
||||
public var showsPaperSelectionForLoadedPapers = false
|
||||
public var showsPaperOrientation = true
|
||||
public var _maximumContentHeight: NSNumber?
|
||||
public var maximumContentHeight: Double? {
|
||||
get {
|
||||
return _maximumContentHeight?.doubleValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_maximumContentHeight = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_maximumContentHeight = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var _maximumContentWidth: NSNumber?
|
||||
public var maximumContentWidth: Double? {
|
||||
get {
|
||||
return _maximumContentWidth?.doubleValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_maximumContentWidth = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_maximumContentWidth = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var _footerHeight: NSNumber?
|
||||
public var footerHeight: Double? {
|
||||
get {
|
||||
return _footerHeight?.doubleValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_footerHeight = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_footerHeight = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
public var _headerHeight: NSNumber?
|
||||
public var headerHeight: Double? {
|
||||
get {
|
||||
return _headerHeight?.doubleValue
|
||||
}
|
||||
set {
|
||||
if let newValue = newValue {
|
||||
_headerHeight = NSNumber.init(value: newValue)
|
||||
} else {
|
||||
_headerHeight = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override init(){
|
||||
super.init()
|
||||
}
|
||||
|
||||
override func parse(settings: [String: Any?]) -> PrintJobSettings {
|
||||
let _ = super.parse(settings: settings)
|
||||
if let marginsMap = settings["margins"] as? [String : Double] {
|
||||
margins = UIEdgeInsets.fromMap(map: marginsMap)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
override func getRealSettings(obj: PrintJobController?) -> [String: Any?] {
|
||||
var realOptions: [String: Any?] = toMap()
|
||||
return realOptions
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
var headlessInAppWebViewManager: HeadlessInAppWebViewManager?
|
||||
var chromeSafariBrowserManager: ChromeSafariBrowserManager?
|
||||
var webAuthenticationSessionManager: WebAuthenticationSessionManager?
|
||||
var printJobManager: PrintJobManager?
|
||||
|
||||
var webViewControllers: [String: InAppBrowserWebViewController?] = [:]
|
||||
var safariViewControllers: [String: Any?] = [:]
|
||||
|
@ -58,6 +59,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
myWebStorageManager = MyWebStorageManager(registrar: registrar)
|
||||
}
|
||||
webAuthenticationSessionManager = WebAuthenticationSessionManager(registrar: registrar)
|
||||
printJobManager = PrintJobManager()
|
||||
}
|
||||
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
|
@ -87,5 +89,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
}
|
||||
webAuthenticationSessionManager?.dispose()
|
||||
webAuthenticationSessionManager = nil
|
||||
printJobManager?.dispose()
|
||||
printJobManager = nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// CGRect.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 10/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension CGRect {
|
||||
public static func fromMap(map: [String: Double]) -> CGRect {
|
||||
return CGRect(x: map["x"]!, y: map["y"]!, width: map["width"]!, height: map["height"]!)
|
||||
}
|
||||
|
||||
public func toMap () -> [String:Any?] {
|
||||
return [
|
||||
"x": minX,
|
||||
"y": minY,
|
||||
"width": width,
|
||||
"height": height
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// UIEdgeInsets.swift
|
||||
// flutter_inappwebview
|
||||
//
|
||||
// Created by Lorenzo Pichilli on 11/05/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension UIEdgeInsets {
|
||||
public static func fromMap(map: [String: Double]) -> UIEdgeInsets {
|
||||
return UIEdgeInsets.init(top: map["top"]!, left: map["left"]!, bottom: map["bottom"]!, right: map["right"]!)
|
||||
}
|
||||
|
||||
public func toMap () -> [String:Any?] {
|
||||
return [
|
||||
"top": top,
|
||||
"right": self.right,
|
||||
"bottom": bottom,
|
||||
"left": self.left
|
||||
]
|
||||
}
|
||||
}
|
|
@ -124,7 +124,7 @@ window.flutter_inappwebview = {
|
|||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onPrint', viewId, [iframeUrl]);
|
||||
window.flutter_inappwebview.nativeCommunication('onPrintRequest', viewId, [iframeUrl]);
|
||||
originalPrint.call(iframe.contentWindow);
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import '../in_app_webview/in_app_webview_controller.dart';
|
|||
import '../in_app_webview/in_app_webview_settings.dart';
|
||||
|
||||
import '../util.dart';
|
||||
import '../print_job/main.dart';
|
||||
import 'in_app_browser_settings.dart';
|
||||
|
||||
class InAppBrowserAlreadyOpenedException implements Exception {
|
||||
|
@ -724,14 +725,24 @@ class InAppBrowser {
|
|||
///- iOS
|
||||
void onUpdateVisitedHistory(Uri? url, bool? isReload) {}
|
||||
|
||||
///Use [onPrintRequest] instead
|
||||
@Deprecated("Use onPrintRequest instead")
|
||||
void onPrint(Uri? url) {}
|
||||
|
||||
///Event fired when `window.print()` is called from JavaScript side.
|
||||
///Return `true` if you want to handle the print job.
|
||||
///Otherwise return `false`, so the [PrintJobController] will be handled and disposed automatically by the system.
|
||||
///
|
||||
///[url] represents the url on which is called.
|
||||
///
|
||||
///[printJobController] represents the controller of the print job created.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
void onPrint(Uri? url) {}
|
||||
Future<bool?>? onPrintRequest(Uri? url, PrintJobController? printJobController) {
|
||||
return null;
|
||||
}
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
///
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:flutter_inappwebview/src/util.dart';
|
|||
|
||||
import '../context_menu.dart';
|
||||
import '../types/main.dart';
|
||||
import '../print_job/main.dart';
|
||||
import 'webview.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
import 'in_app_webview_settings.dart';
|
||||
|
@ -74,7 +75,8 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.onScrollChanged,
|
||||
@Deprecated('Use onDownloadStartRequest instead') this.onDownloadStart,
|
||||
this.onDownloadStartRequest,
|
||||
@Deprecated('Use onLoadResourceWithCustomScheme instead') this.onLoadResourceCustomScheme,
|
||||
@Deprecated('Use onLoadResourceWithCustomScheme instead')
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onLoadResourceWithCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
|
@ -90,7 +92,8 @@ class HeadlessInAppWebView implements WebView {
|
|||
this.onAjaxProgress,
|
||||
this.shouldInterceptFetchRequest,
|
||||
this.onUpdateVisitedHistory,
|
||||
this.onPrint,
|
||||
@Deprecated("Use onPrintRequest instead") this.onPrint,
|
||||
this.onPrintRequest,
|
||||
this.onLongPressHitTestResult,
|
||||
this.onEnterFullscreen,
|
||||
this.onExitFullscreen,
|
||||
|
@ -460,7 +463,8 @@ class HeadlessInAppWebView implements WebView {
|
|||
|
||||
@override
|
||||
Future<CustomSchemeResponse?> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme;
|
||||
InAppWebViewController controller, WebResourceRequest request)?
|
||||
onLoadResourceWithCustomScheme;
|
||||
|
||||
@override
|
||||
void Function(InAppWebViewController controller, Uri? url)? onLoadStart;
|
||||
|
@ -472,9 +476,15 @@ class HeadlessInAppWebView implements WebView {
|
|||
void Function(InAppWebViewController controller,
|
||||
InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult;
|
||||
|
||||
///Use [onPrintRequest] instead
|
||||
@Deprecated("Use onPrintRequest instead")
|
||||
@override
|
||||
void Function(InAppWebViewController controller, Uri? url)? onPrint;
|
||||
|
||||
@override
|
||||
Future<bool?> Function(InAppWebViewController controller, Uri? url,
|
||||
PrintJobController? printJobController)? onPrintRequest;
|
||||
|
||||
@override
|
||||
void Function(InAppWebViewController controller, int progress)?
|
||||
onProgressChanged;
|
||||
|
|
|
@ -13,6 +13,7 @@ import '../web/web_platform_manager.dart';
|
|||
|
||||
import '../context_menu.dart';
|
||||
import '../types/main.dart';
|
||||
import '../print_job/main.dart';
|
||||
|
||||
import 'webview.dart';
|
||||
import 'in_app_webview_controller.dart';
|
||||
|
@ -65,7 +66,8 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.onScrollChanged,
|
||||
@Deprecated('Use onDownloadStartRequest instead') this.onDownloadStart,
|
||||
this.onDownloadStartRequest,
|
||||
@Deprecated('Use onLoadResourceWithCustomScheme instead') this.onLoadResourceCustomScheme,
|
||||
@Deprecated('Use onLoadResourceWithCustomScheme instead')
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onLoadResourceWithCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
|
@ -81,7 +83,8 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
this.onAjaxProgress,
|
||||
this.shouldInterceptFetchRequest,
|
||||
this.onUpdateVisitedHistory,
|
||||
this.onPrint,
|
||||
@Deprecated("Use onPrintRequest instead") this.onPrint,
|
||||
this.onPrintRequest,
|
||||
this.onLongPressHitTestResult,
|
||||
this.onEnterFullscreen,
|
||||
this.onExitFullscreen,
|
||||
|
@ -345,7 +348,8 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
|
||||
@override
|
||||
final Future<CustomSchemeResponse?> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme;
|
||||
InAppWebViewController controller, WebResourceRequest request)?
|
||||
onLoadResourceWithCustomScheme;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onLoadStart;
|
||||
|
@ -357,9 +361,15 @@ class InAppWebView extends StatefulWidget implements WebView {
|
|||
final void Function(InAppWebViewController controller,
|
||||
InAppWebViewHitTestResult hitTestResult)? onLongPressHitTestResult;
|
||||
|
||||
///Use [onPrintRequest] instead
|
||||
@Deprecated("Use onPrintRequest instead")
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onPrint;
|
||||
|
||||
@override
|
||||
final Future<bool?> Function(InAppWebViewController controller, Uri? url,
|
||||
PrintJobController? printJobController)? onPrintRequest;
|
||||
|
||||
@override
|
||||
final void Function(InAppWebViewController controller, int progress)?
|
||||
onProgressChanged;
|
||||
|
|
|
@ -28,6 +28,8 @@ import 'in_app_webview_settings.dart';
|
|||
import 'webview.dart';
|
||||
import '_static_channel.dart';
|
||||
|
||||
import '../print_job/main.dart';
|
||||
|
||||
///List of forbidden names for JavaScript handlers.
|
||||
// ignore: non_constant_identifier_names
|
||||
final _JAVASCRIPT_HANDLER_FORBIDDEN_NAMES = UnmodifiableListView<String>([
|
||||
|
@ -36,7 +38,7 @@ final _JAVASCRIPT_HANDLER_FORBIDDEN_NAMES = UnmodifiableListView<String>([
|
|||
"onAjaxReadyStateChange",
|
||||
"onAjaxProgress",
|
||||
"shouldInterceptFetchRequest",
|
||||
"onPrint",
|
||||
"onPrintRequest",
|
||||
"onWindowFocus",
|
||||
"onWindowBlur",
|
||||
"callAsyncJavaScript",
|
||||
|
@ -1089,15 +1091,31 @@ class InAppWebViewController {
|
|||
_webview!.onWindowBlur!(this);
|
||||
else if (_inAppBrowser != null) _inAppBrowser!.onWindowBlur();
|
||||
break;
|
||||
case "onPrint":
|
||||
if ((_webview != null && _webview!.onPrint != null) ||
|
||||
case "onPrintRequest":
|
||||
if ((_webview != null &&
|
||||
(_webview!.onPrintRequest != null ||
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
_webview!.onPrint != null)) ||
|
||||
_inAppBrowser != null) {
|
||||
String? url = call.arguments["url"];
|
||||
String? printJobId = call.arguments["printJobId"];
|
||||
Uri? uri = url != null ? Uri.parse(url) : null;
|
||||
if (_webview != null && _webview!.onPrint != null)
|
||||
_webview!.onPrint!(this, uri);
|
||||
else
|
||||
PrintJobController? printJob =
|
||||
printJobId != null ? PrintJobController(id: printJobId) : null;
|
||||
|
||||
if (_webview != null) {
|
||||
if (_webview!.onPrintRequest != null)
|
||||
return await _webview!.onPrintRequest!(this, uri, printJob);
|
||||
else {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
_webview!.onPrint!(this, uri);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
_inAppBrowser!.onPrint(uri);
|
||||
return await _inAppBrowser!.onPrintRequest(uri, printJob);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "onInjectedScriptLoaded":
|
||||
|
@ -1235,17 +1253,6 @@ class InAppWebViewController {
|
|||
await _inAppBrowser!.shouldInterceptFetchRequest(request));
|
||||
}
|
||||
return null;
|
||||
case "onPrint":
|
||||
if ((_webview != null && _webview!.onPrint != null) ||
|
||||
_inAppBrowser != null) {
|
||||
String? url = args[0];
|
||||
Uri? uri = url != null ? Uri.parse(url) : null;
|
||||
if (_webview != null && _webview!.onPrint != null)
|
||||
_webview!.onPrint!(this, uri);
|
||||
else
|
||||
_inAppBrowser!.onPrint(uri);
|
||||
}
|
||||
return null;
|
||||
case "onWindowFocus":
|
||||
if (_webview != null && _webview!.onWindowFocus != null)
|
||||
_webview!.onWindowFocus!(this);
|
||||
|
@ -2273,17 +2280,25 @@ class InAppWebViewController {
|
|||
|
||||
///Prints the current page.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
///To obtain the [PrintJobController], use [settings] argument with [PrintJobSettings.handledByClient] to `true`.
|
||||
///Otherwise this method will return `null` and the [PrintJobController] will be handled and disposed automatically by the system.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///**NOTE**: available on Android 19+.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin. Also, [PrintJobController] is always `null`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintManager](https://developer.android.com/reference/android/print/PrintManager))
|
||||
///- iOS ([Official API - UIPrintInteractionController](https://developer.apple.com/documentation/uikit/uiprintinteractioncontroller))
|
||||
///- Android native WebView ([Official API - PrintManager.print](https://developer.android.com/reference/android/print/PrintManager#print(java.lang.String,%20android.print.PrintDocumentAdapter,%20android.print.PrintAttributes)))
|
||||
///- iOS ([Official API - UIPrintInteractionController.present](https://developer.apple.com/documentation/uikit/uiprintinteractioncontroller/1618149-present))
|
||||
///- Web ([Official API - Window.print](https://developer.mozilla.org/en-US/docs/Web/API/Window/print))
|
||||
Future<void> printCurrentPage() async {
|
||||
Future<PrintJobController?> printCurrentPage({PrintJobSettings? settings}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('printCurrentPage', args);
|
||||
args.putIfAbsent("settings", () => settings?.toMap());
|
||||
String? jobId = await _channel.invokeMethod('printCurrentPage', args);
|
||||
if (jobId != null) {
|
||||
return PrintJobController(id: jobId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets the height of the HTML content.
|
||||
|
@ -3205,7 +3220,7 @@ class InAppWebViewController {
|
|||
///
|
||||
///[pdfConfiguration] represents the object that specifies the portion of the web view to capture as PDF data.
|
||||
///
|
||||
///**NOTE**: available only on iOS 14.0+.
|
||||
///**NOTE for iOS**: available only on iOS 14.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - WKWebView.createPdf](https://developer.apple.com/documentation/webkit/wkwebview/3650490-createpdf))
|
||||
|
@ -3223,7 +3238,7 @@ class InAppWebViewController {
|
|||
///Creates a web archive of the web view’s current contents asynchronously.
|
||||
///Returns `null` if a problem occurred.
|
||||
///
|
||||
///**NOTE**: available only on iOS 14.0+.
|
||||
///**NOTE for iOS**: available only on iOS 14.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - WKWebView.createWebArchiveData](https://developer.apple.com/documentation/webkit/wkwebview/3650491-createwebarchivedata))
|
||||
|
@ -3472,7 +3487,7 @@ class InAppWebViewController {
|
|||
///
|
||||
///[urlScheme] represents the URL scheme associated with the resource.
|
||||
///
|
||||
///**NOTE**: available only on iOS 11.0+.
|
||||
///**NOTE for iOS**: available only on iOS 11.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - WKWebView.handlesURLScheme](https://developer.apple.com/documentation/webkit/wkwebview/2875370-handlesurlscheme))
|
||||
|
|
|
@ -4,4 +4,4 @@ export 'in_app_webview_controller.dart';
|
|||
export 'in_app_webview_settings.dart';
|
||||
export 'headless_in_app_webview.dart';
|
||||
export 'android/main.dart';
|
||||
export 'apple/main.dart';
|
||||
export 'apple/main.dart';
|
|
@ -9,15 +9,20 @@ import '../types/main.dart';
|
|||
import 'in_app_webview_controller.dart';
|
||||
import 'in_app_webview_settings.dart';
|
||||
import 'headless_in_app_webview.dart';
|
||||
import '../print_job/main.dart';
|
||||
|
||||
import '../debug_logging_settings.dart';
|
||||
|
||||
///Abstract class that represents a WebView. Used by [InAppWebView], [HeadlessInAppWebView] and the WebView of [InAppBrowser].
|
||||
abstract class WebView {
|
||||
///Debug settings used by [InAppWebView], [HeadlessInAppWebView] and [InAppBrowser].
|
||||
///The default value excludes the [WebView.onScrollChanged] and [WebView.onOverScrolled] events.
|
||||
///The default value excludes the [WebView.onScrollChanged], [WebView.onOverScrolled] and [WebView.onReceivedIcon] events.
|
||||
static DebugLoggingSettings debugLoggingSettings = DebugLoggingSettings(
|
||||
excludeFilter: [RegExp(r"onScrollChanged"), RegExp(r"onOverScrolled")]);
|
||||
excludeFilter: [
|
||||
RegExp(r"onScrollChanged"),
|
||||
RegExp(r"onOverScrolled"),
|
||||
RegExp(r"onReceivedIcon")
|
||||
]);
|
||||
|
||||
///The window id of a [CreateWindowAction.windowId].
|
||||
final int? windowId;
|
||||
|
@ -184,7 +189,8 @@ abstract class WebView {
|
|||
///- Android native WebView
|
||||
///- iOS ([Official API - WKURLSchemeHandler](https://developer.apple.com/documentation/webkit/wkurlschemehandler))
|
||||
final Future<CustomSchemeResponse?> Function(
|
||||
InAppWebViewController controller, WebResourceRequest request)? onLoadResourceWithCustomScheme;
|
||||
InAppWebViewController controller, WebResourceRequest request)?
|
||||
onLoadResourceWithCustomScheme;
|
||||
|
||||
///Event fired when the [WebView] requests the host application to create a new window,
|
||||
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
|
||||
|
@ -433,17 +439,27 @@ abstract class WebView {
|
|||
InAppWebViewController controller, Uri? url, bool? isReload)?
|
||||
onUpdateVisitedHistory;
|
||||
|
||||
///Use [onPrintRequest] instead
|
||||
@Deprecated("Use onPrintRequest instead")
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onPrint;
|
||||
|
||||
///Event fired when `window.print()` is called from JavaScript side.
|
||||
///Return `true` if you want to handle the print job.
|
||||
///Otherwise return `false`, so the [PrintJobController] will be handled and disposed automatically by the system.
|
||||
///
|
||||
///[url] represents the url on which is called.
|
||||
///
|
||||
///[printJobController] represents the controller of the print job created.
|
||||
///**NOTE**: on Web, it is always `null`
|
||||
///
|
||||
///**NOTE for Web**: this event will be called only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
///- Web
|
||||
final void Function(InAppWebViewController controller, Uri? url)? onPrint;
|
||||
final Future<bool?> Function(InAppWebViewController controller, Uri? url,
|
||||
PrintJobController? printJobController)? onPrintRequest;
|
||||
|
||||
///Event fired when an HTML element of the webview has been clicked and held.
|
||||
///
|
||||
|
@ -967,7 +983,8 @@ abstract class WebView {
|
|||
@Deprecated('Use onDownloadStartRequest instead')
|
||||
this.onDownloadStart,
|
||||
this.onDownloadStartRequest,
|
||||
@Deprecated('Use onLoadResourceWithCustomScheme instead') this.onLoadResourceCustomScheme,
|
||||
@Deprecated('Use onLoadResourceWithCustomScheme instead')
|
||||
this.onLoadResourceCustomScheme,
|
||||
this.onLoadResourceWithCustomScheme,
|
||||
this.onCreateWindow,
|
||||
this.onCloseWindow,
|
||||
|
@ -983,7 +1000,9 @@ abstract class WebView {
|
|||
this.onAjaxProgress,
|
||||
this.shouldInterceptFetchRequest,
|
||||
this.onUpdateVisitedHistory,
|
||||
this.onPrint,
|
||||
@Deprecated("Use onPrintRequest instead")
|
||||
this.onPrint,
|
||||
this.onPrintRequest,
|
||||
this.onLongPressHitTestResult,
|
||||
this.onEnterFullscreen,
|
||||
this.onExitFullscreen,
|
||||
|
|
|
@ -15,4 +15,5 @@ export 'context_menu.dart';
|
|||
export 'pull_to_refresh/main.dart';
|
||||
export 'web_message/main.dart';
|
||||
export 'web_authentication_session/main.dart';
|
||||
export 'print_job/main.dart';
|
||||
export 'debug_logging_settings.dart';
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export 'print_job_controller.dart';
|
||||
export 'print_job_settings.dart';
|
|
@ -0,0 +1,103 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import '../types/print_job_info.dart';
|
||||
import '../in_app_webview/in_app_webview_controller.dart';
|
||||
|
||||
///A completion handler for the [PrintJobController].
|
||||
typedef PrintJobCompletionHandler = Future<void> Function(bool completed, String? error)?;
|
||||
|
||||
///Class representing a print job eventually returned by [InAppWebViewController.printCurrentPage].
|
||||
class PrintJobController {
|
||||
///Print job ID.
|
||||
final String id;
|
||||
|
||||
late MethodChannel _channel;
|
||||
|
||||
///A completion handler used to handle the conclusion of the print job (for instance, to reset state) and to handle any errors encountered in printing.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS ([Official API - UIPrintInteractionController.CompletionHandler](https://developer.apple.com/documentation/uikit/uiprintinteractioncontroller/completionhandler))
|
||||
PrintJobCompletionHandler onComplete;
|
||||
|
||||
PrintJobController(
|
||||
{required this.id}) {
|
||||
this._channel = MethodChannel(
|
||||
'com.pichillilorenzo/flutter_inappwebview_printjobcontroller_$id');
|
||||
this._channel.setMethodCallHandler(_handleMethod);
|
||||
}
|
||||
|
||||
Future<dynamic> _handleMethod(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case "onComplete":
|
||||
bool completed = call.arguments["completed"];
|
||||
String? error = call.arguments["error"];
|
||||
if (onComplete != null) {
|
||||
onComplete!(completed, error);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw UnimplementedError("Unimplemented ${call.method} method");
|
||||
}
|
||||
}
|
||||
|
||||
///Cancels this print job.
|
||||
///You can request cancellation of a queued, started, blocked, or failed print job.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJob.cancel](https://developer.android.com/reference/android/print/PrintJob#cancel()))
|
||||
Future<void> cancel() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('cancel', args);
|
||||
}
|
||||
|
||||
///Restarts this print job.
|
||||
///You can request restart of a failed print job.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJob.restart](https://developer.android.com/reference/android/print/PrintJob#restart()))
|
||||
Future<void> restart() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('restart', args);
|
||||
}
|
||||
|
||||
///Dismisses the printing-options sheet or popover.
|
||||
///
|
||||
///You should dismiss the printing options when they are presented in a sheet or
|
||||
///animated from a rectangle and the user changes the orientation of the device.
|
||||
///(This, of course, assumes your application responds to orientation changes.)
|
||||
///You should then present the printing options again once the new orientation takes effect.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
Future<void> dismiss({bool animated: true}) async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent("animated", () => animated);
|
||||
await _channel.invokeMethod('dismiss', args);
|
||||
}
|
||||
|
||||
///Gets the [PrintJobInfo] that describes this job.
|
||||
///
|
||||
///**NOTE**: The returned info object is a snapshot of the
|
||||
///current print job state. Every call to this method returns a fresh
|
||||
///info object that reflects the current print job state.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJob.getInfo](https://developer.android.com/reference/android/print/PrintJob#getInfo()))
|
||||
///- iOS
|
||||
Future<PrintJobInfo?> getInfo() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
Map<String, dynamic>? infoMap =
|
||||
(await _channel.invokeMethod('getInfo', args))
|
||||
?.cast<String, dynamic>();
|
||||
return PrintJobInfo.fromMap(infoMap);
|
||||
}
|
||||
|
||||
///Disposes the print job.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
Future<void> dispose() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('dispose', args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_inappwebview/src/types/print_job_media_size.dart';
|
||||
|
||||
import '../types/main.dart';
|
||||
import '../util.dart';
|
||||
import 'print_job_controller.dart';
|
||||
|
||||
///Class that represents the settings of a [PrintJobController].
|
||||
class PrintJobSettings {
|
||||
///Set this to `true` to handle the [PrintJobController].
|
||||
///Otherwise, it will be handled and disposed automatically by the system.
|
||||
///The default value is `false`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
bool handledByClient;
|
||||
|
||||
///The name of the print job.
|
||||
///An application should set this property to a name appropriate to the content being printed.
|
||||
///The default job name is the current webpage title concatenated with the "Document" word at the end.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
String? jobName;
|
||||
|
||||
///`true` to animate the display of the sheet, `false` to display the sheet immediately.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
bool animated;
|
||||
|
||||
///The orientation of the printed content, portrait or landscape.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
PrintJobOrientation? orientation;
|
||||
|
||||
///The number of pages to render.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
int? numberOfPages;
|
||||
|
||||
///Force rendering quality.
|
||||
///
|
||||
///**NOTE for iOS**: available only on iOS 14.5+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
PrintJobRenderingQuality? forceRenderingQuality;
|
||||
|
||||
///The margins for each printed page.
|
||||
///Margins define the white space around the content where the left margin defines
|
||||
///the amount of white space on the left of the content and so on.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
EdgeInsets? margins;
|
||||
|
||||
///The media size.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
PrintJobMediaSize? mediaSize;
|
||||
|
||||
///The color mode.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
PrintJobColorMode? colorMode;
|
||||
|
||||
///The duplex mode to use for the print job.
|
||||
///
|
||||
///**NOTE for Android native WebView**: available only on Android 23+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
PrintJobDuplexMode? duplexMode;
|
||||
|
||||
///The kind of printable content.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
PrintJobOutputType? outputType;
|
||||
|
||||
///The supported resolution in DPI (dots per inch).
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
PrintJobResolution? resolution;
|
||||
|
||||
///A Boolean value that determines whether the printing options include the number of copies.
|
||||
///The default value is `true`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
bool showsNumberOfCopies;
|
||||
|
||||
///A Boolean value that determines whether the paper selection menu displays.
|
||||
///The default value of this property is `false`.
|
||||
///Setting the value to `true` enables a paper selection menu on printers that support different types of paper and have more than one paper type loaded.
|
||||
///On printers where only one paper type is available, no paper selection menu is displayed, regardless of the value of this property.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
bool showsPaperSelectionForLoadedPapers;
|
||||
|
||||
///A Boolean value that determines whether the printing options include the paper orientation control when available.
|
||||
///The default value is `true`.
|
||||
///
|
||||
///**NOTE for iOS**: available only on iOS 15.0+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
bool showsPaperOrientation;
|
||||
|
||||
///The height of the page footer.
|
||||
///
|
||||
///The footer is measured in points from the bottom of [printableRect] and is below the content area.
|
||||
///The default footer height is `0.0`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? footerHeight;
|
||||
|
||||
///The height of the page header.
|
||||
///
|
||||
///The header is measured in points from the top of [printableRect] and is above the content area.
|
||||
///The default header height is `0.0`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? headerHeight;
|
||||
|
||||
///The maximum height of the content area.
|
||||
///
|
||||
///The Print Formatter uses this value to determine where the content rectangle begins on the first page.
|
||||
///It compares the value of this property with the printing rectangle’s height minus the header and footer heights and
|
||||
///the top inset value; it uses the lower of the two values.
|
||||
///The default value of this property is the maximum float value.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? maximumContentHeight;
|
||||
|
||||
///The maximum width of the content area.
|
||||
///
|
||||
///The Print Formatter uses this value to determine the maximum width of the content rectangle.
|
||||
///It compares the value of this property with the printing rectangle’s width minus the left and right inset values and uses the lower of the two.
|
||||
///The default value of this property is the maximum float value.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? maximumContentWidth;
|
||||
|
||||
PrintJobSettings(
|
||||
{this.handledByClient = false,
|
||||
this.jobName,
|
||||
this.animated = true,
|
||||
this.orientation,
|
||||
this.numberOfPages,
|
||||
this.forceRenderingQuality,
|
||||
this.margins,
|
||||
this.mediaSize,
|
||||
this.colorMode,
|
||||
this.duplexMode,
|
||||
this.outputType,
|
||||
this.resolution,
|
||||
this.showsNumberOfCopies = true,
|
||||
this.showsPaperSelectionForLoadedPapers = false,
|
||||
this.showsPaperOrientation = true,
|
||||
this.maximumContentHeight,
|
||||
this.maximumContentWidth,
|
||||
this.footerHeight,
|
||||
this.headerHeight});
|
||||
|
||||
///Gets a possible [PrintJobSettings] instance from a [Map] value.
|
||||
static PrintJobSettings fromMap(Map<String, dynamic> map) {
|
||||
var settings = PrintJobSettings();
|
||||
settings.handledByClient = map["handledByClient"];
|
||||
settings.jobName = map["jobName"];
|
||||
settings.animated = map["animated"];
|
||||
settings.orientation = PrintJobOrientation.fromValue(map["orientation"]);
|
||||
settings.numberOfPages = map["numberOfPages"];
|
||||
settings.forceRenderingQuality =
|
||||
PrintJobRenderingQuality.fromValue(map["forceRenderingQuality"]);
|
||||
settings.margins =
|
||||
MapEdgeInsets.fromMap(map["margins"]?.cast<String, dynamic>());
|
||||
settings.mediaSize =
|
||||
PrintJobMediaSize.fromMap(map["mediaSize"]?.cast<String, dynamic>());
|
||||
settings.colorMode = PrintJobColorMode.fromValue(map["colorMode"]);
|
||||
settings.duplexMode = PrintJobDuplexMode.fromNativeValue(map["duplexMode"]);
|
||||
settings.outputType = PrintJobOutputType.fromValue(map["outputType"]);
|
||||
settings.resolution =
|
||||
PrintJobResolution.fromMap(map["resolution"]?.cast<String, dynamic>());
|
||||
settings.showsNumberOfCopies = map["showsNumberOfCopies"];
|
||||
settings.showsPaperSelectionForLoadedPapers =
|
||||
map["showsPaperSelectionForLoadedPapers"];
|
||||
settings.showsPaperOrientation = map["showsPaperOrientation"];
|
||||
settings.maximumContentHeight = map["maximumContentHeight"];
|
||||
settings.maximumContentWidth = map["maximumContentWidth"];
|
||||
settings.footerHeight = map["footerHeight"];
|
||||
settings.headerHeight = map["headerHeight"];
|
||||
return settings;
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"handledByClient": handledByClient,
|
||||
"jobName": jobName,
|
||||
"animated": animated,
|
||||
"orientation": orientation?.toValue(),
|
||||
"numberOfPages": numberOfPages,
|
||||
"forceRenderingQuality": forceRenderingQuality?.toValue(),
|
||||
"margins": margins?.toMap(),
|
||||
"mediaSize": mediaSize?.toMap(),
|
||||
"colorMode": colorMode?.toValue(),
|
||||
"duplexMode": duplexMode?.toNativeValue(),
|
||||
"outputType": outputType?.toValue(),
|
||||
"resolution": resolution?.toMap(),
|
||||
"showsNumberOfCopies": showsNumberOfCopies,
|
||||
"showsPaperSelectionForLoadedPapers": showsPaperSelectionForLoadedPapers,
|
||||
"showsPaperOrientation": showsPaperOrientation,
|
||||
"maximumContentHeight": maximumContentHeight,
|
||||
"maximumContentWidth": maximumContentWidth,
|
||||
"footerHeight": footerHeight,
|
||||
"headerHeight": headerHeight,
|
||||
};
|
||||
}
|
||||
|
||||
///Gets a copy of the current instance.
|
||||
PrintJobSettings copy() {
|
||||
return PrintJobSettings.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
|
@ -20,6 +20,20 @@ class InAppWebViewRect {
|
|||
assert(this.x >= 0 && this.y >= 0 && this.width >= 0 && this.height >= 0);
|
||||
}
|
||||
|
||||
///Gets a possible [InAppWebViewRect] instance from a [Map] value.
|
||||
static InAppWebViewRect? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return InAppWebViewRect(
|
||||
x: map["x"],
|
||||
y: map["y"],
|
||||
width: map["width"],
|
||||
height: map["height"],
|
||||
);
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"x": x, "y": y, "width": width, "height": height};
|
||||
|
|
|
@ -149,4 +149,14 @@ export 'proxy_rule.dart';
|
|||
export 'proxy_scheme_filter.dart';
|
||||
export 'force_dark_strategy.dart';
|
||||
export 'url_request_attribution.dart';
|
||||
export 'web_authentication_session_error.dart';
|
||||
export 'web_authentication_session_error.dart';
|
||||
export 'print_job_info.dart';
|
||||
export 'print_job_state.dart';
|
||||
export 'print_job_orientation.dart';
|
||||
export 'print_job_rendering_quality.dart';
|
||||
export 'print_job_media_size.dart';
|
||||
export 'print_job_color_mode.dart';
|
||||
export 'print_job_duplex_mode.dart';
|
||||
export 'print_job_output_type.dart';
|
||||
export 'print_job_resolution.dart';
|
||||
export 'print_job_attributes.dart';
|
|
@ -30,7 +30,7 @@ class PermissionResourceType {
|
|||
return null;
|
||||
}
|
||||
|
||||
///Gets a possible [PermissionResourceType] instance from a value.
|
||||
///Gets a possible [PermissionResourceType] instance from a native value.
|
||||
static PermissionResourceType? fromNativeValue(dynamic value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import '../util.dart';
|
||||
import '../print_job/main.dart';
|
||||
import '../types/main.dart';
|
||||
|
||||
///Class representing the attributes of a [PrintJobController].
|
||||
///These attributes describe how the printed content should be laid out.
|
||||
class PrintJobAttributes {
|
||||
///The color mode.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
int? colorMode;
|
||||
|
||||
///The duplex mode to use for the print job.
|
||||
///
|
||||
///**NOTE for Android native WebView**: available only on Android 23+.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
PrintJobDuplexMode? duplex;
|
||||
|
||||
///The orientation of the printed content, portrait or landscape.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
PrintJobOrientation? orientation;
|
||||
|
||||
///The media size.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
PrintJobMediaSize? mediaSize;
|
||||
|
||||
///The supported resolution in DPI (dots per inch).
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
PrintJobResolution? resolution;
|
||||
|
||||
///The margins for each printed page.
|
||||
///Margins define the white space around the content where the left margin defines
|
||||
///the amount of white space on the left of the content and so on.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
EdgeInsets? margins;
|
||||
|
||||
///The height of the page footer.
|
||||
///
|
||||
///The footer is measured in points from the bottom of [printableRect] and is below the content area.
|
||||
///The default footer height is `0.0`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? footerHeight;
|
||||
|
||||
///The height of the page header.
|
||||
///
|
||||
///The header is measured in points from the top of [printableRect] and is above the content area.
|
||||
///The default header height is `0.0`.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? headerHeight;
|
||||
|
||||
///The area in which printing can occur.
|
||||
///
|
||||
///The value of this property is a rectangle that defines the area in which the printer can print content.
|
||||
///Sometimes this is referred to as the imageable area of the paper.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
InAppWebViewRect? printableRect;
|
||||
|
||||
///The size of the paper used for printing.
|
||||
///
|
||||
///The value of this property is a rectangle that defines the size of paper chosen for the print job.
|
||||
///The origin is always (0,0).
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
InAppWebViewRect? paperRect;
|
||||
|
||||
///The maximum height of the content area.
|
||||
///
|
||||
///The Print Formatter uses this value to determine where the content rectangle begins on the first page.
|
||||
///It compares the value of this property with the printing rectangle’s height minus the header and footer heights and
|
||||
///the top inset value; it uses the lower of the two values.
|
||||
///The default value of this property is the maximum float value.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? maximumContentHeight;
|
||||
|
||||
///The maximum width of the content area.
|
||||
///
|
||||
///The Print Formatter uses this value to determine the maximum width of the content rectangle.
|
||||
///It compares the value of this property with the printing rectangle’s width minus the left and right inset values and uses the lower of the two.
|
||||
///The default value of this property is the maximum float value.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- iOS
|
||||
double? maximumContentWidth;
|
||||
|
||||
PrintJobAttributes(
|
||||
{this.colorMode,
|
||||
this.duplex,
|
||||
this.orientation,
|
||||
this.mediaSize,
|
||||
this.resolution,
|
||||
this.margins,
|
||||
this.maximumContentHeight,
|
||||
this.maximumContentWidth,
|
||||
this.footerHeight,
|
||||
this.headerHeight,
|
||||
this.paperRect,
|
||||
this.printableRect});
|
||||
|
||||
///Gets a possible [PrintJobAttributes] instance from a [Map] value.
|
||||
static PrintJobAttributes? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return PrintJobAttributes(
|
||||
colorMode: map["colorMode"],
|
||||
duplex: PrintJobDuplexMode.fromNativeValue(map["duplex"]),
|
||||
orientation: PrintJobOrientation.fromValue(map["orientation"]),
|
||||
mediaSize: PrintJobMediaSize.fromMap(
|
||||
map["mediaSize"]?.cast<String, dynamic>()),
|
||||
resolution: PrintJobResolution.fromMap(
|
||||
map["resolution"]?.cast<String, dynamic>()),
|
||||
margins: MapEdgeInsets.fromMap(map["margins"]?.cast<String, dynamic>()),
|
||||
maximumContentHeight: map["maximumContentHeight"],
|
||||
maximumContentWidth: map["maximumContentWidth"],
|
||||
footerHeight: map["footerHeight"],
|
||||
headerHeight: map["headerHeight"],
|
||||
paperRect: InAppWebViewRect.fromMap(map["paperRect"]?.cast<String, dynamic>()),
|
||||
printableRect: InAppWebViewRect.fromMap(map["printableRect"]?.cast<String, dynamic>()));
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"colorMode": colorMode,
|
||||
"duplex": duplex?.toNativeValue(),
|
||||
"orientation": orientation?.toValue(),
|
||||
"mediaSize": mediaSize?.toMap(),
|
||||
"resolution": resolution?.toMap(),
|
||||
"margins": margins?.toMap(),
|
||||
"maximumContentHeight": maximumContentHeight,
|
||||
"maximumContentWidth": maximumContentWidth,
|
||||
"footerHeight": footerHeight,
|
||||
"headerHeight": headerHeight,
|
||||
"paperRect": paperRect?.toMap(),
|
||||
"printableRect": printableRect?.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing how the printed content of a [PrintJobController] should be laid out.
|
||||
class PrintJobColorMode {
|
||||
final int _value;
|
||||
|
||||
const PrintJobColorMode._internal(this._value);
|
||||
|
||||
///Set of all values of [PrintJobColorMode].
|
||||
static final Set<PrintJobColorMode> values = [
|
||||
PrintJobColorMode.MONOCHROME,
|
||||
PrintJobColorMode.COLOR,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [PrintJobColorMode] instance from an [int] value.
|
||||
static PrintJobColorMode? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobColorMode.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "MONOCHROME";
|
||||
case 2:
|
||||
default:
|
||||
return "COLOR";
|
||||
}
|
||||
}
|
||||
|
||||
///Monochrome color scheme, for example one color is used.
|
||||
static const MONOCHROME = const PrintJobColorMode._internal(1);
|
||||
|
||||
///Color color scheme, for example many colors are used.
|
||||
static const COLOR = const PrintJobColorMode._internal(2);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the orientation of a [PrintJobController].
|
||||
class PrintJobDuplexMode {
|
||||
final String _value;
|
||||
final int _nativeValue;
|
||||
|
||||
const PrintJobDuplexMode._internal(this._value, this._nativeValue);
|
||||
|
||||
///Set of all values of [PrintJobDuplexMode].
|
||||
static final Set<PrintJobDuplexMode> values = [
|
||||
PrintJobDuplexMode.NONE,
|
||||
PrintJobDuplexMode.LONG_EDGE,
|
||||
PrintJobDuplexMode.SHORT_EDGE,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [PrintJobDuplexMode] instance from a [String] value.
|
||||
static PrintJobDuplexMode? fromValue(String? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobDuplexMode.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets a possible [PrintJobDuplexMode] instance from an [int] native value.
|
||||
static PrintJobDuplexMode? fromNativeValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobDuplexMode.values
|
||||
.firstWhere((element) => element.toNativeValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [String] value.
|
||||
String toValue() => _value;
|
||||
|
||||
///Gets native value.
|
||||
int toNativeValue() => _nativeValue;
|
||||
|
||||
@override
|
||||
String toString() => _value;
|
||||
|
||||
///No double-sided (duplex) printing; single-sided printing only.
|
||||
static final NONE = PrintJobDuplexMode._internal(
|
||||
'NONE',
|
||||
(defaultTargetPlatform == TargetPlatform.android)
|
||||
? 1
|
||||
: ((defaultTargetPlatform == TargetPlatform.iOS ||
|
||||
defaultTargetPlatform == TargetPlatform.macOS)
|
||||
? 0
|
||||
: 0));
|
||||
|
||||
///Duplex printing that flips the back page along the long edge of the paper.
|
||||
///Pages are turned sideways along the long edge - like a book.
|
||||
static final LONG_EDGE = PrintJobDuplexMode._internal(
|
||||
'LONG_EDGE',
|
||||
(defaultTargetPlatform == TargetPlatform.android)
|
||||
? 2
|
||||
: ((defaultTargetPlatform == TargetPlatform.iOS ||
|
||||
defaultTargetPlatform == TargetPlatform.macOS)
|
||||
? 1
|
||||
: 0));
|
||||
|
||||
///Duplex print that flips the back page along the short edge of the paper.
|
||||
///Pages are turned upwards along the short edge - like a notepad.
|
||||
static final SHORT_EDGE = PrintJobDuplexMode._internal(
|
||||
'SHORT_EDGE',
|
||||
(defaultTargetPlatform == TargetPlatform.android)
|
||||
? 4
|
||||
: ((defaultTargetPlatform == TargetPlatform.iOS ||
|
||||
defaultTargetPlatform == TargetPlatform.macOS)
|
||||
? 2
|
||||
: 0));
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
import 'print_job_state.dart';
|
||||
import '../print_job/main.dart';
|
||||
import '../types/main.dart';
|
||||
|
||||
///Class representing the description of a [PrintJobController].
|
||||
///Note that the print jobs state may change over time and this class represents a snapshot of this state.
|
||||
class PrintJobInfo {
|
||||
///The state of the print job.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
PrintJobState? state;
|
||||
|
||||
///How many copies to print.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
int? copies;
|
||||
|
||||
///The number of pages to print.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
int? numberOfPages;
|
||||
|
||||
///The timestamp when the print job was created.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
int? creationTime;
|
||||
|
||||
///The human readable print job label.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
String? label;
|
||||
|
||||
///The unique id of the printer.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
String? printerId;
|
||||
|
||||
///The attributes of a print job.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
PrintJobAttributes? attributes;
|
||||
|
||||
PrintJobInfo(
|
||||
{this.state,
|
||||
this.copies,
|
||||
this.numberOfPages,
|
||||
this.creationTime,
|
||||
this.label,
|
||||
this.printerId,
|
||||
this.attributes});
|
||||
|
||||
///Gets a possible [PrintJobInfo] instance from a [Map] value.
|
||||
static PrintJobInfo? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return PrintJobInfo(
|
||||
state: PrintJobState.fromValue(map["state"]),
|
||||
copies: map["copies"],
|
||||
numberOfPages: map["numberOfPages"],
|
||||
creationTime: map["creationTime"],
|
||||
label: map["label"],
|
||||
printerId: map["printerId"],
|
||||
attributes: PrintJobAttributes.fromMap(
|
||||
map["attributes"]?.cast<String, dynamic>()));
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"state": state?.toValue(),
|
||||
"copies": copies,
|
||||
"numberOfPages": numberOfPages,
|
||||
"creationTime": creationTime,
|
||||
"label": label,
|
||||
"printerId": printerId,
|
||||
"attributes": attributes?.toMap()
|
||||
};
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the supported media size for a [PrintJobController].
|
||||
///Media size is the dimension of the media on which the content is printed.
|
||||
class PrintJobMediaSize {
|
||||
///The unique media size id.
|
||||
///
|
||||
///It is unique amongst other media sizes supported by the printer.
|
||||
///This id is defined by the client that generated the media size
|
||||
///instance and should not be interpreted by other parties.
|
||||
final String id;
|
||||
|
||||
///The human readable label.
|
||||
final String? label;
|
||||
|
||||
///The media width in mils (thousandths of an inch).
|
||||
final int widthMils;
|
||||
|
||||
///The media height in mils (thousandths of an inch).
|
||||
final int heightMils;
|
||||
|
||||
const PrintJobMediaSize(
|
||||
{required this.id,
|
||||
required this.widthMils,
|
||||
required this.heightMils,
|
||||
this.label});
|
||||
|
||||
///Gets a possible [PrintJobMediaSize] instance from a [Map] value.
|
||||
static PrintJobMediaSize? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return PrintJobMediaSize(
|
||||
id: map["id"],
|
||||
widthMils: map["widthMils"],
|
||||
heightMils: map["heightMils"],
|
||||
label: map["label"],
|
||||
);
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"id": id,
|
||||
"widthMils": widthMils,
|
||||
"heightMils": heightMils,
|
||||
"label": label
|
||||
};
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
///Unknown media size in portrait mode.
|
||||
///
|
||||
///**NOTE**: This is for specifying orientation without media size.
|
||||
///You should not use the dimensions reported by this instance.
|
||||
static const UNKNOWN_PORTRAIT = const PrintJobMediaSize(
|
||||
id: "UNKNOWN_PORTRAIT", widthMils: 1, heightMils: 0x7fffffff);
|
||||
|
||||
///Unknown media size in portrait mode.
|
||||
///
|
||||
///**NOTE**: This is for specifying orientation without media size.
|
||||
///You should not use the dimensions reported by this instance.
|
||||
static const UNKNOWN_LANDSCAPE = const PrintJobMediaSize(
|
||||
id: "UNKNOWN_LANDSCAPE", widthMils: 0x7fffffff, heightMils: 1);
|
||||
|
||||
// ISO sizes
|
||||
|
||||
///ISO A0 media size: 841mm x 1189mm (33.11" x 46.81")
|
||||
static const ISO_A0 = const PrintJobMediaSize(
|
||||
id: "ISO_A0", widthMils: 33110, heightMils: 46810);
|
||||
|
||||
///ISO A1 media size: 594mm x 841mm (23.39" x 33.11")
|
||||
static const ISO_A1 = const PrintJobMediaSize(
|
||||
id: "ISO_A1", widthMils: 23390, heightMils: 33110);
|
||||
|
||||
///ISO A2 media size: 420mm x 594mm (16.54" x 23.39")
|
||||
static const ISO_A2 = const PrintJobMediaSize(
|
||||
id: "ISO_A2", widthMils: 16540, heightMils: 23390);
|
||||
|
||||
///ISO A3 media size: 297mm x 420mm (11.69" x 16.54")
|
||||
static const ISO_A3 = const PrintJobMediaSize(
|
||||
id: "ISO_A3", widthMils: 11690, heightMils: 16540);
|
||||
|
||||
///ISO A4 media size: 210mm x 297mm (8.27" x 11.69")
|
||||
static const ISO_A4 =
|
||||
const PrintJobMediaSize(id: "ISO_A4", widthMils: 8270, heightMils: 11690);
|
||||
|
||||
///ISO A5 media size: 148mm x 210mm (5.83" x 8.27")
|
||||
static const ISO_A5 =
|
||||
const PrintJobMediaSize(id: "ISO_A5", widthMils: 5830, heightMils: 8270);
|
||||
|
||||
///ISO A6 media size: 105mm x 148mm (4.13" x 5.83")
|
||||
static const ISO_A6 =
|
||||
const PrintJobMediaSize(id: "ISO_A6", widthMils: 4130, heightMils: 5830);
|
||||
|
||||
///ISO A7 media size: 74mm x 105mm (2.91" x 4.13")
|
||||
static const ISO_A7 =
|
||||
const PrintJobMediaSize(id: "ISO_A7", widthMils: 2910, heightMils: 4130);
|
||||
|
||||
///ISO A8 media size: 52mm x 74mm (2.05" x 2.91")
|
||||
static const ISO_A8 =
|
||||
const PrintJobMediaSize(id: "ISO_A8", widthMils: 2050, heightMils: 2910);
|
||||
|
||||
///ISO A9 media size: 37mm x 52mm (1.46" x 2.05")
|
||||
static const ISO_A9 =
|
||||
const PrintJobMediaSize(id: "ISO_A9", widthMils: 1460, heightMils: 2050);
|
||||
|
||||
///ISO A10 media size: 26mm x 37mm (1.02" x 1.46")
|
||||
static const ISO_A10 =
|
||||
const PrintJobMediaSize(id: "ISO_A10", widthMils: 1020, heightMils: 1460);
|
||||
|
||||
///ISO B0 media size: 1000mm x 1414mm (39.37" x 55.67")
|
||||
static const ISO_B0 = const PrintJobMediaSize(
|
||||
id: "ISO_B0", widthMils: 39370, heightMils: 55670);
|
||||
|
||||
///ISO B1 media size: 707mm x 1000mm (27.83" x 39.37")
|
||||
static const ISO_B1 = const PrintJobMediaSize(
|
||||
id: "ISO_B1", widthMils: 27830, heightMils: 39370);
|
||||
|
||||
///ISO B2 media size: 500mm x 707mm (19.69" x 27.83")
|
||||
static const ISO_B2 = const PrintJobMediaSize(
|
||||
id: "ISO_B2", widthMils: 19690, heightMils: 27830);
|
||||
|
||||
///ISO B3 media size: 353mm x 500mm (13.90" x 19.69")
|
||||
static const ISO_B3 = const PrintJobMediaSize(
|
||||
id: "ISO_B3", widthMils: 13900, heightMils: 19690);
|
||||
|
||||
///ISO B4 media size: 250mm x 353mm (9.84" x 13.90")
|
||||
static const ISO_B4 =
|
||||
const PrintJobMediaSize(id: "ISO_B4", widthMils: 9840, heightMils: 13900);
|
||||
|
||||
///ISO B5 media size: 176mm x 250mm (6.93" x 9.84")
|
||||
static const ISO_B5 =
|
||||
const PrintJobMediaSize(id: "ISO_B5", widthMils: 6930, heightMils: 9840);
|
||||
|
||||
///ISO B6 media size: 125mm x 176mm (4.92" x 6.93")
|
||||
static const ISO_B6 =
|
||||
const PrintJobMediaSize(id: "ISO_B6", widthMils: 4920, heightMils: 6930);
|
||||
|
||||
///ISO B7 media size: 88mm x 125mm (3.46" x 4.92")
|
||||
static const ISO_B7 =
|
||||
const PrintJobMediaSize(id: "ISO_B7", widthMils: 3460, heightMils: 4920);
|
||||
|
||||
///ISO B8 media size: 62mm x 88mm (2.44" x 3.46")
|
||||
static const ISO_B8 =
|
||||
const PrintJobMediaSize(id: "ISO_B8", widthMils: 2440, heightMils: 3460);
|
||||
|
||||
///ISO B9 media size: 44mm x 62mm (1.73" x 2.44")
|
||||
static const ISO_B9 =
|
||||
const PrintJobMediaSize(id: "ISO_B9", widthMils: 1730, heightMils: 2440);
|
||||
|
||||
///ISO B10 media size: 31mm x 44mm (1.22" x 1.73")
|
||||
static const ISO_B10 =
|
||||
const PrintJobMediaSize(id: "ISO_B10", widthMils: 1220, heightMils: 1730);
|
||||
|
||||
///ISO C0 media size: 917mm x 1297mm (36.10" x 51.06")
|
||||
static const ISO_C0 = const PrintJobMediaSize(
|
||||
id: "ISO_C0", widthMils: 36100, heightMils: 51060);
|
||||
|
||||
///ISO C1 media size: 648mm x 917mm (25.51" x 36.10")
|
||||
static const ISO_C1 = const PrintJobMediaSize(
|
||||
id: "ISO_C1", widthMils: 25510, heightMils: 36100);
|
||||
|
||||
///ISO C2 media size: 458mm x 648mm (18.03" x 25.51")
|
||||
static const ISO_C2 = const PrintJobMediaSize(
|
||||
id: "ISO_C2", widthMils: 18030, heightMils: 25510);
|
||||
|
||||
///ISO C3 media size: 324mm x 458mm (12.76" x 18.03")
|
||||
static const ISO_C3 = const PrintJobMediaSize(
|
||||
id: "ISO_C3", widthMils: 12760, heightMils: 18030);
|
||||
|
||||
///ISO C4 media size: 229mm x 324mm (9.02" x 12.76")
|
||||
static const ISO_C4 =
|
||||
const PrintJobMediaSize(id: "ISO_C4", widthMils: 9020, heightMils: 12760);
|
||||
|
||||
///ISO C5 media size: 162mm x 229mm (6.38" x 9.02")
|
||||
static const ISO_C5 =
|
||||
const PrintJobMediaSize(id: "ISO_C5", widthMils: 6380, heightMils: 9020);
|
||||
|
||||
///ISO C6 media size: 114mm x 162mm (4.49" x 6.38")
|
||||
static const ISO_C6 =
|
||||
const PrintJobMediaSize(id: "ISO_C6", widthMils: 4490, heightMils: 6380);
|
||||
|
||||
///ISO C7 media size: 81mm x 114mm (3.19" x 4.49")
|
||||
static const ISO_C7 =
|
||||
const PrintJobMediaSize(id: "ISO_C7", widthMils: 3190, heightMils: 4490);
|
||||
|
||||
///ISO C8 media size: 57mm x 81mm (2.24" x 3.19")
|
||||
static const ISO_C8 =
|
||||
const PrintJobMediaSize(id: "ISO_C8", widthMils: 2240, heightMils: 3190);
|
||||
|
||||
///ISO C9 media size: 40mm x 57mm (1.57" x 2.24")
|
||||
static const ISO_C9 =
|
||||
const PrintJobMediaSize(id: "ISO_C9", widthMils: 1570, heightMils: 2240);
|
||||
|
||||
///ISO C10 media size: 28mm x 40mm (1.10" x 1.57")
|
||||
static const ISO_C10 =
|
||||
const PrintJobMediaSize(id: "ISO_C10", widthMils: 1100, heightMils: 1570);
|
||||
|
||||
// North America
|
||||
|
||||
///North America Letter media size: 8.5" x 11" (279mm x 216mm)
|
||||
static const NA_LETTER = const PrintJobMediaSize(
|
||||
id: "NA_LETTER", widthMils: 8500, heightMils: 11000);
|
||||
|
||||
///North America Government-Letter media size: 8.0" x 10.5" (203mm x 267mm)
|
||||
static const NA_GOVT_LETTER = const PrintJobMediaSize(
|
||||
id: "NA_GOVT_LETTER", widthMils: 8000, heightMils: 10500);
|
||||
|
||||
///North America Legal media size: 8.5" x 14" (216mm x 356mm)
|
||||
static const NA_LEGAL = const PrintJobMediaSize(
|
||||
id: "NA_LEGAL", widthMils: 8500, heightMils: 14000);
|
||||
|
||||
///North America Junior Legal media size: 8.0" x 5.0" (203mm × 127mm)
|
||||
static const NA_JUNIOR_LEGAL = const PrintJobMediaSize(
|
||||
id: "NA_JUNIOR_LEGAL", widthMils: 8000, heightMils: 5000);
|
||||
|
||||
///North America Ledger media size: 17" x 11" (432mm × 279mm)
|
||||
static const NA_LEDGER = const PrintJobMediaSize(
|
||||
id: "NA_LEDGER", widthMils: 17000, heightMils: 11000);
|
||||
|
||||
///North America Tabloid media size: 11" x 17" (279mm × 432mm)
|
||||
static const NA_TABLOID = const PrintJobMediaSize(
|
||||
id: "NA_TABLOID", widthMils: 11000, heightMils: 17000);
|
||||
|
||||
///North America Index Card 3x5 media size: 3" x 5" (76mm x 127mm)
|
||||
static const NA_INDEX_3X5 = const PrintJobMediaSize(
|
||||
id: "NA_INDEX_3X5", widthMils: 3000, heightMils: 5000);
|
||||
|
||||
///North America Index Card 4x6 media size: 4" x 6" (102mm x 152mm)
|
||||
static const NA_INDEX_4X6 = const PrintJobMediaSize(
|
||||
id: "NA_INDEX_4X6", widthMils: 4000, heightMils: 6000);
|
||||
|
||||
///North America Index Card 5x8 media size: 5" x 8" (127mm x 203mm)
|
||||
static const NA_INDEX_5X8 = const PrintJobMediaSize(
|
||||
id: "NA_INDEX_5X8", widthMils: 5000, heightMils: 8000);
|
||||
|
||||
///North America Monarch media size: 7.25" x 10.5" (184mm x 267mm)
|
||||
static const NA_MONARCH = const PrintJobMediaSize(
|
||||
id: "NA_MONARCH", widthMils: 7250, heightMils: 10500);
|
||||
|
||||
///North America Quarto media size: 8" x 10" (203mm x 254mm)
|
||||
static const NA_QUARTO = const PrintJobMediaSize(
|
||||
id: "NA_QUARTO", widthMils: 8000, heightMils: 10000);
|
||||
|
||||
///North America Foolscap media size: 8" x 13" (203mm x 330mm)
|
||||
static const NA_FOOLSCAP = const PrintJobMediaSize(
|
||||
id: "NA_FOOLSCAP", widthMils: 8000, heightMils: 13000);
|
||||
|
||||
///North America ANSI C media size: 17" x 22" (432mm x 559mm)
|
||||
static const ANSI_C = const PrintJobMediaSize(
|
||||
id: "ANSI_C", widthMils: 17000, heightMils: 22000);
|
||||
|
||||
///North America ANSI D media size: 22" x 34" (559mm x 864mm)
|
||||
static const ANSI_D = const PrintJobMediaSize(
|
||||
id: "ANSI_D", widthMils: 22000, heightMils: 34000);
|
||||
|
||||
///North America ANSI E media size: 34" x 44" (864mm x 1118mm)
|
||||
static const ANSI_E = const PrintJobMediaSize(
|
||||
id: "ANSI_E", widthMils: 34000, heightMils: 44000);
|
||||
|
||||
///North America ANSI F media size: 28" x 40" (711mm x 1016mm)
|
||||
static const ANSI_F = const PrintJobMediaSize(
|
||||
id: "ANSI_F", widthMils: 28000, heightMils: 40000);
|
||||
|
||||
///North America Arch A media size: 9" x 12" (229mm x 305mm)
|
||||
static const NA_ARCH_A = const PrintJobMediaSize(
|
||||
id: "NA_ARCH_A", widthMils: 9000, heightMils: 12000);
|
||||
|
||||
///North America Arch B media size: 12" x 18" (305mm x 457mm)
|
||||
static const NA_ARCH_B = const PrintJobMediaSize(
|
||||
id: "NA_ARCH_B", widthMils: 12000, heightMils: 18000);
|
||||
|
||||
///North America Arch C media size: 18" x 24" (457mm x 610mm)
|
||||
static const NA_ARCH_C = const PrintJobMediaSize(
|
||||
id: "NA_ARCH_C", widthMils: 18000, heightMils: 24000);
|
||||
|
||||
///North America Arch D media size: 24" x 36" (610mm x 914mm)
|
||||
static const NA_ARCH_D = const PrintJobMediaSize(
|
||||
id: "NA_ARCH_D", widthMils: 24000, heightMils: 36000);
|
||||
|
||||
///North America Arch E media size: 36" x 48" (914mm x 1219mm)
|
||||
static const NA_ARCH_E = const PrintJobMediaSize(
|
||||
id: "NA_ARCH_E", widthMils: 36000, heightMils: 48000);
|
||||
|
||||
///North America Arch E1 media size: 30" x 42" (762mm x 1067mm)
|
||||
static const NA_ARCH_E1 = const PrintJobMediaSize(
|
||||
id: "NA_ARCH_E1", widthMils: 30000, heightMils: 42000);
|
||||
|
||||
///North America Super B media size: 13" x 19" (330mm x 483mm)
|
||||
static const NA_SUPER_B = const PrintJobMediaSize(
|
||||
id: "NA_SUPER_B", widthMils: 13000, heightMils: 19000);
|
||||
|
||||
// Chinese
|
||||
|
||||
///Chinese ROC 8K media size: 270mm x 390mm (10.629" x 15.3543")
|
||||
static const ROC_8K = const PrintJobMediaSize(
|
||||
id: "ROC_8K", widthMils: 10629, heightMils: 15354);
|
||||
|
||||
///Chinese ROC 16K media size: 195mm x 270mm (7.677" x 10.629")
|
||||
static const ROC_16K = const PrintJobMediaSize(
|
||||
id: "ROC_16K", widthMils: 7677, heightMils: 10629);
|
||||
|
||||
///Chinese PRC 1 media size: 102mm x 165mm (4.015" x 6.496")
|
||||
static const PRC_1 =
|
||||
const PrintJobMediaSize(id: "PRC_1", widthMils: 4015, heightMils: 6496);
|
||||
|
||||
///Chinese PRC 2 media size: 102mm x 176mm (4.015" x 6.929")
|
||||
static const PRC_2 =
|
||||
const PrintJobMediaSize(id: "PRC_2", widthMils: 4015, heightMils: 6929);
|
||||
|
||||
///Chinese PRC 3 media size: 125mm x 176mm (4.921" x 6.929")
|
||||
static const PRC_3 =
|
||||
const PrintJobMediaSize(id: "PRC_3", widthMils: 4921, heightMils: 6929);
|
||||
|
||||
///Chinese PRC 4 media size: 110mm x 208mm (4.330" x 8.189")
|
||||
static const PRC_4 =
|
||||
const PrintJobMediaSize(id: "PRC_4", widthMils: 4330, heightMils: 8189);
|
||||
|
||||
///Chinese PRC 5 media size: 110mm x 220mm (4.330" x 8.661")
|
||||
static const PRC_5 =
|
||||
const PrintJobMediaSize(id: "PRC_5", widthMils: 4330, heightMils: 8661);
|
||||
|
||||
///Chinese PRC 6 media size: 120mm x 320mm (4.724" x 12.599")
|
||||
static const PRC_6 =
|
||||
const PrintJobMediaSize(id: "PRC_6", widthMils: 4724, heightMils: 12599);
|
||||
|
||||
///Chinese PRC 7 media size: 160mm x 230mm (6.299" x 9.055")
|
||||
static const PRC_7 =
|
||||
const PrintJobMediaSize(id: "PRC_7", widthMils: 6299, heightMils: 9055);
|
||||
|
||||
///Chinese PRC 8 media size: 120mm x 309mm (4.724" x 12.165")
|
||||
static const PRC_8 =
|
||||
const PrintJobMediaSize(id: "PRC_8", widthMils: 4724, heightMils: 12165);
|
||||
|
||||
///Chinese PRC 9 media size: 229mm x 324mm (9.016" x 12.756")
|
||||
static const PRC_9 =
|
||||
const PrintJobMediaSize(id: "PRC_9", widthMils: 9016, heightMils: 12756);
|
||||
|
||||
///Chinese PRC 10 media size: 324mm x 458mm (12.756" x 18.032")
|
||||
static const PRC_10 = const PrintJobMediaSize(
|
||||
id: "PRC_10", widthMils: 12756, heightMils: 18032);
|
||||
|
||||
///Chinese PRC 16k media size: 146mm x 215mm (5.749" x 8.465")
|
||||
static const PRC_16K =
|
||||
const PrintJobMediaSize(id: "PRC_16K", widthMils: 5749, heightMils: 8465);
|
||||
|
||||
///Chinese Pa Kai media size: 267mm x 389mm (10.512" x 15.315")
|
||||
static const OM_PA_KAI = const PrintJobMediaSize(
|
||||
id: "OM_PA_KAI", widthMils: 10512, heightMils: 15315);
|
||||
|
||||
///Chinese Dai Pa Kai media size: 275mm x 395mm (10.827" x 15.551")
|
||||
static const OM_DAI_PA_KAI = const PrintJobMediaSize(
|
||||
id: "OM_DAI_PA_KAI", widthMils: 10827, heightMils: 15551);
|
||||
|
||||
///Chinese Jurro Ku Kai media size: 198mm x 275mm (7.796" x 10.827")
|
||||
static const OM_JUURO_KU_KAI = const PrintJobMediaSize(
|
||||
id: "OM_JUURO_KU_KAI", widthMils: 7796, heightMils: 10827);
|
||||
|
||||
// Japanese
|
||||
|
||||
///Japanese JIS B10 media size: 32mm x 45mm (1.259" x 1.772")
|
||||
static const JIS_B10 =
|
||||
const PrintJobMediaSize(id: "JIS_B10", widthMils: 1259, heightMils: 1772);
|
||||
|
||||
///Japanese JIS B9 media size: 45mm x 64mm (1.772" x 2.52")
|
||||
static const JIS_B9 =
|
||||
const PrintJobMediaSize(id: "JIS_B9", widthMils: 1772, heightMils: 2520);
|
||||
|
||||
///Japanese JIS B8 media size: 64mm x 91mm (2.52" x 3.583")
|
||||
static const JIS_B8 =
|
||||
const PrintJobMediaSize(id: "JIS_B8", widthMils: 2520, heightMils: 3583);
|
||||
|
||||
///Japanese JIS B7 media size: 91mm x 128mm (3.583" x 5.049")
|
||||
static const JIS_B7 =
|
||||
const PrintJobMediaSize(id: "JIS_B7", widthMils: 3583, heightMils: 5049);
|
||||
|
||||
///Japanese JIS B6 media size: 128mm x 182mm (5.049" x 7.165")
|
||||
static const JIS_B6 =
|
||||
const PrintJobMediaSize(id: "JIS_B6", widthMils: 5049, heightMils: 7165);
|
||||
|
||||
///Japanese JIS B5 media size: 182mm x 257mm (7.165" x 10.118")
|
||||
static const JIS_B5 =
|
||||
const PrintJobMediaSize(id: "JIS_B5", widthMils: 7165, heightMils: 10118);
|
||||
|
||||
///Japanese JIS B4 media size: 257mm x 364mm (10.118" x 14.331")
|
||||
static const JIS_B4 = const PrintJobMediaSize(
|
||||
id: "JIS_B4", widthMils: 10118, heightMils: 14331);
|
||||
|
||||
///Japanese JIS B3 media size: 364mm x 515mm (14.331" x 20.276")
|
||||
static const JIS_B3 = const PrintJobMediaSize(
|
||||
id: "JIS_B3", widthMils: 14331, heightMils: 20276);
|
||||
|
||||
///Japanese JIS B2 media size: 515mm x 728mm (20.276" x 28.661")
|
||||
static const JIS_B2 = const PrintJobMediaSize(
|
||||
id: "JIS_B2", widthMils: 20276, heightMils: 28661);
|
||||
|
||||
///Japanese JIS B1 media size: 728mm x 1030mm (28.661" x 40.551")
|
||||
static const JIS_B1 = const PrintJobMediaSize(
|
||||
id: "JIS_B1", widthMils: 28661, heightMils: 40551);
|
||||
|
||||
///Japanese JIS B0 media size: 1030mm x 1456mm (40.551" x 57.323")
|
||||
static const JIS_B0 = const PrintJobMediaSize(
|
||||
id: "JIS_B0", widthMils: 40551, heightMils: 57323);
|
||||
|
||||
///Japanese JIS Exec media size: 216mm x 330mm (8.504" x 12.992")
|
||||
static const JIS_EXEC = const PrintJobMediaSize(
|
||||
id: "JIS_EXEC", widthMils: 8504, heightMils: 12992);
|
||||
|
||||
///Japanese Chou4 media size: 90mm x 205mm (3.543" x 8.071")
|
||||
static const JPN_CHOU4 = const PrintJobMediaSize(
|
||||
id: "JPN_CHOU4", widthMils: 3543, heightMils: 8071);
|
||||
|
||||
///Japanese Chou3 media size: 120mm x 235mm (4.724" x 9.252")
|
||||
static const JPN_CHOU3 = const PrintJobMediaSize(
|
||||
id: "JPN_CHOU3", widthMils: 4724, heightMils: 9252);
|
||||
|
||||
///Japanese Chou2 media size: 111.1mm x 146mm (4.374" x 5.748")
|
||||
static const JPN_CHOU2 = const PrintJobMediaSize(
|
||||
id: "JPN_CHOU2", widthMils: 4374, heightMils: 5748);
|
||||
|
||||
///Japanese Hagaki media size: 100mm x 148mm (3.937" x 5.827")
|
||||
static const JPN_HAGAKI = const PrintJobMediaSize(
|
||||
id: "JPN_HAGAKI", widthMils: 3937, heightMils: 5827);
|
||||
|
||||
///Japanese Oufuku media size: 148mm x 200mm (5.827" x 7.874")
|
||||
static const JPN_OUFUKU = const PrintJobMediaSize(
|
||||
id: "JPN_OUFUKU", widthMils: 5827, heightMils: 7874);
|
||||
|
||||
///Japanese Kahu media size: 240mm x 322.1mm (9.449" x 12.681")
|
||||
static const JPN_KAHU = const PrintJobMediaSize(
|
||||
id: "JPN_KAHU", widthMils: 9449, heightMils: 12681);
|
||||
|
||||
///Japanese Kaku2 media size: 240mm x 332mm (9.449" x 13.071")
|
||||
static const JPN_KAKU2 = const PrintJobMediaSize(
|
||||
id: "JPN_KAKU2", widthMils: 9449, heightMils: 13071);
|
||||
|
||||
///Japanese You4 media size: 105mm x 235mm (4.134" x 9.252")
|
||||
static const JPN_YOU4 = const PrintJobMediaSize(
|
||||
id: "JPN_YOU4", widthMils: 4134, heightMils: 9252);
|
||||
|
||||
///Japanese Photo L media size: 89mm x 127mm (3.5 x 5")
|
||||
static const JPN_OE_PHOTO_L = const PrintJobMediaSize(
|
||||
id: "JPN_OE_PHOTO_L", widthMils: 3500, heightMils: 5000);
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the orientation of a [PrintJobController].
|
||||
class PrintJobOrientation {
|
||||
final int _value;
|
||||
|
||||
const PrintJobOrientation._internal(this._value);
|
||||
|
||||
///Set of all values of [PrintJobOrientation].
|
||||
static final Set<PrintJobOrientation> values = [
|
||||
PrintJobOrientation.PORTRAIT,
|
||||
PrintJobOrientation.LANDSCAPE,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [PrintJobOrientation] instance from an [int] value.
|
||||
static PrintJobOrientation? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobOrientation.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "LANDSCAPE";
|
||||
case 0:
|
||||
default:
|
||||
return "PORTRAIT";
|
||||
}
|
||||
}
|
||||
|
||||
///Pages are printed in portrait orientation.
|
||||
static const PORTRAIT = const PrintJobOrientation._internal(0);
|
||||
|
||||
///Pages are printed in landscape orientation.
|
||||
static const LANDSCAPE = const PrintJobOrientation._internal(1);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the kind of printable content of a [PrintJobController].
|
||||
class PrintJobOutputType {
|
||||
final int _value;
|
||||
|
||||
const PrintJobOutputType._internal(this._value);
|
||||
|
||||
///Set of all values of [PrintJobOutputType].
|
||||
static final Set<PrintJobOutputType> values = [
|
||||
PrintJobOutputType.GENERAL,
|
||||
PrintJobOutputType.PHOTO,
|
||||
PrintJobOutputType.GRAYSCALE,
|
||||
PrintJobOutputType.PHOTO_GRAYSCALE
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [PrintJobOutputType] instance from an [int] value.
|
||||
static PrintJobOutputType? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobOutputType.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "PHOTO";
|
||||
case 2:
|
||||
return "GRAYSCALE";
|
||||
case 3:
|
||||
return "PHOTO_GRAYSCALE";
|
||||
case 0:
|
||||
default:
|
||||
return "GENERAL";
|
||||
}
|
||||
}
|
||||
|
||||
///Specifies that the printed content consists of mixed text, graphics, and images.
|
||||
///The default paper is Letter, A4, or similar locale-specific designation.
|
||||
///Output is normal quality, duplex.
|
||||
static const GENERAL = const PrintJobOutputType._internal(0);
|
||||
|
||||
///Specifies that the printed content consists of black-and-white or color images.
|
||||
///The default paper is 4x6, A6, or similar locale-specific designation.
|
||||
///Output is high quality, simplex.
|
||||
static const PHOTO = const PrintJobOutputType._internal(1);
|
||||
|
||||
///Specifies that the printed content is grayscale.
|
||||
///Set the output type to this value when your printable content contains no color—for example, it’s black text only.
|
||||
///The default paper is Letter/A4. Output is grayscale quality, duplex.
|
||||
///This content type can produce a performance improvement in some cases.
|
||||
static const GRAYSCALE = const PrintJobOutputType._internal(2);
|
||||
|
||||
///Specifies that the printed content is a grayscale image.
|
||||
///Set the output type to this value when your printable content contains no color—for example, it’s black text only.
|
||||
///The default paper is Letter/A4.
|
||||
///Output is high quality grayscale, duplex.
|
||||
static const PHOTO_GRAYSCALE = const PrintJobOutputType._internal(3);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the rendering quality of a [PrintJobController].
|
||||
class PrintJobRenderingQuality {
|
||||
final int _value;
|
||||
|
||||
const PrintJobRenderingQuality._internal(this._value);
|
||||
|
||||
///Set of all values of [PrintJobRenderingQuality].
|
||||
static final Set<PrintJobRenderingQuality> values = [
|
||||
PrintJobRenderingQuality.BEST,
|
||||
PrintJobRenderingQuality.RESPONSIVE,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [PrintJobRenderingQuality] instance from an [int] value.
|
||||
static PrintJobRenderingQuality? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobRenderingQuality.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "RESPONSIVE";
|
||||
case 0:
|
||||
default:
|
||||
return "BEST";
|
||||
}
|
||||
}
|
||||
|
||||
///Renders the printing at the best possible quality, regardless of speed.
|
||||
static const BEST = const PrintJobRenderingQuality._internal(0);
|
||||
|
||||
///Sacrifices the least possible amount of rendering quality for speed to maintain a responsive user interface.
|
||||
///This option should be used only after establishing that best quality rendering does indeed make the user interface unresponsive.
|
||||
static const RESPONSIVE = const PrintJobRenderingQuality._internal(1);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the supported resolution in DPI (dots per inch) for a [PrintJobController].
|
||||
///Resolution defines how many points with different color can be placed
|
||||
///on one inch in horizontal or vertical direction of the target media.
|
||||
///For example, a printer with 600 DPI can produce higher quality images
|
||||
///the one with 300 DPI resolution.
|
||||
class PrintJobResolution {
|
||||
///The unique resolution id.
|
||||
///
|
||||
///It is unique amongst other resolutions supported by the printer.
|
||||
///This id is defined by the client that generated the resolution
|
||||
///instance and should not be interpreted by other parties.
|
||||
final String id;
|
||||
|
||||
///The human readable label.
|
||||
final String label;
|
||||
|
||||
///The vertical resolution in DPI (dots per inch).
|
||||
final int verticalDpi;
|
||||
|
||||
///The horizontal resolution in DPI (dots per inch).
|
||||
final int horizontalDpi;
|
||||
|
||||
const PrintJobResolution(
|
||||
{required this.id,
|
||||
required this.label,
|
||||
required this.verticalDpi,
|
||||
required this.horizontalDpi});
|
||||
|
||||
///Gets a possible [PrintJobResolution] instance from a [Map] value.
|
||||
static PrintJobResolution? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return PrintJobResolution(
|
||||
id: map["id"],
|
||||
label: map["label"],
|
||||
verticalDpi: map["verticalDpi"],
|
||||
horizontalDpi: map["horizontalDpi"],
|
||||
);
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"id": id,
|
||||
"label": label,
|
||||
"verticalDpi": verticalDpi,
|
||||
"horizontalDpi": horizontalDpi,
|
||||
};
|
||||
}
|
||||
|
||||
///Converts instance to a map.
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
import '../print_job/main.dart';
|
||||
|
||||
///Class representing the state of a [PrintJobController].
|
||||
class PrintJobState {
|
||||
final int _value;
|
||||
|
||||
const PrintJobState._internal(this._value);
|
||||
|
||||
///Set of all values of [PrintJobState].
|
||||
static final Set<PrintJobState> values = [
|
||||
PrintJobState.CREATED,
|
||||
PrintJobState.QUEUED,
|
||||
PrintJobState.STARTED,
|
||||
PrintJobState.BLOCKED,
|
||||
PrintJobState.COMPLETED,
|
||||
PrintJobState.FAILED,
|
||||
PrintJobState.CANCELED,
|
||||
].toSet();
|
||||
|
||||
///Gets a possible [PrintJobState] instance from an [int] value.
|
||||
static PrintJobState? fromValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
return PrintJobState.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets [int] value.
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 2:
|
||||
return "QUEUED";
|
||||
case 3:
|
||||
return "STARTED";
|
||||
case 4:
|
||||
return "BLOCKED";
|
||||
case 5:
|
||||
return "COMPLETED";
|
||||
case 6:
|
||||
return "FAILED";
|
||||
case 7:
|
||||
return "CANCELED";
|
||||
case 1:
|
||||
default:
|
||||
return "CREATED";
|
||||
}
|
||||
}
|
||||
|
||||
///Print job state: The print job is being created but not yet ready to be printed.
|
||||
///
|
||||
///Next valid states: [QUEUED].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_CREATED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_CREATED))
|
||||
///- iOS
|
||||
static const CREATED = const PrintJobState._internal(1);
|
||||
|
||||
///Print job state: The print jobs is created, it is ready to be printed and should be processed.
|
||||
///
|
||||
///Next valid states: [STARTED], [FAILED], [CANCELED].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_QUEUED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_QUEUED))
|
||||
static const QUEUED = const PrintJobState._internal(2);
|
||||
|
||||
///Print job state: The print job is being printed.
|
||||
///
|
||||
///Next valid states: [COMPLETED], [FAILED], [CANCELED], [BLOCKED].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_STARTED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_STARTED))
|
||||
///- iOS
|
||||
static const STARTED = const PrintJobState._internal(3);
|
||||
|
||||
///Print job state: The print job is blocked.
|
||||
///
|
||||
///Next valid states: [FAILED], [CANCELED], [STARTED].
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_BLOCKED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_BLOCKED))
|
||||
static const BLOCKED = const PrintJobState._internal(4);
|
||||
|
||||
///Print job state: The print job is successfully printed. This is a terminal state.
|
||||
///
|
||||
///Next valid states: None.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_COMPLETED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_COMPLETED))
|
||||
///- iOS
|
||||
static const COMPLETED = const PrintJobState._internal(5);
|
||||
|
||||
|
||||
///Print job state: The print job was printing but printing failed.
|
||||
///
|
||||
///Next valid states: None.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_FAILED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_FAILED))
|
||||
///- iOS
|
||||
static const FAILED = const PrintJobState._internal(6);
|
||||
|
||||
///Print job state: The print job is canceled. This is a terminal state.
|
||||
///
|
||||
///Next valid states: None.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - PrintJobInfo.STATE_CANCELED](https://developer.android.com/reference/android/print/PrintJobInfo#STATE_CANCELED))
|
||||
///- iOS
|
||||
static const CANCELED = const PrintJobState._internal(7);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -38,7 +38,7 @@ class SslErrorType {
|
|||
return null;
|
||||
}
|
||||
|
||||
///Gets a possible [SslErrorType] instance from a value.
|
||||
///Gets a possible [SslErrorType] instance from a native value.
|
||||
static SslErrorType? fromNativeValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
|
|
|
@ -79,7 +79,7 @@ class WebResourceErrorType {
|
|||
return null;
|
||||
}
|
||||
|
||||
///Gets a possible [WebResourceErrorType] instance from an [int] value.
|
||||
///Gets a possible [WebResourceErrorType] instance from an [int] native value.
|
||||
static WebResourceErrorType? fromNativeValue(int? value) {
|
||||
if (value != null) {
|
||||
try {
|
||||
|
|
|
@ -502,3 +502,21 @@ extension MapSize on Size {
|
|||
return {'width': width, 'height': height};
|
||||
}
|
||||
}
|
||||
|
||||
extension MapEdgeInsets on EdgeInsets {
|
||||
static EdgeInsets? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return EdgeInsets.fromLTRB(
|
||||
map['left'], map['top'], map['right'], map['bottom']);
|
||||
}
|
||||
|
||||
Map<String, double> toJson() {
|
||||
return toMap();
|
||||
}
|
||||
|
||||
Map<String, double> toMap() {
|
||||
return {'top': top, 'right': right, 'bottom': bottom, 'left': left};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ class InAppWebViewWebElement {
|
|||
'flutter_inappwebview for web doesn\'t implement \'${call.method}\'',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void prepare() {
|
||||
|
@ -502,10 +503,13 @@ class InAppWebViewWebElement {
|
|||
await _channel?.invokeMethod("onWindowBlur");
|
||||
}
|
||||
|
||||
void onPrint(String? url) async {
|
||||
var obj = {"url": url};
|
||||
void onPrintRequest(String? url) async {
|
||||
var obj = {
|
||||
"url": url,
|
||||
"printJobId": null
|
||||
};
|
||||
|
||||
await _channel?.invokeMethod("onPrint", obj);
|
||||
await _channel?.invokeMethod("onPrintRequest", obj);
|
||||
}
|
||||
|
||||
void onEnterFullscreen() async {
|
||||
|
|
|
@ -82,9 +82,9 @@ Future<dynamic> _dartNativeCommunication(String method, dynamic viewId,
|
|||
case 'onWindowBlur':
|
||||
webViewHtmlElement.onWindowBlur();
|
||||
break;
|
||||
case 'onPrint':
|
||||
case 'onPrintRequest':
|
||||
String? url = args![0];
|
||||
webViewHtmlElement.onPrint(url);
|
||||
webViewHtmlElement.onPrintRequest(url);
|
||||
break;
|
||||
case 'onEnterFullscreen':
|
||||
webViewHtmlElement.onEnterFullscreen();
|
||||
|
|
Loading…
Reference in New Issue