Intermediate results of net-install support implementation.

Front-end 80% ready. Backend 5% ready.
master
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 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.
@ -81,12 +81,14 @@ Français by [Stephane Meden (JackFromNice)](https://github.com/JackFromNice)
## TODO:
- [x] macOS QA v0.1 (Mojave)
- [x] macOS QA v0.2.2 (Mojave)
- [ ] macOS QA v0.3 (Mojave)
- [x] Windows support
- [x] code refactoring
- [x] GoldLeaf support
- [ ] XCI support
- [ ] File order sort (non-critical)
- [ ] More deep file analyze before uploading.
- [] Network mode support for TinFoil
## Thanks
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";
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 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 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 nsusbloader.AppPreferences;
import nsusbloader.MediatorControl;
import nsusbloader.NET.NETCommunications;
import nsusbloader.NSLMain;
import nsusbloader.ServiceWindow;
import nsusbloader.USB.UsbCommunications;
import java.io.File;
@ -35,7 +37,7 @@ public class NSLMainController implements Initializable {
@FXML
public ProgressBar progressBar; // Accessible from Mediator
@FXML
private ChoiceBox<String> choiceProtocol;
private ChoiceBox<String> choiceProtocol, choiceNetUsb;
@FXML
private Button switchThemeBtn;
@ -44,6 +46,12 @@ public class NSLMainController implements Initializable {
@FXML
public NSTableViewController tableFilesListController; // Accessible from Mediator
@FXML
private NetTabController NetTabController;
@FXML
private TextField nsIpTextField;
@FXML
private Label nsIpLbl;
private UsbCommunications usbCommunications;
private Thread usbThread;
@ -78,10 +86,46 @@ public class NSLMainController implements Initializable {
ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf");
choiceProtocol.setItems(choiceProtocolList);
choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol()); // TODO: shared settings
choiceProtocol.setOnAction(e->tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem())); // Add listener to notify tableView controller
choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol());
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
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;
Region btnSwitchImage = new Region();
@ -133,20 +177,42 @@ public class NSLMainController implements Initializable {
* It's button listener when no transmission executes
* */
private void uploadBtnAction(){
if (usbThread == null || !usbThread.isAlive()){
List<File> nspToUpload;
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");
if ((usbThread == null || !usbThread.isAlive())){
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf") ||
(
choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil")
&& choiceNetUsb.getSelectionModel().getSelectedItem().equals("USB")
)
){
List<File> nspToUpload;
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(){
AppPreferences.getInstance().setProtocol(choiceProtocol.getSelectionModel().getSelectedItem());
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.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
@ -30,6 +32,9 @@
<ToolBar>
<items>
<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" />
<Button fx:id="switchThemeBtn" mnemonicParsing="false" />
</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" />
</graphic>
</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">
<content>
<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?
contextMenuBtnDelete=Remove
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
contextMenuBtnDelete=Supprimer
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
contextMenuBtnDelete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C
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
tableUploadLbl=\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436.?
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 {
-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 {
-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;
}