From c2c4fb18bf4a7f3d1341a6b4eecdeb4019d1390c Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Tue, 31 Jul 2018 15:16:33 -0400 Subject: [PATCH] Help improvements. --- .../lyndir/masterpassword/util/Utilities.java | 8 +++++ .../com/lyndir/masterpassword/gui/Config.java | 4 +-- .../com/lyndir/masterpassword/gui/GUI.java | 5 +-- .../masterpassword/gui/MPGuiConstants.java | 14 ++++++++ .../masterpassword/gui/MasterPassword.java | 33 +++++++++++-------- .../masterpassword/gui/util/Components.java | 2 +- .../gui/view/UserContentPanel.java | 10 +++--- ...MPConstants.java => MPModelConstants.java} | 5 +-- .../model/impl/MPFileUserManager.java | 4 +-- .../model/impl/MPFlatMarshaller.java | 6 ++-- .../model/impl/MPFlatUnmarshaller.java | 6 ++-- .../masterpassword/model/impl/MPJSONFile.java | 12 +++---- 12 files changed, 68 insertions(+), 41 deletions(-) create mode 100644 platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MPGuiConstants.java rename platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/{MPConstants.java => MPModelConstants.java} (93%) diff --git a/platform-independent/java/algorithm/src/main/java/com/lyndir/masterpassword/util/Utilities.java b/platform-independent/java/algorithm/src/main/java/com/lyndir/masterpassword/util/Utilities.java index 1bbe3602..04d90b94 100644 --- a/platform-independent/java/algorithm/src/main/java/com/lyndir/masterpassword/util/Utilities.java +++ b/platform-independent/java/algorithm/src/main/java/com/lyndir/masterpassword/util/Utilities.java @@ -19,6 +19,14 @@ public final class Utilities { return consumer.apply( value ); } + @Nonnull + public static T ifNotNullElse(@Nullable final T value, @Nonnull final T nullValue) { + if (value == null) + return nullValue; + + return value; + } + @Nonnull public static R ifNotNullElse(@Nullable final T value, final Function consumer, @Nonnull final R nullValue) { if (value == null) diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/Config.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/Config.java index 96efa6c1..d412d36c 100644 --- a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/Config.java +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/Config.java @@ -19,7 +19,7 @@ package com.lyndir.masterpassword.gui; import com.lyndir.lhunath.opal.system.util.ConversionUtils; -import com.lyndir.masterpassword.model.MPConstants; +import com.lyndir.masterpassword.model.MPModelConstants; /** @@ -35,6 +35,6 @@ public class Config { } public boolean checkForUpdates() { - return ConversionUtils.toBoolean( System.getenv( MPConstants.env_checkUpdates ) ).orElse( true ); + return ConversionUtils.toBoolean( System.getenv( MPModelConstants.env_checkUpdates ) ).orElse( true ); } } diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/GUI.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/GUI.java index cf37a42d..347de69c 100644 --- a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/GUI.java +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/GUI.java @@ -6,8 +6,6 @@ import com.lyndir.masterpassword.gui.util.Res; import com.lyndir.masterpassword.gui.view.MasterPasswordFrame; import com.tulskiy.keymaster.common.Provider; import java.awt.*; -import java.awt.event.*; -import javax.swing.*; /** @@ -23,8 +21,7 @@ public class GUI { Platform.get().installAppForegroundHandler( this::open ); Platform.get().installAppReopenHandler( this::open ); - KeyStroke keyStroke = KeyStroke.getKeyStroke( KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK ); - Provider.getCurrentProvider( true ).register( keyStroke, hotKey -> open() ); + Provider.getCurrentProvider( true ).register( MPGuiConstants.ui_hotkey, hotKey -> open() ); } public void open() { diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MPGuiConstants.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MPGuiConstants.java new file mode 100644 index 00000000..54b48735 --- /dev/null +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MPGuiConstants.java @@ -0,0 +1,14 @@ +package com.lyndir.masterpassword.gui; + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.*; + + +/** + * @author lhunath, 2018-07-31 + */ +public final class MPGuiConstants { + + public static final KeyStroke ui_hotkey = KeyStroke.getKeyStroke( KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK ); +} diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MasterPassword.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MasterPassword.java index aced49f7..2d803f46 100644 --- a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MasterPassword.java +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/MasterPassword.java @@ -24,6 +24,7 @@ import com.google.common.base.Charsets; import com.google.common.io.ByteSource; import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.util.ObjectUtils; +import com.lyndir.masterpassword.gui.util.Components; import com.lyndir.masterpassword.model.MPUser; import java.io.IOException; import java.io.InputStream; @@ -72,9 +73,14 @@ public final class MasterPassword { listener.onUserSelected( activeUser ); } - private static void checkUpdate() { + @Nullable + public String version() { + return MasterPassword.class.getPackage().getImplementationVersion(); + } + + public void checkUpdate() { try { - String implementationVersion = MasterPassword.class.getPackage().getImplementationVersion(); + String implementationVersion = version(); String latestVersion = new ByteSource() { @Override public InputStream openStream() @@ -86,16 +92,14 @@ public final class MasterPassword { } }.asCharSource( Charsets.UTF_8 ).readFirstLine(); - if ((implementationVersion != null) && (latestVersion != null) && - !implementationVersion.equalsIgnoreCase( latestVersion )) { + if ((implementationVersion != null) && !implementationVersion.equalsIgnoreCase( latestVersion )) { logger.inf( "Implementation: <%s>", implementationVersion ); logger.inf( "Latest : <%s>", latestVersion ); logger.wrn( "You are not running the current official version. Please update from:%n%s", "https://masterpassword.app/masterpassword-gui.jar" ); - JOptionPane.showMessageDialog( null, - strf( "A new version of Master Password is available.%n " - + "Please download the latest version from %s", - "https://masterpassword.app" ), + JOptionPane.showMessageDialog( null, Components.linkLabel( strf( + "A new version of Master Password is available." + + "

Please download the latest version from https://masterpassword.app." ) ), "Update Available", JOptionPane.INFORMATION_MESSAGE ); } } @@ -105,8 +109,8 @@ public final class MasterPassword { } public static void main(final String... args) { - // Thread.setDefaultUncaughtExceptionHandler( - // (t, e) -> logger.bug( e, "Uncaught: %s", e.getLocalizedMessage() ) ); + //Thread.setDefaultUncaughtExceptionHandler( + // (t, e) -> logger.bug( e, "Uncaught: %s", e.getLocalizedMessage() ) ); // Try and set the system look & feel, if available. try { @@ -115,15 +119,16 @@ public final class MasterPassword { catch (final UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) { } - // Check online to see if this version has been superseded. - if (Config.get().checkForUpdates()) - checkUpdate(); - // Create a platform-specific GUI and open it. new GUI().open(); + + // Check online to see if this version has been superseded. + if (Config.get().checkForUpdates()) + get().checkUpdate(); } public interface Listener { + void onUserSelected(@Nullable MPUser user); } } diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/util/Components.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/util/Components.java index 8b38f234..314da5ce 100644 --- a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/util/Components.java +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/util/Components.java @@ -479,7 +479,7 @@ public abstract class Components { } public static JEditorPane linkLabel(@NonNls final String html) { - return new JEditorPane( "text/html", "" + html ) { + return new JEditorPane( "text/html", "" + html ) { { setOpaque( false ); setEditable( false ); diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java index 0c537e44..ea18c4c6 100644 --- a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java @@ -8,6 +8,7 @@ import com.google.common.primitives.UnsignedInteger; import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.util.ObjectUtils; import com.lyndir.masterpassword.*; +import com.lyndir.masterpassword.gui.MPGuiConstants; import com.lyndir.masterpassword.gui.MasterPassword; import com.lyndir.masterpassword.gui.model.MPIncognitoUser; import com.lyndir.masterpassword.gui.model.MPNewSite; @@ -220,14 +221,14 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, private void showHelp() { JOptionPane.showMessageDialog( this, Components.linkLabel( strf( - "

Master Password

" + "

Master Password - v%s

" + "

The primary goal of this application is to provide a reliable security solution that also " + "makes you independent from your computer. If you lose access to this computer or your data, " + "the application can regenerate all your secrets from scratch on any new device.

" + "

Opening Master Password

" + "

To use Master Password, simply open the application on your computer. " + "Once running, you can bring up the user interface at any time by pressing the keys " - + "%s + %s + p." + + "%s+%s." + "

Persistence

" + "

Though at the core, Master Password does not require the use of any form of data " + "storage, the application does remember the names of the sites you've used in the past to " @@ -237,8 +238,9 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, + "Some people even configure this location to be synced between their different computers " + "using services such as those provided by SpiderOak or Dropbox.

" + "

https://masterpassword.app — by Maarten Billemont

", - KeyEvent.getKeyText( KeyEvent.VK_CONTROL ), - KeyEvent.getKeyText( KeyEvent.VK_META ), + MasterPassword.get().version(), + InputEvent.getModifiersExText( MPGuiConstants.ui_hotkey.getModifiers() ), + KeyEvent.getKeyText( MPGuiConstants.ui_hotkey.getKeyCode() ), MPFileUserManager.get().getPath().getAbsolutePath() ) ), "About Master Password", JOptionPane.INFORMATION_MESSAGE ); } diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPConstants.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPModelConstants.java similarity index 93% rename from platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPConstants.java rename to platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPModelConstants.java index 615094a6..86875219 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPConstants.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPModelConstants.java @@ -25,14 +25,15 @@ import org.joda.time.format.ISODateTimeFormat; /** * @author lhunath, 2016-10-29 */ -public final class MPConstants { +public final class MPModelConstants { /* Environment */ /** * mpw: default path to look for run configuration files if the platform default is not desired. */ - public static final String env_rcDir = "MPW_RCDIR"; + public static final String env_rcDir = "MPW_RCDIR"; + /** * mpw: permit automatic update checks. */ diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFileUserManager.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFileUserManager.java index b3d260dd..544b1631 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFileUserManager.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFileUserManager.java @@ -22,7 +22,7 @@ import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*; import com.google.common.collect.ImmutableSortedSet; import com.lyndir.lhunath.opal.system.logging.Logger; -import com.lyndir.masterpassword.model.MPConstants; +import com.lyndir.masterpassword.model.MPModelConstants; import java.io.File; import java.io.IOException; import java.util.*; @@ -42,7 +42,7 @@ public class MPFileUserManager { private static final MPFileUserManager instance; static { - String rcDir = System.getenv( MPConstants.env_rcDir ); + String rcDir = System.getenv( MPModelConstants.env_rcDir ); if (rcDir != null) instance = create( new File( rcDir ) ); diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatMarshaller.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatMarshaller.java index 4e92aa56..e96c50c9 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatMarshaller.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatMarshaller.java @@ -25,7 +25,7 @@ import com.google.common.base.Charsets; import com.google.common.io.CharSink; import com.lyndir.masterpassword.MPAlgorithmException; import com.lyndir.masterpassword.MPKeyUnavailableException; -import com.lyndir.masterpassword.model.MPConstants; +import com.lyndir.masterpassword.model.MPModelConstants; import java.io.*; import org.joda.time.Instant; @@ -50,7 +50,7 @@ public class MPFlatMarshaller implements MPMarshaller { content.append( "# \n" ); content.append( "##\n" ); content.append( "# Format: " ).append( FORMAT ).append( '\n' ); - content.append( "# Date: " ).append( MPConstants.dateTimeFormatter.print( new Instant() ) ).append( '\n' ); + content.append( "# Date: " ).append( MPModelConstants.dateTimeFormatter.print( new Instant() ) ).append( '\n' ); content.append( "# User Name: " ).append( user.getFullName() ).append( '\n' ); content.append( "# Full Name: " ).append( user.getFullName() ).append( '\n' ); content.append( "# Avatar: " ).append( user.getAvatar() ).append( '\n' ); @@ -72,7 +72,7 @@ public class MPFlatMarshaller implements MPMarshaller { } content.append( strf( "%s %8d %8s %25s\t%25s\t%s\n", // - MPConstants.dateTimeFormatter.print( site.getLastUsed() ), // lastUsed + MPModelConstants.dateTimeFormatter.print( site.getLastUsed() ), // lastUsed site.getUses(), // uses strf( "%d:%d:%d", // site.getResultType().getType(), // type diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatUnmarshaller.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatUnmarshaller.java index 68bef9ff..3c10fb34 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatUnmarshaller.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPFlatUnmarshaller.java @@ -25,7 +25,7 @@ import com.lyndir.lhunath.opal.system.CodeUtils; import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.util.ConversionUtils; import com.lyndir.masterpassword.*; -import com.lyndir.masterpassword.model.MPConstants; +import com.lyndir.masterpassword.model.MPModelConstants; import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException; import java.io.*; import java.util.regex.Matcher; @@ -157,7 +157,7 @@ public class MPFlatUnmarshaller implements MPUnmarshaller { MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ), clearContent? null: siteMatcher.group( 6 ), null, null, null, ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ), - MPConstants.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() ); + MPModelConstants.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() ); if (clearContent) site.setSitePassword( site.getResultType(), siteMatcher.group( 6 ) ); break; @@ -171,7 +171,7 @@ public class MPFlatUnmarshaller implements MPUnmarshaller { clearContent? null: siteMatcher.group( 8 ), MPResultType.GeneratedName, clearContent? null: siteMatcher.group( 6 ), null, ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ), - MPConstants.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() ); + MPModelConstants.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() ); if (clearContent) { site.setSitePassword( site.getResultType(), siteMatcher.group( 8 ) ); site.setLoginName( MPResultType.StoredPersonal, siteMatcher.group( 6 ) ); diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPJSONFile.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPJSONFile.java index a387ed72..b58253ca 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPJSONFile.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPJSONFile.java @@ -28,7 +28,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.primitives.UnsignedInteger; import com.lyndir.lhunath.opal.system.CodeUtils; import com.lyndir.masterpassword.*; -import com.lyndir.masterpassword.model.MPConstants; +import com.lyndir.masterpassword.model.MPModelConstants; import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.File; @@ -70,13 +70,13 @@ public class MPJSONFile extends MPJSONAnyObject { export = new Export(); export.format = 1; export.redacted = modelUser.getContentMode().isRedacted(); - export.date = MPConstants.dateTimeFormatter.print( new Instant() ); + export.date = MPModelConstants.dateTimeFormatter.print( new Instant() ); // Section: "user" user = new User(); user.avatar = modelUser.getAvatar(); user.full_name = modelUser.getFullName(); - user.last_used = MPConstants.dateTimeFormatter.print( modelUser.getLastUsed() ); + user.last_used = MPModelConstants.dateTimeFormatter.print( modelUser.getLastUsed() ); user.key_id = modelUser.exportKeyID(); user.algorithm = modelUser.getAlgorithm().version(); user.default_type = modelUser.getDefaultType(); @@ -111,7 +111,7 @@ public class MPJSONFile extends MPJSONAnyObject { site.login_type = modelSite.getLoginType(); site.uses = modelSite.getUses(); - site.last_used = MPConstants.dateTimeFormatter.print( modelSite.getLastUsed() ); + site.last_used = MPModelConstants.dateTimeFormatter.print( modelSite.getLastUsed() ); site.questions = new LinkedHashMap<>(); for (final MPFileQuestion question : modelSite.getQuestions()) @@ -141,7 +141,7 @@ public class MPJSONFile extends MPJSONAnyObject { return new MPFileUser( user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar, (user.default_type != null)? user.default_type: algorithm.mpw_default_result_type(), - (user.last_used != null)? MPConstants.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(), + (user.last_used != null)? MPModelConstants.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(), export.redacted? MPMarshaller.ContentMode.PROTECTED: MPMarshaller.ContentMode.VISIBLE, MPMarshalFormat.JSON, file.getParentFile() ); @@ -157,7 +157,7 @@ public class MPJSONFile extends MPJSONAnyObject { fileSite.type, export.redacted? fileSite.password: null, fileSite.login_type, export.redacted? fileSite.login_name: null, (fileSite._ext_mpw != null)? fileSite._ext_mpw.url: null, fileSite.uses, - (fileSite.last_used != null)? MPConstants.dateTimeFormatter.parseDateTime( fileSite.last_used ): new Instant() ); + (fileSite.last_used != null)? MPModelConstants.dateTimeFormatter.parseDateTime( fileSite.last_used ): new Instant() ); if (!export.redacted) { if (fileSite.password != null)