From 4452ccf7ed421a09ab7b7386fcc56a00ffa212e9 Mon Sep 17 00:00:00 2001 From: Starryi Date: Wed, 12 Jan 2022 15:42:32 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-62688=20=E7=BB=84=E4=BB=B6=E5=95=86?= =?UTF-8?q?=E5=9F=8E=E9=9D=A2=E5=90=91=E9=A3=8E=E6=A0=BC=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【问题原因】 优化JxBrowser接口 1. 减少监听器注册接口的数目 2. 增减全局下载任务的监听接口,以实现列表项/详情页/历史版本等不同页面下载任务状态的同步 3. JS可在Java对象上添加自定义属性,从而在JS环境中跟踪指定下载任务的状态. 4. mini商城中主题下载后弹出的一系列交互窗口的父窗口应当 是mini商城窗口 【改动思路】 同上 --- .../dialog/TemplateThemeGridPagesDialog.java | 9 +- .../dialog/TemplateThemeUsingDialog.java | 7 + .../installation/ComponentInstallation.java | 3 +- .../ComponentsPackageInstallation.java | 3 +- .../TemplateThemeInstallation.java | 22 +- .../online/mini/MiniComponentShopDialog.java | 2 + .../mini/bridge/NativeProductBridge.java | 205 ++++++++++++++++-- .../online/mini/bridge/NativeTaskBridge.java | 54 ++--- .../mini/bridge/SafeJSFunctionInvoker.java | 29 +++ 9 files changed, 266 insertions(+), 68 deletions(-) create mode 100644 designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java index da0649d804..bf65b9be28 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java @@ -7,6 +7,7 @@ import com.fr.design.mainframe.theme.TemplateThemeGridPagesPane; import com.fr.design.mainframe.theme.TemplateThemeGridPane; import javax.swing.JPanel; +import java.awt.Window; /** * @author Starryi @@ -19,13 +20,17 @@ public class TemplateThemeGridPagesDialog extends TemplateThemeDialog implements protected TemplateThemeGridPagesPane overallPane; - public TemplateThemeGridPagesDialog() { - super(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"), CONTENT_WIDTH, CONTENT_HEIGHT); + public TemplateThemeGridPagesDialog(Window parentWindow) { + super(parentWindow, Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"), CONTENT_WIDTH, CONTENT_HEIGHT); setupContentPane(); setupActionButtons(); } + public TemplateThemeGridPagesDialog() { + this(DesignerContext.getDesignerFrame()); + } + @Override protected JPanel createContentPane() { overallPane = new TemplateThemeGridPagesPane(this); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java index 420a7ed439..9818e60b5c 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java @@ -1,11 +1,18 @@ package com.fr.design.mainframe.theme.dialog; +import java.awt.Window; + /** * @author Starryi * @version 1.0 * Created by Starryi on 2021/8/13 */ public class TemplateThemeUsingDialog extends TemplateThemeGridPagesDialog { + public TemplateThemeUsingDialog(Window parentWindow) { + super(parentWindow); + overallPane.showThemeUsingPane(); + } + public TemplateThemeUsingDialog() { super(); overallPane.showThemeUsingPane(); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java index e6403e902d..172bb7d9f3 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java @@ -19,6 +19,7 @@ import com.fr.stable.StringUtils; import javax.swing.SwingWorker; import java.io.File; import java.io.IOException; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; /** @@ -75,7 +76,7 @@ public class ComponentInstallation extends AsyncInstallation { } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); Thread.currentThread().interrupt(); - } catch (ExecutionException e) { + } catch (ExecutionException | CancellationException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java index 56200a0c28..39107a5a11 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java @@ -15,6 +15,7 @@ import javax.swing.SwingWorker; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; /** @@ -164,7 +165,7 @@ public class ComponentsPackageInstallation extends AsyncInstallation { } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); Thread.currentThread().interrupt(); - } catch (ExecutionException e) { + } catch (ExecutionException | CancellationException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java index f61af23d62..4de568db7f 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java @@ -25,6 +25,8 @@ import javax.swing.SwingWorker; import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.HashMap; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; /** @@ -33,13 +35,19 @@ import java.util.concurrent.ExecutionException; * Created by Starryi on 2022/1/5 */ public class TemplateThemeInstallation extends AsyncInstallation { + private final Window parentWindow; private final String themePath; private SwingWorker worker; - public TemplateThemeInstallation(String themePath) { + public TemplateThemeInstallation(Window parentWindow, String themePath) { + this.parentWindow = parentWindow; this.themePath = themePath; } + public TemplateThemeInstallation(String themePath) { + this(DesignerContext.getDesignerFrame(), themePath); + } + @Override public void install() { fetchTheme(); @@ -66,7 +74,7 @@ public class TemplateThemeInstallation extends AsyncInstallation { } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); Thread.currentThread().interrupt(); - } catch (ExecutionException e) { + } catch (ExecutionException | CancellationException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } @@ -78,7 +86,7 @@ public class TemplateThemeInstallation extends AsyncInstallation { private boolean checkAuthority() { if (!WorkContext.getCurrent().isRoot()) { - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + FineJOptionPane.showMessageDialog(parentWindow, Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_No_Authority_Tip_Message"), Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_No_Authority_Tip_Title"), JOptionPane.WARNING_MESSAGE); @@ -87,7 +95,7 @@ public class TemplateThemeInstallation extends AsyncInstallation { String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); if (StringUtils.isEmpty(userName)) { - DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL); + DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL, new HashMap<>(), parentWindow); return false; } @@ -108,7 +116,7 @@ public class TemplateThemeInstallation extends AsyncInstallation { return theme; } else { String newName = (String) FineJOptionPane.showInputDialog( - DesignerContext.getDesignerFrame(), + parentWindow, Toolkit.i18nText("Fine-Design_Share_Rename_Suitable_Theme_Tip"), Toolkit.i18nText("Fine-Design_Basic_Rename"), FineJOptionPane.QUESTION_MESSAGE, null, null, @@ -147,12 +155,12 @@ public class TemplateThemeInstallation extends AsyncInstallation { JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); if (currentTemplate.getUsingTemplateThemeConfig() instanceof FormThemeConfig) { - TemplateThemeUsingDialog dialog = new TemplateThemeUsingDialog(); + TemplateThemeUsingDialog dialog = new TemplateThemeUsingDialog(parentWindow); dialog.addWindowListener(new UsingDialogAdapter(theme, currentTemplate)); dialog.setVisible(true); } else { FineJOptionPane.showConfirmDialog( - MiniComponentShopDialog.getInstance().getContentPane(), + MiniComponentShopDialog.getInstance().getWindow(), Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_Success_Tip"), "", FineJOptionPane.YES_NO_OPTION diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java index 29fbafbaf3..939a7112e1 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.share.ui.online.mini; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.UIDialog; import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker; +import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.IOUtils; import javax.swing.JFrame; @@ -93,6 +94,7 @@ public class MiniComponentShopDialog { } } }); + GUICoreUtils.centerWindow(frame); return frame; } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java index 52379b7f88..a579681747 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java @@ -17,15 +17,18 @@ import com.fr.form.share.Group; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.bean.OnlineShareWidget; import com.fr.form.share.group.DefaultShareGroupManager; -import com.fr.json.JSONArray; import com.fr.json.JSONObject; import com.fr.stable.StringUtils; import com.teamdev.jxbrowser.chromium.JSAccessible; +import com.teamdev.jxbrowser.chromium.JSFunction; import com.teamdev.jxbrowser.chromium.JSObject; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import java.awt.Window; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; /** @@ -35,6 +38,13 @@ import java.util.Set; */ public class NativeProductBridge { private final JSObject window; + private static final Map executingComponentInstallationTasks = new HashMap<>(); + private static final Map executingComponentsPackageInstallationTasks = new HashMap<>(); + private static final Map executingTemplateThemeInstallationTasks = new HashMap<>(); + + private final Map> componentDownloadTaskStartListeners = new HashMap<>(); + private final Map> componentsPackageDownloadTaskStartListeners = new HashMap<>(); + private final Map> themeDownloadTaskStartListeners = new HashMap<>(); public NativeProductBridge(JSObject window) { this.window = window; @@ -42,30 +52,116 @@ public class NativeProductBridge { @JSAccessible @JSBridge - public String getDownloadedProductIds() { - Set uuidList = new HashSet<>(); + public boolean isProductDownloaded(String uuid) { for (Group group : DefaultShareGroupManager.getInstance().getAllGroup()) { SharableWidgetProvider[] widgetProviderList = group.getAllBindInfoList(); for (SharableWidgetProvider widget: widgetProviderList) { - if (StringUtils.isNotEmpty(widget.getId())) { - uuidList.add(widget.getId()); + if (StringUtils.equals(uuid, widget.getId())) { + return true; } } } - JSONArray array = JSONArray.create(uuidList); - return array.toString(); + return false; + } + + @JSAccessible + @JSBridge + public void addProductDownloadTaskStartListener(String json, JSFunction function) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + String uuid = widget.getUuid(); + boolean isPackage = widget.isWidgetPackage(); + + Map> downloadTaskGetters = + isPackage ? componentsPackageDownloadTaskStartListeners : componentDownloadTaskStartListeners; + Set startListeners = downloadTaskGetters.get(widget.getUuid()); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.add(function); + downloadTaskGetters.put(widget.getUuid(), startListeners); + + + } + + @JSAccessible + @JSBridge + public void removeProductDownloadTaskStartListener(String json, JSFunction function) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + String uuid = widget.getUuid(); + boolean isPackage = widget.isWidgetPackage(); + + Map> downloadTaskGetters = isPackage ? componentsPackageDownloadTaskStartListeners : componentDownloadTaskStartListeners; + + Set startListeners = downloadTaskGetters.get(uuid); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.remove(function); + downloadTaskGetters.put(uuid, startListeners); + } + + @JSAccessible + @JSBridge + public Object getExecutingProductDownloadTask(String json) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + String uuid = widget.getUuid(); + boolean isPackage = widget.isWidgetPackage(); + + Map executingDownloadTask = + isPackage ? executingComponentsPackageInstallationTasks : executingComponentInstallationTasks; + NativeTaskBridge task = executingDownloadTask.get(uuid); + if (task != null) { + task.checkJSEnvChange(this.window); + } + return task; } @JSAccessible @JSBridge public Object createProductDownloadTask(String json) { - return new ComponentInstallationTask(window, json); + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + int childrenCount = object.optInt("pkgsize", 0); + if (childrenCount > 0) { + return new ComponentsPackageInstallationTask(window, widget, childrenCount); + } else { + return new ComponentInstallationTask(window, widget); + } + } + + @JSAccessible + @JSBridge + public void addThemeDownloadTaskStartListener(String themePath, JSFunction function) { + Set startListeners = themeDownloadTaskStartListeners.get(themePath); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.add(function); + themeDownloadTaskStartListeners.put(themePath, startListeners); } @JSAccessible @JSBridge - public Object createProductsPackageDownloadTask(String json) { - return new ComponentsPackageInstallationTask(window, json); + public void removeThemeDownloadTaskStartListener(String themePath, JSFunction function) { + Set startListeners = themeDownloadTaskStartListeners.get(themePath); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.remove(function); + themeDownloadTaskStartListeners.put(themePath, startListeners); + } + + @JSAccessible + @JSBridge + public Object getExecutingThemeDownloadTask(String themePath) { + NativeTaskBridge task = executingTemplateThemeInstallationTasks.get(themePath); + if (task != null) { + task.checkJSEnvChange(this.window); + } + return task; } @JSAccessible @@ -74,15 +170,13 @@ public class NativeProductBridge { return new TemplateThemeInstallationTask(window, themePath); } - public static class ComponentInstallationTask extends NativeTaskBridge { + public class ComponentInstallationTask extends NativeTaskBridge { private final OnlineShareWidget widget; private final ComponentInstallation action; - public ComponentInstallationTask(JSObject window, String widgetJson) { + public ComponentInstallationTask(JSObject window, OnlineShareWidget widget) { super(window); - - JSONObject object = new JSONObject(widgetJson); - widget = OnlineShareWidget.parseFromJSONObject(object); + this.widget = widget; action = new ComponentInstallation(widget); action.setActionListener(new AsyncInstallation.AsyncActionListener() { @Override @@ -93,8 +187,8 @@ public class NativeProductBridge { @Override public void onSuccess() { fireSuccessEvent(null); + LocalWidgetRepoPane.getInstance().refreshPane(); if (!DesignerContext.getDesignerFrame().isActive()) { - LocalWidgetRepoPane.getInstance().refreshPane(); FormWidgetDetailPane.getInstance().switch2Local(); EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB); } @@ -147,19 +241,38 @@ public class NativeProductBridge { } }); } + + @Override + protected void fireStartEvent(String event) { + executingComponentInstallationTasks.put(widget.getUuid(), this); + Set startListeners = componentDownloadTaskStartListeners.get(widget.getUuid()); + SafeJSFunctionInvoker.invoke(startListeners, window); + super.fireStartEvent(event); + } + + @Override + protected void fireFailureEvent(String event) { + executingComponentInstallationTasks.remove(widget.getUuid()); + super.fireFailureEvent(event); + } + + @Override + protected void fireSuccessEvent(String event) { + executingComponentInstallationTasks.remove(widget.getUuid()); + super.fireSuccessEvent(event); + } } - public static class ComponentsPackageInstallationTask extends NativeTaskBridge { + public class ComponentsPackageInstallationTask extends NativeTaskBridge { private final ComponentsPackageInstallation action; private final OnlineShareWidget widget; private final int childrenCount; - public ComponentsPackageInstallationTask(JSObject window, String widgetJson) { + public ComponentsPackageInstallationTask(JSObject window, OnlineShareWidget widget, int childrenCount) { super(window); - JSONObject object = new JSONObject(widgetJson); - widget = OnlineShareWidget.parseFromJSONObject(object); - childrenCount = object.optInt("pkgsize", 0); + this.widget = widget; + this.childrenCount = childrenCount; action = new ComponentsPackageInstallation(widget, childrenCount); action.setActionListener(new AsyncInstallation.AsyncActionListener() { @Override @@ -170,8 +283,8 @@ public class NativeProductBridge { @Override public void onSuccess() { fireSuccessEvent(null); + LocalWidgetRepoPane.getInstance().refreshPane(); if (!DesignerContext.getDesignerFrame().isActive()) { - LocalWidgetRepoPane.getInstance().refreshPane(); FormWidgetDetailPane.getInstance().switch2Local(); EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB); } @@ -232,13 +345,37 @@ public class NativeProductBridge { } }); } + + @Override + protected void fireStartEvent(String event) { + executingComponentsPackageInstallationTasks.put(widget.getUuid(), this); + super.fireStartEvent(event); + + Set startListeners = componentsPackageDownloadTaskStartListeners.get(widget.getUuid()); + SafeJSFunctionInvoker.invoke(startListeners, window); + } + + @Override + protected void fireFailureEvent(String event) { + executingComponentsPackageInstallationTasks.remove(widget.getUuid()); + super.fireFailureEvent(event); + } + + @Override + protected void fireSuccessEvent(String event) { + executingComponentsPackageInstallationTasks.remove(widget.getUuid()); + super.fireSuccessEvent(event); + } } - public static class TemplateThemeInstallationTask extends NativeTaskBridge { + public class TemplateThemeInstallationTask extends NativeTaskBridge { + private final String themePath; private final TemplateThemeInstallation action; public TemplateThemeInstallationTask(JSObject window, String themePath) { super(window); - action = new TemplateThemeInstallation(themePath); + this.themePath = themePath; + Window miniShopWindow = MiniComponentShopDialog.getInstance().getWindow(); + action = new TemplateThemeInstallation(miniShopWindow, themePath); action.setActionListener(new AsyncInstallation.AsyncActionListener() { @Override public void onProgress(double value) { @@ -283,5 +420,25 @@ public class NativeProductBridge { } }); } + + @Override + protected void fireStartEvent(String event) { + executingTemplateThemeInstallationTasks.put(themePath, this); + Set startListeners = themeDownloadTaskStartListeners.get(themePath); + SafeJSFunctionInvoker.invoke(startListeners, window); + super.fireStartEvent(event); + } + + @Override + protected void fireFailureEvent(String event) { + executingTemplateThemeInstallationTasks.remove(themePath); + super.fireFailureEvent(event); + } + + @Override + protected void fireSuccessEvent(String event) { + executingTemplateThemeInstallationTasks.remove(themePath); + super.fireSuccessEvent(event); + } } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java index c29fbc786a..eb343c623c 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java @@ -7,6 +7,11 @@ import com.teamdev.jxbrowser.chromium.JSAccessible; import com.teamdev.jxbrowser.chromium.JSFunction; import com.teamdev.jxbrowser.chromium.JSObject; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + /** * @author Starryi * @version 1.0 @@ -14,39 +19,30 @@ import com.teamdev.jxbrowser.chromium.JSObject; */ public class NativeTaskBridge implements MiniShopNativeTask { - private final JSObject window; - - protected JSFunction startCb; - protected JSFunction progressCb; - protected JSFunction successCb; - protected JSFunction failureCb; + private JSObject window; + protected final Set statusCbs = new HashSet<>(); public NativeTaskBridge(JSObject window) { this.window = window; } - @JSBridge - @JSAccessible - public void setStartCallback(JSFunction cb) { - this.startCb = cb; - } - - @JSBridge - @JSAccessible - public void setProgressCallback(JSFunction cb) { - this.progressCb = cb; + public void checkJSEnvChange(JSObject window) { + if (this.window != window) { + this.window = window; + this.statusCbs.clear(); + } } @JSBridge @JSAccessible - public void setSuccessCallback(JSFunction cb) { - this.successCb = cb; + public void addStatusCallback(JSFunction cb) { + this.statusCbs.add(cb); } @JSBridge @JSAccessible - public void setFailureCallback(JSFunction cb) { - this.failureCb = cb; + public void removeStatusCallback(JSFunction cb) { + this.statusCbs.remove(cb); } @JSBridge @@ -60,30 +56,22 @@ public class NativeTaskBridge implements MiniShopNativeTask { @Override public void cancel() { MiniShopNativeTaskManager.getInstance().removeCompletedTask(this); + fireFailureEvent(null); } - protected void fireStartEvent(String event) { MiniShopNativeTaskManager.getInstance().addStartedTask(this); - if (this.startCb != null) { - this.startCb.invoke(window, event); - } + SafeJSFunctionInvoker.invoke(statusCbs, window, "START", event); } protected void fireProgressEvent(String event) { - if (this.progressCb != null) { - this.progressCb.invoke(window, event); - } + SafeJSFunctionInvoker.invoke(statusCbs, window, "PROGRESS", event); } protected void fireSuccessEvent(String event) { MiniShopNativeTaskManager.getInstance().removeCompletedTask(this); - if (this.successCb != null) { - this.successCb.invoke(window, event); - } + SafeJSFunctionInvoker.invoke(statusCbs, window, "SUCCESS", event); } protected void fireFailureEvent(String event) { MiniShopNativeTaskManager.getInstance().removeCompletedTask(this); - if (this.failureCb != null) { - this.failureCb.invoke(window, event); - } + SafeJSFunctionInvoker.invoke(statusCbs, window, "FAILURE", event); } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java new file mode 100644 index 0000000000..238376f9ed --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java @@ -0,0 +1,29 @@ +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.teamdev.jxbrowser.chromium.JSFunction; +import com.teamdev.jxbrowser.chromium.JSObject; + +import java.util.Collection; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/17 + */ +public class SafeJSFunctionInvoker { + + public static void invoke(Collection functions, JSObject instance, Object... args) { + if (functions != null) { + for (JSFunction function: functions) { + if (function != null && !function.getContext().isDisposed()) { + function.invoke(instance, args); + } + } + } + } + public static void invoke(JSFunction function, JSObject instance, Object... args) { + if (function != null && !function.getContext().isDisposed()) { + function.invoke(instance, args); + } + } +}