mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
autosuggest possible words for the last word in a bip39 seed
This commit is contained in:
parent
98b33e184e
commit
fd2b383dbc
2 changed files with 48 additions and 8 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit 7eab644cecc71e591ba805cff1a408b9f31a9303
|
Subproject commit fe19c86544d75d0ce0d8c32b0cbbd44de64ae463
|
|
@ -21,7 +21,6 @@ import javafx.scene.input.Clipboard;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import javafx.util.Callback;
|
import javafx.util.Callback;
|
||||||
import org.controlsfx.control.textfield.AutoCompletionBinding;
|
import org.controlsfx.control.textfield.AutoCompletionBinding;
|
||||||
import org.controlsfx.control.textfield.CustomTextField;
|
|
||||||
import org.controlsfx.control.textfield.TextFields;
|
import org.controlsfx.control.textfield.TextFields;
|
||||||
import org.controlsfx.glyphfont.Glyph;
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
import org.controlsfx.validation.ValidationResult;
|
import org.controlsfx.validation.ValidationResult;
|
||||||
|
@ -250,10 +249,15 @@ public class MnemonicKeystorePane extends TitledDescriptionPane {
|
||||||
if(clipboard.hasString() && clipboard.getString().matches("(?m).+[\\n\\s][\\S\\s]*")) {
|
if(clipboard.hasString() && clipboard.getString().matches("(?m).+[\\n\\s][\\S\\s]*")) {
|
||||||
String[] words = clipboard.getString().split("[\\n\\s]");
|
String[] words = clipboard.getString().split("[\\n\\s]");
|
||||||
WordEntry entry = WordEntry.this;
|
WordEntry entry = WordEntry.this;
|
||||||
for(String word : words) {
|
for(int i = 0; i < words.length; i++) {
|
||||||
|
String word = words[i];
|
||||||
if(entry.nextField != null) {
|
if(entry.nextField != null) {
|
||||||
|
if(i == words.length - 2 && isValid(word)) {
|
||||||
|
label.requestFocus();
|
||||||
|
} else {
|
||||||
entry.nextField.requestFocus();
|
entry.nextField.requestFocus();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
entry.wordField.setText(word);
|
entry.wordField.setText(word);
|
||||||
entry = entry.nextEntry;
|
entry = entry.nextEntry;
|
||||||
|
@ -282,7 +286,7 @@ public class MnemonicKeystorePane extends TitledDescriptionPane {
|
||||||
wordField.setTextFormatter(formatter);
|
wordField.setTextFormatter(formatter);
|
||||||
|
|
||||||
wordList = Bip39MnemonicCode.INSTANCE.getWordList();
|
wordList = Bip39MnemonicCode.INSTANCE.getWordList();
|
||||||
AutoCompletionBinding<String> autoCompletionBinding = TextFields.bindAutoCompletion(wordField, new WordlistSuggestionProvider(wordList));
|
AutoCompletionBinding<String> autoCompletionBinding = TextFields.bindAutoCompletion(wordField, new WordlistSuggestionProvider(wordList, wordNumber, wordEntryList));
|
||||||
autoCompletionBinding.setDelay(50);
|
autoCompletionBinding.setDelay(50);
|
||||||
autoCompletionBinding.setOnAutoCompleted(event -> {
|
autoCompletionBinding.setOnAutoCompleted(event -> {
|
||||||
if(nextField != null) {
|
if(nextField != null) {
|
||||||
|
@ -290,11 +294,20 @@ public class MnemonicKeystorePane extends TitledDescriptionPane {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Show autocomplete for the last word on focus if empty
|
||||||
|
boolean lastWord = wordNumber == wordEntryList.size() - 1;
|
||||||
|
if(lastWord) {
|
||||||
|
wordField.focusedProperty().addListener((observable, oldValue, focused) -> {
|
||||||
|
if(focused && wordField.getText().isEmpty()) {
|
||||||
|
autoCompletionBinding.setUserInput("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ValidationSupport validationSupport = new ValidationSupport();
|
ValidationSupport validationSupport = new ValidationSupport();
|
||||||
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
|
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
|
||||||
validationSupport.registerValidator(wordField, Validator.combine(
|
validationSupport.registerValidator(wordField, Validator.combine(
|
||||||
Validator.createEmptyValidator("Word is required"),
|
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Invalid word", (newValue.length() > 0 || !lastWord) && !wordList.contains(newValue))
|
||||||
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Invalid word", !wordList.contains(newValue))
|
|
||||||
));
|
));
|
||||||
|
|
||||||
wordField.textProperty().addListener((observable, oldValue, newValue) -> {
|
wordField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
@ -323,13 +336,30 @@ public class MnemonicKeystorePane extends TitledDescriptionPane {
|
||||||
|
|
||||||
protected static class WordlistSuggestionProvider implements Callback<AutoCompletionBinding.ISuggestionRequest, Collection<String>> {
|
protected static class WordlistSuggestionProvider implements Callback<AutoCompletionBinding.ISuggestionRequest, Collection<String>> {
|
||||||
private final List<String> wordList;
|
private final List<String> wordList;
|
||||||
|
private final int wordNumber;
|
||||||
|
private final ObservableList<String> wordEntryList;
|
||||||
|
|
||||||
public WordlistSuggestionProvider(List<String> wordList) {
|
public WordlistSuggestionProvider(List<String> wordList, int wordNumber, ObservableList<String> wordEntryList) {
|
||||||
this.wordList = wordList;
|
this.wordList = wordList;
|
||||||
|
this.wordNumber = wordNumber;
|
||||||
|
this.wordEntryList = wordEntryList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> call(AutoCompletionBinding.ISuggestionRequest request) {
|
public Collection<String> call(AutoCompletionBinding.ISuggestionRequest request) {
|
||||||
|
if(wordNumber == wordEntryList.size() - 1 && allPreviousWordsValid()) {
|
||||||
|
try {
|
||||||
|
List<String> possibleLastWords = Bip39MnemonicCode.INSTANCE.getPossibleLastWords(wordEntryList.subList(0, wordEntryList.size() - 1));
|
||||||
|
if(!request.getUserText().isEmpty()) {
|
||||||
|
possibleLastWords.removeIf(s -> !s.startsWith(request.getUserText()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return possibleLastWords;
|
||||||
|
} catch(Exception e) {
|
||||||
|
log.warn("Cannot determine possible last words", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<String> suggestions = new ArrayList<>();
|
List<String> suggestions = new ArrayList<>();
|
||||||
if(!request.getUserText().isEmpty()) {
|
if(!request.getUserText().isEmpty()) {
|
||||||
for(String word : wordList) {
|
for(String word : wordList) {
|
||||||
|
@ -341,6 +371,16 @@ public class MnemonicKeystorePane extends TitledDescriptionPane {
|
||||||
|
|
||||||
return suggestions;
|
return suggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean allPreviousWordsValid() {
|
||||||
|
for(int i = 0; i < wordEntryList.size() - 1; i++) {
|
||||||
|
if(!WordEntry.isValid(wordEntryList.get(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class PassphraseEntry extends HBox {
|
protected class PassphraseEntry extends HBox {
|
||||||
|
|
Loading…
Reference in a new issue