1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-30 13:12:25 -05:00

Added a button to switch the identity in MessageCompose

Originally I wanted to use a Spinner, but it doesn't support multiple
view types (see [1]). Those are necessary because we use different
layouts for accounts (section headers) and identities (selectable list
items).
Removed the ChooseAccount activity because it's now unused.
This commit is contained in:
cketti 2012-03-22 22:17:10 +01:00
parent 1d28eb003d
commit 8180fd9ad2
8 changed files with 215 additions and 380 deletions

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ExpandableListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="?android:attr/listDivider"
android:childDivider="?android:attr/listDivider"
android:indicatorLeft="14dip" />

View File

@ -3,37 +3,21 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingRight="6dip"
android:paddingBottom="2dip"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical" >
<View
android:id="@+id/chip"
android:layout_width="6dip"
android:layout_height="fill_parent"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft" >
android:background="#cccccc"
android:gravity="left|center_vertical">
<TextView
android:id="@+id/description"
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="end"
android:paddingTop="2dp"
android:paddingLeft="18dp"
android:paddingRight="4dp"
android:paddingBottom="2dp"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>

View File

@ -5,25 +5,20 @@
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingRight="6dip"
android:paddingBottom="2dip"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical">
<View
android:id="@+id/chip"
android:layout_width="6dip"
android:layout_height="fill_parent"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true" />
android:layout_width="6dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft" >
android:paddingLeft="12dp"
android:paddingRight="4dp">
<TextView
android:id="@+id/name"

View File

@ -20,17 +20,34 @@
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="6dp"
android:orientation="vertical"
android:background="#ededed" >
<TextView
android:id="@+id/from"
<LinearLayout
android:id="@+id/identity_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:layout_marginRight="6dip"
android:text="@string/send_as"
android:textColor="@android:color/primary_text_light"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<Button
android:id="@+id/identity"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:layout_marginRight="6dip"/>
</LinearLayout>
<LinearLayout
android:id="@+id/to_wrapper"
android:layout_height="wrap_content"

View File

@ -30,12 +30,6 @@
android:title="@string/discard_action"
android:icon="@drawable/ic_menu_close_clear_cancel"
/>
<item
android:id="@+id/choose_identity"
android:alphabeticShortcut="i"
android:title="@string/send_as"
android:icon="@drawable/ic_menu_identity"
/>
<item
android:id="@+id/read_receipt"
android:alphabeticShortcut="r"

View File

@ -1,243 +0,0 @@
package com.fsck.k9.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;
import com.fsck.k9.Account;
import com.fsck.k9.Identity;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.R;
import java.util.List;
/**
* Activity displaying list of accounts/identity for user choice
*
* @see K9ExpandableListActivity
*/
public class ChooseAccount extends K9ExpandableListActivity {
private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[0];
/**
* {@link Intent} extended data name for storing {@link Account#getUuid()
* account UUID}
*/
public static final String EXTRA_ACCOUNT = ChooseAccount.class.getName() + "_account";
/**
* {@link Intent} extended data name for storing serialized {@link Identity}
*/
public static final String EXTRA_IDENTITY = ChooseAccount.class.getName() + "_identity";
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.choose_account);
final ExpandableListView expandableListView = getExpandableListView();
expandableListView.setItemsCanFocus(false);
final IdentitiesAdapter adapter = createAdapter();
setListAdapter(adapter);
expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
final Identity identity = (Identity) adapter.getChild(groupPosition, childPosition);
final Account account = (Account) adapter.getGroup(groupPosition);
if (!account.isAvailable(v.getContext())) {
Log.i(K9.LOG_TAG, "Refusing selection of unavailable account");
return true;
}
final Intent intent = new Intent();
intent.putExtra(EXTRA_ACCOUNT, account.getUuid());
intent.putExtra(EXTRA_IDENTITY, identity);
setResult(RESULT_OK, intent);
finish();
return true;
}
});
final Bundle extras = getIntent().getExtras();
final String uuid = extras.getString(EXTRA_ACCOUNT);
if (uuid != null) {
final Account[] accounts = adapter.getAccounts();
final int length = accounts.length;
for (int i = 0; i < length; i++) {
final Account account = accounts[i];
if (uuid.equals(account.getUuid())) {
// setSelectedChild() doesn't seem to obey the
// shouldExpandGroup parameter (2.1), manually expanding
// group
expandableListView.expandGroup(i);
final List<Identity> identities = account.getIdentities();
final Identity identity = (Identity) extras.getSerializable(EXTRA_IDENTITY);
if (identity == null) {
expandableListView.setSelectedChild(i, 0, true);
break;
}
for (int j = 0; j < identities.size(); j++) {
final Identity loopIdentity = identities.get(j);
if (identity.equals(loopIdentity)) {
expandableListView.setSelectedChild(i, j, true);
break;
}
}
break;
}
}
}
}
private IdentitiesAdapter createAdapter() {
return new IdentitiesAdapter(this, getLayoutInflater());
}
/**
* Dynamically provides accounts/identities data for
* {@link ExpandableListView#setAdapter(ExpandableListAdapter)}:
*
* <ul>
* <li>Groups represent {@link Account accounts}</li>
* <li>Children represent {@link Identity identities} of the parent account</li>
* </ul>
*/
public static class IdentitiesAdapter extends BaseExpandableListAdapter {
private Context mContext;
private LayoutInflater mLayoutInflater;
private Account[] mAccounts;
public IdentitiesAdapter(final Context context, final LayoutInflater layoutInflater) {
mContext = context;
mLayoutInflater = layoutInflater;
Preferences prefs = Preferences.getPreferences(mContext);
mAccounts = prefs.getAvailableAccounts().toArray(EMPTY_ACCOUNT_ARRAY);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return getAccounts()[groupPosition].getIdentity(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return Integer.valueOf(childPosition).longValue();
}
@Override
public int getChildrenCount(int groupPosition) {
return getAccounts()[groupPosition].getIdentities().size();
}
@Override
public Object getGroup(int groupPosition) {
return getAccounts()[groupPosition];
}
@Override
public int getGroupCount() {
return getAccounts().length;
}
@Override
public long getGroupId(int groupPosition) {
return Integer.valueOf(groupPosition).longValue();
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
final View v;
if (convertView == null) {
v = mLayoutInflater.inflate(R.layout.choose_account_item, parent, false);
} else {
v = convertView;
}
final TextView description = (TextView) v.findViewById(R.id.description);
final Account account = getAccounts()[groupPosition];
description.setText(account.getDescription());
description.setTextSize(TypedValue.COMPLEX_UNIT_SP, K9.getFontSizes().getAccountName());
// display unavailable accounts translucent
/*
* 20101030/fiouzy: NullPointerException on null getBackground()
*
if (account.isAvailable(parent.getContext()))
{
description.getBackground().setAlpha(255);
description.getBackground().setAlpha(255);
}
else
{
description.getBackground().setAlpha(127);
description.getBackground().setAlpha(127);
}
*/
v.findViewById(R.id.chip).setBackgroundColor(account.getChipColor());
return v;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
final Account account = getAccounts()[groupPosition];
final Identity identity = account.getIdentity(childPosition);
final View v;
if (convertView == null) {
v = mLayoutInflater.inflate(R.layout.choose_identity_item, parent, false);
} else {
v = convertView;
}
final TextView name = (TextView) v.findViewById(R.id.name);
final TextView description = (TextView) v.findViewById(R.id.description);
name.setTextSize(TypedValue.COMPLEX_UNIT_SP, K9.getFontSizes().getAccountName());
description.setTextSize(TypedValue.COMPLEX_UNIT_SP, K9.getFontSizes().getAccountDescription());
name.setText(identity.getDescription());
description.setText(String.format("%s <%s>", identity.getName(), identity.getEmail()));
v.findViewById(R.id.chip).setBackgroundColor(account.getChipColor());
return v;
}
@Override
public boolean hasStableIds() {
// returning false since accounts/identities are mutable
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
private Account[] getAccounts() {
return mAccounts;
}
}
}

View File

@ -1,18 +0,0 @@
package com.fsck.k9.activity;
import android.app.ExpandableListActivity;
import android.os.Bundle;
import com.fsck.k9.K9;
/**
* @see ExpandableListActivity
*/
public class K9ExpandableListActivity extends ExpandableListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(K9.getK9Theme());
super.onCreate(savedInstanceState);
}
}

View File

@ -15,6 +15,7 @@ import com.fsck.k9.mail.*;
import com.fsck.k9.view.MessageWebView;
import org.apache.james.mime4j.codec.EncoderUtil;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Context;
@ -31,14 +32,17 @@ import android.provider.OpenableColumns;
import android.text.util.Rfc822Tokenizer;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.WebView;
import android.widget.AutoCompleteTextView.Validator;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
@ -84,6 +88,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private static final int DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED = 2;
private static final int DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY = 3;
private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 4;
private static final int DIALOG_CHOOSE_IDENTITY = 5;
private static final long INVALID_DRAFT_ID = MessagingController.INVALID_MESSAGE_ID;
@ -128,12 +133,11 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private static final int MSG_DISCARDED_DRAFT = 6;
private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
private static final int ACTIVITY_CHOOSE_IDENTITY = 2;
private static final int ACTIVITY_CHOOSE_ACCOUNT = 3;
private static final int CONTACT_PICKER_TO = 4;
private static final int CONTACT_PICKER_CC = 5;
private static final int CONTACT_PICKER_BCC = 6;
private static final int CONTACT_PICKER_TO = 2;
private static final int CONTACT_PICKER_CC = 3;
private static final int CONTACT_PICKER_BCC = 4;
private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[0];
/**
* Regular expression to remove the first localized "Re:" prefix in subjects.
@ -186,7 +190,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private QuotedTextMode mQuotedTextMode = QuotedTextMode.NONE;
private TextView mFromView;
private Button mChooseIdentityButton;
private LinearLayout mCcWrapper;
private LinearLayout mBccWrapper;
private MultiAutoCompleteTextView mToView;
@ -410,7 +414,14 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mAddressAdapter = EmailAddressAdapter.getInstance(this);
mAddressValidator = new EmailAddressValidator();
mFromView = (TextView) findViewById(R.id.from);
mChooseIdentityButton = (Button) findViewById(R.id.identity);
mChooseIdentityButton.setOnClickListener(this);
if (mAccount.getIdentities().size() == 1 &&
Preferences.getPreferences(this).getAvailableAccounts().size() == 1) {
findViewById(R.id.identity_container).setVisibility(View.GONE);
}
mToView = (MultiAutoCompleteTextView) findViewById(R.id.to);
mCcView = (MultiAutoCompleteTextView) findViewById(R.id.cc);
mBccView = (MultiAutoCompleteTextView) findViewById(R.id.bcc);
@ -548,8 +559,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mQuotedTextEdit.setOnClickListener(this);
mQuotedTextDelete.setOnClickListener(this);
mFromView.setVisibility(View.GONE);
mToView.setAdapter(mAddressAdapter);
mToView.setTokenizer(new Rfc822Tokenizer());
mToView.setValidator(mAddressValidator);
@ -607,8 +616,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mReadReceipt = mAccount.isMessageReadReceiptAlways();
mQuoteStyle = mAccount.getQuoteStyle();
if (!mSourceMessageProcessed) {
updateFrom();
if (!mSourceMessageProcessed) {
updateSignature();
if (ACTION_REPLY.equals(action) ||
@ -1776,12 +1786,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
addAttachment(data.getData());
mDraftNeedsSaving = true;
break;
case ACTIVITY_CHOOSE_IDENTITY:
onIdentityChosen(data);
break;
case ACTIVITY_CHOOSE_ACCOUNT:
onAccountChosen(data);
break;
case CONTACT_PICKER_TO:
case CONTACT_PICKER_CC:
case CONTACT_PICKER_BCC:
@ -1811,15 +1815,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
startActivityForResult(mContacts.contactPickerIntent(), resultId);
}
private void onAccountChosen(final Intent intent) {
final Bundle extras = intent.getExtras();
final String uuid = extras.getString(ChooseAccount.EXTRA_ACCOUNT);
final Identity identity = (Identity) extras.getSerializable(ChooseAccount.EXTRA_IDENTITY);
final Account account = Preferences.getPreferences(this).getAccount(uuid);
private void onAccountChosen(Account account, Identity identity) {
if (!mAccount.equals(account)) {
if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Switching account from " + mAccount + " to " + account);
@ -1863,11 +1859,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
switchToIdentity(identity);
}
private void onIdentityChosen(Intent intent) {
Bundle bundle = intent.getExtras();
switchToIdentity((Identity) bundle.getSerializable(ChooseIdentity.EXTRA_IDENTITY));
}
private void switchToIdentity(Identity identity) {
mIdentity = identity;
mIdentityChanged = true;
@ -1877,10 +1868,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
}
private void updateFrom() {
if (mIdentityChanged) {
mFromView.setVisibility(View.VISIBLE);
}
mFromView.setText(getString(R.string.message_view_from_format, mIdentity.getName(), mIdentity.getEmail()));
mChooseIdentityButton.setText(getIdentityDescription(mIdentity));
}
private void updateSignature() {
@ -1923,6 +1911,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
MessagingController.getInstance(getApplication()).loadMessageForView(account, folderName, sourceMessageUid, null);
}
break;
case R.id.identity:
showDialog(DIALOG_CHOOSE_IDENTITY);
break;
}
}
@ -1989,9 +1980,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
case R.id.add_attachment_video:
onAddAttachment2("video/*");
break;
case R.id.choose_identity:
onChooseIdentity();
break;
case R.id.read_receipt:
onReadReceipt();
default:
@ -2000,25 +1988,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
return true;
}
private void onChooseIdentity() {
// keep things simple: trigger account choice only if there are more
// than 1 account
mIgnoreOnPause = true;
if (Preferences.getPreferences(this).getAvailableAccounts().size() > 1) {
final Intent intent = new Intent(this, ChooseAccount.class);
intent.putExtra(ChooseAccount.EXTRA_ACCOUNT, mAccount.getUuid());
intent.putExtra(ChooseAccount.EXTRA_IDENTITY, mIdentity);
startActivityForResult(intent, ACTIVITY_CHOOSE_ACCOUNT);
} else if (mAccount.getIdentities().size() > 1) {
Intent intent = new Intent(this, ChooseIdentity.class);
intent.putExtra(ChooseIdentity.EXTRA_ACCOUNT, mAccount.getUuid());
startActivityForResult(intent, ACTIVITY_CHOOSE_IDENTITY);
} else {
Toast.makeText(this, getString(R.string.no_identities),
Toast.LENGTH_LONG).show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
@ -2148,6 +2117,19 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
}
})
.create();
case DIALOG_CHOOSE_IDENTITY:
Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.send_as);
final IdentityAdapter adapter = new IdentityAdapter(this, getLayoutInflater());
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
IdentityContainer container = (IdentityContainer) adapter.getItem(which);
onAccountChosen(container.account, container.identity);
}
});
return builder.create();
}
return super.onCreateDialog(id);
}
@ -3184,4 +3166,137 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
return insertable;
}
/**
* Used to store an {@link Identity} instance together with the {@link Account} it belongs to.
*
* @see IdentityAdapter
*/
static class IdentityContainer {
public final Identity identity;
public final Account account;
IdentityContainer(Identity identity, Account account) {
this.identity = identity;
this.account = account;
}
}
/**
* Adapter for the <em>Choose identity</em> list view.
*
* <p>
* Account names are displayed as section headers, identities as selectable list items.
* </p>
*/
static class IdentityAdapter extends BaseAdapter {
private LayoutInflater mLayoutInflater;
private List<Object> mItems;
private FontSizes mFontSizes;
public IdentityAdapter(Context context, LayoutInflater layoutInflater) {
mLayoutInflater = layoutInflater;
mFontSizes = K9.getFontSizes();
List<Object> items = new ArrayList<Object>();
Preferences prefs = Preferences.getPreferences(context.getApplicationContext());
Account[] accounts = prefs.getAvailableAccounts().toArray(EMPTY_ACCOUNT_ARRAY);
for (Account account : accounts) {
items.add(account);
List<Identity> identities = account.getIdentities();
for (Identity identity : identities) {
items.add(new IdentityContainer(identity, account));
}
}
mItems = items;
}
@Override
public int getCount() {
return mItems.size();
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
return (mItems.get(position) instanceof Account) ? 0 : 1;
}
@Override
public boolean isEnabled(int position) {
return (mItems.get(position) instanceof IdentityContainer);
}
@Override
public Object getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Object item = mItems.get(position);
View view = null;
if (item instanceof Account) {
if (convertView != null && convertView.getTag() instanceof TextView) {
view = convertView;
} else {
view = mLayoutInflater.inflate(R.layout.choose_account_item, parent, false);
TextView name = (TextView) view.findViewById(R.id.name);
view.setTag(name);
}
Account account = (Account) item;
TextView name = (TextView) view.getTag();
name.setText(account.getDescription());
} else if (item instanceof IdentityContainer) {
if (convertView != null && convertView.getTag() instanceof IdentityHolder) {
view = convertView;
} else {
view = mLayoutInflater.inflate(R.layout.choose_identity_item, parent, false);
IdentityHolder holder = new IdentityHolder();
holder.name = (TextView) view.findViewById(R.id.name);
holder.name.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getAccountName());
holder.description = (TextView) view.findViewById(R.id.description);
holder.description.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getAccountDescription());
holder.chip = view.findViewById(R.id.chip);
view.setTag(holder);
}
IdentityContainer identityContainer = (IdentityContainer) item;
Identity identity = identityContainer.identity;
Account account = identityContainer.account;
IdentityHolder holder = (IdentityHolder) view.getTag();
holder.name.setText(identity.getDescription());
holder.description.setText(getIdentityDescription(identity));
holder.chip.setBackgroundColor(account.getChipColor());
}
return view;
}
static class IdentityHolder {
public TextView name;
public TextView description;
public View chip;
}
}
private static String getIdentityDescription(Identity identity) {
return String.format("%s <%s>", identity.getName(), identity.getEmail());
}
}