collaborative mix aesthetic tweaks

This commit is contained in:
Craig Raw 2021-11-29 17:08:58 +02:00
parent 0956c96046
commit 4edd84f6e2
9 changed files with 100 additions and 87 deletions

View file

@ -54,10 +54,6 @@ public class PayNymAvatar extends StackPane {
this.paymentCodeProperty.set(paymentCode); this.paymentCodeProperty.set(paymentCode);
} }
public void setPayNymAvatarUri(String uri) {
setPaymentCode(new PaymentCode(uri.replace("/", "").replace("avatar", "")));
}
private class PayNymAvatarService extends Service<Image> { private class PayNymAvatarService extends Service<Image> {
private final PaymentCode paymentCode; private final PaymentCode paymentCode;
@ -77,7 +73,7 @@ public class PayNymAvatar extends StackPane {
try(InputStream is = (proxy == null ? new URL(url).openStream() : new URL(url).openConnection(proxy).getInputStream())) { try(InputStream is = (proxy == null ? new URL(url).openStream() : new URL(url).openConnection(proxy).getInputStream())) {
return new Image(is, getWidth(), getHeight(), true, false); return new Image(is, getWidth(), getHeight(), true, false);
} catch(Exception e) { } catch(Exception e) {
log.warn("Error loading PayNym avatar", e); log.debug("Error loading PayNym avatar", e);
throw e; throw e;
} }
} }

View file

@ -208,11 +208,11 @@ public class TransactionDiagram extends GridPane {
if(externalUserSet || addUserSet) { if(externalUserSet || addUserSet) {
boolean replace = !isFinal() && set > 0 && SorobanServices.canWalletMix(walletTx.getWallet()); boolean replace = !isFinal() && set > 0 && SorobanServices.canWalletMix(walletTx.getWallet());
Glyph bracketGlyph = !replace && walletTx.isCoinControlUsed() ? getLockGlyph() : (addUserSet ? getUserAddGlyph() : getCoinsGlyph(replace)); Glyph bracketGlyph = !replace && walletTx.isCoinControlUsed() ? getLockGlyph() : (addUserSet ? getUserAddGlyph() : getCoinsGlyph(replace));
String tooltipText = addUserSet ? "Click to add a mixing partner" : (walletTx.getWallet().getFullDisplayName() + (replace ? "\nClick to replace with a mixing partner" : "")); String tooltipText = addUserSet ? "Click to add a mix partner" : (walletTx.getWallet().getFullDisplayName() + (replace ? "\nClick to replace with a mix partner" : ""));
StackPane stackPane = getBracket(width, setHeight, bracketGlyph, tooltipText); StackPane stackPane = getBracket(width, setHeight, bracketGlyph, tooltipText);
allBrackets.getChildren().add(stackPane); allBrackets.getChildren().add(stackPane);
} else { } else {
StackPane stackPane = getBracket(width, setHeight, getUserGlyph(), "Mixing partner"); StackPane stackPane = getBracket(width, setHeight, getUserGlyph(), "Mix partner");
allBrackets.getChildren().add(stackPane); allBrackets.getChildren().add(stackPane);
} }
} }
@ -564,7 +564,7 @@ public class TransactionDiagram extends GridPane {
private Pane getTransactionPane() { private Pane getTransactionPane() {
VBox txPane = new VBox(); VBox txPane = new VBox();
txPane.setPadding(new Insets(0, 10, 0, 10)); txPane.setPadding(new Insets(0, 8, 0, 8));
txPane.setAlignment(Pos.CENTER); txPane.setAlignment(Pos.CENTER);
txPane.getChildren().add(createSpacer()); txPane.getChildren().add(createSpacer());
@ -897,7 +897,7 @@ public class TransactionDiagram extends GridPane {
@Override @Override
public String getLabel() { public String getLabel() {
return "Add Mixing Partner?"; return "Add Mix Partner?";
} }
} }

View file

@ -79,6 +79,9 @@ public class CounterpartyController extends SorobanController {
@FXML @FXML
private Label mixingPartner; private Label mixingPartner;
@FXML
private PayNymAvatar mixPartnerAvatar;
@FXML @FXML
private Label meetingFail; private Label meetingFail;
@ -156,8 +159,6 @@ public class CounterpartyController extends SorobanController {
payNym.managedProperty().bind(payNym.visibleProperty()); payNym.managedProperty().bind(payNym.visibleProperty());
payNymAvatar.managedProperty().bind(payNymAvatar.visibleProperty()); payNymAvatar.managedProperty().bind(payNymAvatar.visibleProperty());
payNymAvatar.visibleProperty().bind(payNym.visibleProperty()); payNymAvatar.visibleProperty().bind(payNym.visibleProperty());
payNymAvatar.prefWidthProperty().bind(payNym.heightProperty());
payNymAvatar.prefHeightProperty().bind(payNym.heightProperty());
payNymButton.managedProperty().bind(payNymButton.visibleProperty()); payNymButton.managedProperty().bind(payNymButton.visibleProperty());
payNymButton.visibleProperty().bind(payNym.visibleProperty().not()); payNymButton.visibleProperty().bind(payNym.visibleProperty().not());
if(Config.get().isUsePayNym()) { if(Config.get().isUsePayNym()) {
@ -242,12 +243,8 @@ public class CounterpartyController extends SorobanController {
private void updateMixPartner(Soroban soroban, PaymentCode paymentCodeInitiator, CahootsType cahootsType) { private void updateMixPartner(Soroban soroban, PaymentCode paymentCodeInitiator, CahootsType cahootsType) {
String code = paymentCodeInitiator.toString(); String code = paymentCodeInitiator.toString();
mixingPartner.setText(code.substring(0, 12) + "..." + code.substring(code.length() - 5)); mixingPartner.setText(code.substring(0, 12) + "..." + code.substring(code.length() - 5));
PayNymAvatar payNymAvatar = new PayNymAvatar();
payNymAvatar.setPrefHeight(mixingPartner.getHeight());
payNymAvatar.setPrefWidth(mixingPartner.getHeight());
payNymAvatar.setPaymentCode(paymentCodeInitiator);
mixingPartner.setGraphic(payNymAvatar);
if(Config.get().isUsePayNym()) { if(Config.get().isUsePayNym()) {
mixPartnerAvatar.setPaymentCode(paymentCodeInitiator);
soroban.getPayNym(paymentCodeInitiator.toString()).subscribe(payNym -> { soroban.getPayNym(paymentCodeInitiator.toString()).subscribe(payNym -> {
mixingPartner.setText(payNym.nymName()); mixingPartner.setText(payNym.nymName());
}, error -> { }, error -> {

View file

@ -148,8 +148,6 @@ public class InitiatorController extends SorobanController {
}); });
payNymAvatar.managedProperty().bind(payNymAvatar.visibleProperty()); payNymAvatar.managedProperty().bind(payNymAvatar.visibleProperty());
payNymAvatar.prefWidthProperty().bind(counterparty.heightProperty());
payNymAvatar.prefHeightProperty().bind(counterparty.heightProperty());
payNymFollowers.prefWidthProperty().bind(counterparty.widthProperty()); payNymFollowers.prefWidthProperty().bind(counterparty.widthProperty());
payNymFollowers.valueProperty().addListener((observable, oldValue, payNym) -> { payNymFollowers.valueProperty().addListener((observable, oldValue, payNym) -> {
if(payNym == FIND_FOLLOWERS) { if(payNym == FIND_FOLLOWERS) {
@ -236,7 +234,12 @@ public class InitiatorController extends SorobanController {
soroban.getFollowers().subscribe(followerPayNyms -> { soroban.getFollowers().subscribe(followerPayNyms -> {
payNymFollowers.setItems(FXCollections.observableList(followerPayNyms)); payNymFollowers.setItems(FXCollections.observableList(followerPayNyms));
}, error -> { }, error -> {
if(error.getMessage().endsWith("404")) {
Config.get().setUsePayNym(false);
AppServices.showErrorDialog("Could not retrieve PayNym", "This wallet does not have an associated PayNym or any followers. You can retrieve the PayNym using the Tools menu → Find Mix Partner.");
} else {
log.warn("Could not retrieve followers: ", error); log.warn("Could not retrieve followers: ", error);
}
}); });
} }
} }
@ -302,17 +305,17 @@ public class InitiatorController extends SorobanController {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(JavaFxScheduler.platform()) .observeOn(JavaFxScheduler.platform())
.subscribe(meetingRequest -> { .subscribe(meetingRequest -> {
sorobanProgressLabel.setText("Waiting for mixing partner..."); sorobanProgressLabel.setText("Waiting for mix partner...");
sorobanMeetingService.receiveMeetingResponse(paymentCodeCounterparty, meetingRequest, TIMEOUT_MS) sorobanMeetingService.receiveMeetingResponse(paymentCodeCounterparty, meetingRequest, TIMEOUT_MS)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(JavaFxScheduler.platform()) .observeOn(JavaFxScheduler.platform())
.subscribe(sorobanResponse -> { .subscribe(sorobanResponse -> {
if(sorobanResponse.isAccept()) { if(sorobanResponse.isAccept()) {
sorobanProgressBar.setProgress(0.1); sorobanProgressBar.setProgress(0.1);
sorobanProgressLabel.setText("Mixing partner accepted!"); sorobanProgressLabel.setText("Mix partner accepted!");
startInitiatorCollaborative(initiatorCahootsWallet, paymentCodeCounterparty); startInitiatorCollaborative(initiatorCahootsWallet, paymentCodeCounterparty);
} else { } else {
step2Desc.setText("Mixing partner declined."); step2Desc.setText("Mix partner declined.");
sorobanProgressLabel.setVisible(false); sorobanProgressLabel.setVisible(false);
} }
}, error -> { }, error -> {
@ -364,7 +367,7 @@ public class InitiatorController extends SorobanController {
if(accepted) { if(accepted) {
interaction.sorobanAccept(); interaction.sorobanAccept();
} else { } else {
interaction.sorobanReject("Mixing partner declined to broadcast the transaction."); interaction.sorobanReject("Mix partner declined to broadcast the transaction.");
} }
}); });

View file

@ -123,7 +123,7 @@ public class PayNymService {
public Observable<PayNym> getPayNym(String nymIdentifier) { public Observable<PayNym> getPayNym(String nymIdentifier) {
return fetchPayNym(nymIdentifier).map(nymMap -> { return fetchPayNym(nymIdentifier).map(nymMap -> {
List<Map<String, Object>> codes = (List<Map<String, Object>>)nymMap.get("codes"); List<Map<String, Object>> codes = (List<Map<String, Object>>)nymMap.get("codes");
PaymentCode code = new PaymentCode((String)codes.get(0).get("code")); PaymentCode code = new PaymentCode((String)codes.stream().filter(codeMap -> codeMap.get("segwit") == Boolean.FALSE).map(codeMap -> codeMap.get("code")).findFirst().orElse(codes.get(0).get("code")));
return new PayNym(code, (String)nymMap.get("nymID"), (String)nymMap.get("nymName"), (Boolean)nymMap.get("segwit")); return new PayNym(code, (String)nymMap.get("nymID"), (String)nymMap.get("nymName"), (Boolean)nymMap.get("segwit"));
}); });
} }

View file

@ -1435,9 +1435,9 @@ public class SendController extends WalletFormController implements Initializabl
} }
if(!SorobanServices.canWalletMix(getWalletForm().getWallet())) { if(!SorobanServices.canWalletMix(getWalletForm().getWallet())) {
addLabel("Can only add mixing partner to Native Segwit software wallets", getInfoGlyph()); addLabel("Can only add mix partner to Native Segwit software wallets", getInfoGlyph());
} else { } else {
addLabel("Add a mixing partner to create a two person coinjoin", getInfoGlyph()); addLabel("Add a mix partner to create a two person coinjoin", getInfoGlyph());
} }
} }
} }

View file

@ -109,7 +109,7 @@
<Menu fx:id="toolsMenu" mnemonicParsing="false" text="Tools"> <Menu fx:id="toolsMenu" mnemonicParsing="false" text="Tools">
<MenuItem mnemonicParsing="false" text="Sign/Verify Message" accelerator="Shortcut+M" onAction="#signVerifyMessage"/> <MenuItem mnemonicParsing="false" text="Sign/Verify Message" accelerator="Shortcut+M" onAction="#signVerifyMessage"/>
<MenuItem fx:id="sendToMany" mnemonicParsing="false" text="Send To Many" onAction="#sendToMany"/> <MenuItem fx:id="sendToMany" mnemonicParsing="false" text="Send To Many" onAction="#sendToMany"/>
<MenuItem fx:id="findMixingPartner" mnemonicParsing="false" text="Find Mixing Partner" onAction="#findMixingPartner"/> <MenuItem fx:id="findMixingPartner" mnemonicParsing="false" text="Find Mix Partner" onAction="#findMixingPartner"/>
<MenuItem styleClass="osxHide,windowsHide" mnemonicParsing="false" text="Install Udev Rules" onAction="#installUdevRules"/> <MenuItem styleClass="osxHide,windowsHide" mnemonicParsing="false" text="Install Udev Rules" onAction="#installUdevRules"/>
<SeparatorMenuItem /> <SeparatorMenuItem />
<CheckMenuItem fx:id="preventSleep" mnemonicParsing="false" text="Prevent Computer Sleep" onAction="#preventSleep"/> <CheckMenuItem fx:id="preventSleep" mnemonicParsing="false" text="Prevent Computer Sleep" onAction="#preventSleep"/>

View file

@ -19,7 +19,7 @@
<VBox spacing="20"> <VBox spacing="20">
<HBox styleClass="title-area"> <HBox styleClass="title-area">
<HBox alignment="CENTER_LEFT"> <HBox alignment="CENTER_LEFT">
<Label fx:id="title" text="Find Mixing Partner" styleClass="title-label" /> <Label fx:id="title" text="Find Mix Partner" styleClass="title-label" />
</HBox> </HBox>
<Region HBox.hgrow="ALWAYS"/> <Region HBox.hgrow="ALWAYS"/>
<ImageView AnchorPane.rightAnchor="0"> <ImageView AnchorPane.rightAnchor="0">
@ -33,16 +33,15 @@
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="RANDOM" styleClass="title-icon" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="RANDOM" styleClass="title-icon" />
</graphic> </graphic>
</Label> </Label>
<Label text="Perform a two person coinjoin transaction using the Samourai Soroban service. Your mixing partner will start the mix, and will need either your PayNym or the Payment code shown below. Click Next once they have indicated they are ready." wrapText="true" styleClass="content-text" /> <Label text="Perform a two person coinjoin transaction using the Samourai Soroban service. Your mix partner will start the mix, and will need either your PayNym or the Payment code shown below. Click Next once they have indicated they are ready." wrapText="true" styleClass="content-text" />
<HBox styleClass="field-box"> <HBox>
<padding> <padding>
<Insets top="20" /> <Insets top="20" />
</padding> </padding>
<VBox spacing="15">
<HBox styleClass="field-box">
<Label text="PayNym:" styleClass="field-label" /> <Label text="PayNym:" styleClass="field-label" />
<HBox spacing="11">
<CopyableTextField fx:id="payNym" promptText="Retrieving..." styleClass="field-control" editable="false"/> <CopyableTextField fx:id="payNym" promptText="Retrieving..." styleClass="field-control" editable="false"/>
<PayNymAvatar fx:id="payNymAvatar" />
</HBox>
<Button fx:id="payNymButton" text="Retrieve PayNym" onAction="#retrievePayNym" /> <Button fx:id="payNymButton" text="Retrieve PayNym" onAction="#retrievePayNym" />
</HBox> </HBox>
<HBox styleClass="field-box"> <HBox styleClass="field-box">
@ -64,6 +63,11 @@
<ComboBox fx:id="mixWallet" /> <ComboBox fx:id="mixWallet" />
</HBox> </HBox>
</VBox> </VBox>
<AnchorPane>
<PayNymAvatar AnchorPane.leftAnchor="100" fx:id="payNymAvatar" prefWidth="150" prefHeight="150" />
</AnchorPane>
</HBox>
</VBox>
<VBox fx:id="step2" spacing="15"> <VBox fx:id="step2" spacing="15">
<HBox> <HBox>
<Label text="Review Mix Type" styleClass="title-text"> <Label text="Review Mix Type" styleClass="title-text">
@ -74,20 +78,22 @@
<Region HBox.hgrow="ALWAYS" /> <Region HBox.hgrow="ALWAYS" />
<ProgressTimer fx:id="step2Timer" seconds="60" /> <ProgressTimer fx:id="step2Timer" seconds="60" />
</HBox> </HBox>
<Label fx:id="step2Desc" text="Your mixing partner will now initiate the Soroban communication. Once communication is established, check the details of the mix and click Next if you'd like to proceed." wrapText="true" styleClass="content-text" /> <Label fx:id="step2Desc" text="Your mix partner will now initiate the Soroban communication. Once communication is established, check the details of the mix and click Next if you'd like to proceed." wrapText="true" styleClass="content-text" />
<HBox styleClass="field-box"> <HBox>
<padding> <padding>
<Insets top="20" /> <Insets top="20" />
</padding> </padding>
<Label text="Mixing partner:" styleClass="field-label" /> <VBox spacing="10">
<Label fx:id="mixingPartner" text="Waiting for mixing partner..." graphicTextGap="10" contentDisplay="RIGHT" /> <HBox styleClass="field-box">
<Label fx:id="meetingFail" text="Failed to find mixing partner." styleClass="failure" graphicTextGap="5"> <Label text="Mix partner:" styleClass="field-label" />
<Label fx:id="mixingPartner" text="Waiting for mix partner..." graphicTextGap="10" contentDisplay="RIGHT" />
<Label fx:id="meetingFail" text="Failed to find mix partner." styleClass="failure" graphicTextGap="5">
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="EXCLAMATION_CIRCLE" styleClass="failure" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="EXCLAMATION_CIRCLE" styleClass="failure" />
</graphic> </graphic>
</Label> </Label>
</HBox> </HBox>
<VBox fx:id="mixDetails" spacing="7"> <VBox fx:id="mixDetails" spacing="10">
<HBox styleClass="field-box"> <HBox styleClass="field-box">
<Label text="Type:" styleClass="field-label" /> <Label text="Type:" styleClass="field-label" />
<Label fx:id="mixType" /> <Label fx:id="mixType" />
@ -98,6 +104,11 @@
</HBox> </HBox>
</VBox> </VBox>
</VBox> </VBox>
<AnchorPane>
<PayNymAvatar AnchorPane.leftAnchor="100" fx:id="mixPartnerAvatar" prefWidth="150" prefHeight="150" />
</AnchorPane>
</HBox>
</VBox>
<VBox fx:id="step3" spacing="15"> <VBox fx:id="step3" spacing="15">
<HBox> <HBox>
<Label text="Perform Mix" styleClass="title-text"> <Label text="Perform Mix" styleClass="title-text">
@ -116,7 +127,7 @@
<ProgressBar fx:id="sorobanProgressBar" prefWidth="680" /> <ProgressBar fx:id="sorobanProgressBar" prefWidth="680" />
</HBox> </HBox>
<VBox alignment="CENTER"> <VBox alignment="CENTER">
<Label fx:id="sorobanProgressLabel" text="Waiting for mixing partner..." styleClass="content-text" alignment="CENTER"/> <Label fx:id="sorobanProgressLabel" text="Waiting for mix partner..." styleClass="content-text" alignment="CENTER"/>
<Glyph fx:id="mixDeclined" fontFamily="Font Awesome 5 Free Solid" fontSize="80" icon="USER_SLASH" /> <Glyph fx:id="mixDeclined" fontFamily="Font Awesome 5 Free Solid" fontSize="80" icon="USER_SLASH" />
</VBox> </VBox>
</VBox> </VBox>

View file

@ -19,7 +19,7 @@
<VBox spacing="20"> <VBox spacing="20">
<HBox styleClass="title-area"> <HBox styleClass="title-area">
<HBox alignment="CENTER_LEFT"> <HBox alignment="CENTER_LEFT">
<Label fx:id="title" text="Add Mixing Partner" styleClass="title-label" /> <Label fx:id="title" text="Add Mix Partner" styleClass="title-label" />
</HBox> </HBox>
<Region HBox.hgrow="ALWAYS"/> <Region HBox.hgrow="ALWAYS"/>
<ImageView AnchorPane.rightAnchor="0"> <ImageView AnchorPane.rightAnchor="0">
@ -33,21 +33,27 @@
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="RANDOM" styleClass="title-icon" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="RANDOM" styleClass="title-icon" />
</graphic> </graphic>
</Label> </Label>
<Label text="Add a mixing partner to your two person coinjoin transaction using the Samourai Soroban service. Ask your partner for their PayNym, or use their payment code found in their Sparrow Tools menu → Find Mixing Partner." wrapText="true" styleClass="content-text" /> <Label text="Add a mix partner to your two person coinjoin transaction using the Samourai Soroban service. Ask your partner for their PayNym, or use their payment code found in their Sparrow Tools menu → Find Mix Partner." wrapText="true" styleClass="content-text" />
<HBox styleClass="field-box"> <HBox>
<padding> <padding>
<Insets top="20" /> <Insets top="20" />
</padding> </padding>
<VBox spacing="15">
<HBox styleClass="field-box">
<Label text="Payment code or PayNym:" styleClass="field-label" /> <Label text="Payment code or PayNym:" styleClass="field-label" />
<HBox spacing="10"> <HBox spacing="10">
<StackPane> <StackPane>
<ComboBox fx:id="payNymFollowers" /> <ComboBox fx:id="payNymFollowers" />
<ComboBoxTextField fx:id="counterparty" styleClass="field-control" comboProperty="$payNymFollowers" /> <ComboBoxTextField fx:id="counterparty" styleClass="field-control" comboProperty="$payNymFollowers" />
</StackPane> </StackPane>
<PayNymAvatar fx:id="payNymAvatar" />
</HBox> </HBox>
</HBox> </HBox>
</VBox> </VBox>
<AnchorPane>
<PayNymAvatar fx:id="payNymAvatar" AnchorPane.leftAnchor="80" prefWidth="150" prefHeight="150"/>
</AnchorPane>
</HBox>
</VBox>
<VBox fx:id="step2" spacing="15"> <VBox fx:id="step2" spacing="15">
<HBox> <HBox>
<Label text="Request Mix" styleClass="title-text"> <Label text="Request Mix" styleClass="title-text">
@ -58,7 +64,7 @@
<Region HBox.hgrow="ALWAYS" /> <Region HBox.hgrow="ALWAYS" />
<ProgressTimer fx:id="step2Timer" seconds="60" /> <ProgressTimer fx:id="step2Timer" seconds="60" />
</HBox> </HBox>
<Label fx:id="step2Desc" text="Ask your mixing partner to select Find Mixing Partner in the Sparrow Tools menu or Receive Online Cahoots in the Samourai Receive menu." wrapText="true" styleClass="content-text" /> <Label fx:id="step2Desc" text="Ask your mix partner to select Find Mix Partner in the Sparrow Tools menu or Receive Online Cahoots in the Samourai Receive menu." wrapText="true" styleClass="content-text" />
<HBox> <HBox>
<padding> <padding>
<Insets top="20" /> <Insets top="20" />
@ -66,7 +72,7 @@
<ProgressBar fx:id="sorobanProgressBar" prefWidth="680" /> <ProgressBar fx:id="sorobanProgressBar" prefWidth="680" />
</HBox> </HBox>
<VBox alignment="CENTER"> <VBox alignment="CENTER">
<Label fx:id="sorobanProgressLabel" text="Waiting for mixing partner..." styleClass="content-text" alignment="CENTER"/> <Label fx:id="sorobanProgressLabel" text="Waiting for mix partner..." styleClass="content-text" alignment="CENTER"/>
<Glyph fx:id="mixDeclined" fontFamily="Font Awesome 5 Free Solid" fontSize="80" icon="USER_SLASH" /> <Glyph fx:id="mixDeclined" fontFamily="Font Awesome 5 Free Solid" fontSize="80" icon="USER_SLASH" />
</VBox> </VBox>
</VBox> </VBox>