2
0

Access login names by holding shift.

This commit is contained in:
Maarten Billemont 2018-09-13 15:49:58 -04:00
parent d8a735e1b1
commit ec9c55ec4d
3 changed files with 88 additions and 56 deletions

View File

@ -73,15 +73,6 @@ public abstract class Res {
return job( job, 0, TimeUnit.MILLISECONDS ); return job( job, 0, TimeUnit.MILLISECONDS );
} }
public static <V> void job(final Callable<V> job, final Consumer<V> callback) {
Futures.addCallback( job( job, 0, TimeUnit.MILLISECONDS ), new FailableCallback<V>( logger ) {
@Override
public void onSuccess(@Nullable final V result) {
callback.accept( result );
}
}, uiExecutor() );
}
public static <V> ListenableFuture<V> job(final Callable<V> job, final long delay, final TimeUnit timeUnit) { public static <V> ListenableFuture<V> job(final Callable<V> job, final long delay, final TimeUnit timeUnit) {
return jobExecutor.schedule( job, delay, timeUnit ); return jobExecutor.schedule( job, delay, timeUnit );
} }
@ -90,6 +81,15 @@ public abstract class Res {
ui( true, job ); ui( true, job );
} }
public static <V> void ui(final ListenableFuture<V> future, final Consumer<V> job) {
Futures.addCallback( future, new FailableCallback<V>( logger ) {
@Override
public void onSuccess(@Nullable final V result) {
job.accept( result );
}
}, uiExecutor() );
}
public static void ui(final boolean immediate, final Runnable job) { public static void ui(final boolean immediate, final Runnable job) {
uiExecutor( immediate ).execute( job ); uiExecutor( immediate ).execute( job );
} }

View File

@ -5,6 +5,7 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
import com.google.common.base.*; import com.google.common.base.*;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.primitives.UnsignedInteger; import com.google.common.primitives.UnsignedInteger;
import com.google.common.util.concurrent.ListenableFuture;
import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.ObjectUtils; import com.lyndir.lhunath.opal.system.util.ObjectUtils;
import com.lyndir.masterpassword.*; import com.lyndir.masterpassword.*;
@ -27,7 +28,6 @@ import java.util.*;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.swing.*; import javax.swing.*;
@ -460,7 +460,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
} }
private final class AuthenticatedUserPanel extends JPanel implements KeyListener, MPUser.Listener { private final class AuthenticatedUserPanel extends JPanel implements KeyListener, MPUser.Listener, KeyEventDispatcher {
private final JButton userButton = Components.button( Res.icons().user(), event -> showUserPreferences(), private final JButton userButton = Components.button( Res.icons().user(), event -> showUserPreferences(),
"Show user preferences." ); "Show user preferences." );
@ -479,8 +479,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
@Nonnull @Nonnull
private final MPUser<?> user; private final MPUser<?> user;
private final JLabel passwordLabel; private final JLabel resultLabel;
private final JLabel passwordField; private final JLabel resultField;
private final JLabel answerLabel; private final JLabel answerLabel;
private final JLabel answerField; private final JLabel answerField;
private final JLabel queryLabel; private final JLabel queryLabel;
@ -489,6 +489,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
private final CollectionListModel<MPQuery.Result<? extends MPQuestion>> questionsModel; private final CollectionListModel<MPQuery.Result<? extends MPQuestion>> questionsModel;
private final JList<MPQuery.Result<? extends MPSite<?>>> sitesList; private final JList<MPQuery.Result<? extends MPSite<?>>> sitesList;
private boolean showLogin;
private Future<?> updateSitesJob; private Future<?> updateSitesJob;
private AuthenticatedUserPanel(@Nonnull final MPUser<?> user) { private AuthenticatedUserPanel(@Nonnull final MPUser<?> user) {
@ -521,10 +522,10 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
add( Components.heading( user.getFullName(), SwingConstants.CENTER ) ); add( Components.heading( user.getFullName(), SwingConstants.CENTER ) );
add( passwordLabel = Components.label( SwingConstants.CENTER ) ); add( resultLabel = Components.label( SwingConstants.CENTER ) );
add( passwordField = Components.heading( SwingConstants.CENTER ) ); add( resultField = Components.heading( SwingConstants.CENTER ) );
passwordField.setForeground( Res.colors().highlightFg() ); resultField.setForeground( Res.colors().highlightFg() );
passwordField.setFont( Res.fonts().bigValueFont( SIZE_RESULT ) ); resultField.setFont( Res.fonts().bigValueFont( SIZE_RESULT ) );
add( Box.createGlue() ); add( Box.createGlue() );
add( Components.strut() ); add( Components.strut() );
@ -550,10 +551,15 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
KeyEvent.getKeyText( copyLoginKeyStroke.getKeyCode() ) ) ) ); KeyEvent.getKeyText( copyLoginKeyStroke.getKeyCode() ) ) ) );
addHierarchyListener( e -> { addHierarchyListener( e -> {
if (null != SwingUtilities.windowForComponent( this )) if (HierarchyEvent.DISPLAYABILITY_CHANGED == (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED)) {
user.addListener( this ); if (null != SwingUtilities.windowForComponent( this )) {
else KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher( this );
user.removeListener( this ); user.addListener( this );
} else {
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher( this );
user.removeListener( this );
}
}
} ); } );
} }
@ -841,7 +847,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
boolean loginResult = (copyLoginKeyStroke.getModifiers() & event.getModifiers()) != 0; boolean loginResult = (copyLoginKeyStroke.getModifiers() & event.getModifiers()) != 0;
MPSite<?> fsite = site; MPSite<?> fsite = site;
showSiteResult( site, loginResult, result -> { Res.ui( getSiteResult( site, loginResult ), result -> {
if (result == null) if (result == null)
return; return;
@ -852,14 +858,33 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
} ); } );
} }
private void setShowLogin(final boolean showLogin) {
if (showLogin == this.showLogin)
return;
this.showLogin = showLogin;
showSiteItem( sitesModel.getSelectedItem() );
}
private void showSiteItem(@Nullable final MPQuery.Result<? extends MPSite<?>> item) { private void showSiteItem(@Nullable final MPQuery.Result<? extends MPSite<?>> item) {
MPSite<?> site = (item != null)? item.getOption(): null; MPSite<?> site = (item != null)? item.getOption(): null;
showSiteResult( site, false, result -> { Res.ui( getSiteResult( site, showLogin ), result -> {
if (!showLogin && (site != null))
resultLabel.setText( (result != null)? strf( "Your password for %s:", site.getSiteName() ): " " );
else if (showLogin && (site != null))
resultLabel.setText( (result != null)? strf( "Your login for %s:", site.getSiteName() ): " " );
resultField.setText( (result != null)? result: " " );
settingsButton.setEnabled( result != null );
questionsButton.setEnabled( result != null );
editButton.setEnabled( result != null );
keyButton.setEnabled( result != null );
deleteButton.setEnabled( result != null );
} ); } );
} }
private void showSiteResult(@Nullable final MPSite<?> site, final boolean loginResult, final Consumer<String> resultCallback) { private ListenableFuture<String> getSiteResult(@Nullable final MPSite<?> site, final boolean loginResult) {
Res.job( () -> { return Res.job( () -> {
try { try {
if (site != null) if (site != null)
return loginResult? site.getLogin(): site.getResult(); return loginResult? site.getLogin(): site.getResult();
@ -869,18 +894,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
} }
return null; return null;
}, resultCallback.andThen( result -> Res.ui( () -> { } );
if (!loginResult && (site != null)) {
passwordLabel.setText( (result != null)? strf( "Your password for %s:", site.getSiteName() ): " " );
passwordField.setText( (result != null)? result: " " );
}
settingsButton.setEnabled( result != null );
questionsButton.setEnabled( result != null );
editButton.setEnabled( result != null );
keyButton.setEnabled( result != null );
deleteButton.setEnabled( result != null );
} ) ) );
} }
private void useQuestion(final ActionEvent event) { private void useQuestion(final ActionEvent event) {
@ -897,7 +911,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
} }
MPQuestion fquestion = question; MPQuestion fquestion = question;
showQuestionResult( question, result -> { Res.ui( getQuestionResult( question ), result -> {
if (result == null) if (result == null)
return; return;
@ -910,22 +924,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
private void showQuestionItem(@Nullable final MPQuery.Result<? extends MPQuestion> item) { private void showQuestionItem(@Nullable final MPQuery.Result<? extends MPQuestion> item) {
MPQuestion question = (item != null)? item.getOption(): null; MPQuestion question = (item != null)? item.getOption(): null;
showQuestionResult( question, answer -> { Res.ui( getQuestionResult( question ), answer -> {
} );
}
private void showQuestionResult(@Nullable final MPQuestion question, final Consumer<String> resultCallback) {
Res.job( () -> {
try {
if (question != null)
return question.getAnswer();
}
catch (final MPKeyUnavailableException | MPAlgorithmException e) {
logger.err( e, "While resolving answer for: %s", question );
}
return null;
}, resultCallback.andThen( answer -> Res.ui( () -> {
if ((answer == null) || (question == null)) if ((answer == null) || (question == null))
answerLabel.setText( " " ); answerLabel.setText( " " );
else else
@ -935,7 +934,21 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
strf( "<html>Answer for site <b>%s</b>, of question with keyword <b>%s</b>:", strf( "<html>Answer for site <b>%s</b>, of question with keyword <b>%s</b>:",
question.getSite().getSiteName(), question.getKeyword() ) ); question.getSite().getSiteName(), question.getKeyword() ) );
answerField.setText( (answer != null)? answer: " " ); answerField.setText( (answer != null)? answer: " " );
} ) ) ); } );
}
private ListenableFuture<String> getQuestionResult(@Nullable final MPQuestion question) {
return Res.job( () -> {
try {
if (question != null)
return question.getAnswer();
}
catch (final MPKeyUnavailableException | MPAlgorithmException e) {
logger.err( e, "While resolving answer for: %s", question );
}
return null;
} );
} }
private void copyResult(final String result) { private void copyResult(final String result) {
@ -950,6 +963,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
Window window = SwingUtilities.windowForComponent( UserContentPanel.this ); Window window = SwingUtilities.windowForComponent( UserContentPanel.this );
if (window instanceof Frame) if (window instanceof Frame)
((Frame) window).setExtendedState( Frame.ICONIFIED ); ((Frame) window).setExtendedState( Frame.ICONIFIED );
setShowLogin( false );
} ); } );
} }
@ -1000,7 +1015,9 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
if (siteItems.stream().noneMatch( MPQuery.Result::isExact )) if (siteItems.stream().noneMatch( MPQuery.Result::isExact ))
siteItems.add( MPQuery.Result.allOf( new MPNewSite( user, query.getQuery() ), query.getQuery() ) ); siteItems.add( MPQuery.Result.allOf( new MPNewSite( user, query.getQuery() ), query.getQuery() ) );
Res.ui( () -> sitesModel.set( siteItems ) ); Res.ui( () -> {
sitesModel.set( siteItems );
} );
} ); } );
} }
@ -1017,5 +1034,13 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
@Override @Override
public void onUserInvalidated(final MPUser<?> user) { public void onUserInvalidated(final MPUser<?> user) {
} }
@Override
public boolean dispatchKeyEvent(final KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
setShowLogin( e.isShiftDown() );
return false;
}
} }
} }

View File

@ -1,5 +1,7 @@
package com.lyndir.masterpassword.model; package com.lyndir.masterpassword.model;
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -146,5 +148,10 @@ public class MPQuery {
public int hashCode() { public int hashCode() {
return getOption().hashCode(); return getOption().hashCode();
} }
@Override
public String toString() {
return strf( "{Result: %s}", key );
}
} }
} }