Extract user preferences into a separate class.
This commit is contained in:
		@@ -584,10 +584,13 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
 | 
			
		||||
            if (fileUser != null) {
 | 
			
		||||
                components.add( Components.label( "Default Password Type:" ),
 | 
			
		||||
                                Components.comboBox( MPResultType.values(), MPResultType::getLongName,
 | 
			
		||||
                                                     fileUser.getDefaultType(), fileUser::setDefaultType ),
 | 
			
		||||
                                                     fileUser.getPreferences().getDefaultType(),
 | 
			
		||||
                                                     fileUser.getPreferences()::setDefaultType ),
 | 
			
		||||
                                Components.strut() );
 | 
			
		||||
 | 
			
		||||
                components.add( Components.checkBox( "Hide Passwords", fileUser.isHidePasswords(), fileUser::setHidePasswords ) );
 | 
			
		||||
                components.add( Components.checkBox( "Hide Passwords",
 | 
			
		||||
                                                     fileUser.getPreferences().isHidePasswords(),
 | 
			
		||||
                                                     fileUser.getPreferences()::setHidePasswords ) );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Components.showDialog( this, user.getFullName(), new JOptionPane( Components.panel(
 | 
			
		||||
@@ -615,14 +618,14 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
 | 
			
		||||
                            Components.strut() );
 | 
			
		||||
 | 
			
		||||
            components.add( Components.label( "Password Type:" ),
 | 
			
		||||
                            Components.comboBox( MPResultType.values(), type -> getTypeDescription(
 | 
			
		||||
                                    type, user.getDefaultType(), user.getAlgorithm().mpw_default_result_type() ),
 | 
			
		||||
                            Components.comboBox( MPResultType.values(), type ->
 | 
			
		||||
                                                         getTypeDescription( type, user.getPreferences().getDefaultType() ),
 | 
			
		||||
                                                 site.getResultType(), site::setResultType ),
 | 
			
		||||
                            Components.strut() );
 | 
			
		||||
 | 
			
		||||
            components.add( Components.label( "Login Type:" ),
 | 
			
		||||
                            Components.comboBox( MPResultType.values(), type -> getTypeDescription(
 | 
			
		||||
                                    type, user.getAlgorithm().mpw_default_login_type() ),
 | 
			
		||||
                            Components.comboBox( MPResultType.values(), type ->
 | 
			
		||||
                                                         getTypeDescription( type, user.getAlgorithm().mpw_default_login_type() ),
 | 
			
		||||
                                                 site.getLoginType(), site::setLoginType ),
 | 
			
		||||
                            Components.strut() );
 | 
			
		||||
 | 
			
		||||
@@ -890,7 +893,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
 | 
			
		||||
 | 
			
		||||
                if ((result == null) || result.isEmpty())
 | 
			
		||||
                    resultField.setText( " " );
 | 
			
		||||
                else if (!showLogin && (user instanceof MPFileUser) && ((MPFileUser) user).isHidePasswords())
 | 
			
		||||
                else if (!showLogin && user.getPreferences().isHidePasswords())
 | 
			
		||||
                    resultField.setText( EACH_CHARACTER.matcher( result ).replaceAll( "•" ) );
 | 
			
		||||
                else
 | 
			
		||||
                    resultField.setText( result );
 | 
			
		||||
@@ -1033,8 +1036,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
 | 
			
		||||
                if (!Strings.isNullOrEmpty( queryText ))
 | 
			
		||||
                    if (siteItems.stream().noneMatch( MPQuery.Result::isExact )) {
 | 
			
		||||
                        MPQuery.Result<? extends MPSite<?>> selectedItem = sitesModel.getSelectedItem();
 | 
			
		||||
                        if ((selectedItem != null) && user.equals( selectedItem.getOption().getUser() ) &&
 | 
			
		||||
                            queryText.equals( selectedItem.getOption().getSiteName() ))
 | 
			
		||||
                        if ((selectedItem != null) && user.equals( selectedItem.getValue().getUser() ) &&
 | 
			
		||||
                            queryText.equals( selectedItem.getValue().getSiteName() ))
 | 
			
		||||
                            siteItems.add( selectedItem );
 | 
			
		||||
                        else
 | 
			
		||||
                            siteItems.add( MPQuery.Result.allOf( new MPNewSite( user, query.getQuery() ), query.getQuery() ) );
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,9 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    String getFullName();
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    MPUserPreferences getPreferences();
 | 
			
		||||
 | 
			
		||||
    // - Algorithm
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
@@ -45,11 +48,6 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
 | 
			
		||||
 | 
			
		||||
    void setAlgorithm(MPAlgorithm algorithm);
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    default MPResultType getDefaultType() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    byte[] getKeyID();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package com.lyndir.masterpassword.model;
 | 
			
		||||
 | 
			
		||||
import com.lyndir.masterpassword.MPResultType;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lhunath, 2018-10-13
 | 
			
		||||
 */
 | 
			
		||||
public interface MPUserPreferences {
 | 
			
		||||
 | 
			
		||||
    MPResultType getDefaultType();
 | 
			
		||||
 | 
			
		||||
    void setDefaultType(@Nullable MPResultType defaultType);
 | 
			
		||||
 | 
			
		||||
    boolean isHidePasswords();
 | 
			
		||||
 | 
			
		||||
    void setHidePasswords(boolean hidePasswords);
 | 
			
		||||
}
 | 
			
		||||
@@ -55,8 +55,7 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
 | 
			
		||||
        this.siteName = siteName;
 | 
			
		||||
        this.algorithm = (algorithm != null)? algorithm: this.user.getAlgorithm();
 | 
			
		||||
        this.counter = (counter != null)? counter: this.algorithm.mpw_default_counter();
 | 
			
		||||
        this.resultType = (resultType != null)? resultType:
 | 
			
		||||
                ifNotNullElse( this.user.getDefaultType(), this.algorithm.mpw_default_result_type() );
 | 
			
		||||
        this.resultType = (resultType != null)? resultType: this.user.getPreferences().getDefaultType();
 | 
			
		||||
        this.loginType = (loginType != null)? loginType: this.algorithm.mpw_default_login_type();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -77,6 +77,12 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> extends Changeabl
 | 
			
		||||
        return fullName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public MPUserPreferences getPreferences() {
 | 
			
		||||
        return new MPBasicUserPreferences<MPBasicUser<?>>( this );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public MPAlgorithm getAlgorithm() {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
package com.lyndir.masterpassword.model.impl;
 | 
			
		||||
 | 
			
		||||
import com.lyndir.masterpassword.MPResultType;
 | 
			
		||||
import com.lyndir.masterpassword.model.MPUserPreferences;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lhunath, 2018-10-13
 | 
			
		||||
 */
 | 
			
		||||
public class MPBasicUserPreferences<U extends MPBasicUser<?>> implements MPUserPreferences {
 | 
			
		||||
 | 
			
		||||
    private final U user;
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    private MPResultType defaultType;
 | 
			
		||||
    private boolean      hidePasswords;
 | 
			
		||||
 | 
			
		||||
    public MPBasicUserPreferences(final U user) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected U getUser() {
 | 
			
		||||
        return user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public MPResultType getDefaultType() {
 | 
			
		||||
        return (defaultType != null)? defaultType: user.getAlgorithm().mpw_default_result_type();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setDefaultType(@Nullable final MPResultType defaultType) {
 | 
			
		||||
        this.defaultType = defaultType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isHidePasswords() {
 | 
			
		||||
        return hidePasswords;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setHidePasswords(final boolean hidePasswords) {
 | 
			
		||||
        this.hidePasswords = hidePasswords;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,8 +20,7 @@ package com.lyndir.masterpassword.model.impl;
 | 
			
		||||
 | 
			
		||||
import com.lyndir.lhunath.opal.system.logging.Logger;
 | 
			
		||||
import com.lyndir.masterpassword.*;
 | 
			
		||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
 | 
			
		||||
import com.lyndir.masterpassword.model.MPUser;
 | 
			
		||||
import com.lyndir.masterpassword.model.*;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import javax.annotation.Nonnull;
 | 
			
		||||
@@ -43,17 +42,16 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
			
		||||
    private File                     file;
 | 
			
		||||
    private MPMarshalFormat          format;
 | 
			
		||||
    private MPMarshaller.ContentMode contentMode;
 | 
			
		||||
    private ReadableInstant          lastUsed;
 | 
			
		||||
    private boolean                  complete;
 | 
			
		||||
 | 
			
		||||
    private MPResultType    defaultType;
 | 
			
		||||
    private ReadableInstant lastUsed;
 | 
			
		||||
    private boolean         hidePasswords;
 | 
			
		||||
    private boolean         complete;
 | 
			
		||||
    private final MPFileUserPreferences preferences;
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public static MPFileUser load(final File file)
 | 
			
		||||
            throws IOException, MPMarshalException {
 | 
			
		||||
        for (final MPMarshalFormat format : MPMarshalFormat.values())
 | 
			
		||||
            if (format.matches(file))
 | 
			
		||||
            if (format.matches( file ))
 | 
			
		||||
                return format.unmarshaller().readUser( file );
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
@@ -74,9 +72,8 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
			
		||||
        super( avatar, fullName, algorithm );
 | 
			
		||||
 | 
			
		||||
        this.keyID = (keyID != null)? keyID.clone(): null;
 | 
			
		||||
        this.defaultType = (defaultType != null)? defaultType: algorithm.mpw_default_result_type();
 | 
			
		||||
        this.lastUsed = lastUsed;
 | 
			
		||||
        this.hidePasswords = hidePasswords;
 | 
			
		||||
        this.preferences = new MPFileUserPreferences( this, defaultType, hidePasswords );
 | 
			
		||||
        this.format = format;
 | 
			
		||||
        this.contentMode = contentMode;
 | 
			
		||||
 | 
			
		||||
@@ -92,6 +89,12 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
			
		||||
        return (keyID == null)? null: keyID.clone();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    @Override
 | 
			
		||||
    public MPUserPreferences getPreferences() {
 | 
			
		||||
        return preferences;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setAlgorithm(final MPAlgorithm algorithm) {
 | 
			
		||||
        if (!algorithm.equals( getAlgorithm() ) && (keyID != null)) {
 | 
			
		||||
@@ -128,19 +131,6 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
			
		||||
        setChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public MPResultType getDefaultType() {
 | 
			
		||||
        return defaultType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setDefaultType(final MPResultType defaultType) {
 | 
			
		||||
        if (this.defaultType == defaultType)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.defaultType = defaultType;
 | 
			
		||||
        setChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ReadableInstant getLastUsed() {
 | 
			
		||||
        return lastUsed;
 | 
			
		||||
    }
 | 
			
		||||
@@ -150,18 +140,6 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
			
		||||
        setChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isHidePasswords() {
 | 
			
		||||
        return hidePasswords;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setHidePasswords(final boolean hidePasswords) {
 | 
			
		||||
        if (Objects.equals( this.hidePasswords, hidePasswords ))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.hidePasswords = hidePasswords;
 | 
			
		||||
        setChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected boolean isComplete() {
 | 
			
		||||
        return complete;
 | 
			
		||||
    }
 | 
			
		||||
@@ -193,7 +171,7 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
 | 
			
		||||
     */
 | 
			
		||||
    public void migrateTo(final File path, final MPMarshalFormat newFormat) {
 | 
			
		||||
        MPMarshalFormat oldFormat = format;
 | 
			
		||||
        File oldFile = file, newFile = new File( path, getFullName() + newFormat.fileSuffix() );
 | 
			
		||||
        File            oldFile   = file, newFile = new File( path, getFullName() + newFormat.fileSuffix() );
 | 
			
		||||
 | 
			
		||||
        // If the format hasn't changed, migrate by moving the file: the contents doesn't need to change.
 | 
			
		||||
        if ((oldFormat == newFormat) && !oldFile.equals( newFile ) && oldFile.exists())
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
package com.lyndir.masterpassword.model.impl;
 | 
			
		||||
 | 
			
		||||
import com.lyndir.masterpassword.MPResultType;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author lhunath, 2018-10-13
 | 
			
		||||
 */
 | 
			
		||||
public class MPFileUserPreferences extends MPBasicUserPreferences<MPFileUser> {
 | 
			
		||||
 | 
			
		||||
    public MPFileUserPreferences(final MPFileUser user, @Nullable final MPResultType defaultType, final boolean hidePasswords) {
 | 
			
		||||
        super( user );
 | 
			
		||||
 | 
			
		||||
        setDefaultType( defaultType );
 | 
			
		||||
        setHidePasswords( hidePasswords );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setDefaultType(@Nullable final MPResultType defaultType) {
 | 
			
		||||
        if (getDefaultType() == defaultType)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        super.setDefaultType( defaultType );
 | 
			
		||||
        getUser().setChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setHidePasswords(final boolean hidePasswords) {
 | 
			
		||||
        if (Objects.equals( isHidePasswords(), hidePasswords ))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        super.setHidePasswords( hidePasswords );
 | 
			
		||||
        getUser().setChanged();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -56,7 +56,7 @@ public class MPFlatMarshaller implements MPMarshaller {
 | 
			
		||||
        content.append( "# Avatar: " ).append( user.getAvatar() ).append( '\n' );
 | 
			
		||||
        content.append( "# Key ID: " ).append( user.exportKeyID() ).append( '\n' );
 | 
			
		||||
        content.append( "# Algorithm: " ).append( user.getAlgorithm().version().toInt() ).append( '\n' );
 | 
			
		||||
        content.append( "# Default Type: " ).append( user.getDefaultType().getType() ).append( '\n' );
 | 
			
		||||
        content.append( "# Default Type: " ).append( user.getPreferences().getDefaultType().getType() ).append( '\n' );
 | 
			
		||||
        content.append( "# Passwords: " ).append( user.getContentMode().name() ).append( '\n' );
 | 
			
		||||
        content.append( "##\n" );
 | 
			
		||||
        content.append( "#\n" );
 | 
			
		||||
 
 | 
			
		||||
@@ -77,10 +77,10 @@ public class MPJSONFile extends MPJSONAnyObject {
 | 
			
		||||
        user.avatar = modelUser.getAvatar();
 | 
			
		||||
        user.full_name = modelUser.getFullName();
 | 
			
		||||
        user.last_used = MPModelConstants.dateTimeFormatter.print( modelUser.getLastUsed() );
 | 
			
		||||
        user.hide_passwords = modelUser.isHidePasswords();
 | 
			
		||||
        user.key_id = modelUser.exportKeyID();
 | 
			
		||||
        user.algorithm = modelUser.getAlgorithm().version();
 | 
			
		||||
        user.default_type = modelUser.getDefaultType();
 | 
			
		||||
        user.default_type = modelUser.getPreferences().getDefaultType();
 | 
			
		||||
        user.hide_passwords = modelUser.getPreferences().isHidePasswords();
 | 
			
		||||
 | 
			
		||||
        // Section "sites"
 | 
			
		||||
        sites = new LinkedHashMap<>();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user