Fixes #138- delays identicon update to avoid leaking interactive keyboard input.
This commit is contained in:
@@ -22,6 +22,9 @@ import com.google.common.io.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.lhunath.opal.system.util.TypeUtils;
|
||||
|
||||
import com.lyndir.masterpassword.gui.model.User;
|
||||
import com.lyndir.masterpassword.gui.view.PasswordFrame;
|
||||
import com.lyndir.masterpassword.gui.view.UnlockFrame;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
@@ -30,12 +30,16 @@ import javax.swing.*;
|
||||
*/
|
||||
public abstract class Res {
|
||||
|
||||
private static final WeakHashMap<Window, ExecutorService> executorByWindow = new WeakHashMap<>();
|
||||
private static final Logger logger = Logger.get( Res.class );
|
||||
private static final Colors colors = new Colors();
|
||||
private static final WeakHashMap<Window, ScheduledExecutorService> executorByWindow = new WeakHashMap<>();
|
||||
private static final Logger logger = Logger.get( Res.class );
|
||||
private static final Colors colors = new Colors();
|
||||
|
||||
public static Future<?> execute(final Window host, final Runnable job) {
|
||||
return getExecutor( host ).submit( new Runnable() {
|
||||
return schedule( host, job, 0, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
|
||||
public static Future<?> schedule(final Window host, final Runnable job, final long delay, final TimeUnit timeUnit) {
|
||||
return getExecutor( host ).schedule( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@@ -45,12 +49,16 @@ public abstract class Res {
|
||||
logger.err( t, "Unexpected: %s", t.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}, delay, timeUnit );
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> execute(final Window host, final Callable<V> job) {
|
||||
ExecutorService executor = getExecutor( host );
|
||||
return JdkFutureAdapters.listenInPoolThread( executor.submit( new Callable<V>() {
|
||||
return schedule( host, job, 0, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> schedule(final Window host, final Callable<V> job, final long delay, final TimeUnit timeUnit) {
|
||||
ScheduledExecutorService executor = getExecutor( host );
|
||||
return JdkFutureAdapters.listenInPoolThread( executor.schedule( new Callable<V>() {
|
||||
@Override
|
||||
public V call()
|
||||
throws Exception {
|
||||
@@ -62,14 +70,14 @@ public abstract class Res {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
} ), executor );
|
||||
}, delay, timeUnit ), executor );
|
||||
}
|
||||
|
||||
private static ExecutorService getExecutor(final Window host) {
|
||||
ExecutorService executor = executorByWindow.get( host );
|
||||
private static ScheduledExecutorService getExecutor(final Window host) {
|
||||
ScheduledExecutorService executor = executorByWindow.get( host );
|
||||
|
||||
if (executor == null) {
|
||||
executorByWindow.put( host, executor = Executors.newSingleThreadExecutor() );
|
||||
executorByWindow.put( host, executor = Executors.newSingleThreadScheduledExecutor() );
|
||||
|
||||
host.addWindowListener( new WindowAdapter() {
|
||||
@Override
|
||||
@@ -252,8 +260,8 @@ public abstract class Res {
|
||||
|
||||
public static class Colors {
|
||||
|
||||
private final Color frameBg = Color.decode( "#5A5D6B" );
|
||||
private final Color controlBg = Color.decode( "#ECECEC" );
|
||||
private final Color frameBg = Color.decode( "#5A5D6B" );
|
||||
private final Color controlBg = Color.decode( "#ECECEC" );
|
||||
private final Color controlBorder = Color.decode( "#BFBFBF" );
|
||||
|
||||
public Color frameBg() {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.MPSiteType;
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.masterpassword.MPSiteType;
|
@@ -1,8 +1,9 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.lyndir.masterpassword.gui.*;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -43,7 +44,7 @@ public class ModelUser extends User {
|
||||
}
|
||||
|
||||
public void setAvatar(final int avatar) {
|
||||
model.setAvatar(avatar % Res.avatars());
|
||||
model.setAvatar( avatar % Res.avatars());
|
||||
MPUserFileManager.get().save();
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.model;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Maps;
|
@@ -2,8 +2,8 @@ package com.lyndir.masterpassword.gui.platform.mac;
|
||||
|
||||
import com.apple.eawt.*;
|
||||
import com.lyndir.masterpassword.gui.GUI;
|
||||
import com.lyndir.masterpassword.gui.PasswordFrame;
|
||||
import com.lyndir.masterpassword.gui.User;
|
||||
import com.lyndir.masterpassword.gui.view.PasswordFrame;
|
||||
import com.lyndir.masterpassword.gui.model.User;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@@ -1,8 +1,10 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.view;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lyndir.masterpassword.MPIdenticon;
|
||||
import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.model.User;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import com.lyndir.masterpassword.gui.view.UnlockFrame;
|
||||
import java.awt.*;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
@@ -1,5 +1,8 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.view;
|
||||
|
||||
import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.model.IncognitoUser;
|
||||
import com.lyndir.masterpassword.gui.model.User;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.view;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.model.ModelUser;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import com.lyndir.masterpassword.model.MPUserFileManager;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
@@ -1,4 +1,4 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.view;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
@@ -9,6 +9,8 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.gui.Res;
|
||||
import com.lyndir.masterpassword.gui.model.*;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import com.lyndir.masterpassword.gui.util.UnsignedIntegerModel;
|
||||
import java.awt.*;
|
@@ -1,12 +1,16 @@
|
||||
package com.lyndir.masterpassword.gui;
|
||||
package com.lyndir.masterpassword.gui.view;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
|
||||
import com.lyndir.masterpassword.MPIdenticon;
|
||||
import com.lyndir.masterpassword.gui.*;
|
||||
import com.lyndir.masterpassword.gui.model.User;
|
||||
import com.lyndir.masterpassword.gui.util.Components;
|
||||
import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -22,6 +26,7 @@ public class UnlockFrame extends JFrame {
|
||||
private final JButton signInButton;
|
||||
private final JPanel authenticationContainer;
|
||||
private AuthenticationPanel authenticationPanel;
|
||||
private Future<?> identiconFuture;
|
||||
private boolean incognito;
|
||||
public User user;
|
||||
|
||||
@@ -139,18 +144,34 @@ public class UnlockFrame extends JFrame {
|
||||
}
|
||||
|
||||
boolean checkSignIn() {
|
||||
if (identiconFuture != null)
|
||||
identiconFuture.cancel( false );
|
||||
identiconFuture = Res.schedule( this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SwingUtilities.invokeLater( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String fullName = user == null? "": user.getFullName();
|
||||
char[] masterPassword = authenticationPanel.getMasterPassword();
|
||||
|
||||
if (fullName.isEmpty() || masterPassword.length == 0) {
|
||||
identiconLabel.setText( " " );
|
||||
return;
|
||||
}
|
||||
|
||||
MPIdenticon identicon = new MPIdenticon( fullName, masterPassword );
|
||||
identiconLabel.setText( identicon.getText() );
|
||||
identiconLabel.setForeground(
|
||||
Res.colors().fromIdenticonColor( identicon.getColor(), Res.Colors.BackgroundMode.DARK ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}, 300, TimeUnit.MILLISECONDS );
|
||||
|
||||
String fullName = user == null? "": user.getFullName();
|
||||
char[] masterPassword = authenticationPanel.getMasterPassword();
|
||||
boolean enabled = !fullName.isEmpty() && masterPassword.length > 0;
|
||||
|
||||
if (fullName.isEmpty() || masterPassword.length == 0)
|
||||
identiconLabel.setText( " " );
|
||||
else {
|
||||
MPIdenticon identicon = new MPIdenticon( fullName, masterPassword );
|
||||
identiconLabel.setText( identicon.getText() );
|
||||
identiconLabel.setForeground( Res.colors().fromIdenticonColor( identicon.getColor(), Res.Colors.BackgroundMode.DARK ) );
|
||||
}
|
||||
|
||||
signInButton.setEnabled( enabled );
|
||||
|
||||
return enabled;
|
||||
@@ -197,7 +218,7 @@ public class UnlockFrame extends JFrame {
|
||||
} );
|
||||
}
|
||||
|
||||
interface SignInCallback {
|
||||
public interface SignInCallback {
|
||||
|
||||
void signedIn(User user);
|
||||
}
|
Reference in New Issue
Block a user