Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 22417427 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #3650 from williamvds/drawer

Add preferences and unified inbox to drawer
parents e531b8af 387a6688
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.Parcelable;

public class LocalSearch implements SearchSpecification {

    private String id;
    private String mName;
    private boolean mPredefined;
    private boolean mManualSearch = false;
@@ -103,6 +104,16 @@ public class LocalSearch implements SearchSpecification {
        this.mName = name;
    }

    /**
     * Set the ID of the search. This is used to identify a unified inbox
     * search
     *
     * @param id ID to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * Add a new account to the search. When no accounts are
     * added manually we search all accounts on the device.
@@ -301,6 +312,15 @@ public class LocalSearch implements SearchSpecification {
        return (mName == null) ? "" : mName;
    }

    /**
     * Returns the ID of the search
     *
     * @return The ID of the search
     */
    public String getId() {
        return (id == null) ? "" : id;
    }

    /**
     * Checks if this search was hard coded and shipped with K-9
     *
@@ -364,6 +384,7 @@ public class LocalSearch implements SearchSpecification {

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(mName);
        dest.writeByte((byte) (mPredefined ? 1 : 0));
        dest.writeByte((byte) (mManualSearch ? 1 : 0));
@@ -386,6 +407,7 @@ public class LocalSearch implements SearchSpecification {
    };

    public LocalSearch(Parcel in) {
        id = in.readString();
        mName = in.readString();
        mPredefined = (in.readByte() == 1);
        mManualSearch = (in.readByte() == 1);
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ public class SearchAccount implements BaseAccount {
        CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
        String name = resourceProvider.searchUnifiedInboxTitle();
        LocalSearch tmpSearch = new LocalSearch(name);
        tmpSearch.setId(UNIFIED_INBOX);
        tmpSearch.and(SearchField.INTEGRATE, "1", Attribute.EQUALS);
        return new SearchAccount(UNIFIED_INBOX, tmpSearch, name, resourceProvider.searchUnifiedInboxDetail());
    }
+31 −125
Original line number Diff line number Diff line
package com.fsck.k9.activity;


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@@ -19,7 +18,6 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
@@ -27,7 +25,6 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -46,13 +43,12 @@ import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.K9.SplitViewMode;
import com.fsck.k9.Preferences;
import com.fsck.k9.controller.MessageReference;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.ui.R;
import com.fsck.k9.activity.compose.MessageActions;
import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener;
import com.fsck.k9.controller.MessageReference;
import com.fsck.k9.fragment.MessageListFragment;
import com.fsck.k9.fragment.MessageListFragment.MessageListFragmentListener;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.helper.ParcelableUtil;
import com.fsck.k9.mailstore.Folder;
import com.fsck.k9.mailstore.SearchStatusManager;
@@ -64,7 +60,8 @@ import com.fsck.k9.search.SearchSpecification;
import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.SearchCondition;
import com.fsck.k9.search.SearchSpecification.SearchField;
import com.fsck.k9.ui.folders.FolderNameFormatter;
import com.fsck.k9.ui.K9Drawer;
import com.fsck.k9.ui.R;
import com.fsck.k9.ui.messagelist.MessageListViewModel;
import com.fsck.k9.ui.messagelist.MessageListViewModelFactory;
import com.fsck.k9.ui.messageview.MessageViewFragment;
@@ -74,11 +71,7 @@ import com.fsck.k9.view.MessageHeader;
import com.fsck.k9.view.MessageTitleView;
import com.fsck.k9.view.ViewSwitcher;
import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.Drawer.OnDrawerListener;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import de.cketti.library.changelog.ChangeLog;
import timber.log.Timber;

@@ -169,12 +162,11 @@ public class MessageList extends K9Activity implements MessageListFragmentListen

    protected final SearchStatusManager searchStatusManager = DI.get(SearchStatusManager.class);
    private StorageManager.StorageListener mStorageListener = new StorageListenerImplementation();
    private final FolderNameFormatter folderNameFormatter = DI.get(FolderNameFormatter.class);
    private final Preferences preferences = DI.get(Preferences.class);

    private ActionBar actionBar;
    private ActionBarDrawerToggle drawerToggle;
    private Drawer drawer;
    private K9Drawer drawer;
    private FragmentTransaction openFolderTransaction;
    private View actionBarMessageList;
    private View actionBarMessageView;
@@ -183,15 +175,6 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
    private TextView actionBarSubTitle;
    private Menu menu;

    private int iconFolderInboxResId;
    private int iconFolderOutbotResId;
    private int iconFolderSentResId;
    private int iconFolderTrashResId;
    private int iconFolderDraftsResId;
    private int iconFolderArchiveResId;
    private int iconFolderSpamResId;
    private int iconFolderResId;

    private ViewGroup messageViewContainer;
    private View messageViewPlaceHolder;

@@ -202,7 +185,6 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
    private Account account;
    private LocalSearch search;
    private boolean singleFolderMode;
    private String openedFolder;
    private boolean singleAccountMode;

    private ProgressBar actionBarProgress;
@@ -252,7 +234,6 @@ public class MessageList extends K9Activity implements MessageListFragmentListen

        initializeActionBar();
        initializeDrawer(savedInstanceState);
        initializeFolderIcons();

        // Enable gesture detection for MessageLists
        setupGestureDetector(this);
@@ -268,7 +249,7 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
            viewModel.getFolders(account).observe(this, new Observer<List<Folder>>() {
                @Override
                public void onChanged(@Nullable List<Folder> folders) {
                    populateDrawerWithFolders(folders);
                    drawer.setUserFolders(folders);
                }
            });
        }
@@ -494,7 +475,8 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
        if (messageReference != null) {
            search = new LocalSearch();
            search.addAccountUuid(messageReference.getAccountUuid());
            search.addAllowedFolder(messageReference.getFolderServerId());
            String folderServerId = messageReference.getFolderServerId();
            search.addAllowedFolder(folderServerId);
        }

        if (search == null) {
@@ -590,18 +572,9 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
            return;
        }

        drawer = new DrawerBuilder()
                .withActivity(this)
                .withDisplayBelowStatusBar(false)
                .withTranslucentStatusBar(false)
                .withDrawerLayout(R.layout.material_drawer_fits_not)
                .withActionBarDrawerToggle(true)
                .withOnDrawerItemClickListener(createDrawerItemClickListener())
                .withOnDrawerListener(createOnDrawerListener())
                .withSavedInstance(savedInstanceState)
                .build();
        drawer = new K9Drawer(this, savedInstanceState);

        DrawerLayout drawerLayout = drawer.getDrawerLayout();
        DrawerLayout drawerLayout = drawer.getLayout();
        drawerToggle = new ActionBarDrawerToggle(
                this, drawerLayout, null,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close
@@ -610,19 +583,7 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
        drawerToggle.syncState();
    }

    @NonNull
    private Drawer.OnDrawerItemClickListener createDrawerItemClickListener() {
        return new Drawer.OnDrawerItemClickListener() {
            @Override
            public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                Folder folder = (Folder) drawerItem.getTag();
                openFolderTransaction = openFolder(folder.getServerId());
                return false;
            }
        };
    }

    private OnDrawerListener createOnDrawerListener() {
    public OnDrawerListener createOnDrawerListener() {
        return new OnDrawerListener() {
            @Override
            public void onDrawerClosed(View drawerView) {
@@ -644,83 +605,26 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
        };
    }

    private void populateDrawerWithFolders(@Nullable List<Folder> folders) {
        if (folders != null) {
            List<IDrawerItem> drawerItems = new ArrayList<>(folders.size());
            long openedFolderId = -1;
            for (Folder folder : folders) {
                PrimaryDrawerItem item = new PrimaryDrawerItem()
                        .withIcon(getFolderIcon(folder))
                        .withIdentifier(folder.getId())
                        .withTag(folder)
                        .withName(getFolderDisplayName(folder));

                drawerItems.add(item);

                if (folder.getServerId().equals(openedFolder)) {
                    openedFolderId = folder.getId();
                }
            }
            drawer.setItems(drawerItems);

            if (openedFolderId != -1) {
                drawer.setSelection(openedFolderId, false);
            }
        } else {
            drawer.removeAllItems();
        }
    }

    private void initializeFolderIcons() {
        iconFolderInboxResId = getResId(R.attr.iconFolderInbox);
        iconFolderOutbotResId = getResId(R.attr.iconFolderOutbox);
        iconFolderSentResId = getResId(R.attr.iconFolderSent);
        iconFolderTrashResId = getResId(R.attr.iconFolderTrash);
        iconFolderDraftsResId = getResId(R.attr.iconFolderDrafts);
        iconFolderArchiveResId = getResId(R.attr.iconFolderArchive);
        iconFolderSpamResId = getResId(R.attr.iconFolderSpam);
        iconFolderResId = getResId(R.attr.iconFolder);
    }

    private int getResId(int resAttribute) {
        TypedValue typedValue = new TypedValue();
        boolean found = getTheme().resolveAttribute(resAttribute, typedValue, true);
        if (!found) {
            throw new AssertionError("Couldn't find resource with attribute " + resAttribute);
        }
        return typedValue.resourceId;
    }
    public void openFolder(String folderName) {
        LocalSearch search = new LocalSearch(folderName);
        search.addAccountUuid(account.getUuid());
        search.addAllowedFolder(folderName);

    private int getFolderIcon(Folder folder) {
        switch (folder.getType()) {
            case INBOX: return iconFolderInboxResId;
            case OUTBOX: return iconFolderOutbotResId;
            case SENT: return iconFolderSentResId;
            case TRASH: return iconFolderTrashResId;
            case DRAFTS: return iconFolderDraftsResId;
            case ARCHIVE: return iconFolderArchiveResId;
            case SPAM: return iconFolderSpamResId;
            default: return iconFolderResId;
        }
        performSearch(search);
    }

    private String getFolderDisplayName(Folder folder) {
        return folderNameFormatter.displayName(folder);
    public void openUnifiedInbox() {
        drawer.selectUnifiedInbox();
        performSearch(SearchAccount.createUnifiedInboxAccount().getRelatedSearch());
    }

    private FragmentTransaction openFolder(String folderName) {
        LocalSearch search = new LocalSearch(folderName);
        search.addAccountUuid(account.getUuid());
        search.addAllowedFolder(folderName);

    private void performSearch(LocalSearch search) {
        initializeFromLocalSearch(search);

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction ft = fragmentManager.beginTransaction();
        openFolderTransaction = fragmentManager.beginTransaction();
        messageListFragment = MessageListFragment.newInstance(search, false, K9.isThreadedViewEnabled());
        ft.replace(R.id.message_list_container, messageListFragment);

        return ft;
        openFolderTransaction.replace(R.id.message_list_container, messageListFragment);
    }

    protected boolean isDrawerEnabled() {
@@ -969,10 +873,10 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
        if (id == android.R.id.home) {
            if (displayMode != DisplayMode.MESSAGE_VIEW && !isAdditionalMessageListDisplayed()) {
                if (isDrawerEnabled()) {
                    if (drawer.isDrawerOpen()) {
                        drawer.closeDrawer();
                    if (drawer.isOpen()) {
                        drawer.close();
                    } else {
                        drawer.openDrawer();
                        drawer.open();
                    }
                } else {
                    finish();
@@ -1762,12 +1666,12 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
    }

    private void lockDrawer() {
        drawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawer.lock();
        drawerToggle.setDrawerIndicatorEnabled(false);
    }

    private void unlockDrawer() {
        drawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawer.unlock();
        drawerToggle.setDrawerIndicatorEnabled(true);
    }

@@ -1791,9 +1695,11 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
        List<String> folderServerIds = search.getFolderServerIds();
        singleFolderMode = singleAccountMode && folderServerIds.size() == 1;
        if (singleFolderMode) {
            openedFolder = folderServerIds.get(0);
            drawer.selectFolder(folderServerIds.get(0));
        } else if (search.getId().equals(SearchAccount.UNIFIED_INBOX)) {
            drawer.selectUnifiedInbox();
        } else {
            openedFolder = null;
            drawer.selectFolder(null);
        }

        // now we know if we are in single account mode and need a subtitle
+233 −0
Original line number Diff line number Diff line
package com.fsck.k9.ui;


import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.DrawerLayout;
import android.util.TypedValue;
import android.view.View;

import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.activity.MessageList;
import com.fsck.k9.mailstore.Folder;
import com.fsck.k9.ui.folders.FolderNameFormatter;
import com.fsck.k9.ui.settings.SettingsActivity;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.Drawer.OnDrawerItemClickListener;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;


public class K9Drawer {
    // Bit shift for identifiers of user folders items, to leave space for other items
    private static final short DRAWER_FOLDER_SHIFT = 2;

    private static final long DRAWER_ID_UNIFIED_INBOX = 0;
    private static final long DRAWER_ID_PREFERENCES = 1;


    private final FolderNameFormatter folderNameFormatter = DI.get(FolderNameFormatter.class);

    private final Drawer drawer;
    private final MessageList parent;
    private int headerItemCount = 0;

    private int iconFolderInboxResId;
    private int iconFolderOutboxResId;
    private int iconFolderSentResId;
    private int iconFolderTrashResId;
    private int iconFolderDraftsResId;
    private int iconFolderArchiveResId;
    private int iconFolderSpamResId;
    private int iconFolderResId;

    private final List<Long> userFolderDrawerIds = new ArrayList<>();
    private boolean unifiedInboxSelected;
    private String openedFolderServerId;


    public K9Drawer(MessageList parent, Bundle savedInstanceState) {
        this.parent = parent;

        drawer = new DrawerBuilder()
                .withActivity(parent)
                .withDisplayBelowStatusBar(false)
                .withTranslucentStatusBar(false)
                .withDrawerLayout(R.layout.material_drawer_fits_not)
                .withActionBarDrawerToggle(true)
                .withOnDrawerItemClickListener(createItemClickListener())
                .withOnDrawerListener(parent.createOnDrawerListener())
                .withSavedInstance(savedInstanceState)
                .build();

        addHeaderItems();
        addFooterItems();

        initializeFolderIcons();
    }

    private void addHeaderItems() {
        if (!K9.isHideSpecialAccounts()) {
            drawer.addItems(new PrimaryDrawerItem()
                            .withName(R.string.integrated_inbox_title)
                            .withIcon(getResId(R.attr.iconUnifiedInbox))
                            .withIdentifier(DRAWER_ID_UNIFIED_INBOX),
                    new DividerDrawerItem());

            headerItemCount += 2;
        }
    }

    private void addFooterItems() {
        drawer.addItems(new DividerDrawerItem(),
                new PrimaryDrawerItem()
                .withName(R.string.preferences_action)
                .withIcon(getResId(R.attr.iconActionSettings))
                .withIdentifier(DRAWER_ID_PREFERENCES)
                .withSelectable(false));
    }

    private void initializeFolderIcons() {
        iconFolderInboxResId = getResId(R.attr.iconFolderInbox);
        iconFolderOutboxResId = getResId(R.attr.iconFolderOutbox);
        iconFolderSentResId = getResId(R.attr.iconFolderSent);
        iconFolderTrashResId = getResId(R.attr.iconFolderTrash);
        iconFolderDraftsResId = getResId(R.attr.iconFolderDrafts);
        iconFolderArchiveResId = getResId(R.attr.iconFolderArchive);
        iconFolderSpamResId = getResId(R.attr.iconFolderSpam);
        iconFolderResId = getResId(R.attr.iconFolder);
    }

    private int getResId(int resAttribute) {
        TypedValue typedValue = new TypedValue();
        boolean found = parent.getTheme().resolveAttribute(resAttribute, typedValue, true);
        if (!found) {
            throw new AssertionError("Couldn't find resource with attribute " + resAttribute);
        }
        return typedValue.resourceId;
    }

    private int getFolderIcon(Folder folder) {
        switch (folder.getType()) {
            case INBOX: return iconFolderInboxResId;
            case OUTBOX: return iconFolderOutboxResId;
            case SENT: return iconFolderSentResId;
            case TRASH: return iconFolderTrashResId;
            case DRAFTS: return iconFolderDraftsResId;
            case ARCHIVE: return iconFolderArchiveResId;
            case SPAM: return iconFolderSpamResId;
            default: return iconFolderResId;
        }
    }

    private String getFolderDisplayName(Folder folder) {
        return folderNameFormatter.displayName(folder);
    }

    private OnDrawerItemClickListener createItemClickListener() {
        return new OnDrawerItemClickListener() {
            @Override
            public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                long id = drawerItem.getIdentifier();
                if (id == DRAWER_ID_UNIFIED_INBOX) {
                    parent.openUnifiedInbox();
                    return false;
                } else if (id == DRAWER_ID_PREFERENCES) {
                    SettingsActivity.launch(parent);
                    return false;
                }

                Folder folder = (Folder) drawerItem.getTag();
                parent.openFolder(folder.getServerId());
                return false;
            }
        };
    }

    public void setUserFolders(@Nullable List<Folder> folders) {
        clearUserFolders();

        if (folders == null) {
            return;
        }

        long openedFolderDrawerId = -1;
        for (int i = folders.size() - 1; i >= 0; i--) {
            Folder folder = folders.get(i);
            long drawerId = folder.getId() << DRAWER_FOLDER_SHIFT;
            drawer.addItemAtPosition(new PrimaryDrawerItem()
                    .withIcon(getFolderIcon(folder))
                    .withIdentifier(drawerId)
                    .withTag(folder)
                    .withName(getFolderDisplayName(folder)),
                    headerItemCount);

            userFolderDrawerIds.add(drawerId);

            if (folder.getServerId().equals(openedFolderServerId)) {
                openedFolderDrawerId = drawerId;
            }
        }

        if (openedFolderDrawerId != -1) {
            drawer.setSelection(openedFolderDrawerId, false);
        } else if (unifiedInboxSelected) {
            selectUnifiedInbox();
        }
    }

    private void clearUserFolders() {
        for (long drawerId : userFolderDrawerIds) {
            drawer.removeItem(drawerId);
        }
        userFolderDrawerIds.clear();
    }

    public void selectFolder(String folderServerId) {
        unifiedInboxSelected = false;
        openedFolderServerId = folderServerId;
        for (long drawerId : userFolderDrawerIds) {
            Folder folder = (Folder) drawer.getDrawerItem(drawerId).getTag();
            if (folder.getServerId().equals(folderServerId)) {
                drawer.setSelection(drawerId, false);
                return;
            }
        }
    }

    public void selectUnifiedInbox() {
        unifiedInboxSelected = true;
        openedFolderServerId = null;
        drawer.setSelection(DRAWER_ID_UNIFIED_INBOX, false);
    }

    public DrawerLayout getLayout() {
        return drawer.getDrawerLayout();
    }

    public boolean isOpen() {
        return drawer.isDrawerOpen();
    }

    public void open() {
        drawer.openDrawer();
    }

    public void close() {
        drawer.closeDrawer();
    }

    public void lock() {
        drawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    }

    public void unlock() {
        drawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    }
}
+7 −0
Original line number Diff line number Diff line
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="24dp"
    android:width="24dp"
    android:viewportWidth="24"
		android:viewportHeight="24">
    <path android:fillColor="#fff" android:pathData="M19 3H5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 6h-4c0 1.62-1.38 3-3 3s-3-1.38-3-3H5V5h14v4zm-4 7h6v3c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3z" />
</vector>
Loading