Enable users to filter folders by identity
This commit is contained in:
@@ -3,6 +3,9 @@ package i2p.bote.android;
|
|||||||
public class Constants {
|
public class Constants {
|
||||||
public static final String ANDROID_LOG_TAG = "I2P-Bote";
|
public static final String ANDROID_LOG_TAG = "I2P-Bote";
|
||||||
|
|
||||||
|
public static final String SHARED_PREFS = "i2p.bote";
|
||||||
|
public static final String PREF_SELECTED_IDENTITY = "selectedIdentity";
|
||||||
|
|
||||||
public static final String EMAILDEST_SCHEME = "bote";
|
public static final String EMAILDEST_SCHEME = "bote";
|
||||||
|
|
||||||
public static final String NDEF_DOMAIN = "i2p.bote";
|
public static final String NDEF_DOMAIN = "i2p.bote";
|
||||||
|
|||||||
@@ -23,12 +23,19 @@ import android.widget.AdapterView;
|
|||||||
|
|
||||||
import com.mikepenz.materialdrawer.Drawer;
|
import com.mikepenz.materialdrawer.Drawer;
|
||||||
import com.mikepenz.materialdrawer.DrawerBuilder;
|
import com.mikepenz.materialdrawer.DrawerBuilder;
|
||||||
|
import com.mikepenz.materialdrawer.accountswitcher.AccountHeader;
|
||||||
|
import com.mikepenz.materialdrawer.accountswitcher.AccountHeaderBuilder;
|
||||||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
||||||
|
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||||
|
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||||
|
|
||||||
import net.i2p.android.ui.I2PAndroidHelper;
|
import net.i2p.android.ui.I2PAndroidHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import i2p.bote.I2PBote;
|
import i2p.bote.I2PBote;
|
||||||
@@ -42,6 +49,7 @@ import i2p.bote.android.service.Init.RouterChoice;
|
|||||||
import i2p.bote.android.util.BetterAsyncTaskLoader;
|
import i2p.bote.android.util.BetterAsyncTaskLoader;
|
||||||
import i2p.bote.android.util.BoteHelper;
|
import i2p.bote.android.util.BoteHelper;
|
||||||
import i2p.bote.android.util.MoveToDialogFragment;
|
import i2p.bote.android.util.MoveToDialogFragment;
|
||||||
|
import i2p.bote.email.EmailIdentity;
|
||||||
import i2p.bote.fileencryption.PasswordCacheListener;
|
import i2p.bote.fileencryption.PasswordCacheListener;
|
||||||
import i2p.bote.fileencryption.PasswordException;
|
import i2p.bote.fileencryption.PasswordException;
|
||||||
import i2p.bote.folder.EmailFolder;
|
import i2p.bote.folder.EmailFolder;
|
||||||
@@ -61,10 +69,10 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
/**
|
/**
|
||||||
* Navigation drawer variables
|
* Navigation drawer variables
|
||||||
*/
|
*/
|
||||||
|
private AccountHeader mAccountHeader;
|
||||||
private Drawer mDrawer;
|
private Drawer mDrawer;
|
||||||
private int mSelected;
|
private int mSelected;
|
||||||
|
|
||||||
private static final String SHARED_PREFS = "i2p.bote";
|
|
||||||
private static final String PREF_FIRST_START = "firstStart";
|
private static final String PREF_FIRST_START = "firstStart";
|
||||||
|
|
||||||
private static final int SHOW_INTRODUCTION = 1;
|
private static final int SHOW_INTRODUCTION = 1;
|
||||||
@@ -73,6 +81,9 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
private static final int ID_ADDRESS_BOOK = 1;
|
private static final int ID_ADDRESS_BOOK = 1;
|
||||||
private static final int ID_NET_STATUS = 2;
|
private static final int ID_NET_STATUS = 2;
|
||||||
|
|
||||||
|
private static final int LOADER_IDENTITIES = 0;
|
||||||
|
private static final int LOADER_DRAWER_FOLDERS = 1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -84,7 +95,21 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
|
|
||||||
// Initialize variables
|
// Initialize variables
|
||||||
mHelper = new I2PAndroidHelper(this);
|
mHelper = new I2PAndroidHelper(this);
|
||||||
mSharedPrefs = getSharedPreferences(SHARED_PREFS, 0);
|
mSharedPrefs = getSharedPreferences(Constants.SHARED_PREFS, 0);
|
||||||
|
|
||||||
|
mAccountHeader = new AccountHeaderBuilder()
|
||||||
|
.withActivity(this)
|
||||||
|
.withHeaderBackground(R.drawable.drawer_header_background)
|
||||||
|
.withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) {
|
||||||
|
if (!currentProfile)
|
||||||
|
identitySelected(profile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.withSavedInstance(savedInstanceState)
|
||||||
|
.build();
|
||||||
|
|
||||||
IDrawerItem addressBook = new PrimaryDrawerItem()
|
IDrawerItem addressBook = new PrimaryDrawerItem()
|
||||||
.withIdentifier(ID_ADDRESS_BOOK)
|
.withIdentifier(ID_ADDRESS_BOOK)
|
||||||
@@ -109,6 +134,7 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
.withToolbar(toolbar)
|
.withToolbar(toolbar)
|
||||||
.withDrawerWidthPx(drawerWidth)
|
.withDrawerWidthPx(drawerWidth)
|
||||||
.withShowDrawerOnFirstLaunch(true)
|
.withShowDrawerOnFirstLaunch(true)
|
||||||
|
.withAccountHeader(mAccountHeader)
|
||||||
.addStickyDrawerItems(addressBook, networkStatus)
|
.addStickyDrawerItems(addressBook, networkStatus)
|
||||||
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
|
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -160,6 +186,7 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
mAccountHeader.saveInstanceState(outState);
|
||||||
mDrawer.saveInstanceState(outState);
|
mDrawer.saveInstanceState(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +220,16 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
getSupportLoaderManager().initLoader(0, null, new DrawerFolderLoaderCallbacks());
|
|
||||||
|
if (I2PBote.getInstance().isPasswordRequired()) {
|
||||||
|
// Ensure any existing data is destroyed.
|
||||||
|
getSupportLoaderManager().destroyLoader(LOADER_IDENTITIES);
|
||||||
|
} else {
|
||||||
|
// Password is cached, or not set.
|
||||||
|
getSupportLoaderManager().initLoader(LOADER_IDENTITIES, null, new IdentityLoaderCallbacks());
|
||||||
|
}
|
||||||
|
|
||||||
|
getSupportLoaderManager().initLoader(LOADER_DRAWER_FOLDERS, null, new DrawerFolderLoaderCallbacks());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -287,6 +323,16 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
.withSelectedIconColorRes(R.color.primary);
|
.withSelectedIconColorRes(R.color.primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void identitySelected(IProfile profile) {
|
||||||
|
EmailIdentity identity = (EmailIdentity) ((ProfileDrawerItem) profile).getTag();
|
||||||
|
mSharedPrefs.edit()
|
||||||
|
.putString(Constants.PREF_SELECTED_IDENTITY, identity.getKey())
|
||||||
|
.apply();
|
||||||
|
EmailListFragment f = (EmailListFragment) getSupportFragmentManager()
|
||||||
|
.findFragmentById(R.id.list_fragment);
|
||||||
|
f.onIdentitySelected();
|
||||||
|
}
|
||||||
|
|
||||||
private void drawerFolderSelected(EmailFolder folder, boolean alreadySelected) {
|
private void drawerFolderSelected(EmailFolder folder, boolean alreadySelected) {
|
||||||
if (!alreadySelected) {
|
if (!alreadySelected) {
|
||||||
// Create the new fragment
|
// Create the new fragment
|
||||||
@@ -351,6 +397,87 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
// Loaders
|
// Loaders
|
||||||
//
|
//
|
||||||
|
|
||||||
|
private class IdentityLoaderCallbacks implements LoaderManager.LoaderCallbacks<ArrayList<IProfile>> {
|
||||||
|
@Override
|
||||||
|
public Loader<ArrayList<IProfile>> onCreateLoader(int id, Bundle args) {
|
||||||
|
return new DrawerIdentityLoader(EmailListActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(Loader<ArrayList<IProfile>> loader, ArrayList<IProfile> data) {
|
||||||
|
mAccountHeader.setProfiles(data);
|
||||||
|
String selectedIdentity = mSharedPrefs.getString(Constants.PREF_SELECTED_IDENTITY, null);
|
||||||
|
if (selectedIdentity != null) {
|
||||||
|
for (IProfile profile : data) {
|
||||||
|
EmailIdentity identity = (EmailIdentity) ((ProfileDrawerItem) profile).getTag();
|
||||||
|
if (selectedIdentity.equals(identity.getKey())) {
|
||||||
|
mAccountHeader.setActiveProfile(profile, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else // AccountHeader selects the first one by default
|
||||||
|
identitySelected(data.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(Loader<ArrayList<IProfile>> loader) {
|
||||||
|
mAccountHeader.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DrawerIdentityLoader extends BetterAsyncTaskLoader<ArrayList<IProfile>> {
|
||||||
|
private int identiconSize;
|
||||||
|
|
||||||
|
public DrawerIdentityLoader(Context context) {
|
||||||
|
super(context);
|
||||||
|
identiconSize = context.getResources().getDimensionPixelSize(
|
||||||
|
com.mikepenz.materialdrawer.R.dimen.material_drawer_item_profile_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<IProfile> loadInBackground() {
|
||||||
|
ArrayList<IProfile> profiles = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
Collection<EmailIdentity> identities = I2PBote.getInstance().getIdentities().getAll();
|
||||||
|
for (EmailIdentity identity : identities) {
|
||||||
|
profiles.add(getIdentityDrawerItem(identity));
|
||||||
|
}
|
||||||
|
} catch (PasswordException e) {
|
||||||
|
// TODO handle, but should not get here
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return profiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IProfile getIdentityDrawerItem(EmailIdentity identity) {
|
||||||
|
return new ProfileDrawerItem()
|
||||||
|
.withIdentifier(identity.hashCode())
|
||||||
|
.withTag(identity)
|
||||||
|
.withName(identity.getPublicName())
|
||||||
|
.withEmail(identity.getDescription())
|
||||||
|
.withIcon(BoteHelper.getIdentityPicture(identity, identiconSize, identiconSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStartMonitoring() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStopMonitoring() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources(ArrayList<IProfile> data) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class DrawerFolderLoaderCallbacks implements LoaderManager.LoaderCallbacks<List<IDrawerItem>> {
|
private class DrawerFolderLoaderCallbacks implements LoaderManager.LoaderCallbacks<List<IDrawerItem>> {
|
||||||
@Override
|
@Override
|
||||||
public Loader<List<IDrawerItem>> onCreateLoader(int id, Bundle args) {
|
public Loader<List<IDrawerItem>> onCreateLoader(int id, Bundle args) {
|
||||||
@@ -405,6 +532,7 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
.withName(BoteHelper.getFolderDisplayName(getContext(), folder));
|
.withName(BoteHelper.getFolderDisplayName(getContext(), folder));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// TODO change this when per-identity new emails can be determined
|
||||||
int numNew = folder.getNumNewEmails();
|
int numNew = folder.getNumNewEmails();
|
||||||
if (numNew > 0)
|
if (numNew > 0)
|
||||||
item.withBadge("" + numNew);
|
item.withBadge("" + numNew);
|
||||||
@@ -484,14 +612,20 @@ public class EmailListActivity extends BoteActivityBase implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void passwordProvided() {
|
public void passwordProvided() {
|
||||||
// Trigger the loader to show the drawer badges
|
// Password is cached, or not set.
|
||||||
getSupportLoaderManager().restartLoader(0, null, new DrawerFolderLoaderCallbacks());
|
getSupportLoaderManager().restartLoader(LOADER_IDENTITIES, null, new IdentityLoaderCallbacks());
|
||||||
|
// Trigger the drawer folder loader to show the drawer badges
|
||||||
|
getSupportLoaderManager().restartLoader(LOADER_DRAWER_FOLDERS, null, new DrawerFolderLoaderCallbacks());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void passwordCleared() {
|
public void passwordCleared() {
|
||||||
// Trigger the loader to hide the drawer badges
|
if (mAccountHeader.isSelectionListShown())
|
||||||
getSupportLoaderManager().restartLoader(0, null, new DrawerFolderLoaderCallbacks());
|
mAccountHeader.toggleSelectionList(this);
|
||||||
|
// Ensure any existing data is destroyed.
|
||||||
|
getSupportLoaderManager().destroyLoader(LOADER_IDENTITIES);
|
||||||
|
// Trigger the drawer folder loader to hide the drawer badges
|
||||||
|
getSupportLoaderManager().restartLoader(LOADER_DRAWER_FOLDERS, null, new DrawerFolderLoaderCallbacks());
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkStatusListener
|
// NetworkStatusListener
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ import net.i2p.util.Log;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.mail.Address;
|
||||||
import javax.mail.Flags.Flag;
|
import javax.mail.Flags.Flag;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
|
|
||||||
@@ -370,6 +372,12 @@ public class EmailListFragment extends AuthenticatedFragment implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by EmailListActivity.onIdentitySelected()
|
||||||
|
|
||||||
|
public void onIdentitySelected() {
|
||||||
|
getLoaderManager().restartLoader(EMAIL_LIST_LOADER, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
// Called by EmailListActivity.onFolderSelected()
|
// Called by EmailListActivity.onFolderSelected()
|
||||||
|
|
||||||
public void onFolderSelected(EmailFolder newFolder) {
|
public void onFolderSelected(EmailFolder newFolder) {
|
||||||
@@ -384,26 +392,61 @@ public class EmailListFragment extends AuthenticatedFragment implements
|
|||||||
// LoaderManager.LoaderCallbacks<List<Email>>
|
// LoaderManager.LoaderCallbacks<List<Email>>
|
||||||
|
|
||||||
public Loader<List<Email>> onCreateLoader(int id, Bundle args) {
|
public Loader<List<Email>> onCreateLoader(int id, Bundle args) {
|
||||||
return new EmailListLoader(getActivity(), mFolder);
|
return new EmailListLoader(getActivity(), mFolder,
|
||||||
|
getActivity().getSharedPreferences(Constants.SHARED_PREFS, 0)
|
||||||
|
.getString(Constants.PREF_SELECTED_IDENTITY, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class EmailListLoader extends BetterAsyncTaskLoader<List<Email>> implements
|
private static class EmailListLoader extends BetterAsyncTaskLoader<List<Email>> implements
|
||||||
FolderListener {
|
FolderListener {
|
||||||
private EmailFolder mFolder;
|
private EmailFolder mFolder;
|
||||||
|
private String mSelectedIdentityKey;
|
||||||
|
|
||||||
public EmailListLoader(Context context, EmailFolder folder) {
|
public EmailListLoader(Context context, EmailFolder folder, String selectedIdentityKey) {
|
||||||
super(context);
|
super(context);
|
||||||
mFolder = folder;
|
mFolder = folder;
|
||||||
|
mSelectedIdentityKey = selectedIdentityKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Email> loadInBackground() {
|
public List<Email> loadInBackground() {
|
||||||
List<Email> emails = null;
|
List<Email> emails = null;
|
||||||
try {
|
try {
|
||||||
emails = BoteHelper.getEmails(mFolder, null, true);
|
List<Email> allEmails = BoteHelper.getEmails(mFolder, null, true);
|
||||||
|
|
||||||
|
if (mSelectedIdentityKey != null) {
|
||||||
|
emails = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Email email : allEmails) {
|
||||||
|
boolean add = false;
|
||||||
|
if (BoteHelper.isSentEmail(email)) {
|
||||||
|
String senderDest = BoteHelper.extractEmailDestination(email.getOneFromAddress());
|
||||||
|
if (mSelectedIdentityKey.equals(senderDest))
|
||||||
|
add = true;
|
||||||
|
} else {
|
||||||
|
for (Address recipient : email.getAllRecipients()) {
|
||||||
|
String recipientDest = BoteHelper.extractEmailDestination(recipient.toString());
|
||||||
|
if (mSelectedIdentityKey.equals(recipientDest)) {
|
||||||
|
add = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (add)
|
||||||
|
emails.add(email);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
emails = allEmails;
|
||||||
} catch (PasswordException pe) {
|
} catch (PasswordException pe) {
|
||||||
// XXX: Should not get here.
|
// XXX: Should not get here.
|
||||||
|
} catch (MessagingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return emails;
|
return emails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,13 +89,8 @@ public class IdentityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||||||
final IdentityViewHolder cvh = (IdentityViewHolder) holder;
|
final IdentityViewHolder cvh = (IdentityViewHolder) holder;
|
||||||
EmailIdentity identity = mIdentities.get(position);
|
EmailIdentity identity = mIdentities.get(position);
|
||||||
|
|
||||||
String pic = identity.getPictureBase64();
|
ViewGroup.LayoutParams lp = cvh.mPicture.getLayoutParams();
|
||||||
if (pic != null && !pic.isEmpty())
|
cvh.mPicture.setImageBitmap(BoteHelper.getIdentityPicture(identity, lp.width, lp.height));
|
||||||
cvh.mPicture.setImageBitmap(BoteHelper.decodePicture(pic));
|
|
||||||
else {
|
|
||||||
ViewGroup.LayoutParams lp = cvh.mPicture.getLayoutParams();
|
|
||||||
cvh.mPicture.setImageBitmap(BoteHelper.getIdenticonForAddress(identity.getKey(), lp.width, lp.height));
|
|
||||||
}
|
|
||||||
|
|
||||||
cvh.mName.setText(identity.getPublicName());
|
cvh.mName.setText(identity.getPublicName());
|
||||||
|
|
||||||
|
|||||||
@@ -208,6 +208,14 @@ public class BoteHelper extends GeneralHelper {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Bitmap getIdentityPicture(EmailIdentity identity, int identiconWidth, int identiconHeight) {
|
||||||
|
String pic = identity.getPictureBase64();
|
||||||
|
if (pic != null && !pic.isEmpty())
|
||||||
|
return BoteHelper.decodePicture(pic);
|
||||||
|
else
|
||||||
|
return BoteHelper.getIdenticonForAddress(identity.getKey(), identiconWidth, identiconHeight);
|
||||||
|
}
|
||||||
|
|
||||||
private static final String PROPERTY_SENT = "sent";
|
private static final String PROPERTY_SENT = "sent";
|
||||||
public static void setEmailSent(Email email, boolean isSent) {
|
public static void setEmailSent(Email email, boolean isSent) {
|
||||||
email.getMetadata().setProperty(PROPERTY_SENT, isSent ? "true" : "false");
|
email.getMetadata().setProperty(PROPERTY_SENT, isSent ? "true" : "false");
|
||||||
|
|||||||
4
app/src/main/res/drawable/drawer_header_background.xml
Normal file
4
app/src/main/res/drawable/drawer_header_background.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/primary"/>
|
||||||
|
</shape>
|
||||||
Reference in New Issue
Block a user