Intermediate results of net-install support implementation.

Front-end 80% ready. Backend 5% ready.
This commit is contained in:
Dmitry Isaenko 2019-03-17 19:45:51 +03:00
parent d41401c85e
commit d55e1c9ba9
13 changed files with 321 additions and 20 deletions

View file

@ -1,6 +1,6 @@
# NS-USBloader # NS-USBloader
NS-USBloader is a PC-side TinFoil and GoldLeaf NSP USB uploader. Replacement for default *usb_install_pc.py* and *GoldTree*. NS-USBloader is a PC-side TinFoil (USB and Network) and GoldLeaf NSP USB uploader. Replacement for default *usb_install_pc.py*, *remote_install_pc.py* and *GoldTree*.
With GUI and cookies. With GUI and cookies.
@ -81,12 +81,14 @@ Français by [Stephane Meden (JackFromNice)](https://github.com/JackFromNice)
## TODO: ## TODO:
- [x] macOS QA v0.1 (Mojave) - [x] macOS QA v0.1 (Mojave)
- [x] macOS QA v0.2.2 (Mojave) - [x] macOS QA v0.2.2 (Mojave)
- [ ] macOS QA v0.3 (Mojave)
- [x] Windows support - [x] Windows support
- [x] code refactoring - [x] code refactoring
- [x] GoldLeaf support - [x] GoldLeaf support
- [ ] XCI support - [ ] XCI support
- [ ] File order sort (non-critical) - [ ] File order sort (non-critical)
- [ ] More deep file analyze before uploading. - [ ] More deep file analyze before uploading.
- [] Network mode support for TinFoil
## Thanks ## Thanks
Appreciate assistance and support of both Vitaliy and Konstantin. Without you all this magic would not have happened. Appreciate assistance and support of both Vitaliy and Konstantin. Without you all this magic would not have happened.

View file

@ -22,10 +22,24 @@ public class AppPreferences {
protocol = "TinFoil"; protocol = "TinFoil";
return protocol; return protocol;
} }
public String getNetUsb(){
String netUsb = preferences.get("NETUSB", "USB"); // Don't let user to change settings manually
if (!netUsb.matches("(^USB$)|(^NET$)"))
netUsb = "USB";
return netUsb;
}
public void setTheme(String theme){ preferences.put("THEME", theme); } public void setTheme(String theme){ preferences.put("THEME", theme); }
public void setProtocol(String protocol){ preferences.put("PROTOCOL", protocol); } public void setProtocol(String protocol){ preferences.put("PROTOCOL", protocol); }
public void setNetUsb(String netUsb){ preferences.put("NETUSB", netUsb); }
public void setNsIp(String ip){preferences.put("NSIP", ip);}
public String getNsIp(){return preferences.get("NSIP", "192.168.1.42");}
public String getRecent(){ return preferences.get("RECENT", System.getProperty("user.home")); } public String getRecent(){ return preferences.get("RECENT", System.getProperty("user.home")); }
public void setRecent(String path){ preferences.put("RECENT", path); } public void setRecent(String path){ preferences.put("RECENT", path); }
//------------ SETTINGS ------------------//
public boolean getNsIpValidationNeeded() {return preferences.getBoolean("NSIPVALIDATION", true);}
public void setNsIpValidationNeeded(boolean need){preferences.putBoolean("NSIPVALIDATION", need);}
public boolean getExpertMode(){return preferences.getBoolean("EXPERTMODE", false);}
public void setExpertMode(boolean mode){preferences.putBoolean("EXPERTMODE", mode);}
} }

View file

@ -12,7 +12,9 @@ import javafx.scene.layout.Region;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
import nsusbloader.NET.NETCommunications;
import nsusbloader.NSLMain; import nsusbloader.NSLMain;
import nsusbloader.ServiceWindow;
import nsusbloader.USB.UsbCommunications; import nsusbloader.USB.UsbCommunications;
import java.io.File; import java.io.File;
@ -35,7 +37,7 @@ public class NSLMainController implements Initializable {
@FXML @FXML
public ProgressBar progressBar; // Accessible from Mediator public ProgressBar progressBar; // Accessible from Mediator
@FXML @FXML
private ChoiceBox<String> choiceProtocol; private ChoiceBox<String> choiceProtocol, choiceNetUsb;
@FXML @FXML
private Button switchThemeBtn; private Button switchThemeBtn;
@ -44,6 +46,12 @@ public class NSLMainController implements Initializable {
@FXML @FXML
public NSTableViewController tableFilesListController; // Accessible from Mediator public NSTableViewController tableFilesListController; // Accessible from Mediator
@FXML
private NetTabController NetTabController;
@FXML
private TextField nsIpTextField;
@FXML
private Label nsIpLbl;
private UsbCommunications usbCommunications; private UsbCommunications usbCommunications;
private Thread usbThread; private Thread usbThread;
@ -78,10 +86,46 @@ public class NSLMainController implements Initializable {
ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf"); ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf");
choiceProtocol.setItems(choiceProtocolList); choiceProtocol.setItems(choiceProtocolList);
choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol()); // TODO: shared settings choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol());
choiceProtocol.setOnAction(e->tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem())); // Add listener to notify tableView controller choiceProtocol.setOnAction(e-> {
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem());
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) {
choiceNetUsb.setDisable(true);
nsIpLbl.setVisible(false);
nsIpTextField.setVisible(false);
}
else {
choiceNetUsb.setDisable(false);
if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")) {
nsIpLbl.setVisible(true);
nsIpTextField.setVisible(true);
}
}
}); // Add listener to notify tableView controller
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller
ObservableList<String> choiceNetUsbList = FXCollections.observableArrayList("USB", "NET");
choiceNetUsb.setItems(choiceNetUsbList);
choiceNetUsb.getSelectionModel().select(AppPreferences.getInstance().getNetUsb());
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) {
choiceNetUsb.setDisable(true);
}
choiceNetUsb.setOnAction(e->{
if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){
nsIpLbl.setVisible(true);
nsIpTextField.setVisible(true);
}
else{
nsIpLbl.setVisible(false);
nsIpTextField.setVisible(false);
}
});
nsIpTextField.setText(AppPreferences.getInstance().getNsIp());
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil") && choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){
nsIpLbl.setVisible(true);
nsIpTextField.setVisible(true);
}
this.previouslyOpenedPath = null; this.previouslyOpenedPath = null;
Region btnSwitchImage = new Region(); Region btnSwitchImage = new Region();
@ -133,20 +177,42 @@ public class NSLMainController implements Initializable {
* It's button listener when no transmission executes * It's button listener when no transmission executes
* */ * */
private void uploadBtnAction(){ private void uploadBtnAction(){
if (usbThread == null || !usbThread.isAlive()){ if ((usbThread == null || !usbThread.isAlive())){
List<File> nspToUpload; if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf") ||
if ((nspToUpload = tableFilesListController.getFilesForUpload()) == null) { (
logArea.setText(resourceBundle.getString("logsNoFolderFileSelected")); choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil")
return; && choiceNetUsb.getSelectionModel().getSelectedItem().equals("USB")
}else { )
logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n"); ){
for (File item: nspToUpload) List<File> nspToUpload;
logArea.appendText(" "+item.getAbsolutePath()+"\n"); if ((nspToUpload = tableFilesListController.getFilesForUpload()) == null) {
logArea.setText(resourceBundle.getString("logsNoFolderFileSelected"));
return;
}else {
logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n");
for (File item: nspToUpload)
logArea.appendText(" "+item.getAbsolutePath()+"\n");
}
usbCommunications = new UsbCommunications(nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem());
usbThread = new Thread(usbCommunications);
usbThread.setDaemon(true);
usbThread.start();
}
else { // NET INSTALL OVER TINFOIL
if (NetTabController.isNsIpValidate() && !nsIpTextField.getText().trim().matches("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"))
if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"),resourceBundle.getString("windowBodyBadIp")))
return;
String nsIP = nsIpTextField.getText().trim();
if (!NetTabController.getExpertModeSelected()) {
NETCommunications netCommunications = new NETCommunications(nsIP);
usbThread = new Thread(netCommunications);
usbThread.setDaemon(true);
usbThread.start();
}
else {
// TODO; pass to another constructor
}
} }
usbCommunications = new UsbCommunications(nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem());
usbThread = new Thread(usbCommunications);
usbThread.setDaemon(true);
usbThread.start();
} }
} }
/** /**
@ -235,5 +301,9 @@ public class NSLMainController implements Initializable {
public void exit(){ public void exit(){
AppPreferences.getInstance().setProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); AppPreferences.getInstance().setProtocol(choiceProtocol.getSelectionModel().getSelectedItem());
AppPreferences.getInstance().setRecent(previouslyOpenedPath); AppPreferences.getInstance().setRecent(previouslyOpenedPath);
AppPreferences.getInstance().setNetUsb(choiceNetUsb.getSelectionModel().getSelectedItem());
AppPreferences.getInstance().setNsIp(nsIpTextField.getText().trim());
AppPreferences.getInstance().setNsIpValidationNeeded(NetTabController.isNsIpValidate());
AppPreferences.getInstance().setExpertMode(NetTabController.getExpertModeSelected());
} }
} }

View file

@ -0,0 +1,49 @@
package nsusbloader.Controllers;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import nsusbloader.AppPreferences;
import java.net.URL;
import java.util.ResourceBundle;
public class NetTabController implements Initializable {
@FXML
private CheckBox validateNSHostNameCb;
@FXML
private TextField pcIpTextField;
@FXML
private CheckBox expertModeCb;
@FXML
private Label hostIpLbl;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
validateNSHostNameCb.setSelected(AppPreferences.getInstance().getNsIpValidationNeeded());
if (AppPreferences.getInstance().getExpertMode()) {
expertModeCb.setSelected(true);
hostIpLbl.setVisible(true);
pcIpTextField.setVisible(true);
}
expertModeCb.setOnAction(e->{
if (expertModeCb.isSelected()){
hostIpLbl.setVisible(true);
pcIpTextField.setVisible(true);
}
else {
hostIpLbl.setVisible(false);
pcIpTextField.setVisible(false);
}
});
}
public boolean getExpertModeSelected(){
return expertModeCb.isSelected();
}
public boolean isNsIpValidate(){ return validateNSHostNameCb.isSelected(); }
}

View file

@ -0,0 +1,62 @@
package nsusbloader.NET;
import javafx.concurrent.Task;
import java.io.*;
import java.net.*;
public class NETCommunications extends Task<Void> { // todo: thows IOException
private String hostIP;
private String switchIP;
private ServerSocket serverSocket;
public NETCommunications(String switchIP){
this.switchIP = switchIP;
try{ // todo: check other method if internet unavaliable
DatagramSocket socket = new DatagramSocket();
socket.connect(InetAddress.getByName("8.8.8.8"), 10002); //193.0.14.129 RIPE NCC
hostIP = socket.getLocalAddress().getHostAddress();
System.out.println(hostIP);
socket.close();
}
catch (SocketException | UnknownHostException e){
e.printStackTrace();
}
try {
serverSocket = new ServerSocket(6000); // TODO: randomize
//System.out.println(serverSocket.getInetAddress()); 0.0.0.0
}
catch (IOException ioe){
ioe.printStackTrace();
System.out.println("unable to use socket");
}
}
@Override
protected Void call() throws Exception {
Socket clientSocket = serverSocket.accept();
InputStream is = clientSocket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
OutputStream os = clientSocket.getOutputStream();
OutputStreamWriter osr = new OutputStreamWriter(os);
PrintWriter pw = new PrintWriter(osr);
String line;
while ((line = br.readLine()) != null) {
if (line.equals("hello world")) {
pw.write("stop doing it!");
pw.flush();
break;
}
System.out.println(line);
}
serverSocket.close();
return null;
}
}

View file

@ -3,10 +3,12 @@
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?> <?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?> <?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.Tab?> <?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?> <?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?> <?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToolBar?> <?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
@ -30,6 +32,9 @@
<ToolBar> <ToolBar>
<items> <items>
<ChoiceBox fx:id="choiceProtocol" prefWidth="120.0" /> <ChoiceBox fx:id="choiceProtocol" prefWidth="120.0" />
<ChoiceBox fx:id="choiceNetUsb" prefWidth="75.0" />
<Label fx:id="nsIpLbl" text="%NSIPlable" visible="false" />
<TextField fx:id="nsIpTextField" prefWidth="120.0" visible="false" />
<Pane HBox.hgrow="ALWAYS" /> <Pane HBox.hgrow="ALWAYS" />
<Button fx:id="switchThemeBtn" mnemonicParsing="false" /> <Button fx:id="switchThemeBtn" mnemonicParsing="false" />
</items> </items>
@ -58,6 +63,14 @@
<SVGPath content="M21,19V17H8V19H21M21,13V11H8V13H21M8,7H21V5H8V7M4,5V7H6V5H4M3,5A1,1 0 0,1 4,4H6A1,1 0 0,1 7,5V7A1,1 0 0,1 6,8H4A1,1 0 0,1 3,7V5M4,11V13H6V11H4M3,11A1,1 0 0,1 4,10H6A1,1 0 0,1 7,11V13A1,1 0 0,1 6,14H4A1,1 0 0,1 3,13V11M4,17V19H6V17H4M3,17A1,1 0 0,1 4,16H6A1,1 0 0,1 7,17V19A1,1 0 0,1 6,20H4A1,1 0 0,1 3,19V17Z" /> <SVGPath content="M21,19V17H8V19H21M21,13V11H8V13H21M8,7H21V5H8V7M4,5V7H6V5H4M3,5A1,1 0 0,1 4,4H6A1,1 0 0,1 7,5V7A1,1 0 0,1 6,8H4A1,1 0 0,1 3,7V5M4,11V13H6V11H4M3,11A1,1 0 0,1 4,10H6A1,1 0 0,1 7,11V13A1,1 0 0,1 6,14H4A1,1 0 0,1 3,13V11M4,17V19H6V17H4M3,17A1,1 0 0,1 4,16H6A1,1 0 0,1 7,17V19A1,1 0 0,1 6,20H4A1,1 0 0,1 3,19V17Z" />
</graphic> </graphic>
</Tab> </Tab>
<Tab closable="false">
<content>
<fx:include fx:id="NetTab" source="NetTab.fxml" VBox.vgrow="ALWAYS" />
</content>
<graphic>
<SVGPath content="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" />
</graphic>
</Tab>
<Tab closable="false"> <Tab closable="false">
<content> <content>
<VBox prefHeight="200.0" prefWidth="100.0"> <VBox prefHeight="200.0" prefWidth="100.0">

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="150.0" minWidth="150.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NetTabController">
<children>
<VBox spacing="5.0">
<children>
<CheckBox fx:id="validateNSHostNameCb" mnemonicParsing="false" text="%netTabValidateNSHostNameCb">
<VBox.margin>
<Insets />
</VBox.margin>
</CheckBox>
<CheckBox fx:id="expertModeCb" mnemonicParsing="false" text="%netTabExpertModeCB" />
<Label fx:id="hostIpLbl" text="%netTabHostIPlbl" visible="false">
<VBox.margin>
<Insets left="10.0" />
</VBox.margin>
</Label>
<TextField fx:id="pcIpTextField" visible="false">
<VBox.margin>
<Insets left="10.0" />
</VBox.margin>
</TextField>
</children>
</VBox>
</children>
<padding>
<Insets bottom="2.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>

View file

@ -21,3 +21,11 @@ tableSizeLbl=Size
tableUploadLbl=Upload? tableUploadLbl=Upload?
contextMenuBtnDelete=Remove contextMenuBtnDelete=Remove
contextMenuBtnDeleteAll=Remove all contextMenuBtnDeleteAll=Remove all
netTabHostIPlbl=Host IP
NSIPlable=NS IP:
netTabValidateNSHostNameCb=Always validate NS IP input.
windowBodyBadIp=Are you sure that you entered NS IP address correctly?
windowTitleBadIp=IP address of NS most likely incorrect
netTabExpertModeCB=Expert mode (I have issues with NET isntallations).
windowTitleExpectModeIncomplete=Check your settings
windowBodyExpectModeIncomplete=You selected 'Expert Mode' in settings and have mistakes in parameters\nDouble check if settings valid.

View file

@ -20,4 +20,12 @@ tableFileNameLbl=Nom de fichier
tableStatusLbl=Statut tableStatusLbl=Statut
contextMenuBtnDelete=Supprimer contextMenuBtnDelete=Supprimer
contextMenuBtnDeleteAll=Supprimer tout contextMenuBtnDeleteAll=Supprimer tout
netTabHostIPlbl=IP de l'ordinateur <-FIX
NSIPlable=IP de NS:
netTabValidateNSHostNameCb=Always validate NS IP input. <-FIX
windowTitleBadIp=IP address of NS most likely incorrect <-FIX
windowBodyBadIp=Are you sure that you entered NS IP address correctly? <-FIX
netTabExpertModeCB=Expert mode (I have issues with NET isntallations). <- FIX
windowTitleExpectModeIncomplete=Check your settings <- FIX
windowBodyExpectModeIncomplete=You selected 'Expert Mode' in settings and have mistakes in parameters\nDouble check if settings valid. <- FIX

View file

@ -22,4 +22,12 @@ tableFileNameLbl=\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430
tableStatusLbl=\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 tableStatusLbl=\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435
contextMenuBtnDelete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C contextMenuBtnDelete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C
contextMenuBtnDeleteAll=\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u0441\u0451 contextMenuBtnDeleteAll=\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u0441\u0451
netTabHostIPlbl=IP \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430
NSIPlable=NS IP:
netTabValidateNSHostNameCb=\u0412\u0441\u0435\u0433\u0434\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C NS IP.
windowTitleBadIp=IP \u0430\u0434\u0440\u0435\u0441 NS \u043F\u043E\u0445\u043E\u0436\u0435 \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439
windowBodyBadIp=\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B \u0447\u0442\u043E IP \u0430\u0434\u0440\u0435\u0441 NS \u0432\u0432\u0435\u0434\u0451\u043D \u0431\u0435\u0437 \u043E\u0448\u0438\u0431\u043E\u043A?
netTabExpertModeCB=\u0420\u0435\u0436\u0438\u043C \u044D\u043A\u0441\u043F\u0435\u0440\u0442\u0430 (\u0423 \u043C\u0435\u043D\u044F \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B \u0441 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u043E\u0439 \u043F\u043E-\u0441\u0435\u0442\u0438).
windowTitleExpectModeIncomplete=\u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043A
windowBodyExpectModeIncomplete=\u0412\u044B \u0432\u044B\u0431\u0440\u0430\u043B\u0438 \u00AB\u0420\u0435\u0436\u0438\u043C \u044D\u043A\u0441\u043F\u0435\u0440\u0442\u0430\u00BB \u0432 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430\u0445 \u0438 \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043B\u0438 \u043E\u0448\u0438\u0431\u043A\u0438 \u0432 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u0445\n\u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0438\u0445 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C \u0435\u0449\u0451 \u0440\u0430\u0437.

View file

@ -20,4 +20,12 @@ tableFileNameLbl=\u0406\u043C'\u044F \u0444\u0430\u0439\u043B\u0443
tableSizeLbl=\u0420\u043E\u0437\u043C\u0456\u0440 tableSizeLbl=\u0420\u043E\u0437\u043C\u0456\u0440
tableUploadLbl=\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436.? tableUploadLbl=\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436.?
contextMenuBtnDelete=\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438 contextMenuBtnDelete=\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438
contextMenuBtnDeleteAll=\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u0432\u0441\u0435 contextMenuBtnDeleteAll=\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u0432\u0441\u0435
netTabHostIPlbl=IP \u043A\u043E\u043C\u043F'\u044E\u0442\u0435\u0440\u0443
NSIPlable=NS IP:
netTabValidateNSHostNameCb=\u0417\u0430\u0432\u0436\u0434\u0438 \u043F\u0435\u0440\u0435\u0432\u0456\u0440\u044F\u0442\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C NS IP.
windowTitleBadIp=IP \u0430\u0434\u0440\u0435\u0441\u0430 NS \u0441\u043A\u043E\u0440\u0456\u0448 \u0437\u0430 \u0432\u0441\u0435 \u043D\u0435\u0432\u0456\u0440\u043D\u0430
windowBodyBadIp=\u0412\u0438 \u0432\u043F\u0435\u0432\u043D\u0435\u043D\u0456 \u0449\u043E IP \u0430\u0434\u0440\u0435\u0441\u0430 NS \u0432\u0432\u0435\u0434\u0435\u043D\u0430 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E?
netTabExpertModeCB=\u0420\u0435\u0436\u0438\u043C \u0435\u043A\u0441\u043F\u0435\u0440\u0442\u0430 (\u0412 \u043C\u0435\u043D\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0438 \u0437 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F\u043C \u043F\u043E \u043C\u0435\u0440\u0435\u0436\u0456).
windowTitleExpectModeIncomplete=\u041F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u044C
windowBodyExpectModeIncomplete=\u0412\u0438 \u0432\u0438\u0431\u0440\u0430\u043B\u0438 "\u0420\u0435\u0436\u0438\u043C \u0454\u043A\u0441\u043F\u0435\u0440\u0442\u0430" \u0432 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F\u0445 \u0442\u0430 \u0437\u0440\u043E\u0431\u0438\u043B\u0438 \u043F\u043E\u043C\u0438\u043B\u043A\u0438 \u0432 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u0445\n\u041F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0457\u0445 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C \u0449\u0435 \u0440\u0430\u0437.

View file

@ -230,7 +230,19 @@
.context-menu .menu-item:focused .label { .context-menu .menu-item:focused .label {
-fx-text-fill: white; -fx-text-fill: white;
} }
// -========================== Text Field =====================-
.text-field {
-fx-border-color: #289de8;
-fx-border-width: 0 0 1 0;
-fx-background-color: transparent;
-fx-text-fill: white;
}
.text-field:focused {
-fx-border-color: #e82382;
-fx-border-width: 0 0 1 0;
-fx-background-color: transparent;
-fx-text-fill: #08f3ff;
}

View file

@ -231,7 +231,19 @@
.context-menu .menu-item:focused .label { .context-menu .menu-item:focused .label {
-fx-text-fill: white; -fx-text-fill: white;
} }
// -========================== Text Field =====================-
.text-field {
-fx-border-color: #289de8;
-fx-border-width: 0 0 1 0;
-fx-background-color: transparent;
-fx-text-fill: #2c2c2c;
}
.text-field:focused {
-fx-border-color: #e82382;
-fx-border-width: 0 0 1 0;
-fx-background-color: transparent;
-fx-text-fill: #e82382;
}