Browse Source

REPORT-62688 组件商城面向风格优化

【问题原因】
1. 设计器在线商城页面网页化
2. URL启动设计器安装主题文件

【改动思路】
同上
feature/x
Starryi 3 years ago
parent
commit
697919f46a
  1. 4
      build.gradle
  2. 7
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  3. 37
      designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopDisposingChecker.java
  4. 11
      designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTask.java
  5. 42
      designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTaskManager.java
  6. 33
      designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationFactory.java
  7. 14
      designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationProvider.java
  8. 35
      designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java
  9. 11
      designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java
  10. 4
      designer-form/src/main/java/com/fr/design/mainframe/share/config/ComponentReuseConfigManager.java
  11. 165
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java
  12. 65
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java
  13. 38
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/AsyncInstallation.java
  14. 147
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java
  15. 179
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java
  16. 10
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/Installation.java
  17. 202
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java
  18. 124
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java
  19. 68
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopPane.java
  20. 26
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/ComposedNativeBridges.java
  21. 34
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeAuthBridge.java
  22. 25
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeBrowserBridge.java
  23. 287
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java
  24. 89
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java
  25. 4
      designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java
  26. 15
      designer-realize/src/main/java/com/fr/design/deeplink/DeepLink.java
  27. 133
      designer-realize/src/main/java/com/fr/design/deeplink/DeepLinkManager.java
  28. 53
      designer-realize/src/main/java/com/fr/design/deeplink/TemplateThemeInstallationDeepLink.java
  29. 2
      designer-realize/src/main/java/com/fr/start/MainDesigner.java

4
build.gradle

@ -44,6 +44,9 @@ allprojects {
repositories {
mavenLocal()
maven {
url 'https://maven.ej-technologies.com/repository'
}
}
idea {
@ -57,6 +60,7 @@ allprojects {
}
dependencies {
implementation 'com.install4j:install4j-runtime:8.0.4'
implementation 'com.fr.third:jxbrowser:6.23'
implementation 'com.fr.third:jxbrowser-mac:6.23'
implementation 'com.fr.third:jxbrowser-win64:6.23'

7
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java

@ -28,6 +28,8 @@ import com.fr.design.fun.impl.AbstractTemplateTreeShortCutProvider;
import com.fr.design.gui.iprogressbar.ProgressDialog;
import com.fr.design.gui.iscrollbar.UIScrollBar;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker;
import com.fr.design.mainframe.share.mini.MiniShopNativeTaskManager;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.mainframe.vcs.common.VcsHelper;
@ -157,6 +159,11 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
@Override
public void windowClosing(WindowEvent e) {
// 检查mini商城是否存在未结束的后台任务
if (!MiniShopDisposingChecker.check()) {
return;
}
// 关闭前check
if (!TemplateSavingChecker.check()) {
return;

37
designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopDisposingChecker.java

@ -0,0 +1,37 @@
package com.fr.design.mainframe.share.mini;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import javax.swing.JOptionPane;
import java.awt.Component;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/8
*/
public class MiniShopDisposingChecker {
public static boolean check() {
return check(DesignerContext.getDesignerFrame());
}
public static boolean check(Component optionParentComponent) {
if (MiniShopNativeTaskManager.getInstance().hasExecutingTasks()) {
int result = FineJOptionPane.showConfirmDialog(
optionParentComponent,
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Close_Tip"),
"",
FineJOptionPane.YES_NO_OPTION
);
if (result == JOptionPane.YES_OPTION) {
MiniShopNativeTaskManager.getInstance().cancelAllExecutingTasks();
return true;
}
return false;
}
return true;
}
}

11
designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTask.java

@ -0,0 +1,11 @@
package com.fr.design.mainframe.share.mini;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/8
*/
public interface MiniShopNativeTask {
void execute();
void cancel();
}

42
designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTaskManager.java

@ -0,0 +1,42 @@
package com.fr.design.mainframe.share.mini;
import java.util.HashSet;
import java.util.Set;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/8
*/
public class MiniShopNativeTaskManager {
private MiniShopNativeTaskManager() {
}
private static class HOLDER {
private static final MiniShopNativeTaskManager singleton = new MiniShopNativeTaskManager();
}
public static MiniShopNativeTaskManager getInstance() {
return MiniShopNativeTaskManager.HOLDER.singleton;
}
private static final Set<MiniShopNativeTask> executingTasks = new HashSet<>();
public void addStartedTask(MiniShopNativeTask task) {
executingTasks.add(task);
}
public void removeCompletedTask(MiniShopNativeTask task) {
executingTasks.remove(task);
}
public boolean hasExecutingTasks() {
return !executingTasks.isEmpty();
}
public void cancelAllExecutingTasks() {
for (MiniShopNativeTask executingTask: executingTasks) {
executingTask.cancel();
}
executingTasks.clear();
}
}

33
designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationFactory.java

@ -0,0 +1,33 @@
package com.fr.design.startup;
import org.jetbrains.annotations.NotNull;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/11
*/
public class FineStartupNotificationFactory {
private static final FineStartupNotificationProvider DEFAULT = Install4jStartupNotificationProvider.getInstance();
private static FineStartupNotificationProvider provider;
public FineStartupNotificationFactory() {
}
public static FineStartupNotificationProvider getNotification() {
return provider;
}
public static void setLogger(@NotNull FineStartupNotificationProvider provider) {
FineStartupNotificationFactory.provider = provider;
}
public static void reset() {
provider = DEFAULT;
}
static {
provider = DEFAULT;
}
}

14
designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationProvider.java

@ -0,0 +1,14 @@
package com.fr.design.startup;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/11
*/
public interface FineStartupNotificationProvider {
void registerStartupListener(Listener listener);
interface Listener {
void startupPerformed(String parameters);
}
}

35
designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java

@ -0,0 +1,35 @@
package com.fr.design.startup;
import com.install4j.api.launcher.StartupNotification;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/11
*/
public class Install4jStartupNotificationProvider implements FineStartupNotificationProvider {
private Install4jStartupNotificationProvider() {
}
private static final Install4jStartupNotificationProvider INSTANCE = new Install4jStartupNotificationProvider();
public static Install4jStartupNotificationProvider getInstance() {
return INSTANCE;
}
@Override
public void registerStartupListener(Listener listener) {
boolean supported = false;
try {
supported = Class.forName("com.install4j.api.launcher.StartupNotification") != null;
} catch (Throwable ignored) {}
if (supported) {
StartupNotification.registerStartupListener(new StartupNotification.Listener() {
@Override
public void startupPerformed(String parameters) {
listener.startupPerformed(parameters);
}
});
}
}
}

11
designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java

@ -18,6 +18,9 @@ import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane;
import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.module.DesignModuleFactory;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.gui.LayoutUtils;
@ -262,7 +265,13 @@ public class FormParaWidgetPane extends JPanel {
jPanel.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
FormWidgetDetailPane.getInstance().enterWidgetLib();
if (OnlineShopUtils.testConnection()) {
MiniComponentShopDialog.getInstance().show();
} else {
OnlineWidgetRepoPane.getInstance().switch2InternetErrorPane();
FormWidgetDetailPane.getInstance().switch2Local();
FormWidgetDetailPane.getInstance().enterWidgetLib();
}
}
@Override

4
designer-form/src/main/java/com/fr/design/mainframe/share/config/ComponentReuseConfigManager.java

@ -22,6 +22,7 @@ public class ComponentReuseConfigManager {
private static final String PROPERTIES_FILE_NAME = "reuse.properties";
private static final String MINI_SHOP_URL = "MINI_SHOP_URL";
private static final String WEB_MINI_SHOP_URL = "WEB_MINI_SHOP_URL";
private static final String COMPONENT_UPLOAD_URL = "COMPONENT_UPLOAD_URL";
private static final String MARKET_LOGIN_URL = "MARKET_LOGIN_URL";
private static final String UPLOAD_REU_SUPPORT = "UPLOAD_REU_SUPPORT";
@ -61,6 +62,9 @@ public class ComponentReuseConfigManager {
return p;
}
public String getWebMiniShopUrl() {
return loadAttribute(WEB_MINI_SHOP_URL, DesignerCloudURLManager.getInstance().acquireUrlByKind("component.miniShop"));
}
public String getMiniShopUrl() {
return loadAttribute(MINI_SHOP_URL, DesignerCloudURLManager.getInstance().acquireUrlByKind("af.reuseInfo"));

165
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java

@ -1,29 +1,44 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.base.BaseUtils;
import com.fr.base.Style;
import com.fr.config.constant.Constant;
import com.fr.design.dialog.BasicPane;
import com.fr.design.form.util.FontTransformUtil;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.ui.base.LoadingPane;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.mainframe.theme.edit.ui.LabelUtils;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.Constants;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
@ -35,13 +50,8 @@ public class OnlineWidgetRepoPane extends BasicPane {
private static final String MARKET_URL = "https://market.fanruan.com/reuse";
private static List<OnlineShareWidget>[] sharableWidgets;
private OnlineWidgetTabPane componentTabPane;
private JPanel centerPane;
private boolean isShowPackagePanel = false;
private CardLayout cardLayout;
private Status currentStatus;
enum Status {LOADING, DISCONNECTED, NORMAL}
private LoadableContentPane loadableContentPane;
public static boolean loadWidgets() {
if (sharableWidgets != null){
@ -82,16 +92,15 @@ public class OnlineWidgetRepoPane extends BasicPane {
}
private void initPane() {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
this.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
this.centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.setLayout(new BorderLayout());
this.loadableContentPane = new LoadableContentPane(createInternetErrorPane());
this.loadableContentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
this.add(new LoadingPane(), Status.LOADING.name());
this.add(this.centerPane, Status.NORMAL.name());
this.add(createInternetErrorPane(), Status.DISCONNECTED.name());
DisabledContentPane disabledContentPane = new DisabledContentPane(this.loadableContentPane);
this.add(disabledContentPane, BorderLayout.CENTER);
switchPane(Status.LOADING);
this.loadableContentPane.showLoading();
setContent();
}
@ -105,18 +114,15 @@ public class OnlineWidgetRepoPane extends BasicPane {
}
private void addCenterPane() {
this.centerPane.removeAll();
this.centerPane.add(this.componentTabPane, BorderLayout.CENTER);
this.switchPane(Status.NORMAL);
JPanel contentPane = this.loadableContentPane.getContentPane();
contentPane.removeAll();
contentPane.setLayout(new BorderLayout());
contentPane.add(this.componentTabPane, BorderLayout.CENTER);
this.loadableContentPane.showContent();
}
public void switch2InternetErrorPane() {
switchPane(Status.DISCONNECTED);
}
private void switchPane(Status status) {
this.currentStatus = status;
cardLayout.show(this, status.name());
this.loadableContentPane.showError();
}
private void synchronizedLoadingContent() {
@ -147,16 +153,18 @@ public class OnlineWidgetRepoPane extends BasicPane {
if (componentTabPane != null) {
componentTabPane.removeTabChangeListener(tabChangeListener);
}
this.componentTabPane = new OnlineWidgetTabPane(sharableWidgets[0].toArray(new OnlineShareWidget[sharableWidgets[0].size()]),
sharableWidgets[1].toArray(new OnlineShareWidget[sharableWidgets[1].size()]));
this.componentTabPane = new OnlineWidgetTabPane(
sharableWidgets[0].toArray(new OnlineShareWidget[0]),
sharableWidgets[1].toArray(new OnlineShareWidget[0])
);
this.componentTabPane.addTabChangeListener(tabChangeListener);
} else {
switchPane(Status.DISCONNECTED);
this.loadableContentPane.showError();
}
return loadWidgetsSuccess;
}
private OnlineWidgetTabPane.TabChangeListener tabChangeListener = new OnlineWidgetTabPane.TabChangeListener() {
private final OnlineWidgetTabPane.TabChangeListener tabChangeListener = new OnlineWidgetTabPane.TabChangeListener() {
@Override
public void tabChange(int selectedIndex) {
setShowPackagePanel(selectedIndex != 0);
@ -173,7 +181,7 @@ public class OnlineWidgetRepoPane extends BasicPane {
private JPanel createInternetErrorPane() {
JPanel panel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5);
UILabel imagePanel = new UILabel(BaseUtils.readIcon("/com/fr/base/images/share/internet_error.png"));
UILabel imagePanel = new UILabel(IOUtils.readIcon("/com/fr/base/images/share/internet_error.png"));
imagePanel.setPreferredSize(new Dimension(240, 96));
imagePanel.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(imagePanel);
@ -240,4 +248,105 @@ public class OnlineWidgetRepoPane extends BasicPane {
this.componentTabPane.completeEmbedFilter();
}
}
private static class LoadableContentPane extends JPanel {
private enum Status {
LOADING,
DISCONNECTED,
NORMAL
}
private final CardLayout cardLayout;
private final JPanel contentPane;
public LoadableContentPane(JPanel errorPane) {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
this.add(new LoadingPane(), Status.LOADING.name());
contentPane = new JPanel();
this.add(contentPane, Status.NORMAL.name());
this.add(errorPane, Status.DISCONNECTED.name());
}
private void switchPane(Status status) {
cardLayout.show(this, status.name());
}
public void showLoading() {
switchPane(Status.LOADING);
}
public void showError() {
switchPane(Status.DISCONNECTED);
}
public void showContent() {
switchPane(Status.NORMAL);
}
public JPanel getContentPane() {
return contentPane;
}
}
private static class DisabledContentPane extends JPanel {
private final CardLayout cardLayout;
public DisabledContentPane(JPanel contentPane) {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
this.add(new MaskPane(), "Disabled");
this.add(contentPane, "Enabled");
MiniComponentShopDialog.getInstance().addWindowAdapter(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
super.windowOpened(e);
setEnabled(false);
}
@Override
public void windowClosed(WindowEvent e) {
super.windowClosed(e);
setEnabled(true);
}
});
setEnabled(true);
}
@Override
public void setEnabled(boolean enabled) {
String constrains = enabled ? "Enabled" : "Disabled";
cardLayout.show(this, constrains);
}
}
private static class MaskPane extends JPanel {
private static final int PADDING = 30;
private final String text;
private final Style style;
public MaskPane() {
setLayout(new BorderLayout());
text = Toolkit.i18nText("Fine-Design_Share_Online_Repo_Pane_Forbidden_Tip");
style = Style.getInstance(FRFont.getInstance().applyForeground(new Color(0x8F8F92)))
.deriveHorizontalAlignment(SwingConstants.CENTER)
.deriveVerticalAlignment(SwingConstants.CENTER)
.deriveTextStyle(Style.TEXTSTYLE_WRAPTEXT);
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g.translate(PADDING, 0);
BaseUtils.drawStringStyleInRotation(g2d, this.getWidth() - PADDING * 2, this.getHeight(), text, style, FontTransformUtil.getDesignerFontResolution());
g.translate(-PADDING, 0);
}
}
}

65
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java

@ -1,18 +1,29 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.design.gui.ibutton.UITabGroup;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.EastRegionContainerPane;
import com.fr.design.mainframe.FormWidgetDetailPane;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.sort.OnlineWidgetSortType;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.ui.online.embed.OnlineEmbedFilterShowPane;
import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog;
import com.fr.design.mainframe.share.ui.online.widgetpackage.OnlineWidgetPackagesShowPane;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.bean.OnlineShareWidget;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;
@ -24,11 +35,14 @@ public class OnlineWidgetTabPane extends JPanel {
private static final String COMPONENT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share");
private static final String COMPONENT_PACKAGE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Package");
private static final String COMPONENT_EMBED = "COMPONENT_EMBED";
private static final int COMPONENT_PACKAGE_TAB_INDEX = 0;
private static final int COMPONENT_TAB_INDEX = 1;
private UITabGroup headGroup;
private CardLayout cardLayout;
private JPanel centerPane;
private boolean packagePaneCreated = false;
private List<TabChangeListener> tabChangeListeners;
private final List<TabChangeListener> tabChangeListeners;
private OnlineEmbedFilterShowPane embedFilterShowPane;
public OnlineWidgetTabPane(OnlineShareWidget[] sharableWidgets, OnlineShareWidget[] sharableWidgetPackage) {
@ -44,12 +58,12 @@ public class OnlineWidgetTabPane extends JPanel {
this.centerPane.add(new OnlineWidgetShowPane(sharableWidgets), COMPONENT);
this.centerPane.add( embedFilterShowPane = new OnlineEmbedFilterShowPane(new OnlineWidgetShowPane(sharableWidgets, OnlineWidgetSortType.SALES)), COMPONENT_EMBED);
//延迟组件包面板的初始化,防止组件面板里组件的缩略图和组件包面板里组件的缩略图一起加载
this.headGroup = new UITabGroup(new String[]{COMPONENT, COMPONENT_PACKAGE}) {
this.headGroup = new UITabGroup(new String[]{COMPONENT_PACKAGE, COMPONENT}) {
public void tabChanged(int newSelectedIndex) {
for (TabChangeListener changeListener : tabChangeListeners) {
changeListener.tabChange(newSelectedIndex);
}
if (newSelectedIndex == 0) {
if (newSelectedIndex == COMPONENT_TAB_INDEX) {
cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT);
} else {
ComponentShareUtil.completeEmbedFilter();
@ -64,15 +78,44 @@ public class OnlineWidgetTabPane extends JPanel {
}
};
this.headGroup.setSelectedIndex(0);
this.headGroup.setSelectedIndex(COMPONENT_PACKAGE_TAB_INDEX);
this.centerPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
jPanel.add(headGroup, BorderLayout.CENTER);
this.add(jPanel, BorderLayout.NORTH);
JPanel fixedContentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
fixedContentPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
fixedContentPane.add(headGroup, BorderLayout.NORTH);
fixedContentPane.add(createMiniShopEntryPane(), BorderLayout.CENTER);
this.add(fixedContentPane, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
}
private JPanel createMiniShopEntryPane() {
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
JButton button = new JButton(Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Entry_Text"));
button.setPreferredSize(new Dimension(button.getWidth(), 20));
button.setUI(new BasicButtonUI());
button.setOpaque(true);
button.setBackground(Color.WHITE);
button.setForeground(new Color(0x419BF9));
button.setBorder(BorderFactory.createLineBorder(new Color(0x419BF9), 1, true));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (OnlineShopUtils.testConnection()) {
MiniComponentShopDialog.getInstance().show();
FormWidgetDetailPane.getInstance().switch2Local();
FormWidgetDetailPane.getInstance().enterWidgetLib();
} else {
OnlineWidgetRepoPane.getInstance().switch2InternetErrorPane();
}
}
});
container.add(button, BorderLayout.NORTH);
return container;
}
public void completeEmbedFilter(){
if (embedFilterShowPane!= null){
embedFilterShowPane.completeEmbedFilter();
@ -85,8 +128,8 @@ public class OnlineWidgetTabPane extends JPanel {
}
}
public void refreshPane() {
this.headGroup.setSelectedIndex(0);
this.cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT);
this.headGroup.setSelectedIndex(COMPONENT_PACKAGE_TAB_INDEX);
this.cardLayout.show(centerPane, COMPONENT_PACKAGE);
}
public void refreshShowPaneUI(){

38
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/AsyncInstallation.java

@ -0,0 +1,38 @@
package com.fr.design.mainframe.share.ui.online.installation;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/5
*/
public abstract class AsyncInstallation implements Installation {
private AsyncActionListener actionListener;
public void setActionListener(AsyncActionListener actionListener) {
this.actionListener = actionListener;
}
protected void notifyProgress(double value) {
if (this.actionListener != null) {
this.actionListener.onProgress(value);
}
}
protected void notifySuccess() {
if (this.actionListener != null) {
this.actionListener.onSuccess();
}
}
protected void notifyFailed() {
if (this.actionListener != null) {
this.actionListener.onFailed();
}
}
public abstract void cancel();
public interface AsyncActionListener {
void onProgress(double value);
void onSuccess();
void onFailed();
}
}

147
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java

@ -0,0 +1,147 @@
package com.fr.design.mainframe.share.ui.online.installation;
import com.fr.design.DesignerEnvManager;
import com.fr.design.extra.Process;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.form.share.Group;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.group.DefaultShareGroup;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.form.share.utils.ShareUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.SwingWorker;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/5
*/
public class ComponentInstallation extends AsyncInstallation {
private final OnlineShareWidget widget;
private SwingWorker<Boolean, Void> worker;
public ComponentInstallation(OnlineShareWidget widget) {
this.widget = widget;
}
@Override
public void install() {
if (!checkLoginStatus()) {
notifyFailed();
return;
}
notifyProgress(0.0D);
worker = createWorker();
worker.execute();
}
private SwingWorker<Boolean, Void> createWorker() {
return new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() {
String tempFilePath = fetchRemoteReuFile2TempDir();
if (StringUtils.isEmpty(tempFilePath)) {
return false;
}
if (isCancelled()) {
return false;
}
ShareComponentUtils.checkReadMe();
if (isCancelled()) {
return false;
}
installTempReuFile(tempFilePath);
StableUtils.deleteFile(new File(tempFilePath));
return true;
}
@Override
protected void done() {
boolean result = false;
try {
result = get();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
notifyProgress(0.0D);
if (result) {
notifySuccess();
} else {
notifyFailed();
}
}
};
}
private boolean checkLoginStatus() {
String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername();
if (StringUtils.isEmpty(userName)) {
DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL);
return false;
}
return true;
}
private String createLocalReuFilename() {
String filename = widget.getFileLoca();
if (StringUtils.isEmpty(filename) || !filename.endsWith(".reu")) {
filename = widget.getName() + "." + widget.getUuid() + ".reu";
}
return filename;
}
private String fetchRemoteReuFile2TempDir() {
try {
String filename = createLocalReuFilename();
return DownloadUtils.download(widget.getId(), filename, new Process<Double>() {
@Override
public void process(Double value) {
notifyProgress(value);
}
});
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return null;
}
}
private void installTempReuFile(String tempFilePath) {
File file = new File(tempFilePath);
try {
Group targetGroup = getTargetGroup();
if (file.exists() && targetGroup.installUniqueIdModule(file)) {
ShareUtils.recordInstallTime(file.getName(), System.currentTimeMillis());
ComponentCollector.getInstance().collectCmpDownLoad(widget.getUuid());
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private Group getTargetGroup() {
return DefaultShareGroupManager.getInstance().getGroup(DefaultShareGroup.GROUP_NAME);
}
@Override
public void cancel() {
if (worker != null) {
worker.cancel(false);
}
}
}

179
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java

@ -0,0 +1,179 @@
package com.fr.design.mainframe.share.ui.online.installation;
import com.fr.design.extra.Process;
import com.fr.design.mainframe.share.ui.base.ImitationProgress;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.share.util.InstallUtils;
import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.form.share.Group;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import org.jetbrains.annotations.Nullable;
import javax.swing.SwingWorker;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/5
*/
public class ComponentsPackageInstallation extends AsyncInstallation {
private final OnlineShareWidget packageWidget;
private final int childrenCount;
private ImitationThread imitationThread;
private DownLoadSwingWorker worker;
public ComponentsPackageInstallation(OnlineShareWidget packageWidget, int childrenCount) {
this.packageWidget = packageWidget;
this.childrenCount = childrenCount;
}
@Override
public void install() {
final Process<Double> downloadProcess = new Process<Double>() {
@Override
public void process(Double value) {
notifyProgress(0.8 * value);
}
};
final Process<Double> installProcess = new Process<Double>() {
@Override
public void process(Double value) {
notifyProgress(0.8 + 0.2 * value);
}
};
downloadProcess.process(0.0D);
//假进度线程
final ImitationProgress imitationProgress = new ImitationProgress(downloadProcess, childrenCount);
imitationThread = new ImitationThread(imitationProgress);
imitationThread.setName("Component-ImitationProcessThread");
//下载线程
worker = new DownLoadSwingWorker(installProcess, packageWidget);
imitationThread.start();
worker.execute();
}
@Override
public void cancel() {
if (imitationThread != null) {
imitationThread.interrupt();
}
if (worker != null) {
worker.cancel(false);
}
}
/**
* 假进度线程
*/
private static class ImitationThread extends Thread {
private final ImitationProgress imitationProgress;
public ImitationThread(ImitationProgress progress) {
imitationProgress = progress;
}
@Override
public void run() {
imitationProgress.start();
}
public void complete() {
imitationProgress.completed();
this.interrupt();
}
public void stopThread() {
imitationProgress.stop();
this.interrupt();
}
}
private class DownLoadSwingWorker extends SwingWorker<Group, Void> {
final Process<Double> installProcess;
final OnlineShareWidget onlineShareWidget;
public DownLoadSwingWorker(Process<Double> installProcess, OnlineShareWidget onlineShareWidget) {
this.installProcess = installProcess;
this.onlineShareWidget = onlineShareWidget;
}
@Override
@Nullable
protected Group doInBackground() {
final String filePath;
List<String> failureList = new ArrayList<>();
try {
filePath = DownloadUtils.downloadPackage(onlineShareWidget.getId(), onlineShareWidget.getName(), DownLoadSwingWorker.this::isCancelled);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
imitationThread.stopThread();
return null;
}
if (this.isCancelled()) {
imitationThread.stopThread();
StableUtils.deleteFile(new File(filePath));
return null;
}
//等待假进度线程结束
imitationThread.complete();
try {
imitationThread.join();
} catch (InterruptedException ignore) {
}
//再判断一次
if (this.isCancelled()) {
StableUtils.deleteFile(new File(filePath));
return null;
}
ShareComponentUtils.checkReadMe();
//安装
File file = new File(filePath);
installProcess.process(0.0D);
InstallUtils.InstallResult result = null;
try {
if (file.exists()) {
result = InstallUtils.installReusFile(file, System.currentTimeMillis(), failureList, installProcess);
}
} finally {
//删掉下载组件的目录
StableUtils.deleteFile(file);
}
return result == null ? null : result.group;
}
@Override
protected void done() {
Group group = null;
try {
group = get();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
notifyProgress(0.0D);
if (group != null) {
notifySuccess();
} else {
notifyFailed();
}
}
}
}

10
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/Installation.java

@ -0,0 +1,10 @@
package com.fr.design.mainframe.share.ui.online.installation;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/5
*/
public interface Installation {
void install();
}

202
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java

@ -0,0 +1,202 @@
package com.fr.design.mainframe.share.ui.online.installation;
import com.fr.base.theme.FormTheme;
import com.fr.base.theme.FormThemeConfig;
import com.fr.base.theme.TemplateTheme;
import com.fr.base.theme.TemplateThemeConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.transaction.CallBackAdaptor;
import com.fr.workspace.WorkContext;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.ExecutionException;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/5
*/
public class TemplateThemeInstallation extends AsyncInstallation {
private final String themePath;
private SwingWorker<FormTheme, Void> worker;
public TemplateThemeInstallation(String themePath) {
this.themePath = themePath;
}
@Override
public void install() {
fetchTheme();
}
private void fetchTheme() {
if (!checkAuthority()) {
onThemeFetched(null);
return;
}
worker = new SwingWorker<FormTheme, Void>() {
@Override
protected FormTheme doInBackground() {
return DownloadUtils.downloadThemeFile(themePath);
}
@Override
protected void done() {
FormTheme theme = null;
try {
theme = get();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
onThemeFetched(theme);
}
};
worker.execute();
}
private boolean checkAuthority() {
if (!WorkContext.getCurrent().isRoot()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
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);
return false;
}
String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername();
if (StringUtils.isEmpty(userName)) {
DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL);
return false;
}
return true;
}
public void onThemeFetched(FormTheme theme) {
if (theme == null) {
notifyFailed();
return;
}
saveTheme(theme);
}
private FormTheme ensureThemeHasUniqueName(FormTheme theme, String expectedName) {
if (!FormThemeConfig.getInstance().contains(expectedName)) {
theme.setName(expectedName);
return theme;
} else {
String newName = (String) FineJOptionPane.showInputDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Rename_Suitable_Theme_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Rename"),
FineJOptionPane.QUESTION_MESSAGE, null, null,
expectedName);
return StringUtils.isEmpty(newName) ? null : ensureThemeHasUniqueName(theme, newName);
}
}
private void saveTheme(FormTheme theme) {
final FormTheme uniqueNamedTheme = ensureThemeHasUniqueName(theme, theme.getName());
if (uniqueNamedTheme != null) {
FormThemeConfig.getInstance().addTheme(theme, true, new CallBackAdaptor() {
@Override
public void afterCommit() {
super.afterCommit();
onThemeSaved(uniqueNamedTheme);
}
@Override
public void afterRollback() {
super.afterRollback();
onThemeSaved(null);
}
});
} else {
onThemeSaved(null);
}
}
public void onThemeSaved(FormTheme theme) {
if (theme == null) {
notifyFailed();
return;
}
JTemplate<?, ?> currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (currentTemplate.getUsingTemplateThemeConfig() instanceof FormThemeConfig) {
TemplateThemeUsingDialog dialog = new TemplateThemeUsingDialog();
dialog.addWindowListener(new UsingDialogAdapter(theme, currentTemplate));
dialog.setVisible(true);
} else {
FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_Success_Tip"),
"",
FineJOptionPane.YES_NO_OPTION
);
}
notifySuccess();
}
public void applyTheme(JTemplate<?, ?> template, final String name, Window dialog) {
TemplateThemeConfig<? extends TemplateTheme> config = template.getUsingTemplateThemeConfig();
TemplateTheme theme = config.cachedFetch(name);
template.setTemplateTheme(theme);
dialog.repaint();
}
@Override
public void cancel() {
if (worker != null) {
worker.cancel(true);
}
}
private class UsingDialogAdapter extends WindowAdapter {
private final FormTheme theme;
private final JTemplate<?, ?> currentFormTemplate;
public UsingDialogAdapter(FormTheme theme, JTemplate<?, ?> currentFormTemplate) {
this.theme = theme;
this.currentFormTemplate = currentFormTemplate;
}
@Override
public void windowOpened(WindowEvent e) {
super.windowOpened(e);
Window window = e.getWindow();
int returnVal = FineJOptionPane.showConfirmDialog(
window,
Toolkit.i18nText("Fine-Design_Share_Apply_Suitable_Theme_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
FineJOptionPane.OK_CANCEL_OPTION);
if (returnVal == JOptionPane.YES_OPTION) {
applyTheme(currentFormTemplate, theme.getName(), window);
}
window.removeWindowListener(this);
}
}
}

124
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java

@ -0,0 +1,124 @@
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.general.IOUtils;
import javax.swing.JFrame;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.HashSet;
import java.util.Set;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/4
*/
public class MiniComponentShopDialog {
private static class HOLDER {
private static final MiniComponentShopDialog singleton = new MiniComponentShopDialog();
}
public static MiniComponentShopDialog getInstance() {
return MiniComponentShopDialog.HOLDER.singleton;
}
private final Set<WindowListener> windowListeners = new HashSet<>();
private JFrame frame;
private JFrame createFrame() {
final JFrame frame = new JFrame();
final MiniComponentShopPane shopPane = new MiniComponentShopPane();
frame.setSize(1200, 800);
frame.add(shopPane);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
for (WindowListener listener: windowListeners) {
listener.windowOpened(e);
}
}
@Override
public void windowClosing(WindowEvent e) {
for (WindowListener listener : windowListeners) {
listener.windowClosing(e);
}
if (MiniShopDisposingChecker.check(frame.getContentPane())) {
e.getWindow().dispose();
}
}
@Override
public void windowClosed(WindowEvent e) {
for (WindowListener listener: windowListeners) {
listener.windowClosed(e);
}
getInstance().frame = null;
shopPane.dispose();
}
@Override
public void windowIconified(WindowEvent e) {
for (WindowListener listener: windowListeners) {
listener.windowIconified(e);
}
}
@Override
public void windowDeiconified(WindowEvent e) {
for (WindowListener listener: windowListeners) {
listener.windowDeiconified(e);
}
}
@Override
public void windowActivated(WindowEvent e) {
for (WindowListener listener: windowListeners) {
listener.windowActivated(e);
}
}
@Override
public void windowDeactivated(WindowEvent e) {
for (WindowListener listener: windowListeners) {
listener.windowDeactivated(e);
}
}
});
return frame;
}
public void show() {
if (frame == null) {
frame = createFrame();
}
frame.setVisible(true);
}
public Container getContentPane() {
if (frame != null) {
return frame.getContentPane();
}
return null;
}
public Window getWindow() {
return frame;
}
public void addWindowAdapter(WindowListener windowListener) {
windowListeners.add(windowListener);
if (frame != null) {
frame.removeWindowListener(windowListener);
frame.addWindowListener(windowListener);
}
}
}

68
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopPane.java

@ -0,0 +1,68 @@
package com.fr.design.mainframe.share.ui.online.mini;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.share.ui.online.mini.bridge.ComposedNativeBridges;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.ui.ModernUIPane;
import com.fr.design.upm.event.CertificateEvent;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.teamdev.jxbrowser.chromium.JSObject;
import com.teamdev.jxbrowser.chromium.events.ScriptContextAdapter;
import com.teamdev.jxbrowser.chromium.events.ScriptContextEvent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.BorderLayout;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/12/20
*/
public class MiniComponentShopPane extends JPanel {
private final ModernUIPane<Object> modernUIPane;
private final Listener<String> loginListener;
private final Listener<String> logoutListener;
public MiniComponentShopPane() {
setLayout(new BorderLayout());
DesignerEnvManager.getEnvManager().setOpenDebug(true);
modernUIPane = new ModernUIPane.Builder<>()
.withURL(OnlineShopUtils.getWebMiniShopPath())
.prepare(new ScriptContextAdapter() {
@Override
public void onScriptContextCreated(ScriptContextEvent event) {
super.onScriptContextCreated(event);
JSObject window = event.getBrowser().executeJavaScriptAndReturnValue("window").asObject();
window.asObject().setProperty("ShopHelper", new ComposedNativeBridges(window, JOptionPane.getFrameForComponent(MiniComponentShopPane.this)));
}
})
.build();
add(modernUIPane, BorderLayout.CENTER);
loginListener = new Listener<String>() {
@Override
public void on(Event event, String param) {
modernUIPane.redirect(OnlineShopUtils.getWebMiniShopPath());
}
};
logoutListener = new Listener<String>() {
@Override
public void on(Event event, String param) {
modernUIPane.redirect(OnlineShopUtils.getWebMiniShopPath());
}
};
EventDispatcher.listen(CertificateEvent.LOGIN, loginListener);
EventDispatcher.listen(CertificateEvent.LOGOUT, logoutListener);
}
public void dispose() {
modernUIPane.disposeBrowser();
EventDispatcher.stopListen(loginListener);
EventDispatcher.stopListen(logoutListener);
}
}

26
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/ComposedNativeBridges.java

@ -0,0 +1,26 @@
package com.fr.design.mainframe.share.ui.online.mini.bridge;
import com.teamdev.jxbrowser.chromium.JSAccessible;
import com.teamdev.jxbrowser.chromium.JSObject;
import java.awt.Window;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/12/20
*/
public class ComposedNativeBridges {
@JSAccessible
public final NativeBrowserBridge Browser;
@JSAccessible
public final NativeAuthBridge Auth;
@JSAccessible
public final NativeProductBridge Product;
public ComposedNativeBridges(JSObject window, Window nativeWindow) {
this.Browser = new NativeBrowserBridge(nativeWindow);
this.Auth = new NativeAuthBridge();
this.Product = new NativeProductBridge(window);
}
}

34
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeAuthBridge.java

@ -0,0 +1,34 @@
package com.fr.design.mainframe.share.ui.online.mini.bridge;
import com.fr.design.DesignerEnvManager;
import com.fr.design.bridge.exec.JSBridge;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog;
import com.teamdev.jxbrowser.chromium.JSAccessible;
import java.awt.Window;
import java.util.HashMap;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/12/20
*/
public class NativeAuthBridge {
@JSAccessible
@JSBridge
public String getLoginUsername() {
return DesignerEnvManager.getEnvManager().getDesignerLoginUsername();
}
@JSAccessible
@JSBridge
public void goLogin() {
Window parentWindow = MiniComponentShopDialog.getInstance().getWindow();
if (parentWindow != null) {
parentWindow.toFront();
DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL, new HashMap<>(), parentWindow);
}
}
}

25
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeBrowserBridge.java

@ -0,0 +1,25 @@
package com.fr.design.mainframe.share.ui.online.mini.bridge;
import com.fr.design.bridge.exec.JSBridge;
import com.teamdev.jxbrowser.chromium.JSAccessible;
import java.awt.Window;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/12/20
*/
public class NativeBrowserBridge {
private final Window nativeWindow;
public NativeBrowserBridge(Window nativeWindow) {
this.nativeWindow = nativeWindow;
}
@JSAccessible
@JSBridge
public void dispose() {
this.nativeWindow.dispose();
}
}

287
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java

@ -0,0 +1,287 @@
package com.fr.design.mainframe.share.ui.online.mini.bridge;
import com.fr.design.bridge.exec.JSBridge;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.EastRegionContainerPane;
import com.fr.design.mainframe.FormWidgetDetailPane;
import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane;
import com.fr.design.mainframe.share.ui.online.installation.AsyncInstallation;
import com.fr.design.mainframe.share.ui.online.installation.ComponentInstallation;
import com.fr.design.mainframe.share.ui.online.installation.ComponentsPackageInstallation;
import com.fr.design.mainframe.share.ui.online.installation.TemplateThemeInstallation;
import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog;
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.JSObject;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import java.util.HashSet;
import java.util.Set;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/12/20
*/
public class NativeProductBridge {
private final JSObject window;
public NativeProductBridge(JSObject window) {
this.window = window;
}
@JSAccessible
@JSBridge
public String getDownloadedProductIds() {
Set<String> uuidList = new HashSet<>();
for (Group group : DefaultShareGroupManager.getInstance().getAllGroup()) {
SharableWidgetProvider[] widgetProviderList = group.getAllBindInfoList();
for (SharableWidgetProvider widget: widgetProviderList) {
if (StringUtils.isNotEmpty(widget.getId())) {
uuidList.add(widget.getId());
}
}
}
JSONArray array = JSONArray.create(uuidList);
return array.toString();
}
@JSAccessible
@JSBridge
public Object createProductDownloadTask(String json) {
return new ComponentInstallationTask(window, json);
}
@JSAccessible
@JSBridge
public Object createProductsPackageDownloadTask(String json) {
return new ComponentsPackageInstallationTask(window, json);
}
@JSAccessible
@JSBridge
public Object createTemplateThemeDownloadTask(String themePath) {
return new TemplateThemeInstallationTask(window, themePath);
}
public static class ComponentInstallationTask extends NativeTaskBridge {
private final OnlineShareWidget widget;
private final ComponentInstallation action;
public ComponentInstallationTask(JSObject window, String widgetJson) {
super(window);
JSONObject object = new JSONObject(widgetJson);
widget = OnlineShareWidget.parseFromJSONObject(object);
action = new ComponentInstallation(widget);
action.setActionListener(new AsyncInstallation.AsyncActionListener() {
@Override
public void onProgress(double value) {
fireProgressEvent(Double.toString(value));
}
@Override
public void onSuccess() {
fireSuccessEvent(null);
if (!DesignerContext.getDesignerFrame().isActive()) {
LocalWidgetRepoPane.getInstance().refreshPane();
FormWidgetDetailPane.getInstance().switch2Local();
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB);
}
}
@Override
public void onFailed() {
fireFailureEvent(null);
}
});
}
@JSAccessible
@JSBridge
@Override
public void execute() {
super.execute();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
boolean allowedDownload = true;
if (!widget.isCompatibleWithCurrentEnv()) {
int result = FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Component_Tip"),
"",
FineJOptionPane.YES_NO_OPTION
);
allowedDownload = result == JOptionPane.YES_OPTION;
}
if (allowedDownload) {
fireStartEvent(null);
action.install();
} else {
fireFailureEvent(null);
}
}
});
}
@JSAccessible
@JSBridge
@Override
public void cancel() {
super.cancel();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
action.cancel();
}
});
}
}
public static class ComponentsPackageInstallationTask extends NativeTaskBridge {
private final ComponentsPackageInstallation action;
private final OnlineShareWidget widget;
private final int childrenCount;
public ComponentsPackageInstallationTask(JSObject window, String widgetJson) {
super(window);
JSONObject object = new JSONObject(widgetJson);
widget = OnlineShareWidget.parseFromJSONObject(object);
childrenCount = object.optInt("pkgsize", 0);
action = new ComponentsPackageInstallation(widget, childrenCount);
action.setActionListener(new AsyncInstallation.AsyncActionListener() {
@Override
public void onProgress(double value) {
fireProgressEvent(Double.toString(value));
}
@Override
public void onSuccess() {
fireSuccessEvent(null);
if (!DesignerContext.getDesignerFrame().isActive()) {
LocalWidgetRepoPane.getInstance().refreshPane();
FormWidgetDetailPane.getInstance().switch2Local();
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB);
}
}
@Override
public void onFailed() {
fireFailureEvent(null);
}
});
}
@JSAccessible
@JSBridge
@Override
public void execute() {
super.execute();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
boolean allowedDownload;
if (!widget.isCompatibleWithCurrentEnv()) {
int result = FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Components_Package_Tip", childrenCount),
"",
FineJOptionPane.YES_NO_OPTION
);
allowedDownload = result == JOptionPane.YES_OPTION;
} else {
int result = FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Components_Package_Tip", childrenCount),
"",
FineJOptionPane.YES_NO_OPTION
);
allowedDownload = result == JOptionPane.YES_OPTION;
}
if (allowedDownload) {
fireStartEvent(null);
action.install();
} else {
fireFailureEvent(null);
}
}
});
}
@JSAccessible
@JSBridge
@Override
public void cancel() {
super.cancel();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
action.cancel();
}
});
}
}
public static class TemplateThemeInstallationTask extends NativeTaskBridge {
private final TemplateThemeInstallation action;
public TemplateThemeInstallationTask(JSObject window, String themePath) {
super(window);
action = new TemplateThemeInstallation(themePath);
action.setActionListener(new AsyncInstallation.AsyncActionListener() {
@Override
public void onProgress(double value) {
fireProgressEvent(Double.toString(value));
}
@Override
public void onSuccess() {
fireSuccessEvent(null);
}
@Override
public void onFailed() {
fireFailureEvent(null);
}
});
}
@JSAccessible
@JSBridge
@Override
public void execute() {
super.execute();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
fireStartEvent(null);
action.install();
}
});
}
@JSAccessible
@JSBridge
@Override
public void cancel() {
super.cancel();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
action.cancel();
}
});
}
}
}

89
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java

@ -0,0 +1,89 @@
package com.fr.design.mainframe.share.ui.online.mini.bridge;
import com.fr.design.bridge.exec.JSBridge;
import com.fr.design.mainframe.share.mini.MiniShopNativeTask;
import com.fr.design.mainframe.share.mini.MiniShopNativeTaskManager;
import com.teamdev.jxbrowser.chromium.JSAccessible;
import com.teamdev.jxbrowser.chromium.JSFunction;
import com.teamdev.jxbrowser.chromium.JSObject;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/12/20
*/
public class NativeTaskBridge implements MiniShopNativeTask {
private final JSObject window;
protected JSFunction startCb;
protected JSFunction progressCb;
protected JSFunction successCb;
protected JSFunction failureCb;
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;
}
@JSBridge
@JSAccessible
public void setSuccessCallback(JSFunction cb) {
this.successCb = cb;
}
@JSBridge
@JSAccessible
public void setFailureCallback(JSFunction cb) {
this.failureCb = cb;
}
@JSBridge
@JSAccessible
@Override
public void execute() {
}
@JSBridge
@JSAccessible
@Override
public void cancel() {
MiniShopNativeTaskManager.getInstance().removeCompletedTask(this);
}
protected void fireStartEvent(String event) {
MiniShopNativeTaskManager.getInstance().addStartedTask(this);
if (this.startCb != null) {
this.startCb.invoke(window, event);
}
}
protected void fireProgressEvent(String event) {
if (this.progressCb != null) {
this.progressCb.invoke(window, event);
}
}
protected void fireSuccessEvent(String event) {
MiniShopNativeTaskManager.getInstance().removeCompletedTask(this);
if (this.successCb != null) {
this.successCb.invoke(window, event);
}
}
protected void fireFailureEvent(String event) {
MiniShopNativeTaskManager.getInstance().removeCompletedTask(this);
if (this.failureCb != null) {
this.failureCb.invoke(window, event);
}
}
}

4
designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java

@ -42,6 +42,10 @@ public class OnlineShopUtils {
}
public static String getWebMiniShopPath() {
return ComponentReuseConfigManager.getInstance().getWebMiniShopUrl();
}
public static String getReuInfoPath() {
return ComponentReuseConfigManager.getInstance().getMiniShopUrl();
}

15
designer-realize/src/main/java/com/fr/design/deeplink/DeepLink.java

@ -0,0 +1,15 @@
package com.fr.design.deeplink;
import java.util.Map;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/6
*/
public abstract class DeepLink {
public abstract boolean accept(String url, String host, String path, Map<String, Object> params);
public abstract void run(String url, String host, String path, Map<String, Object> params);
}

133
designer-realize/src/main/java/com/fr/design/deeplink/DeepLinkManager.java

@ -0,0 +1,133 @@
package com.fr.design.deeplink;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.startup.FineStartupNotificationFactory;
import com.fr.design.startup.FineStartupNotificationProvider;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.third.org.apache.http.NameValuePair;
import com.fr.web.URLUtils;
import javax.swing.SwingUtilities;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/6
*/
public class DeepLinkManager {
private DeepLinkManager(){}
private static final DeepLinkManager instance = new DeepLinkManager();
public static DeepLinkManager getInstance(){
return instance;
}
private String pendingURL;
private final List<DeepLink> deepLinkList = new ArrayList<>();
private boolean isDesignerStartUpCompleted = false;
private void register(DeepLink deepLink) {
if (deepLink != null) {
deepLinkList.add(deepLink);
}
}
public void prepare() {
register(new TemplateThemeInstallationDeepLink());
FineStartupNotificationFactory.getNotification()
.registerStartupListener(new FineStartupNotificationProvider.Listener() {
@Override
public void startupPerformed(String parameters) {
if (canAcceptNewURL()) {
acceptNewURL(parameters);
if (canConsumePendingURL()) {
consumePendingURL();
}
}
}
});
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
isDesignerStartUpCompleted = true;
if (canConsumePendingURL()) {
consumePendingURL();
}
}
});
}
private boolean canAcceptNewURL() {
return StringUtils.isEmpty(this.pendingURL);
}
private void acceptNewURL(String url) {
this.pendingURL = url;
}
private boolean canConsumePendingURL() {
return StringUtils.isNotEmpty(this.pendingURL) && isDesignerStartUpCompleted;
}
private void consumePendingURL() {
String host = null;
String path = null;
Map<String, Object> params = new HashMap<>();
URL url = null;
try {
url = new URL(null, this.pendingURL, new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
});
} catch (MalformedURLException ignored) {}
if (url != null) {
host = url.getHost();
path = url.getPath();
List<NameValuePair> pairs = URLUtils.parse(url.getQuery());
for (NameValuePair pair: pairs) {
params.put(pair.getName(), pair.getValue());
}
}
FineLoggerFactory.getLogger().info("consume deep link: " + this.pendingURL);
performDeepLinks(this.pendingURL, host, path, params);
this.pendingURL = null;
}
private void performDeepLinks(String url, String host, String path, Map<String, Object> params) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (DeepLink deepLink: deepLinkList) {
if (deepLink.accept(url, host, path, params)) {
deepLink.run(url, host, path, params);
}
}
}
});
}
}

53
designer-realize/src/main/java/com/fr/design/deeplink/TemplateThemeInstallationDeepLink.java

@ -0,0 +1,53 @@
package com.fr.design.deeplink;
import com.fr.design.mainframe.share.ui.online.installation.Installation;
import com.fr.design.mainframe.share.ui.online.installation.TemplateThemeInstallation;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StringUtils;
import com.fr.third.springframework.web.util.UriUtils;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/10
*/
public class TemplateThemeInstallationDeepLink extends DeepLink {
public TemplateThemeInstallationDeepLink() {
}
private static class Holder {
public static TemplateThemeInstallationDeepLink INSTANCE = new TemplateThemeInstallationDeepLink();
}
public static TemplateThemeInstallationDeepLink getInstance() {
return TemplateThemeInstallationDeepLink.Holder.INSTANCE;
}
public static final String HOST = "template_theme";
public static final String PATH = "/add";
public static final String FILE_KEY = "file";
@Override
public boolean accept(String url, String host, String path, Map<String, Object> params) {
return host != null && StringUtils.equals(HOST, host)
&& path != null && StringUtils.equals(PATH, path)
&& params != null && params.containsKey(FILE_KEY)
;
}
@Override
public void run(String url, String host, String path, Map<String, Object> params) {
String remoteFileAddress = (String) params.get(FILE_KEY);
try {
remoteFileAddress = UriUtils.decode(remoteFileAddress, EncodeConstants.ENCODING_UTF_8);
FineLoggerFactory.getLogger().info("TemplateThemeInstallationDeepLink: " + remoteFileAddress);
Installation installation = new TemplateThemeInstallation(remoteFileAddress);
installation.install();
} catch (UnsupportedEncodingException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}

2
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -11,6 +11,7 @@ import com.fr.design.actions.server.TemplateThemeManagerAction;
import com.fr.design.actions.server.WidgetManagerAction;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.constants.UIConstants;
import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.file.MutilTempalteTabPane;
@ -106,6 +107,7 @@ public class MainDesigner extends BaseDesigner {
*/
public static void main(String[] args) {
DeepLinkManager.getInstance().prepare();
StopWatch watch = new StopWatch();
watch.start();
DesignerLifecycleMonitorContext.getMonitor().beforeStart();

Loading…
Cancel
Save