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"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="15007"
|
||||
android:versionName="4.107" package="com.fsck.k9"
|
||||
android:versionCode="15009"
|
||||
android:versionName="4.109" package="com.fsck.k9"
|
||||
>
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
@ -43,13 +43,13 @@
|
||||
<uses-permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"/>
|
||||
<permission android:name="com.fsck.k9.permission.READ_MESSAGES"
|
||||
android:permissionGroup="android.permission-group.MESSAGES"
|
||||
android:protectionLevel="normal"
|
||||
android:protectionLevel="dangerous"
|
||||
android:label="@string/read_messages_label"
|
||||
android:description="@string/read_messages_desc"/>
|
||||
<uses-permission android:name="com.fsck.k9.permission.READ_MESSAGES"/>
|
||||
<permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"
|
||||
android:permissionGroup="android.permission-group.MESSAGES"
|
||||
android:protectionLevel="normal"
|
||||
android:protectionLevel="dangerous"
|
||||
android:label="@string/delete_messages_label"
|
||||
android:description="@string/read_messages_desc"/>
|
||||
<uses-permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"/>
|
||||
@ -208,6 +208,10 @@
|
||||
android:launchMode="singleTask"
|
||||
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
|
||||
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: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>
|
||||
</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_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>
|
||||
|
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 address = mContacts.getEmail(cursor);
|
||||
|
||||
return new Address(address, name).toString();
|
||||
return (address == null) ? "" : new Address(address, name).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +31,7 @@ import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.internet.BinaryTempFileBody;
|
||||
import com.fsck.k9.provider.UnreadWidgetProvider;
|
||||
import com.fsck.k9.service.BootReceiver;
|
||||
import com.fsck.k9.service.MailService;
|
||||
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
|
||||
public void synchronizeMailboxRemovedMessage(Account account, String folder, Message message) {
|
||||
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
|
||||
updateUnreadWidget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageDeleted(Account account, String folder, Message message) {
|
||||
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
|
||||
updateUnreadWidget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
|
||||
broadcastIntent(K9.Intents.EmailReceived.ACTION_EMAIL_RECEIVED, account, folder, message);
|
||||
updateUnreadWidget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void folderStatusChanged(Account account, String folderName,
|
||||
int unreadMessageCount) {
|
||||
updateUnreadWidget();
|
||||
}
|
||||
|
||||
@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.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
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];
|
||||
|
||||
/**
|
||||
* 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_CLEAR_ACCOUNT = 2;
|
||||
private static final int DIALOG_RECREATE_ACCOUNT = 3;
|
||||
private static final int DIALOG_NO_FILE_MANAGER = 4;
|
||||
private static final String TRUE = "true";
|
||||
|
||||
private ConcurrentHashMap<String, AccountStats> accountStats = new ConcurrentHashMap<String, AccountStats>();
|
||||
|
||||
private ConcurrentHashMap<BaseAccount, String> pendingWork = new ConcurrentHashMap<BaseAccount, String>();
|
||||
@ -328,13 +341,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
||||
super.onCreate(icicle);
|
||||
|
||||
if (!K9.isHideSpecialAccounts()) {
|
||||
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));
|
||||
createSpecialAccounts();
|
||||
}
|
||||
|
||||
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")
|
||||
private void restoreAccountStats(Bundle icicle) {
|
||||
if (icicle != null) {
|
||||
@ -461,9 +481,13 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
||||
accounts = Preferences.getPreferences(this).getAccounts();
|
||||
|
||||
List<BaseAccount> newAccounts;
|
||||
if (!K9.isHideSpecialAccounts()
|
||||
&& accounts.length > 0) {
|
||||
newAccounts = new ArrayList<BaseAccount>(accounts.length + 2);
|
||||
if (!K9.isHideSpecialAccounts() && accounts.length > 0) {
|
||||
if (integratedInboxAccount == null || unreadAccount == null) {
|
||||
createSpecialAccounts();
|
||||
}
|
||||
|
||||
newAccounts = new ArrayList<BaseAccount>(accounts.length +
|
||||
SPECIAL_ACCOUNTS_COUNT);
|
||||
newAccounts.add(integratedInboxAccount);
|
||||
newAccounts.add(unreadAccount);
|
||||
} 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);
|
||||
}
|
||||
@ -1011,6 +1049,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
||||
alert.setMessage(getString(R.string.account_recreate_dlg_instructions_fmt,
|
||||
mSelectedContextAccount.getDescription()));
|
||||
break;
|
||||
case DIALOG_NO_FILE_MANAGER:
|
||||
alert.setMessage(getString(R.string.import_dialog_error_message));
|
||||
break;
|
||||
}
|
||||
|
||||
super.onPrepareDialog(id, d);
|
||||
@ -1266,7 +1307,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
||||
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
i.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
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
|
||||
|
@ -3,53 +3,42 @@ package com.fsck.k9.activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
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.FontSizes;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.BaseAccount;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.SearchSpecification;
|
||||
|
||||
public class LauncherShortcuts extends K9ListActivity implements OnItemClickListener {
|
||||
private AccountsAdapter mAdapter;
|
||||
private FontSizes mFontSizes = K9.getFontSizes();
|
||||
|
||||
public class LauncherShortcuts extends AccountList {
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
// finish() immediately if we aren't supposed to be here
|
||||
if (!Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.launcher_shortcuts);
|
||||
ListView listView = getListView();
|
||||
listView.setOnItemClickListener(this);
|
||||
listView.setItemsCanFocus(false);
|
||||
|
||||
refresh();
|
||||
super.onCreate(icicle);
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
||||
|
||||
mAdapter = new AccountsAdapter(accounts);
|
||||
getListView().setAdapter(mAdapter);
|
||||
@Override
|
||||
protected boolean displaySpecialAccounts() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setupShortcut(Account account) {
|
||||
final Intent shortcutIntent = FolderList.actionHandleAccountIntent(this, account, null, true);
|
||||
@Override
|
||||
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.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||
String description = account.getDescription();
|
||||
@ -63,66 +52,4 @@ public class LauncherShortcuts extends K9ListActivity implements OnItemClickList
|
||||
setResult(RESULT_OK, intent);
|
||||
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 String folderName = mMessageReference.folderName;
|
||||
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;
|
||||
|
@ -52,10 +52,12 @@ import android.widget.Toast;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.AccountStats;
|
||||
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;
|
||||
import com.fsck.k9.SearchSpecification;
|
||||
import com.fsck.k9.activity.setup.AccountSettings;
|
||||
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.store.LocalStore;
|
||||
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
||||
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
|
||||
|
||||
@ -613,7 +616,11 @@ public class MessageList
|
||||
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.putExtra(EXTRA_QUERY, searchSpecification.getQuery());
|
||||
if (searchSpecification.getRequiredFlags() != null) {
|
||||
@ -629,6 +636,13 @@ public class MessageList
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_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);
|
||||
}
|
||||
|
||||
@ -1392,13 +1406,21 @@ public class MessageList
|
||||
}
|
||||
|
||||
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;
|
||||
mHandler.sortMessages();
|
||||
}
|
||||
|
||||
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;
|
||||
mHandler.sortMessages();
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.helper.FileBrowserHelper;
|
||||
import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback;
|
||||
import com.fsck.k9.mail.*;
|
||||
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
|
||||
import com.fsck.k9.mail.store.StorageManager;
|
||||
import com.fsck.k9.view.AttachmentView;
|
||||
import com.fsck.k9.view.ToggleScrollView;
|
||||
@ -715,17 +714,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
if (mMessage != null) {
|
||||
boolean newState = !mMessage.isSet(Flag.FLAGGED);
|
||||
mController.setFlag(mAccount, mMessage.getFolder().getName(),
|
||||
new String[] {mMessage.getUid()}, Flag.FLAGGED, newState);
|
||||
try {
|
||||
// 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);
|
||||
}
|
||||
new Message[] { mMessage }, Flag.FLAGGED, newState);
|
||||
mMessageView.setHeaders(mMessage, mAccount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -858,18 +848,10 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
private void onMarkAsUnread() {
|
||||
if (mMessage != null) {
|
||||
mController.setFlag(mAccount, mMessage.getFolder().getName(),
|
||||
new String[] { mMessage.getUid() }, Flag.SEEN, false);
|
||||
try {
|
||||
// FIXME: This is a hack to mark our message object as unread. We can't call
|
||||
// Message.setFlag() because that would "adjust" the unread count twice.
|
||||
((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);
|
||||
}
|
||||
new Message[] { mMessage }, Flag.SEEN, false);
|
||||
mMessageView.setHeaders(mMessage, mAccount);
|
||||
String subject = mMessage.getSubject();
|
||||
setTitle(subject);
|
||||
}
|
||||
}
|
||||
|
||||
|
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
|
||||
public void act(final Account account, final Folder folder,
|
||||
final List<Message> messages) {
|
||||
String[] uids = new String[messages.size()];
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
uids[i] = messages.get(i).getUid();
|
||||
}
|
||||
setFlag(account, folder.getName(), uids, flag, newState);
|
||||
setFlag(account, folder.getName(), messages.toArray(EMPTY_MESSAGE_ARRAY), flag,
|
||||
newState);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void setFlag(
|
||||
final Account account,
|
||||
final String folderName,
|
||||
final String[] uids,
|
||||
final Flag flag,
|
||||
final boolean newState) {
|
||||
// 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
|
||||
/**
|
||||
* Set or remove a flag for a set of messages in a specific folder.
|
||||
*
|
||||
* <p>
|
||||
* The {@link Message} objects passed in are updated to reflect the new flag state.
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
try {
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
localFolder = localStore.getFolder(folderName);
|
||||
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
|
||||
if (flag == Flag.FLAGGED && !newState
|
||||
&& uid != null
|
||||
&& account.getOutboxFolderName().equals(folderName)) {
|
||||
sendCount.remove(uid);
|
||||
}
|
||||
Message msg = localFolder.getMessage(uid);
|
||||
if (msg != null) {
|
||||
messages.add(msg);
|
||||
|
||||
// Allows for re-allowing sending of messages that could not be sent
|
||||
if (flag == Flag.FLAGGED && !newState &&
|
||||
account.getOutboxFolderName().equals(folderName)) {
|
||||
for (Message message : messages) {
|
||||
String uid = message.getUid();
|
||||
if (uid != null) {
|
||||
sendCount.remove(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
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)) {
|
||||
return;
|
||||
}
|
||||
@ -2675,16 +2691,54 @@ public class MessagingController implements Runnable {
|
||||
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);
|
||||
processPendingCommands(account);
|
||||
} catch (MessagingException me) {
|
||||
addErrorMessage(account, null, me);
|
||||
|
||||
throw new RuntimeException(me);
|
||||
} finally {
|
||||
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) {
|
||||
try {
|
||||
@ -3334,6 +3388,8 @@ public class MessagingController implements Runnable {
|
||||
Store remoteStore = account.getRemoteStore();
|
||||
LocalFolder localSrcFolder = localStore.getFolder(srcFolder);
|
||||
LocalFolder localDestFolder = localStore.getFolder(destFolder);
|
||||
|
||||
boolean unreadCountAffected = false;
|
||||
List<String> uids = new LinkedList<String>();
|
||||
List<String> localUids = new LinkedList<String>();
|
||||
|
||||
@ -3350,6 +3406,10 @@ public class MessagingController implements Runnable {
|
||||
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.
|
||||
@ -3417,6 +3477,15 @@ public class MessagingController implements Runnable {
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
localSrcFolder.fetch(messages, fp, null);
|
||||
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 {
|
||||
localSrcFolder.moveMessages(messages, localDestFolder);
|
||||
for (Map.Entry<String, Message> entry : origUidMap.entrySet()) {
|
||||
@ -3427,6 +3496,16 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
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() &&
|
||||
@ -3480,6 +3559,17 @@ public class MessagingController implements Runnable {
|
||||
}
|
||||
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();
|
||||
@ -3495,6 +3585,16 @@ public class MessagingController implements Runnable {
|
||||
// local message copy to local folder
|
||||
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);
|
||||
@ -3752,7 +3852,8 @@ public class MessagingController implements Runnable {
|
||||
localFolder = localStore.getFolder(account.getTrashFolderName());
|
||||
localFolder.open(OpenMode.READ_WRITE);
|
||||
localFolder.setFlags(new Flag[] { Flag.DELETED }, true);
|
||||
localFolder.resetUnreadAndFlaggedCounts();
|
||||
localFolder.setUnreadMessageCount(0);
|
||||
localFolder.setFlaggedMessageCount(0);
|
||||
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.emptyTrashCompleted(account);
|
||||
|
@ -12,191 +12,154 @@ import com.fsck.k9.mail.Part;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defines the interface that MessagingController will use to callback to requesters. 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 @Override annotation in their implementations to avoid being caught by
|
||||
* Defines the interface that {@link MessagingController} will use to callback to requesters.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
public class MessagingListener {
|
||||
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,
|
||||
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,
|
||||
int totalMessagesInMailbox, int numNewMessages) {
|
||||
}
|
||||
int totalMessagesInMailbox, int numNewMessages) {}
|
||||
|
||||
public void synchronizeMailboxFailed(Account account, String folder,
|
||||
String message) {
|
||||
}
|
||||
public void synchronizeMailboxFailed(Account account, String folder, 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,
|
||||
Message message) {
|
||||
}
|
||||
Message message) {}
|
||||
|
||||
public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
|
||||
Message message) {
|
||||
}
|
||||
Message message) {}
|
||||
|
||||
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.
|
||||
*/
|
||||
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 emptyTrashCompleted(Account account) {
|
||||
}
|
||||
public void sendPendingMessagesFailed(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(
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag,
|
||||
boolean requiresDownload) {
|
||||
}
|
||||
public void messageDeleted(Account account, String folder, Message message) {}
|
||||
|
||||
public void loadAttachmentFinished(
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag) {
|
||||
}
|
||||
public void messageUidChanged(Account account, String folder, String oldUid, String newUid) {}
|
||||
|
||||
public void loadAttachmentFailed(
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag,
|
||||
String reason) {
|
||||
}
|
||||
|
||||
public void setPushActive(Account account, String folderName, boolean enabled) {}
|
||||
|
||||
|
||||
public void loadAttachmentStarted(Account account, Message message, Part part, Object tag,
|
||||
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 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
|
||||
* has completed a command. This is useful for turning off progress indicators that may have
|
||||
* 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
|
||||
cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
|
||||
+ ".providers.StatusProvider"), null, null, null, null);
|
||||
if (cursor != null) {
|
||||
cursor.moveToFirst();
|
||||
// These content providers use a special cursor that only has
|
||||
// one element,
|
||||
// an integer that is 1 if the screen reader is running.
|
||||
status = cursor.getInt(0);
|
||||
cursor.close();
|
||||
if (status == 1) {
|
||||
return true;
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// These content providers use a special cursor that only has
|
||||
// one element,
|
||||
// an integer that is 1 if the screen reader is running.
|
||||
status = cursor.getInt(0);
|
||||
if (status == 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user