forked from fanruan/design
xiqiu
3 years ago
30 changed files with 1840 additions and 42 deletions
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue