1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-02-14 06:00:21 -05:00

Merge remote branch 'origin/master' into ms-eas

This commit is contained in:
wongk 2012-01-09 13:05:32 -05:00
commit 6c06fb2071
23 changed files with 375 additions and 135 deletions

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="15003"
android:versionName="4.103" package="com.fsck.k9"
android:versionCode="15004"
android:versionName="4.104" package="com.fsck.k9"
>
<uses-sdk
android:minSdkVersion="7"

View File

@ -19,6 +19,7 @@
<option name="LIBRARY_PROJECT" value="false" />
<option name="RUN_PROCESS_RESOURCES_MAVEN_TASK" value="true" />
<option name="GENERATE_UNSIGNED_APK" value="false" />
<option name="CUSTOM_DEBUG_KEYSTORE_PATH" value="" />
</configuration>
</facet>
</component>

View File

@ -40,8 +40,8 @@
<string name="status_processing_account">\u0020(Behandler <xliff:g id="account">%s</xliff:g>:<xliff:g id="command">%s</xliff:g><xliff:g id="progress">%s</xliff:g>)</string>
<string name="folder_progress">\u0020<xliff:g id="completed">%s</xliff:g>/<xliff:g id="total">%s</xliff:g></string>
<string name="status_next_poll">\u0020(Næste synk @ <xliff:g id="nexttime">%s</xliff:g>)</string>
<string name="status_syncing_off">\u0020(Synk deaktiveret)</string>
<string name="status_next_poll">\u0020(Næste synkronisering @ <xliff:g id="nexttime">%s</xliff:g>)</string>
<string name="status_syncing_off">\u0020(synkronisering deaktiveret)</string>
<!-- Actions will be used as buttons and in menu items -->
<string name="next_action">Næste</string> <!-- Used as part of a multi-step process -->
@ -118,7 +118,7 @@
<string name="dump_settings_action">Dump indstillinger</string>
<string name="empty_trash_action">Tøm papirkurv</string>
<string name="expunge_action">Ryd helt</string>
<string name="clear_local_folder_action">Fjern lokalt lagrede meddelelser</string>
<string name="clear_local_folder_action">Fjern lokalt lagrede mails</string>
<string name="set_sort_action">Vælg sortering</string>
<string name="reverse_sort_action">Omvendt sortering</string>
<string name="about_action">Om</string>
@ -321,10 +321,10 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="global_settings_checkbox_label">Checkbokse for multible valg</string>
<string name="global_settings_checkbox_summary">Vis altid checkbokse for multible valg</string>
<string name="global_settings_touchable_label">Touch venlig visning</string>
<string name="global_settings_touchable_summary">Rummeligere listning med forhåndsvisning</string>
<string name="global_settings_preview_lines_label">Linier med forhåndsvisning</string>
<string name="global_settings_touchable_summary">Rummeligere listning i forhåndsvisning</string>
<string name="global_settings_preview_lines_label">Linier i forhåndsvisning</string>
<string name="global_settings_show_correspondent_names_label">Vis afsenders navne</string>
<string name="global_settings_show_correspondent_names_summary">Vis afsenders navne fremfor deres mailaddresser</string>
<string name="global_settings_show_correspondent_names_summary">Vis afsendernavn fremfor deres mailaddresse</string>
<string name="global_settings_show_contact_name_label">Vis kontaktnavne</string>
<string name="global_settings_show_contact_name_summary">Benyt afsendernavne fra eksisterende kontakter</string>
<string name="global_settings_registered_name_color_label">Farvelæg kontakter</string>
@ -333,7 +333,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="global_settings_messageview_fixedwidth_label">Tegnsæt med fast bredde</string>
<string name="global_settings_messageview_fixedwidth_summary">Benyt tegnsæt med fast bredde til visning af mails med ren tekst</string>
<string name="global_settings_messageview_return_to_list_label">Returner til liste efter sletning</string>
<string name="global_settings_messageview_return_to_list_label">Retur til liste efter sletning</string>
<string name="global_settings_messageview_return_to_list_summary">Returner til mailliste efter sletning af mail</string>
<string name="global_settings_messageview_show_next_label">Vis næste mail efter sletning</string>
<string name="global_settings_messageview_show_next_summary">Vis som standard næste mail efter sletning af mail</string>
@ -370,7 +370,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="account_setup_check_settings_check_incoming_msg">Kontrollerer indstillinger for indgående server\u2026</string>
<string name="account_setup_check_settings_check_outgoing_msg">Kontrollerer indstillinger for udgående server\u2026</string>
<string name="account_setup_check_settings_authenticate">Autentiserer\u2026</string>
<string name="account_setup_check_settings_fetch">Henter konto indstillinger\u2026</string>
<string name="account_setup_check_settings_fetch">Henter kontoindstillinger\u2026</string>
<string name="account_setup_check_settings_finishing_msg">Afslutter\u2026</string>
<string name="account_setup_check_settings_canceling_msg">Afbryder\u2026</string>
@ -472,7 +472,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="compact_action">Komprimer</string>
<string name="clear_action">Ryd mails (farligt!)</string>
<string name="recreate_action">Genskab data (Sidste udvej!)</string>
<string name="recreate_action">Genskab data (sidste udvej!)</string>
<string name="account_setup_options_mail_check_frequency_label">Frekvens for hentning af mail</string>
<!-- Frequency also used in account_settings_* -->
@ -542,7 +542,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="account_settings_notify_self_summary">Vis besked for mails sendt af mig</string>
<string name="account_settings_notification_opens_unread_label">Klik på besked, viser ulæste mails</string>
<string name="account_settings_notification_opens_unread_summary">Søger efter ulæste mails når besked vises</string>
<string name="account_settings_notification_unread_count_label">Vis antallet af ulæste mails</string>
<string name="account_settings_notification_unread_count_label">Vis antal ulæste mails</string>
<string name="account_settings_notification_unread_count_summary">Vis antallet af ulæste mails i statusbar.</string>
<string name="account_settings_hide_buttons_label">Scroll navigations knapper</string>
@ -554,7 +554,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="account_settings_enable_move_buttons_summary">Vis Arkiver, Flyt og Spam knapper.</string>
<string name="account_settings_hide_move_buttons_label">Scroll Flyt knapper</string>
<string name="account_settings_show_pictures_label">Vis altid billeder automatisk</string>
<string name="account_settings_show_pictures_label">Vis altid billeder</string>
<string name="account_settings_show_pictures_never">Aldrig</string>
<string name="account_settings_show_pictures_only_from_contacts">Kun når afsender findes i Kontakter</string>
<string name="account_settings_show_pictures_always">Fra alle</string>
@ -562,10 +562,10 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="account_settings_composition">Skriv mail</string>
<string name="account_settings_default_quoted_text_shown_label">Medtag den originale meddelelse i svar</string>
<string name="account_settings_default_quoted_text_shown_summary">Når du sender svar på mail, vil den oprindelige tekst blive medtaget.</string>
<string name="account_settings_default_quoted_text_shown_summary">Når du sender svar på mail, vil den oprindelige tekst blive medtaget</string>
<string name="account_settings_reply_after_quote_label">Svar placeres efter citeret tekst</string>
<string name="account_settings_reply_after_quote_summary">Når du sender svar på mail, vil den oprindelige tekst blive placeret oven over dit svar.</string>
<string name="account_settings_reply_after_quote_summary">Når du sender svar på mail, vil den oprindelige tekst blive placeret oven over dit svar</string>
<string name="account_settings_strip_signature_label">Fjern signatur fra citeret svar</string>
<string name="account_settings_strip_signature_summary">Når du sender svar på mail, vil evt. signatur i citeret tekst blive fjernet</string>
@ -721,7 +721,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="account_settings_composition_summary">Standardindstilling for afsender, Bcc og signatur</string>
<string name="account_settings_identities_label">Håndter identiteter</string>
<string name="account_settings_identities_summary">Opsæt alternativ \'Fra\' addresse og signatur</string>
<string name="account_settings_identities_summary">Opsæt alternativ afsender-addresse og signatur</string>
<string name="manage_identities_title">Håndter identiteter</string>
@ -792,10 +792,10 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="account_delete_dlg_instructions_fmt">Kontoen \"<xliff:g id="account">%s</xliff:g>\" vil blive fjernet fra K-9 Mail.</string>
<string name="account_recreate_dlg_title">Nulstil konto</string>
<string name="account_recreate_dlg_instructions_fmt">Alle mails, vedhæftede filer, mapper og mappe-indstillinger for \"<xliff:g id="account">%s</xliff:g>\" vil blive fjernet fra K-9 Mail, men konto indstillinger vil blive husket.</string>
<string name="account_recreate_dlg_instructions_fmt">Alle mails, vedhæftede filer, mapper og mappe-indstillinger for \"<xliff:g id="account">%s</xliff:g>\" vil blive fjernet fra K-9 Mail, men kontoindstillinger vil blive husket.</string>
<string name="account_clear_dlg_title">Rens konto</string>
<string name="account_clear_dlg_instructions_fmt">Alle mails i \"<xliff:g id="account">%s</xliff:g>\" vil blive fjernet, men konto indstillinger vil blive husket.</string>
<string name="account_clear_dlg_instructions_fmt">Alle mails i \"<xliff:g id="account">%s</xliff:g>\" vil blive fjernet, men kontoindstillinger vil blive husket.</string>
<string name="provider_note_live">Kun visse \"Plus\" konti tillader adgang via POP
som er nødvendig for at kunne tilgå konto. Hvis du ikke kan logge ind på trods af
@ -827,7 +827,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
3 - Vis alle pånær sekundære mapper\u000A
4 - Vis alle mapper\u000A
Q - Returner til Konti\u000A
S - Rediger konto indstillinger</string>
S - Rediger kontoindstillinger</string>
<string name="folder_list_display_mode_label">Mapper</string>
<string name="folder_list_display_mode_all">Vis alle mapper</string>
@ -862,8 +862,8 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="background_ops_label">Baggrundssynkronisering</string>
<string name="background_ops_never">Aldrig</string>
<string name="background_ops_always">Altid</string>
<string name="background_ops_enabled">Når \'Baggrundsdata\' er aktiveret</string>
<string name="background_ops_auto_sync">Når \'Baggrundsdata\' &amp; \'Auto-sync\' er aktiveret</string>
<string name="background_ops_enabled">Når \"Baggrundsdata\" er aktiveret</string>
<string name="background_ops_auto_sync">Når \"Baggrundsdata\" &amp; \"Auto-sync\" er aktiveret</string>
<string name="no_message_seletected_toast">Ingen mail valgt</string>
@ -908,14 +908,14 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="gestures_summary">Benyt gesture kontrol</string>
<string name="compact_layouts_title">Kompakt layout</string>
<string name="compact_layouts_summary">Juster layouts så der vises mere på hver side</string>
<string name="compact_layouts_summary">Juster layout så der vises mere på hver side</string>
<string name="volume_navigation_title">Volume-knap navigation</string>
<string name="volume_navigation_summary">Skift mellem valg vha. volume-knapper</string>
<string name="volume_navigation_message">Mail-visning</string>
<string name="volume_navigation_list">Diverse listevisninger</string>
<string name="manage_back_title">Håndter \"Tilbageknappen\"</string>
<string name="manage_back_title">Håndter \"Tilbageknap\"</string>
<string name="manage_back_summary">\"Tilbageknap\" går altid et niveau op</string>
<string name="start_integrated_inbox_title">Start i fælles indbakke</string>
@ -928,7 +928,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="count_search_summary">Deaktiver for hurtigere visning</string>
<string name="hide_special_accounts_title">Skjul specialkonti</string>
<string name="hide_special_accounts_summary">Skjul fælles indbakke og alle mailkonti</string>
<string name="hide_special_accounts_summary">Skjul fælles indbakke og fælles mailkonti</string>
<string name="search_title"><xliff:g id="search_name">%s</xliff:g> <xliff:g id="modifier">%s</xliff:g></string>
<string name="flagged_modifier"> - Stjernemarkerede</string>
@ -972,7 +972,7 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="font_size_message_view">Meddelelse</string>
<string name="font_size_message_view_sender">Afsender</string>
<string name="font_size_message_view_to">Modtagere(Til)</string>
<string name="font_size_message_view_to">Modtagere (Til)</string>
<string name="font_size_message_view_cc">Modtagere (Cc)</string>
<string name="font_size_message_view_additional_headers">Yderligere headers</string>
<string name="font_size_message_view_subject">Emne</string>
@ -1058,8 +1058,8 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<string name="error_unable_to_connect">Kunne ikke opnå forbindelse.</string>
<string name="import_export_action">Import &amp; eksport af indstillinger</string>
<string name="settings_export_account">Eksport konto indstillinger</string>
<string name="settings_export_all">Eksport indstillinger og konti</string>
<string name="settings_export_account">Eksporter kontoindstillinger</string>
<string name="settings_export_all">Eksporter indstillinger og konti</string>
<string name="settings_import_dialog_title">Importer</string>
<string name="settings_export_dialog_title">Eksporter</string>
<string name="settings_import">Importer indstillinger</string>

View File

@ -18,6 +18,7 @@ import com.fsck.k9.mail.store.StorageManager;
import com.fsck.k9.mail.store.StorageManager.StorageProvider;
import com.fsck.k9.view.ColorChip;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;

View File

@ -509,7 +509,7 @@ public class K9 extends Application {
DEBUG = sprefs.getBoolean("enableDebugLogging", false);
DEBUG_SENSITIVE = sprefs.getBoolean("enableSensitiveLogging", false);
mAnimations = sprefs.getBoolean("animations", true);
mGesturesEnabled = sprefs.getBoolean("gesturesEnabled", true);
mGesturesEnabled = sprefs.getBoolean("gesturesEnabled", false);
mUseVolumeKeysForNavigation = sprefs.getBoolean("useVolumeKeysForNavigation", false);
mUseVolumeKeysForListNavigation = sprefs.getBoolean("useVolumeKeysForListNavigation", false);
mManageBack = sprefs.getBoolean("manageBack", false);
@ -522,7 +522,7 @@ public class K9 extends Application {
mMessageListTouchable = sprefs.getBoolean("messageListTouchable", false);
mMessageListPreviewLines = sprefs.getInt("messageListPreviewLines", 2);
mMobileOptimizedLayout = sprefs.getBoolean("mobileOptimizedLayout", false);
mZoomControlsEnabled = sprefs.getBoolean("zoomControlsEnabled", false);
mZoomControlsEnabled = sprefs.getBoolean("zoomControlsEnabled", true);
mQuietTimeEnabled = sprefs.getBoolean("quietTimeEnabled", false);
mQuietTimeStarts = sprefs.getString("quietTimeStarts", "21:00");
mQuietTimeEnds = sprefs.getString("quietTimeEnds", "7:00");

View File

@ -7,6 +7,7 @@ import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
@ -15,7 +16,6 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import com.fsck.k9.K9;
import com.fsck.k9.helper.DateFormatter;
import com.fsck.k9.view.ToggleScrollView;
@ -70,12 +70,9 @@ public class K9Activity extends Activity {
setupFormats();
}
private java.text.DateFormat mDateFormat;
private java.text.DateFormat mTimeFormat;
private void setupFormats() {
mDateFormat = DateFormatter.getDateFormat(this);
mTimeFormat = android.text.format.DateFormat.getTimeFormat(this); // 12/24 date format
}
@ -83,10 +80,6 @@ public class K9Activity extends Activity {
return mTimeFormat;
}
public java.text.DateFormat getDateFormat() {
return mDateFormat;
}
/**
* Called when a swipe from right to left is handled by {@link MyGestureDetector}. See
* {@link android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)}
@ -148,7 +141,6 @@ public class K9Activity extends Activity {
this.gesturesEnabled = gesturesEnabled;
}
private static final float SWIPE_MIN_DISTANCE_DIP = 130.0f;
private static final float SWIPE_MAX_OFF_PATH_DIP = 250f;
private static final float SWIPE_THRESHOLD_VELOCITY_DIP = 325f;
@ -172,21 +164,50 @@ public class K9Activity extends Activity {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Do fling-detection if gestures are force-enabled or we have system-wide gestures enabled.
if (gesturesEnabled || K9.gesturesEnabled()) {
// Convert the dips to pixels
// Calculate the minimum distance required for this to count as a swipe.
// Convert the constant dips to pixels.
final float mGestureScale = getResources().getDisplayMetrics().density;
int min_distance = (int)(SWIPE_MIN_DISTANCE_DIP * mGestureScale + 0.5f);
int min_velocity = (int)(SWIPE_THRESHOLD_VELOCITY_DIP * mGestureScale + 0.5f);
int max_off_path = (int)(SWIPE_MAX_OFF_PATH_DIP * mGestureScale + 0.5f);
final int minVelocity = (int)(SWIPE_THRESHOLD_VELOCITY_DIP * mGestureScale + 0.5f);
final int maxOffPath = (int)(SWIPE_MAX_OFF_PATH_DIP * mGestureScale + 0.5f);
// Calculate how much was actually swiped.
final float deltaX = e2.getX() - e1.getX();
final float deltaY = e2.getY() - e1.getY();
// Calculate the minimum distance required for this to be considered a swipe.
final int minDistance = (int)Math.abs(deltaY * 4);
if(K9.DEBUG) {
final boolean movedAcross = (Math.abs(deltaX) > Math.abs(deltaY * 4));
final boolean steadyHand = (Math.abs(deltaX / deltaY) > 2);
Log.d(K9.LOG_TAG, String.format("Old swipe algorithm: movedAcross=%s steadyHand=%s result=%s", movedAcross, steadyHand, movedAcross && steadyHand));
Log.d(K9.LOG_TAG, String.format("New swipe algorithm: deltaX=%.2f deltaY=%.2f minDistance=%d velocity=%.2f (min=%d)", deltaX, deltaY, minDistance, velocityX, minVelocity));
}
try {
if (Math.abs(e1.getY() - e2.getY()) > max_off_path)
if (Math.abs(deltaY) > maxOffPath) {
if(K9.DEBUG)
Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe too far off horizontal path.");
return false;
}
if(Math.abs(velocityX) < minVelocity) {
if(K9.DEBUG)
Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe too slow.");
return false;
}
// right to left swipe
if (e1.getX() - e2.getX() > min_distance && Math.abs(velocityX) > min_velocity) {
if (deltaX < (minDistance * -1)) {
onSwipeRightToLeft(e1, e2);
} else if (e2.getX() - e1.getX() > min_distance && Math.abs(velocityX) > min_velocity) {
if(K9.DEBUG)
Log.d(K9.LOG_TAG, "New swipe algorithm: Right to Left swipe OK.");
} else if (deltaX > minDistance) {
onSwipeLeftToRight(e1, e2);
if(K9.DEBUG)
Log.d(K9.LOG_TAG, "New swipe algorithm: Left to Right swipe OK.");
} else {
if(K9.DEBUG)
Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe did not meet minimum distance requirements.");
return false;
}
} catch (Exception e) {
// nothing

View File

@ -733,6 +733,9 @@ public class MessageList
mCurrentFolder = mAdapter.getFolder(mFolderName, mAccount);
}
// Hide "Load up to x more" footer for search views
mFooterView.setVisibility((mQueryString != null) ? View.GONE : View.VISIBLE);
mController = MessagingController.getInstance(getApplication());
mListView.setAdapter(mAdapter);
}
@ -2386,9 +2389,6 @@ public class MessageList
private View getFooterView(ViewGroup parent) {
if (mFooterView == null) {
mFooterView = mInflater.inflate(R.layout.message_list_item_footer, parent, false);
if (mQueryString != null) {
mFooterView.setVisibility(View.GONE);
}
mFooterView.setId(R.layout.message_list_item_footer);
FooterViewHolder holder = new FooterViewHolder();
holder.progress = (ProgressBar) mFooterView.findViewById(R.id.message_list_progress);

View File

@ -307,16 +307,6 @@ public class MessageView extends K9Activity implements OnClickListener {
public void fetchingAttachment() {
showToast(getString(R.string.message_view_fetching_attachment_toast), Toast.LENGTH_SHORT);
}
public void setHeaders(final Message message, final Account account) {
runOnUiThread(new Runnable() {
public void run() {
mMessageView.setHeaders(message, account);
}
});
}
}
public static void actionView(Context context, MessageReference messRef,
@ -1125,12 +1115,28 @@ public class MessageView extends K9Activity implements OnClickListener {
return;
}
MessageView.this.mMessage = message;
/*
* Clone the message object because the original could be modified by
* MessagingController later. This could lead to a ConcurrentModificationException
* when that same object is accessed by the UI thread (below).
*
* See issue 3953
*
* This is just an ugly hack to get rid of the most pressing problem. A proper way to
* fix this is to make Message thread-safe. Or, even better, rewriting the UI code to
* access messages via a ContentProvider.
*
*/
final Message clonedMessage = message.clone();
runOnUiThread(new Runnable() {
public void run() {
if (!message.isSet(Flag.X_DOWNLOADED_FULL) && !message.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
if (!clonedMessage.isSet(Flag.X_DOWNLOADED_FULL) &&
!clonedMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
mMessageView.loadBodyFromUrl("file:///android_asset/downloading.html");
}
mMessageView.setHeaders(message, account);
mMessageView.setHeaders(clonedMessage, account);
mMessageView.setOnFlagListener(new OnClickListener() {
@Override
public void onClick(View v) {

View File

@ -784,24 +784,24 @@ public class AccountSettings extends K9PreferenceActivity {
mAccount.setScrollMessageViewButtons(Account.ScrollButtons.valueOf(mAccountScrollButtons.getValue()));
mAccount.setShowPictures(Account.ShowPictures.valueOf(mAccountShowPictures.getValue()));
mAccount.save(Preferences.getPreferences(this));
if (mIsPushCapable) {
boolean needsPushRestart = mAccount.setFolderPushMode(Account.FolderMode.valueOf(mPushMode.getValue()));
if (mAccount.getFolderPushMode() != FolderMode.NONE) {
needsPushRestart |= displayModeChanged;
needsPushRestart |= mIncomingChanged;
}
if (needsRefresh && needsPushRestart) {
MailService.actionReset(this, null);
} else if (needsRefresh) {
MailService.actionReschedulePoll(this, null);
} else if (needsPushRestart) {
MailService.actionRestartPushers(this, null);
}
}
if (mIsPushCapable) {
boolean needsPushRestart = mAccount.setFolderPushMode(Account.FolderMode.valueOf(mPushMode.getValue()));
if (mAccount.getFolderPushMode() != FolderMode.NONE) {
needsPushRestart |= displayModeChanged;
needsPushRestart |= mIncomingChanged;
}
if (needsRefresh && needsPushRestart) {
MailService.actionReset(this, null);
} else if (needsRefresh) {
MailService.actionReschedulePoll(this, null);
} else if (needsPushRestart) {
MailService.actionRestartPushers(this, null);
}
}
// TODO: refresh folder list here
mAccount.save(Preferences.getPreferences(this));
}
@Override
@ -817,9 +817,9 @@ public class AccountSettings extends K9PreferenceActivity {
}
@Override
public void onBackPressed() {
protected void onPause() {
saveSettings();
super.onBackPressed();
super.onPause();
}
private void onCompositionSettings() {

View File

@ -144,13 +144,13 @@ public class FolderSettings extends K9PreferenceActivity {
}
@Override
public void onBackPressed() {
public void onPause() {
try {
saveSettings();
} catch (MessagingException e) {
Log.e(K9.LOG_TAG, "Saving folder settings failed", e);
}
super.onBackPressed();
super.onPause();
}
}

View File

@ -403,9 +403,13 @@ public class Prefs extends K9PreferenceActivity {
}
@Override
public void onBackPressed() {
protected void onPause() {
saveSettings();
super.onPause();
}
@Override
public void onBackPressed() {
if (K9.manageBack()) {
Accounts.listAccounts(this);
finish();

View File

@ -186,6 +186,7 @@ public class Utility {
}
}
private static final long MILISECONDS_IN_18_HOURS = 18 * 60 * 60 * 1000;
/**
* Returns true if the specified date is within 18 hours of "now". Returns false otherwise.
* @param date
@ -193,7 +194,7 @@ public class Utility {
*/
public static boolean isDateToday(Date date) {
Date now = new Date();
if (now.getTime() - 64800000 > date.getTime() || now.getTime() + 64800000 < date.getTime()) {
if (now.getTime() - MILISECONDS_IN_18_HOURS > date.getTime() || now.getTime() + MILISECONDS_IN_18_HOURS < date.getTime()) {
return false;
} else {
return true;
@ -500,14 +501,20 @@ public class Utility {
try {
FileInputStream in = new FileInputStream(from);
FileOutputStream out = new FileOutputStream(to);
byte[] buffer = new byte[1024];
int count = -1;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
try {
FileOutputStream out = new FileOutputStream(to);
try {
byte[] buffer = new byte[1024];
int count = -1;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
} finally {
out.close();
}
} finally {
try { in.close(); } catch (Throwable ignore) {}
}
out.close();
in.close();
from.delete();
return true;
} catch (Exception e) {

View File

@ -224,4 +224,32 @@ public abstract class Message implements Part, Body {
return 0;
}
/**
* Copy the contents of this object into another {@code Message} object.
*
* @param destination
* The {@code Message} object to receive the contents of this instance.
*/
protected void copy(Message destination) {
destination.mUid = mUid;
destination.mInternalDate = mInternalDate;
destination.mFolder = mFolder;
destination.mReference = mReference;
// mFlags contents can change during the object lifetime, so copy the Set
destination.mFlags = new HashSet<Flag>(mFlags);
}
/**
* Creates a new {@code Message} object with the same content as this object.
*
* <p>
* <strong>Note:</strong>
* This method was introduced as a hack to prevent {@code ConcurrentModificationException}s. It
* shouldn't be used unless absolutely necessary. See the comment in
* {@link com.fsck.k9.activity.MessageView.Listener#loadMessageForViewHeadersAvailable(com.fsck.k9.Account, String, String, Message)}
* for more information.
* </p>
*/
public abstract Message clone();
}

View File

@ -46,8 +46,11 @@ public class BinaryTempFileBody implements Body {
public void writeTo(OutputStream out) throws IOException, MessagingException {
InputStream in = getInputStream();
Base64OutputStream base64Out = new Base64OutputStream(out);
IOUtils.copy(in, base64Out);
base64Out.close();
try {
IOUtils.copy(in, base64Out);
} finally {
base64Out.close();
}
mFile.delete();
}

View File

@ -133,9 +133,9 @@ public class MimeHeader {
}
static class Field {
String name;
final String name;
String value;
final String value;
public Field(String name, String value) {
this.name = name;
@ -153,4 +153,13 @@ public class MimeHeader {
public void setCharset(String charset) {
mCharset = charset;
}
public MimeHeader clone() {
MimeHeader header = new MimeHeader();
header.mCharset = mCharset;
header.mFields = new ArrayList<Field>(mFields);
return header;
}
}

View File

@ -553,4 +553,38 @@ public class MimeMessage extends Message {
throw new UnsupportedOperationException("Not supported");
}
}
/**
* Copy the contents of this object into another {@code MimeMessage} object.
*
* @param message
* The {@code MimeMessage} object to receive the contents of this instance.
*/
protected void copy(MimeMessage message) {
super.copy(message);
message.mHeader = mHeader.clone();
message.mBody = mBody;
message.mMessageId = mMessageId;
message.mSentDate = mSentDate;
message.mDateFormat = mDateFormat;
message.mSize = mSize;
// These arrays are not supposed to be modified, so it's okay to reuse the references
message.mFrom = mFrom;
message.mTo = mTo;
message.mCc = mCc;
message.mBcc = mBcc;
message.mReplyTo = mReplyTo;
message.mReferences = mReferences;
message.mInReplyTo = mInReplyTo;
}
@Override
public MimeMessage clone() {
MimeMessage message = new MimeMessage();
copy(message);
return message;
}
}

View File

@ -1092,8 +1092,11 @@ public class MimeUtility {
BinaryTempFileBody tempBody = new BinaryTempFileBody();
OutputStream out = tempBody.getOutputStream();
IOUtils.copy(in, out);
out.close();
try {
IOUtils.copy(in, out);
} finally {
out.close();
}
return tempBody;
}

View File

@ -2380,11 +2380,17 @@ public class LocalStore extends Store implements Serializable {
* so we copy the data into a cached attachment file.
*/
InputStream in = attachment.getBody().getInputStream();
tempAttachmentFile = File.createTempFile("att", null, attachmentDirectory);
FileOutputStream out = new FileOutputStream(tempAttachmentFile);
size = IOUtils.copy(in, out);
in.close();
out.close();
try {
tempAttachmentFile = File.createTempFile("att", null, attachmentDirectory);
FileOutputStream out = new FileOutputStream(tempAttachmentFile);
try {
size = IOUtils.copy(in, out);
} finally {
out.close();
}
} finally {
try { in.close(); } catch (Throwable ignore) {}
}
}
}
@ -3302,6 +3308,25 @@ public class LocalStore extends Store implements Serializable {
loadHeaders();
return super.getHeaderNames();
}
@Override
public LocalMessage clone() {
LocalMessage message = new LocalMessage();
super.copy(message);
message.mId = mId;
message.mAttachmentCount = mAttachmentCount;
message.mSubject = mSubject;
message.mPreview = mPreview;
message.mToMeCalculated = mToMeCalculated;
message.mCcMeCalculated = mCcMeCalculated;
message.mToMe = mToMe;
message.mCcMe = mCcMe;
message.mHeadersLoaded = mHeadersLoaded;
message.mMessageDirty = mMessageDirty;
return message;
}
}
public static class LocalAttachmentBodyPart extends MimeBodyPart {
@ -3355,8 +3380,11 @@ public class LocalStore extends Store implements Serializable {
public void writeTo(OutputStream out) throws IOException, MessagingException {
InputStream in = getInputStream();
Base64OutputStream base64Out = new Base64OutputStream(out);
IOUtils.copy(in, base64Out);
base64Out.close();
try {
IOUtils.copy(in, base64Out);
} finally {
base64Out.close();
}
}
public Uri getContentUri() {

View File

@ -287,20 +287,11 @@ public class SmtpTransport extends Transport {
}
}
List<String> results = executeSimpleCommand("EHLO " + localHost);
List<String> results = sendHello(localHost);
m8bitEncodingAllowed = results.contains("8BITMIME");
/*
* TODO may need to add code to fall back to HELO I switched it from
* using HELO on non STARTTLS connections because of AOL's mail
* server. It won't let you use AUTH without EHLO.
* We should really be paying more attention to the capabilities
* and only attempting auth if it's available, and warning the user
* if not.
*/
if (mConnectionSecurity == CONNECTION_SECURITY_TLS_OPTIONAL
|| mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED) {
if (results.contains("STARTTLS")) {
@ -321,7 +312,7 @@ public class SmtpTransport extends Transport {
* Now resend the EHLO. Required by RFC2487 Sec. 5.2, and more specifically,
* Exim.
*/
results = executeSimpleCommand("EHLO " + localHost);
results = sendHello(localHost);
} else if (mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED) {
throw new MessagingException("TLS not supported but required");
}
@ -407,6 +398,46 @@ public class SmtpTransport extends Transport {
}
}
/**
* Send the client "identity" using the EHLO or HELO command.
*
* <p>
* We first try the EHLO command. If the server sends a negative response, it probably doesn't
* support the EHLO command. So we try the older HELO command that all servers need to support.
* And if that fails, too, we pretend everything is fine and continue unimpressed.
* </p>
*
* @param host
* The EHLO/HELO parameter as defined by the RFC.
*
* @return The list of capabilities as returned by the EHLO command or an empty list.
*
* @throws IOException
* In case of a network error.
* @throws MessagingException
* In case of a malformed response.
*/
private List<String> sendHello(String host) throws IOException, MessagingException {
try {
//TODO: We currently assume the extension keywords returned by the server are always
// uppercased. But the RFC allows mixed-case keywords!
return executeSimpleCommand("EHLO " + host);
} catch (NegativeSmtpReplyException e) {
if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Server doesn't support the EHLO command. Trying HELO...");
}
try {
executeSimpleCommand("HELO " + host);
} catch (NegativeSmtpReplyException e2) {
Log.w(K9.LOG_TAG, "Server doesn't support the HELO command. Continuing anyway.");
}
}
return new ArrayList<String>(0);
}
@Override
public void sendMessage(Message message) throws MessagingException {
ArrayList<Address> addresses = new ArrayList<Address>();
@ -569,12 +600,28 @@ public class SmtpTransport extends Transport {
}
private void checkLine(String line) throws MessagingException {
if (line.length() < 1) {
int length = line.length();
if (length < 1) {
throw new MessagingException("SMTP response is 0 length");
}
char c = line.charAt(0);
if ((c == '4') || (c == '5')) {
throw new MessagingException(line);
int replyCode = -1;
String message = line;
if (length >= 3) {
try {
replyCode = Integer.parseInt(line.substring(0, 3));
} catch (NumberFormatException e) { /* ignore */ }
if (length > 4) {
message = line.substring(4);
} else {
message = "";
}
}
throw new NegativeSmtpReplyException(replyCode, message);
}
}
@ -679,4 +726,28 @@ public class SmtpTransport extends Transport {
throw new AuthenticationFailedException("Unable to negotiate MD5 CRAM");
}
}
/**
* Exception that is thrown when the server sends a negative reply (reply codes 4xx or 5xx).
*/
static class NegativeSmtpReplyException extends MessagingException {
private static final long serialVersionUID = 8696043577357897135L;
private final int mReplyCode;
private final String mReplyText;
public NegativeSmtpReplyException(int replyCode, String replyText) {
super("Negative SMTP reply: " + replyCode + " " + replyText);
mReplyCode = replyCode;
mReplyText = replyText;
}
public int getReplyCode() {
return mReplyCode;
}
public String getReplyText() {
return mReplyText;
}
}
}

View File

@ -114,7 +114,8 @@ public class GlobalSettings {
new V(1, new FontSizeSetting(FontSizes.FONT_12DIP))
));
s.put("gesturesEnabled", Settings.versions(
new V(1, new BooleanSetting(true))
new V(1, new BooleanSetting(true)),
new V(4, new BooleanSetting(false))
));
s.put("hideSpecialAccounts", Settings.versions(
new V(1, new BooleanSetting(false))
@ -189,7 +190,8 @@ public class GlobalSettings {
new V(1, new BooleanSetting(false))
));
s.put("zoomControlsEnabled", Settings.versions(
new V(1, new BooleanSetting(false))
new V(1, new BooleanSetting(false)),
new V(4, new BooleanSetting(true))
));
SETTINGS = Collections.unmodifiableMap(s);

View File

@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;
@ -34,7 +35,7 @@ public class Settings {
*
* @see SettingsExporter
*/
public static final int VERSION = 3;
public static final int VERSION = 4;
public static Map<String, Object> validate(int version, Map<String,
TreeMap<Integer, SettingsDescription>> settings,
@ -44,15 +45,25 @@ public class Settings {
for (Map.Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting :
settings.entrySet()) {
Entry<Integer, SettingsDescription> setting =
versionedSetting.getValue().floorEntry(version);
// Get the setting description with the highest version lower than or equal to the
// supplied content version.
TreeMap<Integer, SettingsDescription> versions = versionedSetting.getValue();
SortedMap<Integer, SettingsDescription> headMap = versions.headMap(version + 1);
if (setting == null) {
// Skip this setting if it was introduced after 'version'
if (headMap.size() == 0) {
continue;
}
Integer settingVersion = headMap.lastKey();
SettingsDescription desc = versions.get(settingVersion);
// Skip this setting if it is no longer used in 'version'
if (desc == null) {
continue;
}
String key = versionedSetting.getKey();
SettingsDescription desc = setting.getValue();
boolean useDefaultValue;
if (!importedSettings.containsKey(key)) {
@ -127,7 +138,7 @@ public class Settings {
// Check if it was already added to upgradedSettings by the SettingsUpgrader
if (!upgradedSettings.containsKey(settingName)) {
// Insert default value to upgradedSettings
SettingsDescription setting = versionedSettings.firstEntry().getValue();
SettingsDescription setting = versionedSettings.get(toVersion);
Object defaultValue = setting.getDefaultValue();
upgradedSettings.put(settingName, defaultValue);
@ -140,8 +151,9 @@ public class Settings {
}
// Handle removed settings
Entry<Integer, SettingsDescription> lastEntry = versionedSettings.lastEntry();
if (lastEntry.getKey().intValue() == toVersion && lastEntry.getValue() == null) {
Integer highestVersion = versionedSettings.lastKey();
if (highestVersion.intValue() == toVersion &&
versionedSettings.get(highestVersion) == null) {
upgradedSettings.remove(settingName);
if (deletedSettings == null) {
deletedSettings = new HashSet<String>();
@ -179,8 +191,10 @@ public class Settings {
String settingName = setting.getKey();
Object internalValue = setting.getValue();
SettingsDescription settingDesc =
settingDescriptions.get(settingName).lastEntry().getValue();
TreeMap<Integer, SettingsDescription> versionedSetting =
settingDescriptions.get(settingName);
Integer highestVersion = versionedSetting.lastKey();
SettingsDescription settingDesc = versionedSetting.get(highestVersion);
if (settingDesc != null) {
String stringValue = settingDesc.toString(internalValue);

View File

@ -171,7 +171,9 @@ public class SettingsExporter {
String key = versionedSetting.getKey();
String valueString = (String) prefs.get(key);
SettingsDescription setting = versionedSetting.getValue().lastEntry().getValue();
TreeMap<Integer, SettingsDescription> versions = versionedSetting.getValue();
Integer highestVersion = versions.lastKey();
SettingsDescription setting = versions.get(highestVersion);
if (setting == null) {
// Setting was removed.
continue;
@ -323,7 +325,8 @@ public class SettingsExporter {
AccountSettings.SETTINGS.get(keyPart);
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
Integer highestVersion = versionedSetting.lastKey();
SettingsDescription setting = versionedSetting.get(highestVersion);
if (setting != null) {
// Only export account settings that can be found in AccountSettings.SETTINGS
@ -417,7 +420,8 @@ public class SettingsExporter {
IdentitySettings.SETTINGS.get(identityKey);
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
Integer highestVersion = versionedSetting.lastKey();
SettingsDescription setting = versionedSetting.get(highestVersion);
if (setting != null) {
// Only write settings that have an entry in IdentitySettings.SETTINGS
@ -468,7 +472,8 @@ public class SettingsExporter {
FolderSettings.SETTINGS.get(folderKey);
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
Integer highestVersion = versionedSetting.lastKey();
SettingsDescription setting = versionedSetting.get(highestVersion);
if (setting != null) {
// Only write settings that have an entry in FolderSettings.SETTINGS

View File

@ -180,11 +180,14 @@ public class AttachmentProvider extends ContentProvider {
if (thumbnail != null) {
thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true);
FileOutputStream out = new FileOutputStream(file);
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
try {
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out);
} finally {
out.close();
}
}
} finally {
in.close();
try { in.close(); } catch (Throwable ignore) {}
}
} catch (IOException ioe) {
return null;