mirror of
https://github.com/moparisthebest/k-9
synced 2025-01-09 20:58:07 -05:00
Merge branch 'master' into issue-162
This commit is contained in:
commit
ffb8227c45
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest
|
<manifest
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:versionCode="15007"
|
android:versionCode="15009"
|
||||||
android:versionName="4.107" package="com.fsck.k9"
|
android:versionName="4.109" package="com.fsck.k9"
|
||||||
>
|
>
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="7"
|
android:minSdkVersion="7"
|
||||||
@ -43,13 +43,13 @@
|
|||||||
<uses-permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"/>
|
<uses-permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"/>
|
||||||
<permission android:name="com.fsck.k9.permission.READ_MESSAGES"
|
<permission android:name="com.fsck.k9.permission.READ_MESSAGES"
|
||||||
android:permissionGroup="android.permission-group.MESSAGES"
|
android:permissionGroup="android.permission-group.MESSAGES"
|
||||||
android:protectionLevel="normal"
|
android:protectionLevel="dangerous"
|
||||||
android:label="@string/read_messages_label"
|
android:label="@string/read_messages_label"
|
||||||
android:description="@string/read_messages_desc"/>
|
android:description="@string/read_messages_desc"/>
|
||||||
<uses-permission android:name="com.fsck.k9.permission.READ_MESSAGES"/>
|
<uses-permission android:name="com.fsck.k9.permission.READ_MESSAGES"/>
|
||||||
<permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"
|
<permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"
|
||||||
android:permissionGroup="android.permission-group.MESSAGES"
|
android:permissionGroup="android.permission-group.MESSAGES"
|
||||||
android:protectionLevel="normal"
|
android:protectionLevel="dangerous"
|
||||||
android:label="@string/delete_messages_label"
|
android:label="@string/delete_messages_label"
|
||||||
android:description="@string/read_messages_desc"/>
|
android:description="@string/read_messages_desc"/>
|
||||||
<uses-permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"/>
|
<uses-permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"/>
|
||||||
@ -208,6 +208,10 @@
|
|||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:configChanges="locale"
|
android:configChanges="locale"
|
||||||
>
|
>
|
||||||
|
<intent-filter>
|
||||||
|
<!-- This action is only to allow an entry point for launcher shortcuts -->
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name="com.fsck.k9.activity.MessageView"
|
android:name="com.fsck.k9.activity.MessageView"
|
||||||
@ -387,5 +391,25 @@ otherwise it would make K-9 start at the wrong time
|
|||||||
android:readPermission="com.fsck.k9.permission.READ_MESSAGES"
|
android:readPermission="com.fsck.k9.permission.READ_MESSAGES"
|
||||||
android:writePermission="com.fsck.k9.permission.DELETE_MESSAGES"
|
android:writePermission="com.fsck.k9.permission.DELETE_MESSAGES"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".provider.UnreadWidgetProvider"
|
||||||
|
android:label="@string/unread_widget_label"
|
||||||
|
android:icon="@drawable/icon">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/unread_widget_info" />
|
||||||
|
</receiver>
|
||||||
|
<activity android:name=".activity.UnreadWidgetConfiguration">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activity.AccountList">
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
9
res/drawable/rounded_corners.xml
Normal file
9
res/drawable/rounded_corners.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<solid android:color="#a0000000"/>
|
||||||
|
<corners android:radius="7dp"/>
|
||||||
|
|
||||||
|
</shape>
|
9
res/drawable/unread_count_background.xml
Normal file
9
res/drawable/unread_count_background.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<solid android:color="#ffcc0000"/>
|
||||||
|
<corners android:radius="17dp"/>
|
||||||
|
|
||||||
|
</shape>
|
15
res/drawable/unread_widget_background.xml
Normal file
15
res/drawable/unread_widget_background.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- FIXME: find a nicer looking way than using 'menuitem_background' -->
|
||||||
|
<item android:drawable="@android:drawable/menuitem_background"
|
||||||
|
android:state_pressed="true" />
|
||||||
|
|
||||||
|
<item android:drawable="@android:drawable/menuitem_background"
|
||||||
|
android:state_focused="true"
|
||||||
|
android:state_enabled="true"
|
||||||
|
android:state_window_focused="true" />
|
||||||
|
|
||||||
|
<item android:drawable="@android:color/transparent" />
|
||||||
|
|
||||||
|
</selector>
|
26
res/layout/account_list.xml
Normal file
26
res/layout/account_list.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_width="fill_parent">
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@android:id/list"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@android:id/empty"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_vertical|center_horizontal">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_width="fill_parent">
|
|
||||||
<ListView
|
|
||||||
android:id="@android:id/list"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
59
res/layout/unread_widget_layout.xml
Normal file
59
res/layout/unread_widget_layout.xml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/unread_widget_layout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="2dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:background="@drawable/unread_widget_background"
|
||||||
|
android:gravity="bottom|center_horizontal">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@android:dimen/app_icon_size"
|
||||||
|
android:layout_height="@android:dimen/app_icon_size"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/icon" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/unread_count"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:textSize="10dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right|bottom"
|
||||||
|
android:paddingTop="0.5dp"
|
||||||
|
android:paddingBottom="0.5dp"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:background="@drawable/unread_count_background"
|
||||||
|
android:textColor="#ffffff"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/account_name"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:textSize="12dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:paddingTop="1dp"
|
||||||
|
android:paddingBottom="1dp"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="3dp"
|
||||||
|
android:background="@drawable/rounded_corners"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:shadowColor="#000000"
|
||||||
|
android:shadowRadius="2.0"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -1145,4 +1145,12 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
|
|||||||
<string name="manage_accounts_move_down_action">Move down</string>
|
<string name="manage_accounts_move_down_action">Move down</string>
|
||||||
<string name="manage_accounts_moving_message">Moving account...</string>
|
<string name="manage_accounts_moving_message">Moving account...</string>
|
||||||
|
|
||||||
|
<string name="unread_widget_label">K-9 Unread</string>
|
||||||
|
<string name="unread_widget_select_account">Show unread count for…</string>
|
||||||
|
|
||||||
|
<string name="import_dialog_error_title">Missing File Manager Application</string>
|
||||||
|
<string name="import_dialog_error_message">There is no suitable application to handle
|
||||||
|
the import operation. Please install a file manager application from Android Market</string>
|
||||||
|
<string name="open_market">Open Market</string>
|
||||||
|
<string name="close">Close</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
8
res/xml/unread_widget_info.xml
Normal file
8
res/xml/unread_widget_info.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:initialLayout="@layout/unread_widget_layout"
|
||||||
|
android:minHeight="72dp"
|
||||||
|
android:minWidth="72dp"
|
||||||
|
android:configure="com.fsck.k9.activity.UnreadWidgetConfiguration"
|
||||||
|
android:updatePeriodMillis="0">
|
||||||
|
</appwidget-provider>
|
@ -48,7 +48,7 @@ public class EmailAddressAdapter extends ResourceCursorAdapter {
|
|||||||
final String name = mContacts.getName(cursor);
|
final String name = mContacts.getName(cursor);
|
||||||
final String address = mContacts.getEmail(cursor);
|
final String address = mContacts.getEmail(cursor);
|
||||||
|
|
||||||
return new Address(address, name).toString();
|
return (address == null) ? "" : new Address(address, name).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,6 +31,7 @@ import com.fsck.k9.mail.Address;
|
|||||||
import com.fsck.k9.mail.Message;
|
import com.fsck.k9.mail.Message;
|
||||||
import com.fsck.k9.mail.MessagingException;
|
import com.fsck.k9.mail.MessagingException;
|
||||||
import com.fsck.k9.mail.internet.BinaryTempFileBody;
|
import com.fsck.k9.mail.internet.BinaryTempFileBody;
|
||||||
|
import com.fsck.k9.provider.UnreadWidgetProvider;
|
||||||
import com.fsck.k9.service.BootReceiver;
|
import com.fsck.k9.service.BootReceiver;
|
||||||
import com.fsck.k9.service.MailService;
|
import com.fsck.k9.service.MailService;
|
||||||
import com.fsck.k9.service.ShutdownReceiver;
|
import com.fsck.k9.service.ShutdownReceiver;
|
||||||
@ -505,19 +506,38 @@ public class K9 extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateUnreadWidget() {
|
||||||
|
try {
|
||||||
|
UnreadWidgetProvider.updateUnreadCount(K9.this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (K9.DEBUG) {
|
||||||
|
Log.e(LOG_TAG, "Error while updating unread widget(s)", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxRemovedMessage(Account account, String folder, Message message) {
|
public void synchronizeMailboxRemovedMessage(Account account, String folder, Message message) {
|
||||||
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
|
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
|
||||||
|
updateUnreadWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageDeleted(Account account, String folder, Message message) {
|
public void messageDeleted(Account account, String folder, Message message) {
|
||||||
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
|
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
|
||||||
|
updateUnreadWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
|
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
|
||||||
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_RECEIVED, account, folder, message);
|
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_RECEIVED, account, folder, message);
|
||||||
|
updateUnreadWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void folderStatusChanged(Account account, String folderName,
|
||||||
|
int unreadMessageCount) {
|
||||||
|
updateUnreadWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
192
src/com/fsck/k9/activity/AccountList.java
Normal file
192
src/com/fsck/k9/activity/AccountList.java
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package com.fsck.k9.activity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
|
import com.fsck.k9.BaseAccount;
|
||||||
|
import com.fsck.k9.FontSizes;
|
||||||
|
import com.fsck.k9.K9;
|
||||||
|
import com.fsck.k9.Preferences;
|
||||||
|
import com.fsck.k9.R;
|
||||||
|
import com.fsck.k9.SearchAccount;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activity displaying the list of accounts.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Classes extending this abstract class have to provide an {@link #onAccountSelected(BaseAccount)}
|
||||||
|
* method to perform an action when an account is selected.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public abstract class AccountList extends K9ListActivity implements OnItemClickListener {
|
||||||
|
private FontSizes mFontSizes = K9.getFontSizes();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
|
||||||
|
setResult(RESULT_CANCELED);
|
||||||
|
|
||||||
|
setContentView(R.layout.account_list);
|
||||||
|
|
||||||
|
ListView listView = getListView();
|
||||||
|
listView.setOnItemClickListener(this);
|
||||||
|
listView.setItemsCanFocus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload list of accounts when this activity is resumed.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
new LoadAccounts().execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
BaseAccount account = (BaseAccount) parent.getItemAtPosition(position);
|
||||||
|
onAccountSelected(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link AccountsAdapter} instance and assign it to the {@link ListView}.
|
||||||
|
*
|
||||||
|
* @param realAccounts
|
||||||
|
* An array of accounts to display.
|
||||||
|
*/
|
||||||
|
public void populateListView(Account[] realAccounts) {
|
||||||
|
List<BaseAccount> accounts = new ArrayList<BaseAccount>();
|
||||||
|
|
||||||
|
if (displaySpecialAccounts() && !K9.isHideSpecialAccounts()) {
|
||||||
|
BaseAccount integratedInboxAccount = new SearchAccount(this, true, null, null);
|
||||||
|
integratedInboxAccount.setDescription(getString(R.string.integrated_inbox_title));
|
||||||
|
integratedInboxAccount.setEmail(getString(R.string.integrated_inbox_detail));
|
||||||
|
|
||||||
|
BaseAccount unreadAccount = new SearchAccount(this, false, null, null);
|
||||||
|
unreadAccount.setDescription(getString(R.string.search_all_messages_title));
|
||||||
|
unreadAccount.setEmail(getString(R.string.search_all_messages_detail));
|
||||||
|
|
||||||
|
accounts.add(integratedInboxAccount);
|
||||||
|
accounts.add(unreadAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts.addAll(Arrays.asList(realAccounts));
|
||||||
|
AccountsAdapter adapter = new AccountsAdapter(accounts);
|
||||||
|
ListView listView = getListView();
|
||||||
|
listView.setAdapter(adapter);
|
||||||
|
listView.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementing decide whether or not to display special accounts in the list.
|
||||||
|
*
|
||||||
|
* @return {@code true}, if special accounts should be listed. {@code false}, otherwise.
|
||||||
|
*/
|
||||||
|
protected abstract boolean displaySpecialAccounts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be called when an account was selected.
|
||||||
|
*
|
||||||
|
* @param account
|
||||||
|
* The account the user selected.
|
||||||
|
*/
|
||||||
|
protected abstract void onAccountSelected(BaseAccount account);
|
||||||
|
|
||||||
|
class AccountsAdapter extends ArrayAdapter<BaseAccount> {
|
||||||
|
public AccountsAdapter(List<BaseAccount> accounts) {
|
||||||
|
super(AccountList.this, 0, accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
final BaseAccount account = getItem(position);
|
||||||
|
|
||||||
|
final View view;
|
||||||
|
if (convertView != null) {
|
||||||
|
view = convertView;
|
||||||
|
} else {
|
||||||
|
view = getLayoutInflater().inflate(R.layout.accounts_item, parent, false);
|
||||||
|
view.findViewById(R.id.active_icons).setVisibility(View.GONE);
|
||||||
|
view.findViewById(R.id.folders).setVisibility(View.GONE);
|
||||||
|
view.getBackground().setAlpha(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountViewHolder holder = (AccountViewHolder) view.getTag();
|
||||||
|
if (holder == null) {
|
||||||
|
holder = new AccountViewHolder();
|
||||||
|
holder.description = (TextView) view.findViewById(R.id.description);
|
||||||
|
holder.email = (TextView) view.findViewById(R.id.email);
|
||||||
|
holder.chip = view.findViewById(R.id.chip);
|
||||||
|
|
||||||
|
view.setTag(holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
String description = account.getDescription();
|
||||||
|
if (account.getEmail().equals(description)) {
|
||||||
|
holder.email.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
holder.email.setVisibility(View.VISIBLE);
|
||||||
|
holder.email.setText(account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description == null || description.length() == 0) {
|
||||||
|
description = account.getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.description.setText(description);
|
||||||
|
|
||||||
|
if (account instanceof Account) {
|
||||||
|
Account realAccount = (Account) account;
|
||||||
|
holder.chip.setBackgroundColor(realAccount.getChipColor());
|
||||||
|
} else {
|
||||||
|
holder.chip.setBackgroundColor(0xff999999);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.chip.getBackground().setAlpha(255);
|
||||||
|
|
||||||
|
holder.description.setTextSize(TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
mFontSizes.getAccountName());
|
||||||
|
holder.email.setTextSize(TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
mFontSizes.getAccountDescription());
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountViewHolder {
|
||||||
|
public TextView description;
|
||||||
|
public TextView email;
|
||||||
|
public View chip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load accounts in a background thread
|
||||||
|
*/
|
||||||
|
class LoadAccounts extends AsyncTask<Void, Void, Account[]> {
|
||||||
|
@Override
|
||||||
|
protected Account[] doInBackground(Void... params) {
|
||||||
|
Account[] accounts = Preferences.getPreferences(getApplicationContext()).getAccounts();
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Account[] accounts) {
|
||||||
|
populateListView(accounts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ import android.content.DialogInterface;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -108,10 +109,22 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
*/
|
*/
|
||||||
private static final Flag[] EMPTY_FLAG_ARRAY = new Flag[0];
|
private static final Flag[] EMPTY_FLAG_ARRAY = new Flag[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL used to open Android Market application
|
||||||
|
*/
|
||||||
|
private static final String ANDROID_MARKET_URL = "https://market.android.com/search?q=oi+file+manager&c=apps";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of special accounts ('Unified Inbox' and 'All Messages')
|
||||||
|
*/
|
||||||
|
private static final int SPECIAL_ACCOUNTS_COUNT = 2;
|
||||||
|
|
||||||
private static final int DIALOG_REMOVE_ACCOUNT = 1;
|
private static final int DIALOG_REMOVE_ACCOUNT = 1;
|
||||||
private static final int DIALOG_CLEAR_ACCOUNT = 2;
|
private static final int DIALOG_CLEAR_ACCOUNT = 2;
|
||||||
private static final int DIALOG_RECREATE_ACCOUNT = 3;
|
private static final int DIALOG_RECREATE_ACCOUNT = 3;
|
||||||
|
private static final int DIALOG_NO_FILE_MANAGER = 4;
|
||||||
private static final String TRUE = "true";
|
private static final String TRUE = "true";
|
||||||
|
|
||||||
private ConcurrentHashMap<String, AccountStats> accountStats = new ConcurrentHashMap<String, AccountStats>();
|
private ConcurrentHashMap<String, AccountStats> accountStats = new ConcurrentHashMap<String, AccountStats>();
|
||||||
|
|
||||||
private ConcurrentHashMap<BaseAccount, String> pendingWork = new ConcurrentHashMap<BaseAccount, String>();
|
private ConcurrentHashMap<BaseAccount, String> pendingWork = new ConcurrentHashMap<BaseAccount, String>();
|
||||||
@ -328,13 +341,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
if (!K9.isHideSpecialAccounts()) {
|
if (!K9.isHideSpecialAccounts()) {
|
||||||
unreadAccount = new SearchAccount(this, false, null, null);
|
createSpecialAccounts();
|
||||||
unreadAccount.setDescription(getString(R.string.search_all_messages_title));
|
|
||||||
unreadAccount.setEmail(getString(R.string.search_all_messages_detail));
|
|
||||||
|
|
||||||
integratedInboxAccount = new SearchAccount(this, true, null, null);
|
|
||||||
integratedInboxAccount.setDescription(getString(R.string.integrated_inbox_title));
|
|
||||||
integratedInboxAccount.setEmail(getString(R.string.integrated_inbox_detail));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
||||||
@ -377,6 +384,19 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and initializes the special accounts ('Integrated Inbox' and 'All Messages')
|
||||||
|
*/
|
||||||
|
private void createSpecialAccounts() {
|
||||||
|
unreadAccount = new SearchAccount(this, false, null, null);
|
||||||
|
unreadAccount.setDescription(getString(R.string.search_all_messages_title));
|
||||||
|
unreadAccount.setEmail(getString(R.string.search_all_messages_detail));
|
||||||
|
|
||||||
|
integratedInboxAccount = new SearchAccount(this, true, null, null);
|
||||||
|
integratedInboxAccount.setDescription(getString(R.string.integrated_inbox_title));
|
||||||
|
integratedInboxAccount.setEmail(getString(R.string.integrated_inbox_detail));
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void restoreAccountStats(Bundle icicle) {
|
private void restoreAccountStats(Bundle icicle) {
|
||||||
if (icicle != null) {
|
if (icicle != null) {
|
||||||
@ -461,9 +481,13 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
accounts = Preferences.getPreferences(this).getAccounts();
|
accounts = Preferences.getPreferences(this).getAccounts();
|
||||||
|
|
||||||
List<BaseAccount> newAccounts;
|
List<BaseAccount> newAccounts;
|
||||||
if (!K9.isHideSpecialAccounts()
|
if (!K9.isHideSpecialAccounts() && accounts.length > 0) {
|
||||||
&& accounts.length > 0) {
|
if (integratedInboxAccount == null || unreadAccount == null) {
|
||||||
newAccounts = new ArrayList<BaseAccount>(accounts.length + 2);
|
createSpecialAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
newAccounts = new ArrayList<BaseAccount>(accounts.length +
|
||||||
|
SPECIAL_ACCOUNTS_COUNT);
|
||||||
newAccounts.add(integratedInboxAccount);
|
newAccounts.add(integratedInboxAccount);
|
||||||
newAccounts.add(unreadAccount);
|
newAccounts.add(unreadAccount);
|
||||||
} else {
|
} else {
|
||||||
@ -990,6 +1014,20 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
case DIALOG_NO_FILE_MANAGER:
|
||||||
|
return ConfirmationDialog.create(this, id,
|
||||||
|
R.string.import_dialog_error_title,
|
||||||
|
getString(R.string.import_dialog_error_message),
|
||||||
|
R.string.open_market,
|
||||||
|
R.string.close,
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Uri uri = Uri.parse(ANDROID_MARKET_URL);
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return super.onCreateDialog(id);
|
return super.onCreateDialog(id);
|
||||||
}
|
}
|
||||||
@ -1011,6 +1049,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
alert.setMessage(getString(R.string.account_recreate_dlg_instructions_fmt,
|
alert.setMessage(getString(R.string.account_recreate_dlg_instructions_fmt,
|
||||||
mSelectedContextAccount.getDescription()));
|
mSelectedContextAccount.getDescription()));
|
||||||
break;
|
break;
|
||||||
|
case DIALOG_NO_FILE_MANAGER:
|
||||||
|
alert.setMessage(getString(R.string.import_dialog_error_message));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onPrepareDialog(id, d);
|
super.onPrepareDialog(id, d);
|
||||||
@ -1266,7 +1307,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
i.addCategory(Intent.CATEGORY_OPENABLE);
|
i.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
i.setType(MimeUtility.K9_SETTINGS_MIME_TYPE);
|
i.setType(MimeUtility.K9_SETTINGS_MIME_TYPE);
|
||||||
startActivityForResult(Intent.createChooser(i, null), ACTIVITY_REQUEST_PICK_SETTINGS_FILE);
|
|
||||||
|
PackageManager packageManager = getPackageManager();
|
||||||
|
List<ResolveInfo> infos = packageManager.queryIntentActivities(i, 0);
|
||||||
|
|
||||||
|
if (infos.size() > 0) {
|
||||||
|
startActivityForResult(Intent.createChooser(i, null),
|
||||||
|
ACTIVITY_REQUEST_PICK_SETTINGS_FILE);
|
||||||
|
} else {
|
||||||
|
showDialog(DIALOG_NO_FILE_MANAGER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,53 +3,42 @@ package com.fsck.k9.activity;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.fsck.k9.Account;
|
import com.fsck.k9.Account;
|
||||||
import com.fsck.k9.FontSizes;
|
import com.fsck.k9.BaseAccount;
|
||||||
import com.fsck.k9.K9;
|
|
||||||
import com.fsck.k9.Preferences;
|
|
||||||
import com.fsck.k9.R;
|
import com.fsck.k9.R;
|
||||||
|
import com.fsck.k9.SearchSpecification;
|
||||||
|
|
||||||
public class LauncherShortcuts extends K9ListActivity implements OnItemClickListener {
|
public class LauncherShortcuts extends AccountList {
|
||||||
private AccountsAdapter mAdapter;
|
|
||||||
private FontSizes mFontSizes = K9.getFontSizes();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
|
||||||
|
|
||||||
// finish() immediately if we aren't supposed to be here
|
// finish() immediately if we aren't supposed to be here
|
||||||
if (!Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
|
if (!Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(R.layout.launcher_shortcuts);
|
super.onCreate(icicle);
|
||||||
ListView listView = getListView();
|
|
||||||
listView.setOnItemClickListener(this);
|
|
||||||
listView.setItemsCanFocus(false);
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refresh() {
|
@Override
|
||||||
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
protected boolean displaySpecialAccounts() {
|
||||||
|
return true;
|
||||||
mAdapter = new AccountsAdapter(accounts);
|
|
||||||
getListView().setAdapter(mAdapter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupShortcut(Account account) {
|
@Override
|
||||||
final Intent shortcutIntent = FolderList.actionHandleAccountIntent(this, account, null, true);
|
protected void onAccountSelected(BaseAccount account) {
|
||||||
|
Intent shortcutIntent = null;
|
||||||
|
|
||||||
|
if (account instanceof SearchSpecification) {
|
||||||
|
shortcutIntent = MessageList.actionHandleAccountIntent(this, account.getDescription(),
|
||||||
|
(SearchSpecification) account);
|
||||||
|
} else {
|
||||||
|
shortcutIntent = FolderList.actionHandleAccountIntent(this, (Account) account, null,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||||
String description = account.getDescription();
|
String description = account.getDescription();
|
||||||
@ -63,66 +52,4 @@ public class LauncherShortcuts extends K9ListActivity implements OnItemClickList
|
|||||||
setResult(RESULT_OK, intent);
|
setResult(RESULT_OK, intent);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
Account account = (Account) parent.getItemAtPosition(position);
|
|
||||||
setupShortcut(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
class AccountsAdapter extends ArrayAdapter<Account> {
|
|
||||||
public AccountsAdapter(Account[] accounts) {
|
|
||||||
super(LauncherShortcuts.this, 0, accounts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
final Account account = getItem(position);
|
|
||||||
|
|
||||||
final View view;
|
|
||||||
if (convertView != null) {
|
|
||||||
view = convertView;
|
|
||||||
} else {
|
|
||||||
view = getLayoutInflater().inflate(R.layout.accounts_item, parent, false);
|
|
||||||
view.findViewById(R.id.active_icons).setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
AccountViewHolder holder = (AccountViewHolder) view.getTag();
|
|
||||||
if (holder == null) {
|
|
||||||
holder = new AccountViewHolder();
|
|
||||||
holder.description = (TextView) view.findViewById(R.id.description);
|
|
||||||
holder.email = (TextView) view.findViewById(R.id.email);
|
|
||||||
holder.chip = view.findViewById(R.id.chip);
|
|
||||||
|
|
||||||
view.setTag(holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
String description = account.getDescription();
|
|
||||||
if (account.getEmail().equals(description)) {
|
|
||||||
holder.email.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
holder.email.setVisibility(View.VISIBLE);
|
|
||||||
holder.email.setText(account.getEmail());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (description == null || description.length() == 0) {
|
|
||||||
description = account.getEmail();
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.description.setText(description);
|
|
||||||
|
|
||||||
holder.chip.setBackgroundColor(account.getChipColor());
|
|
||||||
holder.chip.getBackground().setAlpha(255);
|
|
||||||
|
|
||||||
holder.description.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getAccountName());
|
|
||||||
holder.email.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getAccountDescription());
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AccountViewHolder {
|
|
||||||
public TextView description;
|
|
||||||
public TextView email;
|
|
||||||
public View chip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1611,7 +1611,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
|
||||||
final String folderName = mMessageReference.folderName;
|
final String folderName = mMessageReference.folderName;
|
||||||
final String sourceMessageUid = mMessageReference.uid;
|
final String sourceMessageUid = mMessageReference.uid;
|
||||||
MessagingController.getInstance(getApplication()).setFlag(account, folderName, new String[] {sourceMessageUid}, mMessageReference.flag, true);
|
MessagingController.getInstance(getApplication()).setFlag(account, folderName, sourceMessageUid, mMessageReference.flag, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDraftNeedsSaving = false;
|
mDraftNeedsSaving = false;
|
||||||
|
@ -52,10 +52,12 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.fsck.k9.Account;
|
import com.fsck.k9.Account;
|
||||||
import com.fsck.k9.AccountStats;
|
import com.fsck.k9.AccountStats;
|
||||||
|
import com.fsck.k9.BaseAccount;
|
||||||
import com.fsck.k9.FontSizes;
|
import com.fsck.k9.FontSizes;
|
||||||
import com.fsck.k9.K9;
|
import com.fsck.k9.K9;
|
||||||
import com.fsck.k9.Preferences;
|
import com.fsck.k9.Preferences;
|
||||||
import com.fsck.k9.R;
|
import com.fsck.k9.R;
|
||||||
|
import com.fsck.k9.SearchAccount;
|
||||||
import com.fsck.k9.SearchSpecification;
|
import com.fsck.k9.SearchSpecification;
|
||||||
import com.fsck.k9.activity.setup.AccountSettings;
|
import com.fsck.k9.activity.setup.AccountSettings;
|
||||||
import com.fsck.k9.activity.setup.FolderSettings;
|
import com.fsck.k9.activity.setup.FolderSettings;
|
||||||
@ -70,6 +72,7 @@ import com.fsck.k9.mail.Folder;
|
|||||||
import com.fsck.k9.mail.Message;
|
import com.fsck.k9.mail.Message;
|
||||||
import com.fsck.k9.mail.store.LocalStore;
|
import com.fsck.k9.mail.store.LocalStore;
|
||||||
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
||||||
|
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
|
||||||
import com.fsck.k9.mail.store.StorageManager;
|
import com.fsck.k9.mail.store.StorageManager;
|
||||||
|
|
||||||
|
|
||||||
@ -613,7 +616,11 @@ public class MessageList
|
|||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void actionHandle(Context context, String title, SearchSpecification searchSpecification) {
|
/**
|
||||||
|
* Creates and returns an intent that opens Unified Inbox or All Messages screen.
|
||||||
|
*/
|
||||||
|
public static Intent actionHandleAccountIntent(Context context, String title,
|
||||||
|
SearchSpecification searchSpecification) {
|
||||||
Intent intent = new Intent(context, MessageList.class);
|
Intent intent = new Intent(context, MessageList.class);
|
||||||
intent.putExtra(EXTRA_QUERY, searchSpecification.getQuery());
|
intent.putExtra(EXTRA_QUERY, searchSpecification.getQuery());
|
||||||
if (searchSpecification.getRequiredFlags() != null) {
|
if (searchSpecification.getRequiredFlags() != null) {
|
||||||
@ -629,6 +636,13 @@ public class MessageList
|
|||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void actionHandle(Context context, String title,
|
||||||
|
SearchSpecification searchSpecification) {
|
||||||
|
Intent intent = actionHandleAccountIntent(context, title, searchSpecification);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1392,13 +1406,21 @@ public class MessageList
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onToggleRead(MessageInfoHolder holder) {
|
private void onToggleRead(MessageInfoHolder holder) {
|
||||||
mController.setFlag(holder.message.getFolder().getAccount(), holder.message.getFolder().getName(), new String[] { holder.uid }, Flag.SEEN, !holder.read);
|
LocalMessage message = holder.message;
|
||||||
|
Folder folder = message.getFolder();
|
||||||
|
Account account = folder.getAccount();
|
||||||
|
String folderName = folder.getName();
|
||||||
|
mController.setFlag(account, folderName, new Message[] { message }, Flag.SEEN, !holder.read);
|
||||||
holder.read = !holder.read;
|
holder.read = !holder.read;
|
||||||
mHandler.sortMessages();
|
mHandler.sortMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onToggleFlag(MessageInfoHolder holder) {
|
private void onToggleFlag(MessageInfoHolder holder) {
|
||||||
mController.setFlag(holder.message.getFolder().getAccount(), holder.message.getFolder().getName(), new String[] { holder.uid }, Flag.FLAGGED, !holder.flagged);
|
LocalMessage message = holder.message;
|
||||||
|
Folder folder = message.getFolder();
|
||||||
|
Account account = folder.getAccount();
|
||||||
|
String folderName = folder.getName();
|
||||||
|
mController.setFlag(account, folderName, new Message[] { message }, Flag.FLAGGED, !holder.flagged);
|
||||||
holder.flagged = !holder.flagged;
|
holder.flagged = !holder.flagged;
|
||||||
mHandler.sortMessages();
|
mHandler.sortMessages();
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import com.fsck.k9.crypto.PgpData;
|
|||||||
import com.fsck.k9.helper.FileBrowserHelper;
|
import com.fsck.k9.helper.FileBrowserHelper;
|
||||||
import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback;
|
import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback;
|
||||||
import com.fsck.k9.mail.*;
|
import com.fsck.k9.mail.*;
|
||||||
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
|
|
||||||
import com.fsck.k9.mail.store.StorageManager;
|
import com.fsck.k9.mail.store.StorageManager;
|
||||||
import com.fsck.k9.view.AttachmentView;
|
import com.fsck.k9.view.AttachmentView;
|
||||||
import com.fsck.k9.view.ToggleScrollView;
|
import com.fsck.k9.view.ToggleScrollView;
|
||||||
@ -715,17 +714,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
if (mMessage != null) {
|
if (mMessage != null) {
|
||||||
boolean newState = !mMessage.isSet(Flag.FLAGGED);
|
boolean newState = !mMessage.isSet(Flag.FLAGGED);
|
||||||
mController.setFlag(mAccount, mMessage.getFolder().getName(),
|
mController.setFlag(mAccount, mMessage.getFolder().getName(),
|
||||||
new String[] {mMessage.getUid()}, Flag.FLAGGED, newState);
|
new Message[] { mMessage }, Flag.FLAGGED, newState);
|
||||||
try {
|
mMessageView.setHeaders(mMessage, mAccount);
|
||||||
// FIXME: This is a hack to change the flagged state of our message object. We
|
|
||||||
// can't call Message.setFlag() because that would "adjust" the flagged count
|
|
||||||
// another time (first time by MessagingController.setFlag(...)).
|
|
||||||
((LocalMessage)mMessage).setFlagInternal(Flag.FLAGGED, newState);
|
|
||||||
|
|
||||||
mMessageView.setHeaders(mMessage, mAccount);
|
|
||||||
} catch (MessagingException me) {
|
|
||||||
Log.e(K9.LOG_TAG, "Could not set flag on local message", me);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -858,18 +848,10 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
private void onMarkAsUnread() {
|
private void onMarkAsUnread() {
|
||||||
if (mMessage != null) {
|
if (mMessage != null) {
|
||||||
mController.setFlag(mAccount, mMessage.getFolder().getName(),
|
mController.setFlag(mAccount, mMessage.getFolder().getName(),
|
||||||
new String[] { mMessage.getUid() }, Flag.SEEN, false);
|
new Message[] { mMessage }, Flag.SEEN, false);
|
||||||
try {
|
mMessageView.setHeaders(mMessage, mAccount);
|
||||||
// FIXME: This is a hack to mark our message object as unread. We can't call
|
String subject = mMessage.getSubject();
|
||||||
// Message.setFlag() because that would "adjust" the unread count twice.
|
setTitle(subject);
|
||||||
((LocalMessage)mMessage).setFlagInternal(Flag.SEEN, false);
|
|
||||||
|
|
||||||
mMessageView.setHeaders(mMessage, mAccount);
|
|
||||||
String subject = mMessage.getSubject();
|
|
||||||
setTitle(subject);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Unable to unset SEEN flag on message", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
106
src/com/fsck/k9/activity/UnreadWidgetConfiguration.java
Normal file
106
src/com/fsck/k9/activity/UnreadWidgetConfiguration.java
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package com.fsck.k9.activity;
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.Editor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
|
import com.fsck.k9.BaseAccount;
|
||||||
|
import com.fsck.k9.R;
|
||||||
|
import com.fsck.k9.provider.UnreadWidgetProvider;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activity to select an account for the unread widget.
|
||||||
|
*/
|
||||||
|
public class UnreadWidgetConfiguration extends AccountList {
|
||||||
|
/**
|
||||||
|
* Name of the preference file to store the widget configuration.
|
||||||
|
*/
|
||||||
|
private static final String PREFS_NAME = "unread_widget_configuration.xml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix for the preference keys.
|
||||||
|
*/
|
||||||
|
private static final String PREF_PREFIX_KEY = "unread_widget.";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the widget we are configuring.
|
||||||
|
*/
|
||||||
|
private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
|
||||||
|
// Find the widget ID from the intent.
|
||||||
|
Intent intent = getIntent();
|
||||||
|
Bundle extras = intent.getExtras();
|
||||||
|
if (extras != null) {
|
||||||
|
mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||||
|
AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they gave us an intent without the widget ID, just bail.
|
||||||
|
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle(R.string.unread_widget_select_account);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean displaySpecialAccounts() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAccountSelected(BaseAccount baseAccount) {
|
||||||
|
if (!(baseAccount instanceof Account)) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Account account = (Account) baseAccount;
|
||||||
|
|
||||||
|
// Save widget configuration
|
||||||
|
String accountUuid = account.getUuid();
|
||||||
|
saveAccountUuid(this, mAppWidgetId, accountUuid);
|
||||||
|
|
||||||
|
// Update widget
|
||||||
|
Context context = getApplicationContext();
|
||||||
|
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||||
|
UnreadWidgetProvider.updateWidget(context, appWidgetManager, mAppWidgetId, accountUuid);
|
||||||
|
|
||||||
|
// Let the caller know that the configuration was successful
|
||||||
|
Intent resultValue = new Intent();
|
||||||
|
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
|
||||||
|
setResult(RESULT_OK, resultValue);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void saveAccountUuid(Context context, int appWidgetId, String accountUuid) {
|
||||||
|
SharedPreferences.Editor editor =
|
||||||
|
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE).edit();
|
||||||
|
editor.putString(PREF_PREFIX_KEY + appWidgetId, accountUuid);
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAccountUuid(Context context, int appWidgetId) {
|
||||||
|
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||||
|
String accountUuid = prefs.getString(PREF_PREFIX_KEY + appWidgetId, null);
|
||||||
|
return accountUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteWidgetConfiguration(Context context, int appWidgetId) {
|
||||||
|
Editor editor = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE).edit();
|
||||||
|
editor.remove(PREF_PREFIX_KEY + appWidgetId);
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
|
}
|
@ -2622,51 +2622,67 @@ public class MessagingController implements Runnable {
|
|||||||
@Override
|
@Override
|
||||||
public void act(final Account account, final Folder folder,
|
public void act(final Account account, final Folder folder,
|
||||||
final List<Message> messages) {
|
final List<Message> messages) {
|
||||||
String[] uids = new String[messages.size()];
|
setFlag(account, folder.getName(), messages.toArray(EMPTY_MESSAGE_ARRAY), flag,
|
||||||
for (int i = 0; i < messages.size(); i++) {
|
newState);
|
||||||
uids[i] = messages.get(i).getUid();
|
|
||||||
}
|
|
||||||
setFlag(account, folder.getName(), uids, flag, newState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFlag(
|
/**
|
||||||
final Account account,
|
* Set or remove a flag for a set of messages in a specific folder.
|
||||||
final String folderName,
|
*
|
||||||
final String[] uids,
|
* <p>
|
||||||
final Flag flag,
|
* The {@link Message} objects passed in are updated to reflect the new flag state.
|
||||||
final boolean newState) {
|
* </p>
|
||||||
// TODO: put this into the background, but right now that causes odd behavior
|
*
|
||||||
// because the FolderMessageList doesn't have its own cache of the flag states
|
* @param account
|
||||||
|
* The account the folder containing the messages belongs to.
|
||||||
|
* @param folderName
|
||||||
|
* The name of the folder.
|
||||||
|
* @param messages
|
||||||
|
* The messages to change the flag for.
|
||||||
|
* @param flag
|
||||||
|
* The flag to change.
|
||||||
|
* @param newState
|
||||||
|
* {@code true}, if the flag should be set. {@code false} if it should be removed.
|
||||||
|
*/
|
||||||
|
public void setFlag(Account account, String folderName, Message[] messages, Flag flag,
|
||||||
|
boolean newState) {
|
||||||
|
// TODO: Put this into the background, but right now some callers depend on the message
|
||||||
|
// objects being modified right after this method returns.
|
||||||
LocalFolder localFolder = null;
|
LocalFolder localFolder = null;
|
||||||
try {
|
try {
|
||||||
LocalStore localStore = account.getLocalStore();
|
LocalStore localStore = account.getLocalStore();
|
||||||
localFolder = localStore.getFolder(folderName);
|
localFolder = localStore.getFolder(folderName);
|
||||||
localFolder.open(OpenMode.READ_WRITE);
|
localFolder.open(OpenMode.READ_WRITE);
|
||||||
ArrayList<Message> messages = new ArrayList<Message>();
|
|
||||||
for (String uid : uids) {
|
// Allows for re-allowing sending of messages that could not be sent
|
||||||
// Allows for re-allowing sending of messages that could not be sent
|
if (flag == Flag.FLAGGED && !newState &&
|
||||||
if (flag == Flag.FLAGGED && !newState
|
account.getOutboxFolderName().equals(folderName)) {
|
||||||
&& uid != null
|
for (Message message : messages) {
|
||||||
&& account.getOutboxFolderName().equals(folderName)) {
|
String uid = message.getUid();
|
||||||
sendCount.remove(uid);
|
if (uid != null) {
|
||||||
}
|
sendCount.remove(uid);
|
||||||
Message msg = localFolder.getMessage(uid);
|
}
|
||||||
if (msg != null) {
|
|
||||||
messages.add(msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localFolder.setFlags(messages.toArray(EMPTY_MESSAGE_ARRAY), new Flag[] {flag}, newState);
|
// Update the messages in the local store
|
||||||
|
localFolder.setFlags(messages, new Flag[] {flag}, newState);
|
||||||
|
|
||||||
for (MessagingListener l : getListeners()) {
|
for (MessagingListener l : getListeners()) {
|
||||||
l.folderStatusChanged(account, folderName, localFolder.getUnreadMessageCount());
|
l.folderStatusChanged(account, folderName, localFolder.getUnreadMessageCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the remote side
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The error folder is always a local folder
|
||||||
|
// TODO: Skip the remote part for all local-only folders
|
||||||
if (account.getErrorFolderName().equals(folderName)) {
|
if (account.getErrorFolderName().equals(folderName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2675,16 +2691,54 @@ public class MessagingController implements Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String[] uids = new String[messages.length];
|
||||||
|
for (int i = 0, end = uids.length; i < end; i++) {
|
||||||
|
uids[i] = messages[i].getUid();
|
||||||
|
}
|
||||||
|
|
||||||
queueSetFlag(account, folderName, Boolean.toString(newState), flag.toString(), uids);
|
queueSetFlag(account, folderName, Boolean.toString(newState), flag.toString(), uids);
|
||||||
processPendingCommands(account);
|
processPendingCommands(account);
|
||||||
} catch (MessagingException me) {
|
} catch (MessagingException me) {
|
||||||
addErrorMessage(account, null, me);
|
addErrorMessage(account, null, me);
|
||||||
|
|
||||||
throw new RuntimeException(me);
|
throw new RuntimeException(me);
|
||||||
} finally {
|
} finally {
|
||||||
closeFolder(localFolder);
|
closeFolder(localFolder);
|
||||||
}
|
}
|
||||||
}//setMesssageFlag
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or remove a flag for a message referenced by message UID.
|
||||||
|
*
|
||||||
|
* @param account
|
||||||
|
* The account the folder containing the message belongs to.
|
||||||
|
* @param folderName
|
||||||
|
* The name of the folder.
|
||||||
|
* @param uid
|
||||||
|
* The UID of the message to change the flag for.
|
||||||
|
* @param flag
|
||||||
|
* The flag to change.
|
||||||
|
* @param newState
|
||||||
|
* {@code true}, if the flag should be set. {@code false} if it should be removed.
|
||||||
|
*/
|
||||||
|
public void setFlag(Account account, String folderName, String uid, Flag flag,
|
||||||
|
boolean newState) {
|
||||||
|
Folder localFolder = null;
|
||||||
|
try {
|
||||||
|
LocalStore localStore = account.getLocalStore();
|
||||||
|
localFolder = localStore.getFolder(folderName);
|
||||||
|
localFolder.open(OpenMode.READ_WRITE);
|
||||||
|
|
||||||
|
Message message = localFolder.getMessage(uid);
|
||||||
|
if (message != null) {
|
||||||
|
setFlag(account, folderName, new Message[] { message }, flag, newState);
|
||||||
|
}
|
||||||
|
} catch (MessagingException me) {
|
||||||
|
addErrorMessage(account, null, me);
|
||||||
|
throw new RuntimeException(me);
|
||||||
|
} finally {
|
||||||
|
closeFolder(localFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void clearAllPending(final Account account) {
|
public void clearAllPending(final Account account) {
|
||||||
try {
|
try {
|
||||||
@ -3334,6 +3388,8 @@ public class MessagingController implements Runnable {
|
|||||||
Store remoteStore = account.getRemoteStore();
|
Store remoteStore = account.getRemoteStore();
|
||||||
LocalFolder localSrcFolder = localStore.getFolder(srcFolder);
|
LocalFolder localSrcFolder = localStore.getFolder(srcFolder);
|
||||||
LocalFolder localDestFolder = localStore.getFolder(destFolder);
|
LocalFolder localDestFolder = localStore.getFolder(destFolder);
|
||||||
|
|
||||||
|
boolean unreadCountAffected = false;
|
||||||
List<String> uids = new LinkedList<String>();
|
List<String> uids = new LinkedList<String>();
|
||||||
List<String> localUids = new LinkedList<String>();
|
List<String> localUids = new LinkedList<String>();
|
||||||
|
|
||||||
@ -3350,6 +3406,10 @@ public class MessagingController implements Runnable {
|
|||||||
needToLocalizeSourceFolder = true;
|
needToLocalizeSourceFolder = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!unreadCountAffected && !message.isSet(Flag.SEEN)) {
|
||||||
|
unreadCountAffected = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the remote folder actually gets created even though it won't be used yet.
|
// make sure the remote folder actually gets created even though it won't be used yet.
|
||||||
@ -3417,6 +3477,15 @@ public class MessagingController implements Runnable {
|
|||||||
fp.add(FetchProfile.Item.BODY);
|
fp.add(FetchProfile.Item.BODY);
|
||||||
localSrcFolder.fetch(messages, fp, null);
|
localSrcFolder.fetch(messages, fp, null);
|
||||||
localSrcFolder.copyMessages(messages, localDestFolder);
|
localSrcFolder.copyMessages(messages, localDestFolder);
|
||||||
|
|
||||||
|
if (unreadCountAffected) {
|
||||||
|
// If this copy operation changes the unread count in the destination
|
||||||
|
// folder, notify the listeners.
|
||||||
|
int unreadMessageCount = localDestFolder.getUnreadMessageCount();
|
||||||
|
for (MessagingListener l : getListeners()) {
|
||||||
|
l.folderStatusChanged(account, destFolder, unreadMessageCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
localSrcFolder.moveMessages(messages, localDestFolder);
|
localSrcFolder.moveMessages(messages, localDestFolder);
|
||||||
for (Map.Entry<String, Message> entry : origUidMap.entrySet()) {
|
for (Map.Entry<String, Message> entry : origUidMap.entrySet()) {
|
||||||
@ -3427,6 +3496,16 @@ public class MessagingController implements Runnable {
|
|||||||
}
|
}
|
||||||
unsuppressMessage(account, srcFolder, origUid);
|
unsuppressMessage(account, srcFolder, origUid);
|
||||||
}
|
}
|
||||||
|
if (unreadCountAffected) {
|
||||||
|
// If this move operation changes the unread count, notify the listeners
|
||||||
|
// that the unread count changed in both the source and destination folder.
|
||||||
|
int unreadMessageCountSrc = localSrcFolder.getUnreadMessageCount();
|
||||||
|
int unreadMessageCountDest = localDestFolder.getUnreadMessageCount();
|
||||||
|
for (MessagingListener l : getListeners()) {
|
||||||
|
l.folderStatusChanged(account, srcFolder, unreadMessageCountSrc);
|
||||||
|
l.folderStatusChanged(account, destFolder, unreadMessageCountDest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!localDestFolder.isLocalOnly() &&
|
if (!localDestFolder.isLocalOnly() &&
|
||||||
@ -3480,6 +3559,17 @@ public class MessagingController implements Runnable {
|
|||||||
}
|
}
|
||||||
unsuppressMessage(account, srcFolder, origUid);
|
unsuppressMessage(account, srcFolder, origUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unreadCountAffected) {
|
||||||
|
// If this move operation changes the unread count, notify the listeners
|
||||||
|
// that the unread count changed in both the source and destination folder.
|
||||||
|
int unreadMessageCountSrc = localSrcFolder.getUnreadMessageCount();
|
||||||
|
int unreadMessageCountDest = localDestFolder.getUnreadMessageCount();
|
||||||
|
for (MessagingListener l : getListeners()) {
|
||||||
|
l.folderStatusChanged(account, srcFolder, unreadMessageCountSrc);
|
||||||
|
l.folderStatusChanged(account, destFolder, unreadMessageCountDest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchProfile fp = new FetchProfile();
|
FetchProfile fp = new FetchProfile();
|
||||||
@ -3495,6 +3585,16 @@ public class MessagingController implements Runnable {
|
|||||||
// local message copy to local folder
|
// local message copy to local folder
|
||||||
localSrcFolder.copyMessages(localMessages, localDestFolder);
|
localSrcFolder.copyMessages(localMessages, localDestFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCopy && unreadCountAffected) {
|
||||||
|
// ASH this did happen right after removed "localSrcFolder.copyMessages(messages, localDestFolder);"
|
||||||
|
// If this copy operation changes the unread count in the destination
|
||||||
|
// folder, notify the listeners.
|
||||||
|
int unreadMessageCount = localDestFolder.getUnreadMessageCount();
|
||||||
|
for (MessagingListener l : getListeners()) {
|
||||||
|
l.folderStatusChanged(account, destFolder, unreadMessageCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processPendingCommands(account);
|
processPendingCommands(account);
|
||||||
@ -3752,7 +3852,8 @@ public class MessagingController implements Runnable {
|
|||||||
localFolder = localStore.getFolder(account.getTrashFolderName());
|
localFolder = localStore.getFolder(account.getTrashFolderName());
|
||||||
localFolder.open(OpenMode.READ_WRITE);
|
localFolder.open(OpenMode.READ_WRITE);
|
||||||
localFolder.setFlags(new Flag[] { Flag.DELETED }, true);
|
localFolder.setFlags(new Flag[] { Flag.DELETED }, true);
|
||||||
localFolder.resetUnreadAndFlaggedCounts();
|
localFolder.setUnreadMessageCount(0);
|
||||||
|
localFolder.setFlaggedMessageCount(0);
|
||||||
|
|
||||||
for (MessagingListener l : getListeners()) {
|
for (MessagingListener l : getListeners()) {
|
||||||
l.emptyTrashCompleted(account);
|
l.emptyTrashCompleted(account);
|
||||||
|
@ -12,191 +12,154 @@ import com.fsck.k9.mail.Part;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the interface that MessagingController will use to callback to requesters. This class
|
* Defines the interface that {@link MessagingController} will use to callback to requesters.
|
||||||
* is defined as non-abstract so that someone who wants to receive only a few messages can
|
*
|
||||||
* do so without implementing the entire interface. It is highly recommended that users of
|
* <p>
|
||||||
* this interface use the @Override annotation in their implementations to avoid being caught by
|
* This class is defined as non-abstract so that someone who wants to receive only a few messages
|
||||||
|
* can do so without implementing the entire interface. It is highly recommended that users of this
|
||||||
|
* interface use the {@code @Override} annotation in their implementations to avoid being caught by
|
||||||
* changes in this class.
|
* changes in this class.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class MessagingListener {
|
public class MessagingListener {
|
||||||
public void searchStats(AccountStats stats) {}
|
public void searchStats(AccountStats stats) {}
|
||||||
|
|
||||||
public void accountStatusChanged(BaseAccount account, AccountStats stats) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void accountSizeChanged(Account account, long oldSize, long newSize) {
|
public void accountStatusChanged(BaseAccount account, AccountStats stats) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listFoldersStarted(Account account) {
|
public void accountSizeChanged(Account account, long oldSize, long newSize) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listFolders(Account account, Folder[] folders) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void listFoldersFailed(Account account, String message) {
|
public void listFoldersStarted(Account account) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listFoldersFinished(Account account) {
|
public void listFolders(Account account, Folder[] folders) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listLocalMessagesStarted(Account account, String folder) {
|
public void listFoldersFinished(Account account) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listLocalMessages(Account account, String folder, Message[] messages) {
|
public void listFoldersFailed(Account account, String message) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listLocalMessagesAddMessages(Account account, String folder, List<Message> messages) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void listLocalMessagesUpdateMessage(Account account, String folder, Message message) {
|
public void listLocalMessagesStarted(Account account, String folder) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listLocalMessagesRemoveMessage(Account account, String folder, Message message) {
|
public void listLocalMessages(Account account, String folder, Message[] messages) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void listLocalMessagesFailed(Account account, String folder, String message) {
|
public void listLocalMessagesAddMessages(Account account, String folder,
|
||||||
}
|
List<Message> messages) {}
|
||||||
|
|
||||||
public void listLocalMessagesFinished(Account account, String folder) {
|
public void listLocalMessagesUpdateMessage(Account account, String folder, Message message) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void synchronizeMailboxStarted(Account account, String folder) {
|
public void listLocalMessagesRemoveMessage(Account account, String folder, Message message) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void synchronizeMailboxHeadersStarted(Account account, String folder) {
|
public void listLocalMessagesFinished(Account account, String folder) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void synchronizeMailboxHeadersProgress(Account account, String folder, int completed, int total) {
|
public void listLocalMessagesFailed(Account account, String folder, String message) {}
|
||||||
}
|
|
||||||
|
|
||||||
|
public void synchronizeMailboxStarted(Account account, String folder) {}
|
||||||
|
|
||||||
|
public void synchronizeMailboxHeadersStarted(Account account, String folder) {}
|
||||||
|
|
||||||
|
public void synchronizeMailboxHeadersProgress(Account account, String folder,
|
||||||
|
int completed, int total) {}
|
||||||
|
|
||||||
public void synchronizeMailboxHeadersFinished(Account account, String folder,
|
public void synchronizeMailboxHeadersFinished(Account account, String folder,
|
||||||
int totalMessagesInMailbox, int numNewMessages) {
|
int totalMessagesInMailbox, int numNewMessages) {}
|
||||||
}
|
|
||||||
|
|
||||||
|
public void synchronizeMailboxProgress(Account account, String folder, int completed,
|
||||||
|
int total) {}
|
||||||
|
|
||||||
public void synchronizeMailboxProgress(Account account, String folder, int completed, int total)
|
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {}
|
||||||
{}
|
|
||||||
|
|
||||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
|
public void synchronizeMailboxAddOrUpdateMessage(Account account, String folder,
|
||||||
}
|
Message message) {}
|
||||||
|
|
||||||
public void synchronizeMailboxAddOrUpdateMessage(Account account, String folder, Message message) {
|
public void synchronizeMailboxRemovedMessage(Account account, String folder,
|
||||||
}
|
Message message) {}
|
||||||
|
|
||||||
public void synchronizeMailboxRemovedMessage(Account account, String folder, Message message) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void synchronizeMailboxFinished(Account account, String folder,
|
public void synchronizeMailboxFinished(Account account, String folder,
|
||||||
int totalMessagesInMailbox, int numNewMessages) {
|
int totalMessagesInMailbox, int numNewMessages) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void synchronizeMailboxFailed(Account account, String folder,
|
public void synchronizeMailboxFailed(Account account, String folder, String message) {}
|
||||||
String message) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadMessageForViewStarted(Account account, String folder, String uid) {
|
|
||||||
}
|
public void loadMessageForViewStarted(Account account, String folder, String uid) {}
|
||||||
|
|
||||||
public void loadMessageForViewHeadersAvailable(Account account, String folder, String uid,
|
public void loadMessageForViewHeadersAvailable(Account account, String folder, String uid,
|
||||||
Message message) {
|
Message message) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
|
public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
|
||||||
Message message) {
|
Message message) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void loadMessageForViewFinished(Account account, String folder, String uid,
|
public void loadMessageForViewFinished(Account account, String folder, String uid,
|
||||||
Message message) {
|
Message message) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void loadMessageForViewFailed(Account account, String folder, String uid, Throwable t) {
|
public void loadMessageForViewFailed(Account account, String folder, String uid,
|
||||||
}
|
Throwable t) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a message for view has been fully displayed on the screen.
|
* Called when a message for view has been fully displayed on the screen.
|
||||||
*/
|
*/
|
||||||
public void messageViewFinished() {}
|
public void messageViewFinished() {}
|
||||||
|
|
||||||
public void checkMailStarted(Context context, Account account) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkMailFinished(Context context, Account account) {
|
public void checkMailStarted(Context context, Account account) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void checkMailFailed(Context context, Account account, String reason) {
|
public void checkMailFinished(Context context, Account account) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void sendPendingMessagesStarted(Account account) {
|
public void checkMailFailed(Context context, Account account, String reason) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void sendPendingMessagesCompleted(Account account) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendPendingMessagesFailed(Account account) {
|
public void sendPendingMessagesStarted(Account account) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void messageDeleted(Account account, String folder, Message message) {
|
public void sendPendingMessagesCompleted(Account account) {}
|
||||||
|
|
||||||
}
|
public void sendPendingMessagesFailed(Account account) {}
|
||||||
public void emptyTrashCompleted(Account account) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void folderStatusChanged(Account account, String folderName, int unreadMessageCount) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void folderStatusChanged(Account account, String folderName) {
|
public void emptyTrashCompleted(Account account) {}
|
||||||
}
|
|
||||||
|
|
||||||
public void systemStatusChanged() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void messageUidChanged(Account account, String folder, String oldUid, String newUid) {
|
public void folderStatusChanged(Account account, String folderName, int unreadMessageCount) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPushActive(Account account, String folderName, boolean enabled) {
|
public void systemStatusChanged() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadAttachmentStarted(
|
public void messageDeleted(Account account, String folder, Message message) {}
|
||||||
Account account,
|
|
||||||
Message message,
|
|
||||||
Part part,
|
|
||||||
Object tag,
|
|
||||||
boolean requiresDownload) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadAttachmentFinished(
|
public void messageUidChanged(Account account, String folder, String oldUid, String newUid) {}
|
||||||
Account account,
|
|
||||||
Message message,
|
|
||||||
Part part,
|
|
||||||
Object tag) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadAttachmentFailed(
|
|
||||||
Account account,
|
public void setPushActive(Account account, String folderName, boolean enabled) {}
|
||||||
Message message,
|
|
||||||
Part part,
|
|
||||||
Object tag,
|
public void loadAttachmentStarted(Account account, Message message, Part part, Object tag,
|
||||||
String reason) {
|
boolean requiresDownload) {}
|
||||||
}
|
|
||||||
|
public void loadAttachmentFinished(Account account, Message message, Part part, Object tag) {}
|
||||||
|
|
||||||
|
public void loadAttachmentFailed(Account account, Message message, Part part, Object tag,
|
||||||
|
String reason) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void pendingCommandStarted(Account account, String commandTitle) {}
|
||||||
|
|
||||||
public void pendingCommandsProcessing(Account account) {}
|
public void pendingCommandsProcessing(Account account) {}
|
||||||
public void pendingCommandsFinished(Account account) {}
|
|
||||||
public void pendingCommandStarted(Account account, String commandTitle)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public void pendingCommandCompleted(Account account, String commandTitle)
|
public void pendingCommandCompleted(Account account, String commandTitle) {}
|
||||||
{}
|
|
||||||
|
public void pendingCommandsFinished(Account account) {}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General notification messages subclasses can override to be notified that the controller
|
* General notification messages subclasses can override to be notified that the controller
|
||||||
* has completed a command. This is useful for turning off progress indicators that may have
|
* has completed a command. This is useful for turning off progress indicators that may have
|
||||||
* been left over from previous commands.
|
* been left over from previous commands.
|
||||||
* @param moreCommandsToRun True if the controller will continue on to another command
|
*
|
||||||
* immediately.
|
* @param moreCommandsToRun
|
||||||
|
* {@code true} if the controller will continue on to another command immediately.
|
||||||
|
* {@code false} otherwise.
|
||||||
*/
|
*/
|
||||||
public void controllerCommandCompleted(boolean moreCommandsToRun) {
|
public void controllerCommandCompleted(boolean moreCommandsToRun) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
127
src/com/fsck/k9/provider/UnreadWidgetProvider.java
Normal file
127
src/com/fsck/k9/provider/UnreadWidgetProvider.java
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package com.fsck.k9.provider;
|
||||||
|
|
||||||
|
import com.fsck.k9.Account;
|
||||||
|
import com.fsck.k9.AccountStats;
|
||||||
|
import com.fsck.k9.K9;
|
||||||
|
import com.fsck.k9.Preferences;
|
||||||
|
import com.fsck.k9.R;
|
||||||
|
import com.fsck.k9.activity.UnreadWidgetConfiguration;
|
||||||
|
import com.fsck.k9.activity.FolderList;
|
||||||
|
import com.fsck.k9.activity.MessageList;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.appwidget.AppWidgetManager;
|
||||||
|
import android.appwidget.AppWidgetProvider;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.RemoteViews;
|
||||||
|
|
||||||
|
public class UnreadWidgetProvider extends AppWidgetProvider {
|
||||||
|
private static final int MAX_COUNT = 9999;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger update for all of our unread widgets.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* The {@code Context} object to use for the broadcast intent.
|
||||||
|
*/
|
||||||
|
public static void updateUnreadCount(Context context) {
|
||||||
|
Context appContext = context.getApplicationContext();
|
||||||
|
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(appContext);
|
||||||
|
|
||||||
|
ComponentName thisWidget = new ComponentName(appContext, UnreadWidgetProvider.class);
|
||||||
|
int[] widgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
|
||||||
|
|
||||||
|
Intent intent = new Intent(context, UnreadWidgetProvider.class);
|
||||||
|
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
||||||
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds);
|
||||||
|
|
||||||
|
context.sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateWidget(Context context, AppWidgetManager appWidgetManager,
|
||||||
|
int appWidgetId, String accountUuid) {
|
||||||
|
|
||||||
|
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
|
||||||
|
R.layout.unread_widget_layout);
|
||||||
|
|
||||||
|
int unreadCount = 0;
|
||||||
|
String accountName = context.getString(R.string.app_name);
|
||||||
|
Intent clickIntent = null;
|
||||||
|
try {
|
||||||
|
Account account = Preferences.getPreferences(context).getAccount(accountUuid);
|
||||||
|
if (account != null) {
|
||||||
|
AccountStats stats = new AccountStats();
|
||||||
|
account.getLocalStore().getMessageCounts(stats);
|
||||||
|
unreadCount = stats.unreadMessageCount;
|
||||||
|
accountName = account.getDescription();
|
||||||
|
if (K9.FOLDER_NONE.equals(account.getAutoExpandFolderName())) {
|
||||||
|
clickIntent = FolderList.actionHandleAccountIntent(context, account, null);
|
||||||
|
} else {
|
||||||
|
clickIntent = MessageList.actionHandleFolderIntent(context, account,
|
||||||
|
account.getAutoExpandFolderName());
|
||||||
|
}
|
||||||
|
clickIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (K9.DEBUG) {
|
||||||
|
Log.e(K9.LOG_TAG, "Error getting widget configuration", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unreadCount <= 0) {
|
||||||
|
// Hide TextView for unread count if there are no unread messages.
|
||||||
|
remoteViews.setViewVisibility(R.id.unread_count, View.GONE);
|
||||||
|
} else {
|
||||||
|
remoteViews.setViewVisibility(R.id.unread_count, View.VISIBLE);
|
||||||
|
|
||||||
|
String displayCount = (unreadCount <= MAX_COUNT) ?
|
||||||
|
String.valueOf(unreadCount) : String.valueOf(MAX_COUNT) + "+";
|
||||||
|
remoteViews.setTextViewText(R.id.unread_count, displayCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteViews.setTextViewText(R.id.account_name, accountName);
|
||||||
|
|
||||||
|
if (clickIntent == null) {
|
||||||
|
// If the widget configuration couldn't be loaded we open the configuration
|
||||||
|
// activity when the user clicks the widget.
|
||||||
|
clickIntent = new Intent(context, UnreadWidgetConfiguration.class);
|
||||||
|
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||||
|
}
|
||||||
|
clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
||||||
|
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId,
|
||||||
|
clickIntent, 0);
|
||||||
|
|
||||||
|
remoteViews.setOnClickPendingIntent(R.id.unread_widget_layout, pendingIntent);
|
||||||
|
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when one or more widgets need to be updated.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||||
|
for (int widgetId : appWidgetIds) {
|
||||||
|
String accountUuid = UnreadWidgetConfiguration.getAccountUuid(context, widgetId);
|
||||||
|
|
||||||
|
updateWidget(context, appWidgetManager, widgetId, accountUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a widget instance is deleted.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onDeleted(Context context, int[] appWidgetIds) {
|
||||||
|
for (int appWidgetId : appWidgetIds) {
|
||||||
|
UnreadWidgetConfiguration.deleteWidgetConfiguration(context, appWidgetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -102,15 +102,19 @@ public class SingleMessageView extends LinearLayout {
|
|||||||
// content://<nameofpackage>.providers.StatusProvider
|
// content://<nameofpackage>.providers.StatusProvider
|
||||||
cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
|
cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
|
||||||
+ ".providers.StatusProvider"), null, null, null, null);
|
+ ".providers.StatusProvider"), null, null, null, null);
|
||||||
if (cursor != null) {
|
try {
|
||||||
cursor.moveToFirst();
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
// These content providers use a special cursor that only has
|
// These content providers use a special cursor that only has
|
||||||
// one element,
|
// one element,
|
||||||
// an integer that is 1 if the screen reader is running.
|
// an integer that is 1 if the screen reader is running.
|
||||||
status = cursor.getInt(0);
|
status = cursor.getInt(0);
|
||||||
cursor.close();
|
if (status == 1) {
|
||||||
if (status == 1) {
|
return true;
|
||||||
return true;
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user