diff --git a/src/main/java/ecorp/easy/installer/controllers/LogController.java b/src/main/java/ecorp/easy/installer/controllers/LogController.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb7476ff5e2cbb157441e6e17d5a271cf7f74d80
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/LogController.java
@@ -0,0 +1,104 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package ecorp.easy.installer.controllers;
+
+import ecorp.easy.installer.AppConstants;
+import ecorp.easy.installer.logger.GUIAppender;
+import ecorp.easy.installer.logger.LogPathPropertyDefiner;
+import ecorp.easy.installer.tasks.UploadToEcloudTask;
+import ecorp.easy.installer.utils.UiUtils;
+import java.net.URL;
+import java.util.ResourceBundle;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.text.TextFlow;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the controller in charge of UI element to display log
+ * @author vincent Bourgmayer
+ */
+public class LogController implements Initializable{
+
+ private final static Logger logger = LoggerFactory.getLogger(LogController.class);
+
+ //element relatives to log display
+ @FXML ScrollPane logScrollPane;
+ @FXML TextFlow logFlow;
+ @FXML Button showHideLogBtn;
+ @FXML Button sendLogBtn;
+
+ @Override
+ public void initialize(URL arg0, ResourceBundle arg1) {
+ logFlow.heightProperty().addListener(observable -> logScrollPane.setVvalue(1.0));
+
+ logScrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ }
+
+
+ /**
+ * enable/disable log displaying
+ */
+ public void showHideLog(){
+ ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+ GUIAppender appender = (GUIAppender) rootLogger.getAppender("GUI");
+
+ final String text = showHideLogBtn.getText();
+ if(text.equals(">")){
+ showHideLogBtn.setText("V");
+ UiUtils.hideNode(logScrollPane);
+ logFlow.getChildren().clear();
+ appender.setContainer(null);
+ logScrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ }else{
+ showHideLogBtn.setText(">");
+ UiUtils.showNode(logScrollPane);
+ logFlow.getChildren().addAll(appender.getLogsList());
+ appender.setContainer(logFlow);
+ logScrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+ }
+ }
+
+ /**
+ * Send log to support, in special ecloud.global folder
+ * @return
+ */
+ public boolean sendLogToSupport(){
+ //if (thread != null){
+ String filePath = LogPathPropertyDefiner.getLogFilePath();
+ if(filePath != null){
+
+ UploadToEcloudTask uploadTask = new UploadToEcloudTask(AppConstants.LOG_STORAGE_URL, filePath);
+ uploadTask.setOnSucceeded(eh -> {
+ if( (Boolean) eh.getSource().getValue() ){ //if success
+ sendLogBtn.setDisable(true);
+ //sendLogBtn.setText(i18n.getString("install_btn_sendLogSuccess"));
+ logger.info("sendLogToSupport(), sending log: success");
+ }
+ else{
+ //sendLogBtn.setText(i18n.getString("install_btn_sendLogAgain"));
+ logger.warn("sendLogToSupport(), sending log: failure");
+ }
+ });
+
+ uploadTask.setOnFailed(eh->{
+ //sendLogBtn.setText(i18n.getString("install_btn_sendLogAgain"));
+ logger.warn("sendLogToSupport(), sending log: failure, error = {}",eh.getSource().getException().toString() );
+ });
+
+ Thread uploadTaskThread = new Thread(uploadTask);
+ uploadTaskThread.setDaemon(true);
+ uploadTaskThread.start();
+ }
+ return false;
+ }
+
+ public void showSendLogBtn(){
+ UiUtils.showNode(sendLogBtn);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ecorp/easy/installer/controllers/MainWindowController.java b/src/main/java/ecorp/easy/installer/controllers/MainWindowController.java
index 6259a3421ac5a7dc31f940b66c185f9ab53467f8..c54deab94f3aaf86c1edd55726f532c8fb073a8f 100644
--- a/src/main/java/ecorp/easy/installer/controllers/MainWindowController.java
+++ b/src/main/java/ecorp/easy/installer/controllers/MainWindowController.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 - ECORP SAS
+ * Copyright 2019-2021 - ECORP SAS
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +19,13 @@ package ecorp.easy.installer.controllers;
import ecorp.easy.installer.AppConstants;
import ecorp.easy.installer.controllers.subcontrollers.AbstractSubController;
import ecorp.easy.installer.EasyInstaller;
+import ecorp.easy.installer.controllers.stepControllers.CustomExecutableController;
+import ecorp.easy.installer.controllers.stepControllers.CustomStepController;
+import ecorp.easy.installer.controllers.stepControllers.StepController;
+import ecorp.easy.installer.controllers.stepControllers.Stoppable;
import ecorp.easy.installer.models.Phone;
+import ecorp.easy.installer.models.steps.IStep;
+import ecorp.easy.installer.tasks.CommandRunnerService;
import ecorp.easy.installer.threads.ThreadFactory;
import ecorp.easy.installer.utils.UiUtils;
@@ -61,7 +67,9 @@ public class MainWindowController implements Initializable {
ThreadFactory factory = new ThreadFactory("/yaml/");
Phone device; //Object encapsulating data about the device to flash
private boolean isFlashed = false; // True when /e/ OS installed on device
-
+ private String currentStepKey = "f0";
+
+ private Object subController;
/**
* Initializes the controller class.
@@ -81,6 +89,8 @@ public class MainWindowController implements Initializable {
Bindings.concat("-fx-font-size: ", fontSize.asString("%.0f")).concat("px;")
);
+ StepController.setParentController(this);
+
}
/**
@@ -163,36 +173,79 @@ public class MainWindowController implements Initializable {
if(currentSubRootId == null || currentSubRootId.isEmpty()){
- currentSubRootId =loadSubUI("1-beforeYouBegin.fxml", "before_mTitle").getId();
+ currentSubRootId =loadSubUI("1-beforeYouBegin.fxml", "before_mTitle", null).getId();
}else{
switch(currentSubRootId){
case "beforeYouBeginRoot":
- changeView(currentSubRootId, "2-connectDevice.fxml", "connect_mTitle");
+ changeView("2-connectDevice.fxml", "connect_mTitle", null);
break;
case "connectDeviceRoot":
- changeView(currentSubRootId, "3-enableADB.fxml", "devMode_mTitle");
+ changeView("3-enableADB.fxml", "devMode_mTitle", null);
break;
case "enableDevMode":
if(AppConstants.isWindowsOs()){
- changeView(currentSubRootId, "3-2-checkDriverInstallation.fxml", "checkDriverInstall_mTitle");
+ changeView("3-2-checkDriverInstallation.fxml", "checkDriverInstall_mTitle", null);
}else{
- changeView(currentSubRootId, "4-deviceDetected.fxml", "detect_mTitle");
+ changeView("4-deviceDetected.fxml", "detect_mTitle", null);
disableNextButton(true);
}
break;
case "checkDriverInstallation":
- changeView(currentSubRootId, "4-deviceDetected.fxml", "detect_mTitle");
+ changeView("4-deviceDetected.fxml", "detect_mTitle", null);
disableNextButton(true);
break;
case "deviceDetectedRoot":
- changeView(currentSubRootId, "5-downloadSrc.fxml", "download_mTitle");
+ changeView("5-downloadSrc.fxml", "download_mTitle", null);
disableNextButton(true);
break;
+ case "uiRoot":
case "downloadSceneRoot":
- changeView(currentSubRootId, "6-flashScene.fxml", "installationTitle");
- break;
- case "flashSceneRoot":
- changeView(currentSubRootId, "7-flashResult.fxml", "installationTitle");
+ StepController controller = null;
+ String fxmlName = "";
+ String title ="installationTitle";
+ if(currentStepKey.equals(IStep.LAST_STEP_KEY)){
+ if(isFlashed){
+ fxmlName="7-flashResult.fxml";
+ title="installationTitle";
+ }else{
+ fxmlName="9-feedback.fxml";
+ title="feedback_mTitle";
+ }
+ }else{
+ final IStep step = factory.getFlashMould().getSteps().get(currentStepKey);
+
+ switch(step.getType()){
+ case "askAccount":
+ fxmlName = "6-2-eAccount.fxml";
+ break;
+ case "enableOemUnlock":
+ fxmlName = "6-3-unlockOEM.fxml";
+ break;
+ case "custom":
+ controller = new CustomStepController();
+ fxmlName="customStep.fxml";
+ break;
+ case "custom-executable":
+ controller = new CustomExecutableController();
+ fxmlName="customStep.fxml";
+ break;
+ case "executable":
+ //no interface there
+ break;
+ case "load":
+ fxmlName = "loadStep.fxml";
+ break;
+ default:
+ //no interface there
+ break;
+ }
+ }
+
+ if(!fxmlName.isBlank())
+ changeView(fxmlName, title, controller);
+ else
+ logger.error("No interface to load!");
+
break;
case "flashResultRoot":
final String fxmlFileName;
@@ -205,10 +258,10 @@ public class MainWindowController implements Initializable {
fxmlFileName = "9-feedback.fxml";
nextViewTitle ="feedback_mTitle";
}
- changeView(currentSubRootId, fxmlFileName, nextViewTitle);
+ changeView(fxmlFileName, nextViewTitle, null);
break;
case "congratsRoot":
- changeView(currentSubRootId, "9-feedback.fxml", "feedback_mTitle");
+ changeView("9-feedback.fxml", "feedback_mTitle", null);
break;
case "feedbackRoot":
Platform.exit();
@@ -220,8 +273,12 @@ public class MainWindowController implements Initializable {
}
}
+ /**
+ * Reset the flashing process to the begining
+ */
public void retryToFlash(){
- changeView(currentSubRootId, "6-flashScene.fxml", "installationTitle");
+ currentStepKey = "f0";
+ loadSubScene();
}
/**
@@ -231,6 +288,8 @@ public class MainWindowController implements Initializable {
public void setDevice(Phone device){
this.factory.changeMould(device);
this.device = device;
+ CommandRunnerService.updateCommonParam("DEVICE_ID", device.getSerialNo());
+ CommandRunnerService.updateCommonParam("DEVICE_DEVICE", device.getAdbDevice());
}
/**
@@ -247,8 +306,12 @@ public class MainWindowController implements Initializable {
* @param previousNodeId
* @param fxmlName
* @param viewTitle
+ * @param controller optionnal controller for the new UI. Should be null if already defined in FXML
*/
- public void changeView(final String previousNodeId, final String fxmlName, final String viewTitle){
+ public void changeView(final String fxmlName, final String viewTitle, StepController controller){
+ logger.debug("change view()");
+
+ final String previousNodeId = currentSubRootId;
Node elementNode = null;
//get current subroot
for(Node node : root.getChildren() ){
@@ -257,17 +320,24 @@ public class MainWindowController implements Initializable {
break;
}
}
- if(elementNode == null) return ;
+
+ if(elementNode == null){
+ logger.debug("no subnode found");
+ return ;
+ }
//apply transition
final FadeTransition fadeOutTransition = UiUtils.buildFadeTransition(elementNode, true);
fadeOutTransition.setOnFinished(e -> {
removeNodeFromRoot(previousNodeId);
- final Node subRoot = loadSubUI(fxmlName, viewTitle);
- currentSubRootId= subRoot.getId();
-
- subRoot.setOpacity(0.0);
- UiUtils.buildFadeTransition(subRoot,false).play();
+ //logger.debug("Fade out for previous interface finished");
+ final Node subRoot = loadSubUI(fxmlName, viewTitle, controller);
+ if (subRoot != null)
+ {
+ currentSubRootId= subRoot.getId();
+ subRoot.setOpacity(0.0);
+ UiUtils.buildFadeTransition(subRoot,false).play();
+ }
});
fadeOutTransition.play();
}
@@ -276,33 +346,53 @@ public class MainWindowController implements Initializable {
/**
* Load UI from FXML file
* @param fxmlName
+ * @param controller an optionnal controller for the UI. Cann be null!
* @return
*/
- public FXMLLoader loadFXML(String fxmlName){
+ public FXMLLoader loadFXML(String fxmlName, StepController controller){
FXMLLoader loader;
+ loader = new FXMLLoader(getClass().getResource(EasyInstaller.FXML_PATH+fxmlName));
+ loader.setResources(i18n);
+
+ if(controller != null){
+ loader.setController(controller);
+ subController = controller;
+ }
+
try{
- loader = new FXMLLoader(getClass().getResource(EasyInstaller.FXML_PATH+fxmlName));
- loader.setResources(i18n);
loader.load();
- AbstractSubController ctrl = loader.getController();
- if(ctrl != null) ctrl.setParentController(this);
}catch(IOException e){
logger.error("fxmlName = {}, error = {}", fxmlName, e.toString());
+ e.printStackTrace();
return null;
}
+ if(controller == null){
+ final Object ctrl = loader.getController();
+
+ if(ctrl != null){
+ subController = ctrl;
+ if( ctrl instanceof AbstractSubController )
+ {
+ ((AbstractSubController)ctrl).setParentController(this);
+ }
+ }
+ }
return loader;
}
/**
* Load the subScene from FXML and return the controller
* @param fxmlName fxml file name
* @param viewTitle the title for the new View
+ * @param controller optionnal parameter. It's the controller for the UI if not defined in FXML
* @return subRoot.
*/
- public Node loadSubUI(final String fxmlName, final String viewTitle){
- logger.debug("view title: "+viewTitle);
+ public Node loadSubUI(final String fxmlName, final String viewTitle, StepController controller){
if(viewTitle != null) titleLabel.setText(i18n.getString(viewTitle));
- FXMLLoader loader = loadFXML(fxmlName);
+ FXMLLoader loader = loadFXML(fxmlName, controller);
+ if(loader == null) return null;
+
Pane subRoot = (Pane) loader.getRoot();
+
root.getChildren().add(0, subRoot); //adding this element as first subNode, let other element like button to still be clickable on small screen
return subRoot;
@@ -334,6 +424,9 @@ public class MainWindowController implements Initializable {
*/
public void onStop(){
logger.debug("onStop()");
+ if(subController != null && subController instanceof Stoppable){
+ ((Stoppable) subController).stop();
+ }
}
/**
@@ -370,5 +463,15 @@ public class MainWindowController implements Initializable {
public Phone getDevice() {
return device;
}
+
+
+ public String getCurrentStepKey() {
+ return currentStepKey;
+ }
+
+
+ public void setCurrentStepKey(String currentStepKey) {
+ this.currentStepKey = currentStepKey;
+ }
}
diff --git a/src/main/java/ecorp/easy/installer/controllers/stepControllers/CustomExecutableController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/CustomExecutableController.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8ecb9e281400be2431b6bab59b2fecda8ac9992
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/CustomExecutableController.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2019-2021 - ECORP SAS
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ecorp.easy.installer.controllers.stepControllers;
+
+import ecorp.easy.installer.controllers.LogController;
+import static ecorp.easy.installer.controllers.stepControllers.StepController.parentController;
+import ecorp.easy.installer.graphics.Instruction;
+import ecorp.easy.installer.models.Command;
+import ecorp.easy.installer.models.steps.CustomExecutableStep;
+import ecorp.easy.installer.tasks.CommandRunnerService;
+import ecorp.easy.installer.utils.UiUtils;
+import ecorp.easy.installer.graphics.FlashGlobalProgressManager;
+import ecorp.easy.installer.models.steps.IStep;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import javafx.fxml.FXML;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.ContentDisplay;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+
+/**
+ * This is clearly a mix of CustomStepController & ExecutableStepController
+ * It means that it's code duplication. I don't like it but I didn't find a way to reuse
+ * both class because multiple extension isn't possible and any design pattern fit
+ * my need. But If you find a way please implement it!
+ * @author vincent Bourgmayer
+ */
+public class CustomExecutableController extends StepController implements Stoppable{
+
+ protected final ResourceBundle IMG_BUNDLE = ResourceBundle.getBundle("instructions.imageName",
+ new Locale.Builder()
+ .setRegion("en")
+ .setLanguage("EN")
+ .setVariant(parentController.getDevice().getInternalCode())
+ .build());
+
+ private int currentEmphasizedInstruction = 0;
+ private int instructionsCount;
+ private CommandRunnerService backgroundService;
+
+ @FXML private VBox instructionsContainer;
+ @FXML private Label titleLbl;
+ @FXML private ImageView imgView;
+ @FXML private LogController logRootController;
+
+ // progress bar's node of global Flash's process :
+ @FXML HBox globalProgressIndicator;
+ private FlashGlobalProgressManager globalProgressMgr;
+
+ @Override
+ public void initialize(URL url, ResourceBundle rb) {
+ super.initialize(url, rb);
+
+ parentController.setNextButtonVisible(true);
+
+ /** Initialization relatives to Custom **/
+ titleLbl.setText(i18n.getString(step.getTitleKey() ));
+ if(step.getTitleIconName() != null){
+ titleLbl.setGraphic(new ImageView(UiUtils.loadImage(step.getTitleIconName())));
+ titleLbl.setGraphicTextGap(18); //set spacing between icon and text
+ titleLbl.setContentDisplay(ContentDisplay.LEFT); //set Icon to be displayed on left
+ }
+
+ final ArrayList instructions = loadInstructions();
+ instructions.get(currentEmphasizedInstruction).emphasize();
+ instructionsContainer.getChildren().addAll(instructions);
+ displayInstructionImage(instructions.get(currentEmphasizedInstruction));
+ instructionsCount = instructions.size();
+
+ globalProgressMgr = new FlashGlobalProgressManager(parentController.getThreadFactory().getStepsCount());
+ for(int i = 0;i < step.getStepNumber(); i++){
+ globalProgressMgr.updateProgression();
+ }
+ globalProgressIndicator.getChildren().addAll(globalProgressMgr.getSegments());
+
+
+ /** Initialization relatives to Executable **/
+ final Command cmd = step.getCommand();
+ backgroundService = new CommandRunnerService(cmd);
+ backgroundService.setOnSucceeded(eh->{
+ boolean result = backgroundService.getValue();
+ if(result)
+ onStepEnd();
+ else{
+ String errorMsgKey = cmd.getErrorMsg();
+ if (errorMsgKey == null || errorMsgKey.isEmpty()){
+ errorMsgKey = "script_error_unknown";
+ }
+ displayError(errorMsgKey);
+ }
+
+ });
+ backgroundService.start();
+
+ }
+
+ @Override
+ protected void onContinueClicked(){
+ logger.debug("onContinueClicked");
+
+ final Instruction currentInstruction = (Instruction) instructionsContainer
+ .getChildren().get(1+currentEmphasizedInstruction++);//the +1 is to ignore the title
+ currentInstruction.trivialize();
+
+
+ final Instruction nextInstruction = (Instruction) instructionsContainer
+ .getChildren().get(1+currentEmphasizedInstruction); //the +1 is to ignore the title
+ nextInstruction.emphasize();
+
+ displayInstructionImage(nextInstruction);
+
+ if(currentEmphasizedInstruction+1 == instructionsCount){
+ logger.debug("last instruction reached instruction");
+ parentController.setNextButtonVisible(false);
+ }
+ }
+
+
+ /**
+ * Create Instruction nodes with text key from step
+ */
+ private ArrayList loadInstructions(){
+ final ArrayList result = new ArrayList<>();
+
+ for(String key : step.getTextContentKeys()){
+ String contentKey = "all_lbl_notImplemented"; //set default key
+ System.out.println("translation key: "+key);
+ if(i18n.containsKey(key)){
+ contentKey = key;
+ }
+ result.add(new Instruction(key, i18n.getString(contentKey)));
+ }
+ return result;
+ }
+
+
+ /**
+ * Display Image corresponding to the current Instruction
+ * if there is one. In other way, it remove current image
+ * @param instruction
+ */
+ private void displayInstructionImage(Instruction instruction){
+ if(IMG_BUNDLE.containsKey(instruction.getKey())){
+ imgView.setImage(
+ UiUtils.loadImage( IMG_BUNDLE.getString( instruction.getKey() ) ) );
+ }else{
+ imgView.setImage(null);
+ }
+ }
+
+ /**
+ * Display an error due to background task
+ * @param errorMsgKey
+ */
+ protected void displayError(String errorMsgKey){
+
+ parentController.resetNextButtonEventHandler();
+ //parentController.setNextButtonVisible(false);
+ parentController.setIsFlashed(false);
+ parentController.setCurrentStepKey(IStep.LAST_STEP_KEY);
+
+ if(i18n.containsKey(errorMsgKey)){
+ final Label errorLbl = new Label(i18n.getString(errorMsgKey));
+ ((VBox) uiRoot).getChildren().add(2, errorLbl);
+ }else{
+ logger.error("Missing translation for error key: {}", errorMsgKey);
+ }
+ UiUtils.hideNode(instructionsContainer.getParent());
+
+ logRootController.showSendLogBtn();
+
+ Button tryAgainBtn = new Button(i18n.getString("all_lbl_tryAgain"));
+ tryAgainBtn.setOnMouseClicked(( MouseEvent event) -> {
+ parentController.retryToFlash();
+ });
+ ((VBox)uiRoot).setAlignment(Pos.TOP_CENTER);
+ ((VBox)uiRoot).getChildren().add(3, tryAgainBtn);
+ }
+
+ @Override
+ public void stop() {
+ logger.debug("CustomExecutableController.stop()");
+ backgroundService.cancel();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ecorp/easy/installer/controllers/stepControllers/CustomStepController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/CustomStepController.java
new file mode 100644
index 0000000000000000000000000000000000000000..fabe50a980c3458e1a547fc1b429de955dbfcdca
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/CustomStepController.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2019-2021 - ECORP SAS
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ecorp.easy.installer.controllers.stepControllers;
+
+
+import ecorp.easy.installer.graphics.FlashGlobalProgressManager;
+import ecorp.easy.installer.graphics.Instruction;
+import ecorp.easy.installer.models.steps.ICustomStep;
+import ecorp.easy.installer.utils.UiUtils;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import javafx.fxml.FXML;
+import javafx.scene.control.ContentDisplay;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+
+/**
+ *
+ * @author vincent Bourgmayer
+ */
+public class CustomStepController extends StepController{
+
+ protected final ResourceBundle IMG_BUNDLE = ResourceBundle.getBundle("instructions.imageName",
+ new Locale.Builder()
+ .setRegion("en")
+ .setLanguage("EN")
+ .setVariant(parentController.getDevice().getInternalCode())
+ .build());
+
+ private int currentEmphasizedInstruction = 0;
+ private int instructionsCount;
+
+ @FXML private VBox instructionsContainer;
+ @FXML private Label titleLbl;
+ @FXML private ImageView imgView;
+ // progress bar's node of global Flash's process :
+ @FXML HBox globalProgressIndicator;
+ private FlashGlobalProgressManager globalProgressMgr;
+
+
+ @Override
+ public void initialize(URL url, ResourceBundle rb) {
+ super.initialize(url, rb);
+ logger.debug("initialize customStep controller");
+
+ parentController.setNextButtonVisible(true);
+ titleLbl.setText(i18n.getString(step.getTitleKey() ));
+ if(step.getTitleIconName() != null){
+ titleLbl.setGraphic(new ImageView(UiUtils.loadImage(step.getTitleIconName())));
+ titleLbl.setGraphicTextGap(18); //set spacing between icon and text
+ titleLbl.setContentDisplay(ContentDisplay.LEFT); //set Icon to be displayed on left
+ }
+
+ final ArrayList instructions = loadInstructions();
+ instructions.get(currentEmphasizedInstruction).emphasize();
+ instructionsContainer.getChildren().addAll(instructions);
+ displayInstructionImage(instructions.get(currentEmphasizedInstruction));
+
+ instructionsCount = instructions.size();
+
+
+ globalProgressMgr = new FlashGlobalProgressManager(parentController.getThreadFactory().getStepsCount());
+ for(int i = 0;i < step.getStepNumber(); i++){
+ globalProgressMgr.updateProgression();
+ }
+ globalProgressIndicator.getChildren().addAll(globalProgressMgr.getSegments());
+ }
+
+
+ @Override
+ protected void onContinueClicked(){
+ if(currentEmphasizedInstruction+1 == instructionsCount){
+ UiUtils.buildFadeTransition(uiRoot, false);
+ super.onStepEnd();
+ }else{
+ final Instruction currentInstruction = (Instruction) instructionsContainer
+ .getChildren().get(1+currentEmphasizedInstruction++);//the +1 is to ignore the title
+ currentInstruction.trivialize();
+
+ final Instruction nextInstruction = (Instruction) instructionsContainer
+ .getChildren().get(1+currentEmphasizedInstruction); //the +1 is to ignore the title
+ nextInstruction.emphasize();
+
+ displayInstructionImage(nextInstruction);
+ }
+ }
+
+ /**
+ * Create Instruction nodes with text key from step
+ */
+ private ArrayList loadInstructions(){
+ final ArrayList result = new ArrayList<>();
+
+ for(String key : step.getTextContentKeys()){
+ String contentKey = "all_lbl_notImplemented"; //set default key
+ System.out.println("translation key: "+key);
+ if(i18n.containsKey(key)){
+ contentKey = key;
+ }
+ result.add(new Instruction(key, i18n.getString(contentKey)));
+ }
+ return result;
+ }
+
+
+ /**
+ * Display Image corresponding to the current Instruction
+ * if there is one. In other way, it remove current image
+ * @param instruction
+ */
+ private void displayInstructionImage(Instruction instruction){
+ if(IMG_BUNDLE.containsKey(instruction.getKey())){
+ imgView.setManaged(true);
+ imgView.setImage(
+ UiUtils.loadImage( IMG_BUNDLE.getString( instruction.getKey() ) ) );
+ }else{
+ imgView.setImage(null);
+ imgView.setManaged(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/EAccountController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/EAccountController.java
similarity index 89%
rename from src/main/java/ecorp/easy/installer/controllers/subcontrollers/EAccountController.java
rename to src/main/java/ecorp/easy/installer/controllers/stepControllers/EAccountController.java
index 8b5e9da73df8d1e8fc9ce781521cb1510931b819..87f3d81c3222e951b9a0933933483aa85939c34e 100644
--- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/EAccountController.java
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/EAccountController.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 - ECORP SAS
+ * Copyright 2019-2021 - ECORP SAS
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,15 +14,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package ecorp.easy.installer.controllers.subcontrollers;
+package ecorp.easy.installer.controllers.stepControllers;
-import ecorp.easy.installer.controllers.MainWindowController;
import ecorp.easy.installer.tasks.AskAccountTask;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
import java.util.regex.Pattern;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
@@ -33,20 +31,16 @@ import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
*
- * @author vincent
+ * @author vincent Bourgmayer
* This is the controller for eAccount.fxml
*/
-public class EAccountController extends AbstractSubController{
- private static final Logger logger = LoggerFactory.getLogger(EAccountController.class);
+public class EAccountController extends StepController{
private static final String MAIL_REGEX="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
private static final Pattern EMAIL_PATTERN = Pattern.compile(MAIL_REGEX);
- @FXML VBox eAccountRoot;
@FXML HBox alreadyAccountBox;
@FXML HBox askAccountBox;
@FXML Button checkMailBtn;
@@ -59,11 +53,7 @@ public class EAccountController extends AbstractSubController{
@Override
public void initialize(URL location, ResourceBundle resources){
super.initialize(location, resources);
- }
-
- @Override
- public void setParentController(MainWindowController parentController){
- super.setParentController(parentController);
+
parentController.disableNextButton(true);
radioButton.setOnMouseClicked( (eh) -> {
mailInput.requestFocus();
@@ -93,7 +83,6 @@ public class EAccountController extends AbstractSubController{
radioButton2.getLayoutX(), radioButton2.getLayoutY(), radioButton2.getLayoutX(), radioButton2.getLayoutY(), MouseButton.PRIMARY, 1,
true, true, true, true, true, true, true, true, true, true, null));
});
-
}
@@ -109,12 +98,10 @@ public class EAccountController extends AbstractSubController{
mailInput.requestFocus();
break;
case 0:
- ExecutorService executorSrv = Executors.newSingleThreadExecutor( new ThreadFactory() {
- public Thread newThread(Runnable r) {
- Thread t = Executors.defaultThreadFactory().newThread(r);
- t.setDaemon(true);
- return t;
- }
+ ExecutorService executorSrv = Executors.newSingleThreadExecutor((Runnable r) -> {
+ Thread t = Executors.defaultThreadFactory().newThread(r);
+ t.setDaemon(true);
+ return t;
});
AskAccountTask askInvitationTask = new AskAccountTask(userInput, i18n.getString("askAccount_string"));
askInvitationTask.setOnSucceeded(workerStateEvent -> {
diff --git a/src/main/java/ecorp/easy/installer/controllers/stepControllers/ExecutableStepController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/ExecutableStepController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a32e479e945bc0464a59c6dcfbaefec6d89e3fa0
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/ExecutableStepController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019-2021 - ECORP SAS
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ecorp.easy.installer.controllers.stepControllers;
+
+import ecorp.easy.installer.models.Command;
+import ecorp.easy.installer.models.steps.IExecutableStep;
+import ecorp.easy.installer.tasks.CommandRunnerService;
+import java.net.URL;
+import java.util.ResourceBundle;
+import javafx.concurrent.Task;
+
+/**
+ * @TODO - add a error and cancellation listener on the Service
+ * @author vincent Bourgmayer
+ */
+public class ExecutableStepController extends StepController{
+
+ Task task;
+ CommandRunnerService backgroundService;
+
+ @Override
+ public void initialize(URL arg0, ResourceBundle resources) {
+ super.initialize(arg0, resources); //To change body of generated methods, choose Tools | Templates.
+
+ final Command cmd = step.getCommand();
+ backgroundService = new CommandRunnerService(cmd);
+
+ backgroundService.setOnSucceeded(eh->{
+ boolean result = backgroundService.getValue();
+ if(result)
+ onStepEnd();
+ else{
+ String errorMsgKey = cmd.getErrorMsg();
+ if (errorMsgKey == null || errorMsgKey.isEmpty()){
+ errorMsgKey = "script_error_unknown";
+ }
+ displayError(errorMsgKey);
+ }
+
+ });
+
+ backgroundService.start();
+ }
+
+
+ protected void displayError(String errorMsgKey){
+ //Show error UI and hide everything that should be hidden
+ //like restart btn, etc.
+ if(i18n.containsKey(errorMsgKey)){
+ //Set text to a label
+ }
+ }
+
+}
diff --git a/src/main/java/ecorp/easy/installer/controllers/stepControllers/LoadStepController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/LoadStepController.java
new file mode 100644
index 0000000000000000000000000000000000000000..256cc93229f2c08639b556ae44baac4724e5929f
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/LoadStepController.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019-2021 - ECORP SAS
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ecorp.easy.installer.controllers.stepControllers;
+
+import ecorp.easy.installer.controllers.LogController;
+import static ecorp.easy.installer.controllers.stepControllers.StepController.parentController;
+import ecorp.easy.installer.models.Command;
+import ecorp.easy.installer.models.steps.LoadStep;
+import ecorp.easy.installer.tasks.CommandRunnerService;
+import ecorp.easy.installer.graphics.FlashGlobalProgressManager;
+import ecorp.easy.installer.models.steps.IStep;
+import java.net.URL;
+import java.util.ResourceBundle;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
+import javafx.fxml.FXML;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ProgressBar;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.util.Duration;
+
+/**
+ *
+ * @author vincent Bourgmayer
+ */
+public class LoadStepController extends StepController implements Stoppable{
+
+ @FXML private ProgressBar taskProgressBar;
+ @FXML private Label titleLbl;
+ @FXML private VBox instructionsContainer;
+ @FXML private ImageView imgView;
+ @FXML private LogController logRootController; //the field name must be "Controller"
+
+ private Timeline pbTimeline; //progressBar Timeline
+ private CommandRunnerService service;
+
+ // progress bar's node of global Flash's process :
+ @FXML HBox globalProgressIndicator;
+ private FlashGlobalProgressManager globalProgressMgr;
+
+ @Override
+ public void initialize(URL url, ResourceBundle rb) {
+ super.initialize(url, rb);
+
+ parentController.setNextButtonVisible(false);
+
+ instructionsContainer.setManaged(false);
+ imgView.setManaged(false);
+ /*if(step.getTextContentKeys().isEmpty()){
+ instructionsContainer.setVisible(false);
+ }*/
+
+
+ if(i18n.containsKey(step.getTitleKey())){
+ titleLbl.setText(i18n.getString(step.getTitleKey() ) );
+ }
+
+
+ globalProgressMgr = new FlashGlobalProgressManager(parentController.getThreadFactory().getStepsCount());
+ for(int i = 0;i < step.getStepNumber(); i++){
+ globalProgressMgr.updateProgression();
+ }
+ globalProgressIndicator.getChildren().addAll(globalProgressMgr.getSegments());
+
+ /** Prepare ProgressBar animation **/
+ final int averageTime = step.getAverageTime();
+ if(averageTime > 0){
+ pbTimeline = new Timeline(
+ new KeyFrame(Duration.millis(0), new KeyValue(taskProgressBar.progressProperty(), 0.0) ),
+ new KeyFrame(Duration.millis(averageTime*1000.0), new KeyValue(taskProgressBar.progressProperty(), 1.0))
+ );
+ }
+
+ /** Prepare Command execution **/
+ final Command cmd = step.getCommand();
+ service = new CommandRunnerService(cmd);
+
+ service.setOnSucceeded(eh->{
+ pbTimeline.stop();
+ boolean result = service.getValue();
+
+ if(result){
+ onStepEnd();
+ }else{
+ String errorMsgKey = cmd.getErrorMsg();
+ if (errorMsgKey == null || errorMsgKey.isEmpty()){
+ errorMsgKey = "script_error_unknown";
+ }
+ displayError(errorMsgKey);
+ }
+
+ });
+
+ service.setOnRunning(eh->{
+ taskProgressBar.setProgress(0.0); //Reset to prevent showing last value
+ pbTimeline.playFromStart();
+ });
+
+
+ service.setOnCancelled(eh->{
+ pbTimeline.stop();
+ });
+
+ service.start();
+ }
+
+
+ protected void displayError(String errorMsgKey){
+
+ parentController.setIsFlashed(false);
+ parentController.setCurrentStepKey(IStep.LAST_STEP_KEY);
+ parentController.resetNextButtonEventHandler();
+ parentController.setNextButtonVisible(true);
+
+ pbTimeline.stop();
+ taskProgressBar.getStyleClass().add("errorBar");
+ if(i18n.containsKey(errorMsgKey)){
+ Label errorLbl = new Label(i18n.getString(errorMsgKey));
+ ((VBox) uiRoot).getChildren().add(3, errorLbl);
+ }else{
+ logger.error("Missing translation for error key: {}", errorMsgKey);
+ }
+
+ logRootController.showSendLogBtn();
+
+ final Button tryAgainBtn = new Button(i18n.getString("all_lbl_tryAgain"));
+ tryAgainBtn.setOnMouseClicked(( MouseEvent event) -> {
+ parentController.retryToFlash();
+ });
+ ((VBox)uiRoot).setAlignment(Pos.TOP_CENTER);
+ ((VBox)uiRoot).getChildren().add(4,tryAgainBtn);
+
+ }
+
+ @Override
+ public void stop() {
+ logger.debug("LoadStepController.stop()");
+ service.cancel();
+ }
+}
diff --git a/src/main/java/ecorp/easy/installer/controllers/stepControllers/StepController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/StepController.java
new file mode 100644
index 0000000000000000000000000000000000000000..827d51b3db92dee51004fccc3e145cf3d385626b
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/StepController.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019-2021 - ECORP SAS
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ecorp.easy.installer.controllers.stepControllers;
+
+import ecorp.easy.installer.controllers.MainWindowController;
+import ecorp.easy.installer.models.steps.IStep;
+import java.net.URL;
+import java.util.ResourceBundle;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.Node;
+import javafx.scene.input.MouseEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ *
+ * @author vincent Bourgmayer
+ * @param implementation of IStep interface
+ */
+public class StepController implements Initializable{
+ protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+ protected static MainWindowController parentController;
+
+ @FXML Node uiRoot;
+ protected ResourceBundle i18n;
+ protected S step;
+
+ @Override
+ public void initialize(URL url, ResourceBundle rb) {
+ i18n = rb;
+
+ final String stepKey = parentController.getCurrentStepKey();
+ System.out.println("stepKey = "+stepKey);
+
+ step = (S) parentController.getThreadFactory().getFlashMould().getSteps().get(stepKey);
+
+ parentController.setNextButtonOnClickListener( ( MouseEvent event) -> {
+ if(event.getEventType().equals(MouseEvent.MOUSE_CLICKED)){
+ onContinueClicked();
+ }
+ });
+ }
+
+ /**
+ * /!\ it must be called Before the Initialize() method!!
+ * @param parentController
+ */
+ public static void setParentController(MainWindowController parentController) {
+ StepController.parentController = parentController;
+ }
+
+ /**
+ * Behaviour for when user click on "continue button"
+ * defined mostly for subclass overriding
+ */
+ protected void onContinueClicked(){
+ onStepEnd();
+ }
+
+ /**
+ * Code executed when the step is over
+ * Mainly load the next step
+ * apply UI effect like fade in/out
+ */
+ protected void onStepEnd(){
+ System.out.println("onStepEnd() load: "+step.getNextStepKey());
+ parentController.setCurrentStepKey(step.getNextStepKey());
+ if(step.getNextStepKey().equals(IStep.LAST_STEP_KEY)){
+ parentController.setIsFlashed(true);
+ }
+ parentController.loadSubScene();
+
+
+ //Question is: Should I call this only if we are at the last step
+ //Then How to check that from here ?
+ //Or should I always reset behaviour.. As It is always override by new step
+ //this looks like useless call each time except for the latest one...
+ //Answer: this can go like this for now, and be handled later in the refactoring process
+ //@Todo
+ parentController.resetNextButtonEventHandler();
+ }
+}
diff --git a/src/main/java/ecorp/easy/installer/controllers/stepControllers/Stoppable.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/Stoppable.java
new file mode 100644
index 0000000000000000000000000000000000000000..68ef4c0fbc7a27682347ecc1fe26db9d84002cd1
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/Stoppable.java
@@ -0,0 +1,13 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Interface.java to edit this template
+ */
+package ecorp.easy.installer.controllers.stepControllers;
+
+/**
+ *
+ * @author vincent
+ */
+public interface Stoppable {
+ public void stop();
+}
diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/UnlockOemController.java b/src/main/java/ecorp/easy/installer/controllers/stepControllers/UnlockOemController.java
similarity index 80%
rename from src/main/java/ecorp/easy/installer/controllers/subcontrollers/UnlockOemController.java
rename to src/main/java/ecorp/easy/installer/controllers/stepControllers/UnlockOemController.java
index 87a0a666b08256d0f6a6a2e93f611ae7a2c110ab..cda2c2fd4bfa40da305d6e11aa179e8c8efcae61 100644
--- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/UnlockOemController.java
+++ b/src/main/java/ecorp/easy/installer/controllers/stepControllers/UnlockOemController.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2020 - ECORP SAS
+ * Copyright 2019-2021 - ECORP SAS
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,9 +14,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package ecorp.easy.installer.controllers.subcontrollers;
+package ecorp.easy.installer.controllers.stepControllers;
+
-import ecorp.easy.installer.controllers.MainWindowController;
import ecorp.easy.installer.graphics.FlashGlobalProgressManager;
import java.net.URL;
import java.util.ResourceBundle;
@@ -30,9 +30,9 @@ import javafx.scene.layout.HBox;
* This controller is for UI about unlocking OEM on the stock ROM
* It's main goal is to allow to get extra code from website or API
*
- * @author vincent
+ * @author vincent Bourgmayer
*/
-public class UnlockOemController extends AbstractSubController{
+public class UnlockOemController extends StepController{
@FXML Label instruction;
@FXML Hyperlink link;
@@ -44,13 +44,8 @@ public class UnlockOemController extends AbstractSubController{
public void initialize(URL location, ResourceBundle resources){
super.initialize(location, resources);
link.setBorder(Border.EMPTY);
- }
-
- @Override
- public void setParentController(MainWindowController parentController){
- super.setParentController(parentController);
- parentController.setNextButtonVisible(true);
+ parentController.setNextButtonVisible(true);
globalProgressMgr = new FlashGlobalProgressManager( parentController.getThreadFactory().getStepsCount() );
globalProgressIndicator.getChildren().addAll(globalProgressMgr.getSegments());
globalProgressMgr.updateProgression();
diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DeviceDetectedController.java b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DeviceDetectedController.java
index 5b69d8769d41dbf86999a13ca3b17b08ddbebf8d..5ddb79fa18f1ea1afab76fa05938430ab1deacb5 100644
--- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DeviceDetectedController.java
+++ b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DeviceDetectedController.java
@@ -18,12 +18,12 @@ package ecorp.easy.installer.controllers.subcontrollers;
import ecorp.easy.installer.AppConstants;
+import ecorp.easy.installer.helpers.DeviceHelper;
import ecorp.easy.installer.exceptions.TooManyDevicesException;
import ecorp.easy.installer.models.Phone;
import ecorp.easy.installer.tasks.DeviceDetectionTask;
import ecorp.easy.installer.utils.UiUtils;
import java.net.URL;
-import java.util.Arrays;
import java.util.ResourceBundle;
import javafx.concurrent.WorkerStateEvent;
import javafx.fxml.FXML;
@@ -128,8 +128,10 @@ public class DeviceDetectedController extends AbstractSubController{
}else{
detectionMsg.setText(String.format(i18n.getString("detect_lbl_compatibleDeviceFound"), model));
if(parentController != null){
+ phone.setInternalCode(DeviceHelper.getDeviceInternalcode(phone.getAdbDevice()));
+ AppConstants.setDeviceModel(phone.getAdbDevice()); //this line must be before the "parentController.setDevice(phone). If it's not the case,
+ //the AppConstants.getSourceFolder() won't include the device model's name
parentController.setDevice(phone);
- AppConstants.setDeviceModel(phone.getAdbDevice()); //@TODO remove this line ?
parentController.disableNextButton(false);
}
}
diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/FlashSceneController.java b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/FlashSceneController.java
deleted file mode 100644
index e92f5d6ee27dd7d0af3c4e6aefaf6fd5face6234..0000000000000000000000000000000000000000
--- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/FlashSceneController.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright 2019-2020 - ECORP SAS
-
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package ecorp.easy.installer.controllers.subcontrollers;
-
-import ch.qos.logback.classic.LoggerContext;
-import ecorp.easy.installer.AppConstants;
-import ecorp.easy.installer.controllers.MainWindowController;
-import ecorp.easy.installer.graphics.FlashGlobalProgressManager;
-import ecorp.easy.installer.graphics.Instruction;
-import ecorp.easy.installer.helpers.DeviceHelper;
-import ecorp.easy.installer.logger.GUIAppender;
-import ecorp.easy.installer.logger.LogPathPropertyDefiner;
-import ecorp.easy.installer.models.DataBundle;
-import ecorp.easy.installer.threads.FlashThread;
-import ecorp.easy.installer.tasks.UploadToEcloudTask;
-import ecorp.easy.installer.utils.IFlashHandler;
-import ecorp.easy.installer.utils.UiUtils;
-
-import java.net.URL;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import javafx.animation.FadeTransition;
-import javafx.animation.KeyFrame;
-import javafx.animation.KeyValue;
-import javafx.animation.Timeline;
-import javafx.collections.ObservableList;
-import javafx.fxml.FXML;
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.control.ContentDisplay;
-import javafx.scene.control.Label;
-import javafx.scene.control.ProgressBar;
-import javafx.scene.control.ScrollPane;
-import javafx.scene.image.Image;
-import javafx.scene.image.ImageView;
-import javafx.scene.input.MouseEvent;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.TextFlow;
-import javafx.util.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * FXML Controller class
- *
- * @author Vincent Bourgmayer
- * @author Ingo
- */
-public class FlashSceneController extends AbstractSubSteppedController implements IFlashHandler {
- //Current step UI element
- @FXML VBox flashSceneRoot;
- @FXML ProgressBar loadStepProgressIndicator; //'load' step type only
- @FXML VBox instructionsFlow;
- @FXML Label stepTitleLabel;
- @FXML ImageView instructionImage;
- @FXML HBox instructionsContainer;
-
- // progress bar's node of global Flash's process :
- @FXML HBox globalProgressIndicator;
- private FlashGlobalProgressManager globalProgressMgr;
-
- // node relative to Log
- @FXML VBox instructionsVBox;
- @FXML ScrollPane logScrollPane;
- @FXML TextFlow logFlow;
- @FXML Button showHideLogBtn;
- @FXML Button sendLogBtn;
-
- private Timeline timeline; //this animate the progression in ProgressBar
- private boolean stopped = false; //determine if the process has been stopped (due to error or normal ending)
- private List instructionsKey; //Contains the different instruction that have to be currently displayed
- ResourceBundle instructionsImagesBundle; //Give access to image to loads with instructionsKey
- private FlashThread thread;
- private Object pauseLock; //lock used for pausing the FlashThread
- private final static Logger logger = LoggerFactory.getLogger(FlashSceneController.class);
-
- @Override
- public void initialize(URL location, ResourceBundle resources) {
- super.initialize(location, resources);
- logger.debug("Initialize FlashSceneController.java");
- logFlow.heightProperty().addListener(observable -> logScrollPane.setVvalue(1.0));
- UiUtils.hideNode(logScrollPane);
- UiUtils.hideNode(sendLogBtn);
- stepTitleLabel.setGraphicTextGap(18);
- stepTitleLabel.setContentDisplay(ContentDisplay.LEFT);
- }
-
- /**
- * @inheritDoc
- * @param parentController
- */
- @Override
- public void setParentController(MainWindowController parentController) {
- super.setParentController(parentController); //To change body of generated methods, choose Tools | Templates.
-
- //can use Properties instead of ResourceBundle but ResourceBundle use default file for missing value
- //The only problem is that I can't specify any version without region and language...
- instructionsImagesBundle = ResourceBundle.getBundle("instructions.imageName",
- new Locale.Builder()
- .setRegion("en")
- .setLanguage("EN")
- .setVariant(DeviceHelper.getDeviceInternalcode(parentController.getDevice().getAdbDevice()))
- .build());
- pauseLock = new Object(); //This is object used to unpause a thread
-
- thread = parentController.getThreadFactory().buildFlashThread(this, pauseLock);
- if(thread!= null){
- thread.setDaemon(true);
- //@TODO find another way to get the step number as yaml file can contains step for issue. By example
- //if script got issue, then load script 45 if success load script 2.
- //Then the stepSize won't fit with the real step that the user must perform
- globalProgressMgr = new FlashGlobalProgressManager(thread.getCommandsSize());
- globalProgressIndicator.getChildren().addAll(globalProgressMgr.getSegments());
-
- thread.start();
- }
- }
-
- /**
- * Add a new instruction to display without clearing the precedent
- * @param instruction the instruction to add
- */
- public void addInstructionToDisplay(String instructionKey){
- String effectiveTxtKey = "all_lbl_missingTranslation";
- if(i18n.containsKey(instructionKey)){
- effectiveTxtKey = instructionKey;
- }
- Instruction instruction = new Instruction(effectiveTxtKey, i18n.getString(effectiveTxtKey));
-
- //instruction.setWrapText(true); //make text resize if longer than width
- instruction.maxWidthProperty().bind(instructionsFlow.widthProperty()); //Set max Width to its parent width
- instructionsFlow.getChildren().add(instruction);
- }
-
- /**
- * UI changes at beginning of a new step
- * @TODO: move part of code relative to 'action' step to 'setActionStepUI()', and 'load' type to 'setLoadStepUI()'
- * @param db
- */
- @Override
- public void onStepStart(DataBundle db) {
- logger.info("onStepStart()");
- if(db == null)return;
-
- //close the timer of a loadStepType
- if(timeline != null){
- timeline.stop();
- timeline = null;
- }
-
- //Update the progressBar of the global process
- globalProgressMgr.updateProgression();
-
- //Update instruction title
- final String title = db.getString("stepTitle");
- logger.debug("--Title {}", title);
-
- //Get Type of step ("action" or "load")
- final String stepType = db.getString("stepType");
- logger.debug("--Type: {}", stepType);
- switch (stepType) {
- case AppConstants.USER_ACTION_KEY: //@deprecated
- case "custom":
- case "custom-executable":
- instructionsContainer.setOpacity(0.0);
- updateInstructions(title, db.getList("stepInstructions", "String") );
- displayActionStepType(db);
- UiUtils.buildFadeTransition(instructionsContainer, false).play();
- break;
- case AppConstants.LOAD_KEY:
- instructionsContainer.setOpacity(0.0);
- updateInstructions(title, db.getList("stepInstructions", "String"));
- displayLoadStepType(db);
- UiUtils.buildFadeTransition(instructionsContainer, false).play();
- break;
- case AppConstants.ASK_ACCOUNT_KEY:
- displaySpecificView("6-2-eAccount.fxml");
- break;
- case AppConstants.UNLOCK_OEM_KEY:
- displaySpecificView("6-3-unlockOEM.fxml");
- break;
- default:
- logger.warn("Try to load invalid step's type");
- break;
- }
- }
-
- /**
- * Update text and images instructions
- * @param instructionsKey
- */
- private void updateInstructions(final String title, final List instructionsKey){
- if(title != null){
- stepTitleLabel.setText(i18n.getString(title));
- }
-
- //update instructions
- if(instructionsKey == null || instructionsKey.isEmpty()) return;
- this.instructionsKey = instructionsKey;
-
- //Remove precedent instruction
- instructionsFlow.getChildren().clear();
-
- //Add new instructions
- instructionsKey.forEach((instruction) -> {
- addInstructionToDisplay(instruction);
- });
-
- //Update instruction image
- String instructionImgName = instructionsKey.get(0);
- if(instructionsImagesBundle.containsKey(instructionImgName)){
- try{
- this.instructionImage.setImage(new Image(getClass().getResourceAsStream("/images/"+instructionsImagesBundle.getString(instructionImgName))));
- }catch (Exception e) {
- logger.warn("onStepStart(), image key = {}, error = {}", instructionImgName, e.toString());
- this.instructionImage.setImage(null);
- }
- }else{
- this.instructionImage.setImage(null);
- }
- }
-
-
-
-
- /**
- * Display the specific interface for
- * Note: This could be replace by a call to parentController.loadSubUI("6-2-eAccount.fxml")
- * but how to reset current ui to this one after ?
- */
- private void displaySpecificView(final String fxmlName){
- //Masque previous UI
- UiUtils.hideNode(flashSceneRoot);
- //Affiche the new One
- final Node tempRoot = parentController.loadSubUI(fxmlName, null);
-
- //play fade out animation
- tempRoot.setOpacity(0.0);
- UiUtils.buildFadeTransition(tempRoot,false).play();
-
- //Define what happened when user click on continue on this specific view
- final String tempRootId = tempRoot.getId();
- parentController.setNextButtonOnClickListener(( MouseEvent event) -> {
- //this is where I have to put fade in transition
- final FadeTransition fadeInAnimation = UiUtils.buildFadeTransition(tempRoot,true);
- fadeInAnimation.setOnFinished(t->{
- parentController.resetNextButtonEventHandler();
- parentController.removeNodeFromRoot(tempRootId);
- parentController.showCurrentSubRoot();
- parentController.setNextButtonVisible(false);
- synchronized (pauseLock) {
- pauseLock.notify();
- }
- });
-
- fadeInAnimation.play();
- });
- }
-
- /**
- * Set UI for "load" steps
- * @param db
- */
- private void displayLoadStepType(DataBundle db){
- logger.info("onLoadStepType()");
- UiUtils.hideNode(instructionsFlow); //put it invisible instead ?
- instructionsVBox.setAlignment(Pos.TOP_CENTER);
- parentController.setNextButtonVisible(false);
- int averageTime = db.getInt("averageTime");
- logger.debug("averageTime = {} ", averageTime);
- if(averageTime > -1){ //Or > 0 ?
- timeline = new Timeline(
- new KeyFrame(Duration.millis(0), new KeyValue(loadStepProgressIndicator.progressProperty(), 0.0) ),
- new KeyFrame(Duration.millis(averageTime*1000.0), new KeyValue(loadStepProgressIndicator.progressProperty(), 1.0))
- );
- timeline.playFromStart();
- loadStepProgressIndicator.setProgress(0.0); //Reset to prevent showing last value
- UiUtils.showNode(loadStepProgressIndicator);
- }
- stepTitleLabel.setGraphic(null);
- }
-
- /**
- * Set UI for "action" steps.
- * @param db
- */
- private void displayActionStepType(DataBundle db){
- //emphasize first Label
- instructionsVBox.setAlignment(Pos.TOP_LEFT);
- currentSubStepId = 0; //reset the value
-
- ((Instruction)instructionsFlow.getChildren().get(0)).emphasize();
-
- parentController.setNextButtonVisible((instructionsFlow.getChildren().size() >1));
-
- parentController.setNextButtonOnClickListener((MouseEvent event)->{
- final int instructionsCount = instructionsFlow.getChildren().size();
-
- if ( !db.getBoolean("hasScript")
- && currentSubStepId == (instructionsCount-1)
- && !stopped )
- {
- synchronized (pauseLock) { pauseLock.notify(); }
- }else{
- onNextButtonClicked();
- }
- //If there is a script and this instruction before the last one
- if( db.getBoolean("hasScript")
- &¤tSubStepId == (instructionsCount-2)
- && !stopped )
- {
- //hide the button to prevent clicking before the end of the full process
- parentController.setNextButtonVisible(false);
- }// If there is no script and it's the last instruction: notify flashThread
-
- ++currentSubStepId;
- });
-
- //Hide progress Indicator
- UiUtils.hideNode(loadStepProgressIndicator);
- UiUtils.showNode(instructionsFlow);
-
- //Set Title Icon if defined
- String titleIconName = db.getString("titleIconName");
- if(titleIconName != null){
- stepTitleLabel.setGraphic(new ImageView(UiUtils.loadImage(titleIconName)));
- }
- }
-
-
- /**
- * UI modification when an error is detected during the process
- * @param db datas to update the UI. Currently not used
- */
- @Override
- public void onFlashError(DataBundle db) {
- logger.warn("onFlashError()");
- String errorMsgKey = db.getString("errorMsgKey");
-
- if(errorMsgKey == null || errorMsgKey.isEmpty() || !i18n.containsKey(errorMsgKey))
- errorMsgKey ="script_error_unknown";
- stepTitleLabel.setText(i18n.getString(errorMsgKey));
-
- logger.debug("errorMsgKey = {}", errorMsgKey);
-
- UiUtils.hideNode(instructionsFlow);
- UiUtils.showNode(sendLogBtn);
-
- Button tryAgainBtn = new Button(i18n.getString("all_lbl_tryAgain"));
- tryAgainBtn.setOnMouseClicked(( MouseEvent event) -> {
- parentController.retryToFlash();
- });
- instructionsVBox.setAlignment(Pos.TOP_CENTER);
- instructionsVBox.getChildren().add(tryAgainBtn);
- }
-
- /**
- * Behaviour of the UI when the flash process is stop. It also cancel the TimerTask of 'load' type task.
- * @param db bundle containing element to update the UI.
- */
- @Override
- public void onFlashStop(DataBundle db) {
- logger.info("onFlashStop()");
- if(timeline != null){
- timeline.stop();
- timeline = null;
- }
- stopped = true;
- parentController.resetNextButtonEventHandler();
- parentController.setNextButtonVisible(true);
- final boolean isFlashed = db.getBoolean("isFlashed");
- parentController.setIsFlashed(isFlashed);
- //if success, move automaticcaly to the next step
- if(isFlashed){
- parentController.loadSubScene();
- }
- }
-
- /**
- * enable/disable log displaying
- */
- public void showHideLog(){
- ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
- GUIAppender appender = (GUIAppender) rootLogger.getAppender("GUI");
-
- final String text = showHideLogBtn.getText();
- if(text.equals(">")){
- showHideLogBtn.setText("V");
- UiUtils.hideNode(logScrollPane);
- logFlow.getChildren().clear();
- appender.setContainer(null);
- }else{
- showHideLogBtn.setText(">");
- UiUtils.showNode(logScrollPane);
- logFlow.getChildren().addAll(appender.getLogsList());
- appender.setContainer(logFlow);
- }
- }
-
- /**
- * Send log to support, in special ecloud.global folder
- * @return
- */
- public boolean sendLogToSupport(){
- if(thread != null){
- String filePath = LogPathPropertyDefiner.getLogFilePath();
- if(filePath != null){
-
- UploadToEcloudTask uploadTask = new UploadToEcloudTask(AppConstants.LOG_STORAGE_URL, filePath);
- uploadTask.setOnSucceeded(eh -> {
- if( (Boolean) eh.getSource().getValue() ){ //if success
- sendLogBtn.setDisable(true);
- sendLogBtn.setText(i18n.getString("install_btn_sendLogSuccess"));
- logger.info("sendLogToSupport(), sending log: success");
- }
- else{
- sendLogBtn.setText(i18n.getString("install_btn_sendLogAgain"));
- logger.warn("sendLogToSupport(), sending log: failure");
- }
- });
-
- uploadTask.setOnFailed(eh->{
- sendLogBtn.setText(i18n.getString("install_btn_sendLogAgain"));
- logger.warn("sendLogToSupport(), sending log: failure, error = {}",eh.getSource().getException().toString() );
- });
-
- Thread uploadTaskThread = new Thread(uploadTask);
- uploadTaskThread.setDaemon(true);
- uploadTaskThread.start();
- }
- }
- return false;
- }
-
- /**
- * The new behaviour of the parentController's nextButton
- */
- @Override
- protected void onNextButtonClicked() {
- //Si currenttype est action
- final ObservableList children = instructionsFlow.getChildren();
- final int instructionsNumber = children.size();
-
- /*
- check that there is more than 1 instruction. (children's size is > 1).
- Then if it's not the case, just return.
- This behaviour is only expected when there is more than 2 instructions.
- */
- if(instructionsNumber <= 1) return;
-
- /*
- No need to check that currentSubStepId isn't equal or over size
- This won't happens because the next button should be hidden at the last instruction
- */
-
- //get CurrentLabel
- Instruction currentInstruction = (Instruction) children.get(currentSubStepId);
- //get previousLabel
- Instruction nextInstruction = (Instruction) children.get(currentSubStepId+1);
-
- //Update the image using instruction key cod
- final String nextTxtKey = nextInstruction.getKey();
- if(instructionsImagesBundle.containsKey(nextTxtKey) ){
- instructionImage.setImage(UiUtils.loadImage(instructionsImagesBundle.getString(nextTxtKey)));
- }else{
- instructionImage.setImage(null);
- }
- //Deemphase previous instruction and emphasize new current one
- if(currentSubStepId < instructionsNumber-1){
- currentInstruction.trivialize();
- nextInstruction.emphasize();
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/ecorp/easy/installer/tasks/CommandRunnerService.java b/src/main/java/ecorp/easy/installer/tasks/CommandRunnerService.java
new file mode 100644
index 0000000000000000000000000000000000000000..73606d02a2e8acd1b87c7263dad746a6952c17cf
--- /dev/null
+++ b/src/main/java/ecorp/easy/installer/tasks/CommandRunnerService.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2019-2021 - ECORP SAS
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ecorp.easy.installer.tasks;
+
+import ecorp.easy.installer.AppConstants;
+import ecorp.easy.installer.models.Command;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javafx.concurrent.Service;
+import javafx.concurrent.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Service in charge to run Command task
+ * @author vincent Bourgmayer
+ */
+public class CommandRunnerService extends Service{
+ final protected static char COMMON_PARAM_IDENTIFIER = '$';//allow to identify when an param of a step is to load from common parameter
+ final protected static Pattern REGEX_FIND_PARAM = Pattern.compile("\\$\\{(.*?)\\}");
+ private final static Logger logger = LoggerFactory.getLogger(CommandRunnerService.class);
+ private final static HashMap COMMON_PARAMS = new HashMap<>();
+
+ static {
+ final String sourcePath = AppConstants.getSourcesFolderPath();
+
+ COMMON_PARAMS.put("SOURCES_PATH", sourcePath);
+ COMMON_PARAMS.put("TWRP_IMAGE_PATH", sourcePath+AppConstants.getTwrpImgPath());
+ COMMON_PARAMS.put("ARCHIVE_PATH", sourcePath+AppConstants.getEArchivePath());
+ COMMON_PARAMS.put("ADB_FOLDER_PATH", AppConstants.getADBFolderPath());
+ COMMON_PARAMS.put("HEIMDALL_FOLDER_PATH", AppConstants.getHeimdallFolderPath());
+ COMMON_PARAMS.put("JAVA_FOLDER_PATH", AppConstants.JavaHome);
+ }
+
+ private final Command cmd;
+
+ public CommandRunnerService( Command cmd){
+ this.cmd = cmd;
+ }
+
+ @Override
+ protected Task createTask() {
+
+ Task task = new Task() {
+ @Override
+ protected Boolean call() throws Exception {
+ logger.info("Command Task call()");
+ updateParameters();
+ try{
+ cmd.execAndReadOutput();
+ }catch( IOException | InterruptedException e){
+ cmd.cancel();
+ logger.error("cmd.execAndReadOutput(), error = {}", e.toString() );
+ return false;
+ }
+
+ //read result from command object
+ final int exitValue = cmd.getExitValue();
+ final String shellOutput = cmd.getShellOutput();
+
+ logger.debug("command output= {}\nexit value = {}\n", shellOutput, exitValue);
+
+
+ if(cmd.isSuccess()){
+ String outputKey = cmd.getOutputKey();
+ //If an output is expected from succeed script
+
+ if( outputKey != null && outputKey.charAt(0) == COMMON_PARAM_IDENTIFIER){
+ final int lastIndex = shellOutput.lastIndexOf("\n");
+ final int length = shellOutput.length();
+ final String shellOutputCleaned = shellOutput.substring(lastIndex+1, length);
+ logger.debug("shell output cleaned : "+shellOutputCleaned);
+ COMMON_PARAMS.put(outputKey.replace("${","").replace("}", ""), shellOutputCleaned);
+ }
+
+ return true;
+ }else{ //fails case
+ return false;
+ }
+
+ }
+ };
+
+ task.setOnCancelled(eh->{
+ logger.debug("CommandRunnerService.task.onCancelled()");
+ cmd.cancel();
+ });
+ return task;
+ }
+
+
+ /**
+ * Update parameters of the current command
+ * It is called before to execute the command
+ * @param cmd
+ */
+ protected void updateParameters(){
+ //Update Parameters
+ if(cmd.getParameters() != null){ //@TODO: remove functionnal and rewrite it as it was before with simple loop.
+ cmd.getParameters().entrySet().stream().filter((param) -> (param.getValue().contains("$"))).forEachOrdered((param) -> {
+ Matcher matcher = REGEX_FIND_PARAM.matcher(param.getValue());
+ while(matcher.find()){
+ cmd.updateParameter(param.getKey(), param.getValue().replace(matcher.group(0), COMMON_PARAMS.get(matcher.group(1))));
+ }
+ });
+
+ logger.debug("updateParameters(), Parameters = "+cmd.getParameters().toString());
+ }
+ }
+
+ /**
+ * Write a new value for the associated key.
+ * If the value is already present, the precedent value will be overwritten
+ * @param key the key to identify a param
+ * @param value the value of the param
+ */
+ public static void updateCommonParam(String key, String value){
+ COMMON_PARAMS.put(key, value);
+ }
+}
diff --git a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java
index 493f206489441477192c34b778f50b19d18034f2..eb8cfe79b4c3d2a5d7e2c9a3e8ab3576356be510 100644
--- a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java
+++ b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java
@@ -205,4 +205,9 @@ public class ThreadFactory {
if(flashMould == null) return 0;
return flashMould.getSteps().size();
}
+
+
+ public ProcessMould getFlashMould() {
+ return flashMould;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/ecorp/easy/installer/utils/UiUtils.java b/src/main/java/ecorp/easy/installer/utils/UiUtils.java
index 4cfdc19eead8398546c57607b76d8cb843b7827f..cf0be1043c283ff5a68708047cd4382bf7e4f118 100644
--- a/src/main/java/ecorp/easy/installer/utils/UiUtils.java
+++ b/src/main/java/ecorp/easy/installer/utils/UiUtils.java
@@ -5,7 +5,6 @@
*/
package ecorp.easy.installer.utils;
-import ecorp.easy.installer.controllers.subcontrollers.FlashSceneController;
import javafx.animation.FadeTransition;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index d34871f37fa7b27663f94ba36bf80dd0e2207724..1db438fa82bdd7358cb948000500528c5599ec8b 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -34,7 +34,7 @@ module ecorp.easy.installer {
opens ecorp.easy.installer to javafx.fxml;
opens ecorp.easy.installer.controllers to javafx.fxml;
opens ecorp.easy.installer.controllers.subcontrollers to javafx.fxml;
-
+ opens ecorp.easy.installer.controllers.stepControllers to javafx.fxml;
exports ecorp.easy.installer.logger;
exports ecorp.easy.installer;
}
diff --git a/src/main/resources/css/style.css b/src/main/resources/css/style.css
index 038d64d41891bd511c4d37e23ac1c47264fd0df1..1ed35be41d6b7e143dc235dbb6d67c930274f5b0 100644
--- a/src/main/resources/css/style.css
+++ b/src/main/resources/css/style.css
@@ -158,6 +158,9 @@ Button:pressed{
-fx-background-insets: 0;
-fx-background-radius: 20;
}
+.progressBar.errorBar .bar {
+ -fx-background-color: #E50000;
+}
#logScrollPane {
-fx-background-color: #E5E5E5;
diff --git a/src/main/resources/fxml/6-2-eAccount.fxml b/src/main/resources/fxml/6-2-eAccount.fxml
index 87f355c40c7d6a5938b83a00fd02eb070c72d13a..4f8f0273ae49fd34bb070b9f419f05711d24bf93 100644
--- a/src/main/resources/fxml/6-2-eAccount.fxml
+++ b/src/main/resources/fxml/6-2-eAccount.fxml
@@ -27,11 +27,11 @@
-
+ fx:controller="ecorp.easy.installer.controllers.stepControllers.EAccountController">
diff --git a/src/main/resources/fxml/6-3-unlockOEM.fxml b/src/main/resources/fxml/6-3-unlockOEM.fxml
index a4828b96b9f244bec0deea44501f2cc68efb3e46..8974e6d5d781992bd5047c07e79baadc7df3c933 100644
--- a/src/main/resources/fxml/6-3-unlockOEM.fxml
+++ b/src/main/resources/fxml/6-3-unlockOEM.fxml
@@ -27,11 +27,11 @@
-
+ fx:controller="ecorp.easy.installer.controllers.stepControllers.UnlockOemController">
diff --git a/src/main/resources/fxml/6-flashScene.fxml b/src/main/resources/fxml/LogPanel.fxml
similarity index 52%
rename from src/main/resources/fxml/6-flashScene.fxml
rename to src/main/resources/fxml/LogPanel.fxml
index 7d9138a262cd082aaddc9ff2874672b56e26c524..fe113344e7d6ceadf26fb0a0eaced1c68c8f417c 100644
--- a/src/main/resources/fxml/6-flashScene.fxml
+++ b/src/main/resources/fxml/LogPanel.fxml
@@ -1,7 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/fxml/loadStep.fxml b/src/main/resources/fxml/loadStep.fxml
new file mode 100644
index 0000000000000000000000000000000000000000..13fba9498e68fe36ecbbece73c04c8565f39942f
--- /dev/null
+++ b/src/main/resources/fxml/loadStep.fxml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/lang/translation.properties b/src/main/resources/lang/translation.properties
index b4a60f93422702f2312266c8fd05b5d747617916..f937e69bb94b65fb50cebfee828f84b538030c01 100644
--- a/src/main/resources/lang/translation.properties
+++ b/src/main/resources/lang/translation.properties
@@ -226,6 +226,19 @@ script_error_serialNumber_missing=No device's serial number provided
script_error_fastboot_path_missing= No fastboot tool path provided
script_error_fastboot_flashingUnlock_failed=Could not unlock flashing
script_error_unknown= The installation encounter an error
+script_error_cantRebootBootloader= Failed to reboot into bootloader
+script_error_cantUnpackSources=Failed to unpack /e/ sources
+script_error_cantWipeData=Failed to wipe data
+script_error_cantFlashBoot=Failed to flash Boot partition
+script_error_cantFlashRecovery=Failed to flash Recovery
+script_error_cantFlashVbmeta=Failed to flash vb meta partition
+script_error_cantFlashVbmeta_system=Failed to flash vb meta system partition
+script_error_cantFlashVBmeta_vendor=Failed to flash vb Meta vendor partition
+script_error_cantRebootToFastboot=Failed to reboot into fastboot mode
+script_error_cantFlashSystem=Failed to flash system partition
+script_error_cantFlashproduct=Failed to flash product partition
+script_error_cantFlashVendor=Failed to flash vendor partition
+script_error_cantrebootFromFasboot= Failed to reboot from fastboot
java_error_unknow= The installation encounter an internal error
flash_process_cancelled=The installation process has been cancelled
diff --git a/src/main/resources/yaml/GS290_flash.yml b/src/main/resources/yaml/GS290_flash.yml
index 112ff8d20ec7bfee6658c123138ac7cb7722b6b1..0c9a9662ff077f9c70032ac3a40f45979286ed46 100644
--- a/src/main/resources/yaml/GS290_flash.yml
+++ b/src/main/resources/yaml/GS290_flash.yml
@@ -57,8 +57,8 @@ steps:
koCodes:
1: script_error_unknown
10: script_error_cantRebootBootloader
- 101: script_error_deviceID_missing
- 102: script_error_fastbootPath_missing
+ 101: script_error_serialNumber_missing
+ 102: script_error_fastboot_path_missing
f3:
type: custom-executable
stepNumber: 4
@@ -77,9 +77,9 @@ steps:
0: ~
koCodes:
1: script_error_unknown
- 2: script_error_flashingUnlockFailed
- 101: script_error_deviceID_missing
- 102: script_error_fastbootPath_missing
+ 2: script_error_fastboot_flashingUnlock_failed
+ 101: script_error_serialNumber_missing
+ 102: script_error_fastboot_path_missing
f4:
type: load
@@ -106,9 +106,9 @@ steps:
14: script_error_cantFlashsystem
15: script_error_cantFlashLk
16: script_error_cantFlashLogo
- 101: script_error_deviceID_missing
+ 101: script_error_serialNumber_missing
102: script_error_installFromFastboot_102
- 103: script_error_fastbootPath_missing
+ 103: script_error_fastboot_path_missing
f5:
type: askAccount
stepNumber: 6
diff --git a/src/main/resources/yaml/Teracube_2e_flash.yml b/src/main/resources/yaml/Teracube_2e_flash.yml
index f92e4103ca901f20573286f11a2599c6fdd33b9b..a8336662aaa1a9d29db285cbdb55924dbff4e4ec 100644
--- a/src/main/resources/yaml/Teracube_2e_flash.yml
+++ b/src/main/resources/yaml/Teracube_2e_flash.yml
@@ -45,8 +45,8 @@ steps:
koCodes:
1: script_error_unknown
10: script_error_cantRebootBootloader
- 101: script_error_deviceID_missing
- 102: script_error_fastbootPath_missing
+ 101: script_error_serialNumber_missing
+ 102: script_error_fastboot_path_missing
f2:
type: custom-executable
stepNumber: 3
@@ -64,9 +64,9 @@ steps:
0: ~
koCodes:
1: script_error_unknown
- 2: script_error_flashingUnlockFailed
- 101: script_error_deviceID_missing
- 102: script_error_fastbootPath_missing
+ 2: script_error_fastboot_flashingUnlock_failed
+ 101: script_error_serialNumber_missing
+ 102: script_error_fastboot_path_missing
f3:
type: load
stepNumber: 4
@@ -96,9 +96,9 @@ steps:
18: script_error_cantFlashSystem
19: script_error_cantFlashproduct
20: script_error_cantFlashVendor
- 101: script_error_deviceID_missing
+ 101: script_error_serialNumber_missing
102: script_error_installFromFastboot_102
- 103: script_error_fastbootPath_missing
+ 103: script_error_fastboot_path_missing
f4:
type: askAccount
stepNumber: 5
@@ -119,4 +119,4 @@ steps:
koCodes:
1: script_error_unknown
10: script_error_cantrebootFromFasboot
- 101: script_error_noDeviceFoundInFastboot
\ No newline at end of file
+ 101: script_error_waitFastboot_1
\ No newline at end of file