mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-23 09:52:16 -05:00
Some first android wear support for enhancement
#619 "Add android wear support" No reply with voice yet (as requested in the ticket). No user-configurable actions yet, just delete+archive+spam No stacked notification for multiple messages yet.
This commit is contained in:
parent
0f848ee51f
commit
64e22a72ed
@ -211,8 +211,8 @@ public class MessagingController implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* List of messages that should be used for the inbox-style overview.
|
* List of messages that should be used for the inbox-style overview.
|
||||||
* It's sorted from newest to oldest message.
|
* It's sorted from newest to oldest message.
|
||||||
* Don't modify this list directly, but use {@link addMessage} and
|
* Don't modify this list directly, but use {@link #addMessage(com.fsck.k9.mailstore.LocalMessage)} and
|
||||||
* {@link removeMatchingMessage} instead.
|
* {@link #removeMatchingMessage(android.content.Context, com.fsck.k9.activity.MessageReference)} instead.
|
||||||
*/
|
*/
|
||||||
LinkedList<LocalMessage> messages;
|
LinkedList<LocalMessage> messages;
|
||||||
/**
|
/**
|
||||||
@ -4853,6 +4853,7 @@ public class MessagingController implements Runnable {
|
|||||||
NotificationActionService.getReplyIntent(context, account, message.makeMessageReference()));
|
NotificationActionService.getReplyIntent(context, account, message.makeMessageReference()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark Read on phone
|
||||||
builder.addAction(
|
builder.addAction(
|
||||||
platformSupportsLockScreenNotifications()
|
platformSupportsLockScreenNotifications()
|
||||||
? R.drawable.ic_action_mark_as_read_dark_vector
|
? R.drawable.ic_action_mark_as_read_dark_vector
|
||||||
@ -4864,15 +4865,51 @@ public class MessagingController implements Runnable {
|
|||||||
boolean showDeleteAction = deleteOption == NotificationQuickDelete.ALWAYS ||
|
boolean showDeleteAction = deleteOption == NotificationQuickDelete.ALWAYS ||
|
||||||
(deleteOption == NotificationQuickDelete.FOR_SINGLE_MSG && newMessages == 1);
|
(deleteOption == NotificationQuickDelete.FOR_SINGLE_MSG && newMessages == 1);
|
||||||
|
|
||||||
|
NotificationCompat.WearableExtender wearableExtender = new NotificationCompat.WearableExtender();
|
||||||
if (showDeleteAction) {
|
if (showDeleteAction) {
|
||||||
// we need to pass the action directly to the activity, otherwise the
|
// we need to pass the action directly to the activity, otherwise the
|
||||||
// status bar won't be pulled up and we won't see the confirmation (if used)
|
// status bar won't be pulled up and we won't see the confirmation (if used)
|
||||||
|
|
||||||
|
// Delete on phone
|
||||||
builder.addAction(
|
builder.addAction(
|
||||||
platformSupportsLockScreenNotifications()
|
platformSupportsLockScreenNotifications()
|
||||||
? R.drawable.ic_action_delete_dark_vector
|
? R.drawable.ic_action_delete_dark_vector
|
||||||
: R.drawable.ic_action_delete_dark,
|
: R.drawable.ic_action_delete_dark,
|
||||||
context.getString(R.string.notification_action_delete),
|
context.getString(R.string.notification_action_delete),
|
||||||
NotificationDeleteConfirmation.getIntent(context, account, allRefs));
|
NotificationDeleteConfirmation.getIntent(context, account, allRefs));
|
||||||
|
|
||||||
|
// Delete on wear only if no confirmation is required
|
||||||
|
if (!K9.confirmDeleteFromNotification()) {
|
||||||
|
NotificationCompat.Action wearActionDelete =
|
||||||
|
new NotificationCompat.Action.Builder(
|
||||||
|
R.drawable.ic_action_delete_dark,
|
||||||
|
context.getString(R.string.notification_action_delete),
|
||||||
|
NotificationDeleteConfirmation.getIntent(context, account, allRefs))
|
||||||
|
.build();
|
||||||
|
builder.extend(wearableExtender.addAction(wearActionDelete));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NotificationActionService.isArchiveAllMessagesWearAvaliable(context, account, data.messages)) {
|
||||||
|
|
||||||
|
// Archive on wear
|
||||||
|
NotificationCompat.Action wearActionArchive =
|
||||||
|
new NotificationCompat.Action.Builder(
|
||||||
|
R.drawable.ic_action_delete_dark,
|
||||||
|
context.getString(R.string.notification_action_archive),
|
||||||
|
NotificationActionService.getArchiveAllMessagesIntent(context, account, allRefs))
|
||||||
|
.build();
|
||||||
|
builder.extend(wearableExtender.addAction(wearActionArchive));
|
||||||
|
}
|
||||||
|
if (NotificationActionService.isSpamAllMessagesWearAvaliable(context, account, data.messages)) {
|
||||||
|
|
||||||
|
// Archive on wear
|
||||||
|
NotificationCompat.Action wearActionSpam =
|
||||||
|
new NotificationCompat.Action.Builder(
|
||||||
|
R.drawable.ic_action_delete_dark,
|
||||||
|
context.getString(R.string.notification_action_spam),
|
||||||
|
NotificationActionService.getSpamAllMessagesIntent(context, account, allRefs))
|
||||||
|
.build();
|
||||||
|
builder.extend(wearableExtender.addAction(wearActionSpam));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String accountNotice = context.getString(R.string.notification_new_one_account_fmt,
|
String accountNotice = context.getString(R.string.notification_new_one_account_fmt,
|
||||||
|
@ -2,6 +2,7 @@ package com.fsck.k9.service;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.fsck.k9.Account;
|
import com.fsck.k9.Account;
|
||||||
@ -18,10 +19,16 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service called by actions in notifications.
|
||||||
|
* Provides a number of default actions to trigger.
|
||||||
|
*/
|
||||||
public class NotificationActionService extends CoreService {
|
public class NotificationActionService extends CoreService {
|
||||||
private final static String REPLY_ACTION = "com.fsck.k9.service.NotificationActionService.REPLY_ACTION";
|
private final static String REPLY_ACTION = "com.fsck.k9.service.NotificationActionService.REPLY_ACTION";
|
||||||
private final static String READ_ALL_ACTION = "com.fsck.k9.service.NotificationActionService.READ_ALL_ACTION";
|
private final static String READ_ALL_ACTION = "com.fsck.k9.service.NotificationActionService.READ_ALL_ACTION";
|
||||||
private final static String DELETE_ALL_ACTION = "com.fsck.k9.service.NotificationActionService.DELETE_ALL_ACTION";
|
private final static String DELETE_ALL_ACTION = "com.fsck.k9.service.NotificationActionService.DELETE_ALL_ACTION";
|
||||||
|
private final static String ARCHIVE_ALL_ACTION = "com.fsck.k9.service.NotificationActionService.ARCHIVE_ALL_ACTION";
|
||||||
|
private final static String SPAM_ALL_ACTION = "com.fsck.k9.service.NotificationActionService.SPAM_ALL_ACTION";
|
||||||
private final static String ACKNOWLEDGE_ACTION = "com.fsck.k9.service.NotificationActionService.ACKNOWLEDGE_ACTION";
|
private final static String ACKNOWLEDGE_ACTION = "com.fsck.k9.service.NotificationActionService.ACKNOWLEDGE_ACTION";
|
||||||
|
|
||||||
private final static String EXTRA_ACCOUNT = "account";
|
private final static String EXTRA_ACCOUNT = "account";
|
||||||
@ -63,6 +70,69 @@ public class NotificationActionService extends CoreService {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if for the given parameters the ArchiveAllMessages intent is possible for Android Wear.
|
||||||
|
* (No confirmation on the phone required and moving these messages to the spam-folder possible)<br/>
|
||||||
|
* Since we can not show a toast like on the phone screen, we must not offer actions that can not be performed.
|
||||||
|
* @see #getArchiveAllMessagesIntent(android.content.Context, com.fsck.k9.Account, java.io.Serializable)
|
||||||
|
* @param context the context to get a {@link MessagingController}
|
||||||
|
* @param account the account (must allow moving messages to allow true as a result)
|
||||||
|
* @param messages the messages to move to the spam folder (must be synchronized to allow true as a result)
|
||||||
|
* @return true if the ArchiveAllMessages intent is available for the given messages
|
||||||
|
*/
|
||||||
|
public static boolean isArchiveAllMessagesWearAvaliable(Context context, final Account account, final LinkedList<LocalMessage> messages) {
|
||||||
|
final MessagingController controller = MessagingController.getInstance(context);
|
||||||
|
return (account.getArchiveFolderName() != null && !(account.getArchiveFolderName().equals(account.getSpamFolderName()) && K9.confirmSpam()) && isMovePossible(controller, account, account.getSentFolderName(), messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PendingIntent getArchiveAllMessagesIntent(Context context, final Account account, final Serializable refs) {
|
||||||
|
Intent i = new Intent(context, NotificationActionService.class);
|
||||||
|
i.putExtra(EXTRA_ACCOUNT, account.getUuid());
|
||||||
|
i.putExtra(EXTRA_MESSAGE_LIST, refs);
|
||||||
|
i.setAction(ARCHIVE_ALL_ACTION);
|
||||||
|
|
||||||
|
return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if for the given parameters the SpamAllMessages intent is possible for Android Wear.
|
||||||
|
* (No confirmation on the phone required and moving these messages to the spam-folder possible)<br/>
|
||||||
|
* Since we can not show a toast like on the phone screen, we must not offer actions that can not be performed.
|
||||||
|
* @see #getSpamAllMessagesIntent(android.content.Context, com.fsck.k9.Account, java.io.Serializable)
|
||||||
|
* @param context the context to get a {@link MessagingController}
|
||||||
|
* @param account the account (must allow moving messages to allow true as a result)
|
||||||
|
* @param messages the messages to move to the spam folder (must be synchronized to allow true as a result)
|
||||||
|
* @return true if the SpamAllMessages intent is available for the given messages
|
||||||
|
*/
|
||||||
|
public static boolean isSpamAllMessagesWearAvaliable(Context context, final Account account, final LinkedList<LocalMessage> messages) {
|
||||||
|
final MessagingController controller = MessagingController.getInstance(context);
|
||||||
|
return (account.getSpamFolderName() != null && !K9.confirmSpam() && isMovePossible(controller, account, account.getSentFolderName(), messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PendingIntent getSpamAllMessagesIntent(Context context, final Account account, final Serializable refs) {
|
||||||
|
Intent i = new Intent(context, NotificationActionService.class);
|
||||||
|
i.putExtra(EXTRA_ACCOUNT, account.getUuid());
|
||||||
|
i.putExtra(EXTRA_MESSAGE_LIST, refs);
|
||||||
|
i.setAction(SPAM_ALL_ACTION);
|
||||||
|
|
||||||
|
return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isMovePossible(MessagingController controller, Account account, String dstFolder, List<LocalMessage> messages) {
|
||||||
|
if (!controller.isMoveCapable(account)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (K9.FOLDER_NONE.equalsIgnoreCase(dstFolder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for(LocalMessage messageToMove : messages) {
|
||||||
|
if (!controller.isMoveCapable(messageToMove)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public int startService(Intent intent, int startId) {
|
public int startService(Intent intent, int startId) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
@ -98,6 +168,59 @@ public class NotificationActionService extends CoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
controller.deleteMessages(messages, null);
|
controller.deleteMessages(messages, null);
|
||||||
|
} else if (ARCHIVE_ALL_ACTION.equals(action)) {
|
||||||
|
if (K9.DEBUG)
|
||||||
|
Log.i(K9.LOG_TAG, "NotificationActionService archiving messages");
|
||||||
|
|
||||||
|
List<MessageReference> refs =
|
||||||
|
intent.getParcelableArrayListExtra(EXTRA_MESSAGE_LIST);
|
||||||
|
List<LocalMessage> messages = new ArrayList<LocalMessage>();
|
||||||
|
|
||||||
|
for (MessageReference ref : refs) {
|
||||||
|
LocalMessage m = ref.restoreToLocalMessage(this.getApplicationContext());
|
||||||
|
if (m != null) {
|
||||||
|
messages.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String dstFolder = account.getArchiveFolderName();
|
||||||
|
if (dstFolder != null
|
||||||
|
&& !(dstFolder.equals(account.getSpamFolderName()) && K9.confirmSpam())
|
||||||
|
&& isMovePossible(controller, account, dstFolder, messages)) {
|
||||||
|
for(LocalMessage messageToMove : messages) {
|
||||||
|
if (!controller.isMoveCapable(messageToMove)) {
|
||||||
|
//Toast toast = Toast.makeText(getActivity(), R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG);
|
||||||
|
//toast.show();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String srcFolder = messageToMove.getFolder().getName();
|
||||||
|
controller.moveMessage(account, srcFolder, messageToMove, dstFolder, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (SPAM_ALL_ACTION.equals(action)) {
|
||||||
|
if (K9.DEBUG)
|
||||||
|
Log.i(K9.LOG_TAG, "NotificationActionService moving messages to spam");
|
||||||
|
|
||||||
|
List<MessageReference> refs =
|
||||||
|
intent.getParcelableArrayListExtra(EXTRA_MESSAGE_LIST);
|
||||||
|
List<LocalMessage> messages = new ArrayList<LocalMessage>();
|
||||||
|
|
||||||
|
for (MessageReference ref : refs) {
|
||||||
|
LocalMessage m = ref.restoreToLocalMessage(this);
|
||||||
|
if (m != null) {
|
||||||
|
messages.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String dstFolder = account.getSpamFolderName();
|
||||||
|
if (dstFolder != null
|
||||||
|
&& !K9.confirmSpam()
|
||||||
|
&& isMovePossible(controller, account, dstFolder, messages)) {
|
||||||
|
for(LocalMessage messageToMove : messages) {
|
||||||
|
String srcFolder = messageToMove.getFolder().getName();
|
||||||
|
controller.moveMessage(account, srcFolder, messageToMove, dstFolder, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (REPLY_ACTION.equals(action)) {
|
} else if (REPLY_ACTION.equals(action)) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "NotificationActionService initiating reply");
|
Log.i(K9.LOG_TAG, "NotificationActionService initiating reply");
|
||||||
|
@ -167,6 +167,8 @@ Um Fehler zu melden, neue Funktionen vorzuschlagen oder Fragen zu stellen, besuc
|
|||||||
<string name="notification_action_reply">Antworten</string>
|
<string name="notification_action_reply">Antworten</string>
|
||||||
<string name="notification_action_mark_as_read">Gelesen</string>
|
<string name="notification_action_mark_as_read">Gelesen</string>
|
||||||
<string name="notification_action_delete">Löschen</string>
|
<string name="notification_action_delete">Löschen</string>
|
||||||
|
<string name="notification_action_spam">Spam</string>
|
||||||
|
<string name="notification_action_archive">Archivieren</string>
|
||||||
<string name="notification_certificate_error_title">Zertifikatsproblem (<xliff:g id="account">%s</xliff:g>)</string>
|
<string name="notification_certificate_error_title">Zertifikatsproblem (<xliff:g id="account">%s</xliff:g>)</string>
|
||||||
<string name="notification_certificate_error_text">Überprüfen Sie Ihre Servereinstellungen</string>
|
<string name="notification_certificate_error_text">Überprüfen Sie Ihre Servereinstellungen</string>
|
||||||
<string name="notification_bg_sync_ticker">Neue E-Mails in <xliff:g id="account">%s</xliff:g>:<xliff:g id="folder">%s</xliff:g> werden abgerufen</string>
|
<string name="notification_bg_sync_ticker">Neue E-Mails in <xliff:g id="account">%s</xliff:g>:<xliff:g id="folder">%s</xliff:g> werden abgerufen</string>
|
||||||
|
@ -210,6 +210,8 @@ Please submit bug reports, contribute new features and ask questions at
|
|||||||
<string name="notification_action_reply">Reply</string>
|
<string name="notification_action_reply">Reply</string>
|
||||||
<string name="notification_action_mark_as_read">Mark Read</string>
|
<string name="notification_action_mark_as_read">Mark Read</string>
|
||||||
<string name="notification_action_delete">Delete</string>
|
<string name="notification_action_delete">Delete</string>
|
||||||
|
<string name="notification_action_archive">Archive</string>
|
||||||
|
<string name="notification_action_spam">Spam</string>
|
||||||
<string name="notification_certificate_error_title">Certificate error for <xliff:g id="account">%s</xliff:g></string>
|
<string name="notification_certificate_error_title">Certificate error for <xliff:g id="account">%s</xliff:g></string>
|
||||||
<string name="notification_certificate_error_text">Check your server settings</string>
|
<string name="notification_certificate_error_text">Check your server settings</string>
|
||||||
|
|
||||||
@ -1147,4 +1149,5 @@ Please submit bug reports, contribute new features and ask questions at
|
|||||||
<string name="crypto_incomplete_message">Incomplete message</string>
|
<string name="crypto_incomplete_message">Incomplete message</string>
|
||||||
<!-- Note: This references message_view_download_remainder -->
|
<!-- Note: This references message_view_download_remainder -->
|
||||||
<string name="crypto_download_complete_message_to_decrypt">Click \'Download complete message\' to allow decryption.</string>
|
<string name="crypto_download_complete_message_to_decrypt">Click \'Download complete message\' to allow decryption.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user