1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-01-08 04:08:15 -05:00

Merge commit '4.110' into issue-162-new

Conflicts:
	src/com/fsck/k9/activity/FolderList.java
	src/com/fsck/k9/activity/MessageList.java
	src/com/fsck/k9/activity/MessageView.java
	src/com/fsck/k9/activity/setup/AccountSettings.java

Resolutions:
    controller/MessagingController.java:
        public boolean isMoveCapable(final Account account)
        public boolean isMoveCapable(Message message)

    activity/setup/AccountSettings.java:
        private boolean mIsMoveCapable = false; // ASH i seem to have removed this, or renamed it to mIsAppendCapable
This commit is contained in:
ashley willis 2012-09-10 23:33:00 -05:00
commit a62a5babca
55 changed files with 2199 additions and 1213 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="15009"
android:versionName="4.109" package="com.fsck.k9"
android:versionCode="15010"
android:versionName="4.110" package="com.fsck.k9"
>
<uses-sdk
android:minSdkVersion="7"

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.0"
width="168.45"
height="113.9081"
id="svg2393">
<defs
id="defs2395" />
<g
transform="translate(-41.490136,-32.550987)"
id="layer1">
<path
d="M 125.71429,102.3114 L 209.93844,32.550987 L 209.9357,76.729057 L 125.71429,146.45909 L 41.492876,76.729057 L 41.490136,32.550987 L 125.71429,102.3114 z"
id="path2439"
style="fill:#595959;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 735 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<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="@color/message_view_header_background" />
</selector>

BIN
res/drawable/show_less.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

BIN
res/drawable/show_more.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

View File

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="@+id/scrolling_move_buttons"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<Button
android:id="@+id/archive_scrolling"
android:text="@string/message_view_archive_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/move_scrolling"
android:text="@string/message_view_move_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/spam_scrolling"
android:text="@string/message_view_spam_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/scrolling_buttons"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="57dip"
android:background="@android:color/transparent"
android:gravity="center_vertical">
<Button
android:id="@+id/previous_scrolling"
android:text="@string/message_view_prev_action"
android:contentDescription="@string/previous_action"
android:textSize="35dip"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:padding="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/reply_scrolling"
android:text="@string/reply_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/delete_scrolling"
android:text="@string/delete_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/forward_scrolling"
android:text="@string/forward_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/next_scrolling"
android:text="@string/message_view_next_action"
android:contentDescription="@string/next_action"
android:textSize="35dip"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:padding="0dip"
android:layout_weight="1" />
</LinearLayout>
</merge>

View File

@ -1,226 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.view.SingleMessageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/message_view"
android:orientation="vertical"
android:layout_width="fill_parent"
android:background="@android:color/transparent"
android:layout_height="wrap_content"
android:layout_weight="1"
xmlns:android="http://schemas.android.com/apk/res/android">
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<!-- Header area -->
<com.fsck.k9.view.MessageHeader
android:id="@+id/header_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="2dip"
android:paddingRight="2dip"
>
<View
android:id="@+id/chip"
android:layout_marginTop="1dip"
android:layout_marginBottom="1dip"
android:layout_width="6dip"
android:layout_height="fill_parent" />
<LinearLayout
android:id="@+id/top_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="2dip"
android:paddingLeft="4dip"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:gravity="fill_horizontal"
android:layout_height="wrap_content">
<LinearLayout android:id="@+id/people"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="4dip"
android:layout_weight="5"
android:orientation="vertical">
<TextView android:id="@+id/subject"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="10sp"
android:textStyle="bold"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall" />
>
<LinearLayout
android:id="@+id/from_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="true" >
<TextView
android:id="@+id/from"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="6dip"
android:singleLine="true"
android:ellipsize="end"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout
android:id="@+id/to_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true" >
<TextView
android:id="@+id/to_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4dip"
android:text="@string/message_to_label"
android:textSize="10sp"
android:textStyle="bold"
android:textColor="?android:attr/textColorSecondary" />
<TextView android:id="@+id/to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="false"
android:ellipsize="none"
android:textSize="10sp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout android:id="@+id/cc_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true">
<TextView android:id="@+id/cc_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4dip"
android:text="@string/message_view_cc_label"
android:textSize="10sp"
android:textStyle="bold"
android:textColor="?android:attr/textColorSecondary" />
<TextView android:id="@+id/cc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="false"
android:ellipsize="none"
android:textSize="10sp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView android:id="@+id/additional_headers_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="4dip"
android:baselineAligned="true"
android:singleLine="false"
android:ellipsize="none"
android:textSize="10sp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall" >
</TextView>
</LinearLayout>
<LinearLayout android:id="@+id/topright_container"
android:orientation="vertical"
android:layout_weight="0.1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
>
<TextView android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:singleLine="true"
android:ellipsize="none"
android:textSize="10sp"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textSize="10sp"
android:singleLine="true"
android:ellipsize="none"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout android:id="@+id/icons_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:paddingTop="4dip"
>
<View android:id="@+id/answered"
android:layout_width="22sp"
android:layout_height="22sp"
android:layout_centerVertical="true"
android:paddingRight="4dip"
android:background="@drawable/ic_email_answered_small" />
<View android:id="@+id/attachment"
android:layout_width="22sp"
android:layout_height="22sp"
android:layout_centerVertical="true"
android:paddingRight="4dip"
android:background="@drawable/ic_email_attachment_small" />
<CheckBox android:id="@+id/flagged"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:layout_alignParentRight="true"
style="?android:attr/starStyle" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.fsck.k9.view.MessageHeader>
<LinearLayout
android:id="@+id/show_pictures_section"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dip"
android:paddingLeft="6dip"
android:paddingRight="3dip"
android:paddingTop="4dip"
android:paddingBottom="4dip"
android:baselineAligned="false"
android:visibility="gone">
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/message_view_show_pictures_instructions"
android:layout_gravity="center"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
<Button android:id="@+id/show_pictures"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_show_pictures_action" />
android:id="@+id/message_view_header_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<include layout="@layout/message_view_header"/>
</LinearLayout>
<include layout="@layout/message_view_crypto_layout"/>
<!-- Content area -->
<com.fsck.k9.view.MessageWebView
android:id="@+id/message_content"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
android:layout_height="0dip"
android:layout_weight="1"
android:layout_width="fill_parent"/>
<com.fsck.k9.view.AccessibleWebView
android:id="@+id/accessible_message_content"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
android:layout_width="fill_parent"/>
<!-- Attachments area -->
<LinearLayout
android:id="@+id/attachments"
android:orientation="vertical"
<ScrollView
android:id="@+id/attachments_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" />
android:layout_weight="1">
<LinearLayout
android:id="@+id/inside_attachments_container"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/attachments"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip" />
<Button
android:id="@+id/show_hidden_attachments"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/message_view_show_more_attachments_action"/>
<LinearLayout
android:id="@+id/hidden_attachments"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dip"/>
</LinearLayout>
</ScrollView>
<Button android:id="@+id/download_remainder"
android:text="@string/message_view_download_remainder"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_width="fill_parent" />
android:layout_width="fill_parent"/>
</com.fsck.k9.view.SingleMessageView>

View File

@ -3,27 +3,12 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.fsck.k9.view.ToggleScrollView
android:id="@+id/top_view"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:scrollbarStyle="outsideInset"
android:fillViewport="true"
android:background="@android:color/transparent"
android:fadingEdge="none">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:background="@android:color/transparent"
android:layout_height="wrap_content"
android:layout_weight="1">
<include layout="@layout/message" />
<include layout="@layout/message_view_scrolling_buttons"/>
</LinearLayout>
</com.fsck.k9.view.ToggleScrollView>
android:layout_height="fill_parent">
<include layout="@layout/message"/>
<include layout="@layout/message_view_move_buttons"/>
<include layout="@layout/message_view_bottom_buttons"/>
</LinearLayout>

View File

@ -0,0 +1,289 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.view.MessageHeader
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Message header area -->
<TableLayout
android:id="@+id/top_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:shrinkColumns="1"
android:background="@color/message_view_header_background">
<TableRow>
<!-- Color chip -->
<View
android:id="@+id/chip"
android:layout_marginRight="6dip"
android:layout_width="6dip"
android:layout_height="fill_parent"/>
<LinearLayout
android:paddingTop="2dip"
android:layout_column="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Subject -->
<TextView
android:id="@+id/subject"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
android:textSize="10sp"
android:textStyle="bold"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<!-- From -->
<LinearLayout
android:id="@+id/from_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/from"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="6dip"
android:singleLine="true"
android:ellipsize="end"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<!-- To -->
<LinearLayout
android:id="@+id/to_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true">
<TextView
android:id="@+id/to_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4dip"
android:text="@string/message_to_label"
android:textSize="10sp"
android:textStyle="bold"
android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:id="@+id/to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"
android:textSize="10sp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<!-- CC -->
<LinearLayout
android:id="@+id/cc_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true">
<TextView
android:id="@+id/cc_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4dip"
android:text="@string/message_view_cc_label"
android:textSize="10sp"
android:textStyle="bold"
android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:id="@+id/cc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"
android:textSize="10sp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<TextView
android:id="@+id/additional_headers_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="false"
android:ellipsize="none"
android:textSize="10sp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<!-- Date/Time + Icons -->
<LinearLayout
android:id="@+id/topright_container"
android:layout_marginTop="2dip"
android:layout_marginRight="6dip"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:gravity="right">
<LinearLayout
android:id="@+id/icons_container"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<View
android:id="@+id/answered"
android:layout_width="22sp"
android:layout_height="22sp"
android:paddingRight="4dip"
android:background="@drawable/ic_email_answered_small"/>
<CheckBox
android:id="@+id/flagged"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
style="?android:attr/starStyle"/>
</LinearLayout>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
android:textSize="10sp"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10sp"
android:singleLine="true"
android:ellipsize="none"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</TableRow>
</TableLayout>
<!-- Separator -->
<!-- This layout has an explicit height because otherwise there will be strange
display issues when the additional headers are shown. -->
<LinearLayout
android:id="@+id/show_additional_headers_area"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="21.5dp"
android:focusable="true"
android:clickable="true"
android:background="@drawable/separator_area_background">
<RelativeLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="20dp">
<!-- Color chip 2 -->
<View
android:id="@+id/chip2"
android:layout_marginRight="6dip"
android:layout_width="6dip"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"/>
<!-- Show more/less indicator -->
<ImageView
android:id="@+id/show_additional_headers_icon"
android:src="@drawable/show_more"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginRight="12dp"/>
</RelativeLayout>
<View
android:id="@+id/separator"
android:layout_width="fill_parent"
android:layout_height="1.5dp"
android:background="#59000000"/>
</LinearLayout>
<!-- Button area -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:paddingTop="4dip"
android:baselineAligned="false">
<Button
android:id="@+id/show_pictures"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_marginLeft="6dip"
android:layout_marginBottom="4dip"
android:layout_height="wrap_content"
android:text="@string/message_view_show_pictures_action"
style="?android:attr/buttonStyleSmall"/>
<Button
android:id="@+id/show_attachments"
android:visibility="gone"
android:layout_marginLeft="6dip"
android:layout_marginBottom="4dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_show_attachments_action"
style="?android:attr/buttonStyleSmall"/>
<Button
android:id="@+id/show_message"
android:visibility="gone"
android:layout_marginLeft="6dip"
android:layout_marginBottom="4dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_show_message_action"
style="?android:attr/buttonStyleSmall"/>
</LinearLayout>
<include layout="@layout/message_view_crypto_layout"/>
</LinearLayout>
</com.fsck.k9.view.MessageHeader>

View File

@ -1,88 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="@+id/extra_buttons"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:gravity="center_vertical">
<Button
android:id="@+id/reply"
android:text="@string/reply_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<Button
android:id="@+id/reply_all"
android:text="@string/reply_all_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<Button
android:id="@+id/forward"
android:text="@string/forward_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/scrolling_move_buttons"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:gravity="center_vertical">
<Button
android:id="@+id/archive_scrolling"
android:text="@string/message_view_archive_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<Button
android:id="@+id/move_scrolling"
android:text="@string/message_view_move_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<Button
android:id="@+id/spam_scrolling"
android:text="@string/message_view_spam_action"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/scrolling_buttons"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<Button
android:id="@+id/previous_scrolling"
android:text="@string/message_view_prev_action"
android:contentDescription="@string/previous_action"
android:textSize="35dip"
android:padding="0dip"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<ImageButton
android:id="@+id/delete_scrolling"
android:layout_height="wrap_content"
android:src="@drawable/ic_button_delete"
android:layout_width="0dip"
android:layout_weight="1"/>
<Button
android:id="@+id/next_scrolling"
android:padding="0dip"
android:text="@string/message_view_next_action"
android:textSize="35dip"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
</LinearLayout>
</merge>

View File

@ -542,14 +542,8 @@ Benvingut a la configuració del K-9. El K-9 és un client de codi obert per An
<string name="account_settings_notification_unread_count_label">Mostra correu no llegit</string>
<string name="account_settings_notification_unread_count_summary">Mostra el nombre de missatges no llegits a la barra de notificació.</string>
<string name="account_settings_hide_buttons_label">Botons de desplaçament</string>
<string name="account_settings_hide_buttons_never">Mai</string>
<string name="account_settings_hide_buttons_keyboard_avail">Quan el teclat estigui disponible</string>
<string name="account_settings_hide_buttons_always">Sempre</string>
<string name="account_settings_enable_move_buttons_label">Habilita botons emplenat</string>
<string name="account_settings_enable_move_buttons_summary">Mostra els botons dArxiu, Mou, i Brossa.</string>
<string name="account_settings_hide_move_buttons_label">Navega botons emplenament</string>
<string name="account_settings_show_pictures_label">Sempre mostra imatges</string>
<string name="account_settings_show_pictures_never">No</string>

View File

@ -549,14 +549,8 @@ Vítejte v nastavení pošty K-9 Mail. K-9 je open source poštovní klient pro
<!-- NEW: <string name="account_settings_notification_unread_count_label">Show unread count</string>-->
<!-- NEW: <string name="account_settings_notification_unread_count_summary">Show the number of unread messages in the notification bar.</string>-->
<string name="account_settings_hide_buttons_label">Posunovat navigační tlačítka</string>
<string name="account_settings_hide_buttons_never">Nikdy</string>
<string name="account_settings_hide_buttons_keyboard_avail">Je-li dostupná klávesnice</string>
<string name="account_settings_hide_buttons_always">Vždy</string>
<string name="account_settings_enable_move_buttons_label">Povolit přesměrovací tlačítka</string>
<string name="account_settings_enable_move_buttons_summary">Zobrazit tlačítka Archív, Přesunout a Nevyžádaná.</string>
<string name="account_settings_hide_move_buttons_label">Posunovat přesměrovací tlačítka</string>
<string name="account_settings_show_pictures_label">Vždy zobrazovat obrázky</string>
<string name="account_settings_show_pictures_never">Ne</string>

View File

@ -545,14 +545,8 @@ Velkommen til K-9 Mail opsætning. K-9 er en open source mail klient for Androi
<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>
<string name="account_settings_hide_buttons_never">Aldrig</string>
<string name="account_settings_hide_buttons_keyboard_avail">Når tastatur er tilgængeligt</string>
<string name="account_settings_hide_buttons_always">Altid</string>
<string name="account_settings_enable_move_buttons_label">Aktiver Flyt knapper</string>
<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</string>
<string name="account_settings_show_pictures_never">Aldrig</string>

View File

@ -543,14 +543,8 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü
<string name="account_settings_notification_unread_count_label">Anzahl ungelesener Nachrichten anzeigen</string>
<string name="account_settings_notification_unread_count_summary">Zeigt die Anzahl der ungelesenen Nachrichten in der Statuszeile.</string>
<string name="account_settings_hide_buttons_label">Scrolle Navigationsleiste</string>
<string name="account_settings_hide_buttons_never">Leiste bleibt eingeblendet</string>
<string name="account_settings_hide_buttons_keyboard_avail">Nur wenn Tastatur aktiv</string>
<string name="account_settings_hide_buttons_always">Immer</string>
<string name="account_settings_enable_move_buttons_label">Spam-Leiste</string>
<string name="account_settings_enable_move_buttons_summary">Zeige Archivieren-, Verschieben- und Spam-Schaltfläche.</string>
<string name="account_settings_hide_move_buttons_label">Scrolle Spam-Leiste</string>
<string name="account_settings_show_pictures_label">Bilder automatisch anzeigen</string>
<string name="account_settings_show_pictures_never">Niemals</string>
@ -564,15 +558,15 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü
<string name="account_settings_reply_after_quote_label">Antwort unter Zitat</string>
<string name="account_settings_reply_after_quote_summary">Die Antwort auf eine Nachricht unterhalb der Original-Nachricht platzieren.</string>
<string name="account_settings_strip_signature_label">Unterschrift von zitierter Antwort entfernen</string>
<string name="account_settings_strip_signature_summary">Beim Antworten von Nachrichten wird die Unterschrift vom zitiertem Textabschnitt entfernt</string>
<string name="account_settings_strip_signature_label">Entferne Signatur aus zitierter Antwort</string>
<string name="account_settings_strip_signature_summary">Beim Antworten wird die Signatur aus dem Zitat entfernt</string>
<string name="account_settings_message_format_label">Formatierung</string>
<string name="account_settings_message_format_text">Einfacher Text (Bilder und Formatierungen werden entfernt)</string>
<string name="account_settings_message_format_html">HTML (Bilder und Formatierungen bleiben erhalten)</string>
<string name="account_settings_message_format_auto">Automatisch (Einfacher Text, es sei denn bei Antwort auf HTML)</string>
<string name="account_settings_message_format_auto">Automatisch (Einfacher Text, es sei denn bei Antwort auf HTML)</string>
<string name="account_settings_message_read_receipt_label">Empfangsbestätigung</string>
<string name="account_settings_message_read_receipt_summary">Immer eine Empfangsbestätigung anfordern</string>
@ -595,11 +589,11 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü
<string name="account_settings_crypto_auto_signature_summary">Email Adresse des Kontos verwenden um Signaturschlüssel zu schätzen.</string>
<string name="account_settings_crypto_auto_encrypt">Automatische verschlüsselung</string>
<string name="account_settings_crypto_auto_encrypt_summary">Verschlüsselung aktivieren falls für den Empfänger ein öffentlichen Schlüssel abgespeichert ist.</string>
<string name="account_settings_crypto_auto_encrypt_summary">Verschlüsselung aktivieren falls für den Empfänger ein öffentlichen Schlüssel abgespeichert ist.</string>
<string name="account_settings_mail_check_frequency_label">Häufigkeit der E-Mail-Abfrage</string>
<string name="account_settings_second_class_check_frequency_label">Häufigkeit der Abfrage für Nebenordner</string>
<string name="account_settings_storage_title">Speicher</string>
<string name="account_settings_color_label">Farbe des Kontos</string>
@ -1022,10 +1016,10 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü
<string name="save_or_discard_draft_message_dlg_title">Entwurf speichern?</string>
<string name="save_or_discard_draft_message_instructions_fmt">Entwurf speichern oder verwerfen?</string>
<string name="refuse_to_save_draft_marked_encrypted_dlg_title">Speichern des Entwurfs verweigern.</string>
<string name="refuse_to_save_draft_marked_encrypted_instructions_fmt">Die Speicherung von als verschlüsselt markierten Entwürfen verweigern.</string>
<string name="continue_without_public_key_dlg_title">Ohne öffentlichen Schlüssel fortfahren?</string>
<string name="continue_without_public_key_instructions_fmt">Einer oder mehrere Empfänger besitzen keinen abgespeicherten öffentlichen Schlüssel. Fortfahren?</string>
@ -1053,7 +1047,7 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü
<string name="messagelist_sent_to_me_sigil">»</string>
<string name="messagelist_sent_cc_me_sigil"></string>
<string name="error_unable_to_connect">Verbindungsfehler.</string>
<string name="import_export_action">Einstellungen Importieren &amp; Exportieren</string>
<string name="settings_export_account">Kontoeinstellungen exportieren</string>
<string name="settings_export_all">Einstellungen und Konten exportieren</string>
@ -1104,5 +1098,5 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü
<string name="manage_accounts_move_up_action">Nach oben verschieben</string>
<string name="manage_accounts_move_down_action">Nach unten verschieben</string>
<string name="manage_accounts_moving_message">Konto verschieben...</string>
</resources>

View File

@ -541,14 +541,8 @@ Bienvenido a la Configuración de K-9. K-9 es un cliente de correo OpenSource pa
<string name="account_settings_notification_unread_count_label">Mostrar contador de correos sin leer</string>
<string name="account_settings_notification_unread_count_summary">Mostrar el número de mensajes sin leer en la barra de notificaciones.</string>
<string name="account_settings_hide_buttons_label">Botones de desplazamiento</string>
<string name="account_settings_hide_buttons_never">Nunca</string>
<string name="account_settings_hide_buttons_keyboard_avail">Cuando el teclado está disponible</string>
<string name="account_settings_hide_buttons_always">Siempre</string>
<string name="account_settings_enable_move_buttons_label">Habilitar botones de copia</string>
<string name="account_settings_enable_move_buttons_summary">Mostrar botones de archivar, mover y SPAM</string>
<string name="account_settings_hide_move_buttons_label">Botones de copia</string>
<string name="account_settings_show_pictures_label">Mostrar imágenes</string>
<string name="account_settings_show_pictures_never">Nunca</string>

View File

@ -537,14 +537,8 @@ Tervetuloa K-9 Mail asennukseen.  K-9 on avoimen lähdekoodin sähköpostiasiak
<string name="account_settings_notification_unread_count_label">Näytä lukemattomien viestien määrä</string>
<string name="account_settings_notification_unread_count_summary">Näytä lukemattomien viestien määrä osoiterivillä.</string>
<string name="account_settings_hide_buttons_label">Selauksen painikkeet</string>
<string name="account_settings_hide_buttons_never">Ei koskaan</string>
<string name="account_settings_hide_buttons_keyboard_avail">Kun näppäimistö on käytettävissä</string>
<string name="account_settings_hide_buttons_always">Aina</string>
<string name="account_settings_enable_move_buttons_label">Ota käyttöön Siirrä-painikkeet</string>
<string name="account_settings_enable_move_buttons_summary">Näytä Arkistoi-, Siirrä- ja Roskaposti-painikkeet.</string>
<string name="account_settings_hide_move_buttons_label">Vieritä Siirrä painikkeet</string>
<string name="account_settings_show_pictures_label">Näytä kuvat automaattisesti</string>
<string name="account_settings_show_pictures_never">Ei koskaan</string>

View File

@ -567,14 +567,8 @@ Bienvenue dans la configuration de K-9 Mail. K-9 Mail est un client de messageri
<string name="account_settings_notification_unread_count_label">Afficher le nombre de messages non lus</string>
<string name="account_settings_notification_unread_count_summary">Afficher le nombre de messages non lus dans la barre de notification</string>
<string name="account_settings_hide_buttons_label">Défiler les boutons de navigation</string>
<string name="account_settings_hide_buttons_never">Jamais</string>
<string name="account_settings_hide_buttons_keyboard_avail">Lorsque le clavier est disponible</string>
<string name="account_settings_hide_buttons_always">Toujours</string>
<string name="account_settings_enable_move_buttons_label">Activer les boutons de déplacement</string>
<string name="account_settings_enable_move_buttons_summary">Afficher les boutons Archiver, Déplacer ou Spam</string>
<string name="account_settings_hide_move_buttons_label">Défiler les boutons de déplacement</string>
<string name="account_settings_show_pictures_label">Afficher automatiquement les images</string>
<string name="account_settings_show_pictures_never">Jamais</string>
@ -589,13 +583,13 @@ Bienvenue dans la configuration de K-9 Mail. K-9 Mail est un client de messageri
<string name="account_settings_reply_after_quote_label">Réponse après la citation</string>
<string name="account_settings_reply_after_quote_summary">Faire précéder la réponse par le texte d\'origine</string>
<string name="account_settings_strip_signature_label">Retirer signature dans réponse citée</string>
<string name="account_settings_strip_signature_label">Retirer signature dans réponse citée</string>
<string name="account_settings_strip_signature_summary">Lorsque vous répondez à des messages, la signature du texte cité sera éffacée</string>
<string name="account_settings_message_format_label">Format du message</string>
<string name="account_settings_message_format_html">HTML (formattage et images conservés)</string>
<string name="account_settings_message_format_text">Text brut (formattage et images omis)</string>
<string name="account_settings_message_format_auto">Automatique (Text brut à moins de répondre à un message HTML)</string>
<string name="account_settings_message_format_auto">Automatique (Text brut à moins de répondre à un message HTML)</string>
<string name="account_settings_message_read_receipt_label">Accusé de réception</string>
<string name="account_settings_message_read_receipt_summary">Toujours demander un accusé de réception</string>
@ -617,9 +611,9 @@ Bienvenue dans la configuration de K-9 Mail. K-9 Mail est un client de messageri
<string name="account_settings_crypto_app_not_available">Non disponible</string>
<string name="account_settings_crypto_auto_signature">Signature automatique</string>
<string name="account_settings_crypto_auto_signature_summary">Utiliser l\'adresse e-mail du compte pour déduire la clé de signature</string>
<string name="account_settings_crypto_auto_encrypt">Cryptation automatique</string>
<string name="account_settings_crypto_auto_encrypt_summary">Cryptation automatique si une clé publique correspond au destinataire.</string>
<string name="account_settings_crypto_auto_encrypt">Cryptation automatique</string>
<string name="account_settings_crypto_auto_encrypt_summary">Cryptation automatique si une clé publique correspond au destinataire.</string>
<string name="account_settings_mail_check_frequency_label">Fréquence de vérification du dossier</string>
<string name="account_settings_second_class_check_frequency_label">Fréquence de vérification pour 2ème classe</string>
@ -1045,12 +1039,12 @@ Bienvenue dans la configuration de K-9 Mail. K-9 Mail est un client de messageri
<string name="save_or_discard_draft_message_dlg_title">Enregistrer le brouillon\u00A0?</string>
<string name="save_or_discard_draft_message_instructions_fmt">Enregistrer ou abandonner ce message\u00A0?</string>
<string name="refuse_to_save_draft_marked_encrypted_dlg_title">Refuser d\'enregistrer des brouillons.</string>
<string name="refuse_to_save_draft_marked_encrypted_instructions_fmt">Refuser d\'enregistrer un message marqué comme crypté.</string>
<string name="continue_without_public_key_dlg_title">Continuer sans clé publique?</string>
<string name="continue_without_public_key_instructions_fmt">Un ou plusieurs destinataires n\'ont pas de clé publique enregistrée. Continuer?</string>
<string name="refuse_to_save_draft_marked_encrypted_dlg_title">Refuser d\'enregistrer des brouillons.</string>
<string name="refuse_to_save_draft_marked_encrypted_instructions_fmt">Refuser d\'enregistrer un message marqué comme crypté.</string>
<string name="continue_without_public_key_dlg_title">Continuer sans clé publique?</string>
<string name="continue_without_public_key_instructions_fmt">Un ou plusieurs destinataires n\'ont pas de clé publique enregistrée. Continuer?</string>
<string name="charset_not_found">Ce message ne peut être affiché parce que le jeu de caractères «\u00A0<xliff:g id="charset">%s</xliff:g>\u00A0» n\'a pu être trouvé.</string>
<string name="select_text_now">Sélectionnez le texte à copier</string>

View File

@ -541,14 +541,8 @@ Benvido á Configuración de K-9. K-9 é un cliente de correo OpenSource para An
<string name="account_settings_notification_unread_count_label">Amosar número de mensaxes non lidos</string>
<string name="account_settings_notification_unread_count_summary">Amosar número de mensaxen non lidos na barra de notificacións.</string>
<string name="account_settings_hide_buttons_label">Botóns de desprazamento</string>
<string name="account_settings_hide_buttons_never">Nunca</string>
<string name="account_settings_hide_buttons_keyboard_avail">Cando o teclado esté dispoñible</string>
<string name="account_settings_hide_buttons_always">Sempre</string>
<string name="account_settings_enable_move_buttons_label">Habilitar botóns de copia</string>
<string name="account_settings_enable_move_buttons_summary">Amosar botóns de arquivar, mover e SPAM</string>
<string name="account_settings_hide_move_buttons_label">Botóns de copia</string>
<string name="account_settings_show_pictures_label">Amosar imaxes</string>
<string name="account_settings_show_pictures_never">Nunca</string>

View File

@ -154,7 +154,7 @@
<string name="special_mailbox_name_spam_fmt">%s</string>
<string name="send_failure_subject">Néhány üzenetet nem sikerült elküldeni</string>
<string name="send_failure_body_abbrev">Nézze meg a %s mappát a részletekért.</string>
<string name="send_failure_body_fmt">"A K-9 hibát észlelt üzenetküldés közben. A probléma miatt elképzelhető, hogy a levél nem érkezik meg, de az is lehet hogy igen.
<string name="send_failure_body_fmt">"A K-9 hibát észlelt üzenetküldés közben. A probléma miatt elképzelhető, hogy a levél nem érkezik meg, de az is lehet hogy igen.
Az ilyen hibás leveleket csillag jelzi a postázandó mappában. Ha eltávolítja a csillagot a K-9 megpróbálja újból elküldeni a levelet. Hosszan a Postázatlan mappára kattintva válassza az Üzenetek küldését.
@ -162,26 +162,26 @@ Az ilyen hibás leveleket csillag jelzi a postázandó mappában. Ha eltávolít
<string name="alert_header">K-9 riasztás</string>
<string name="no_connection_alert">A szinkronizáció és a levélküldés felfüggesztve, hálozati kapcsolat hiánya miatt.</string>
<string name="end_of_folder">Nincs több üzenet</string>
<string name="accounts_welcome">"Üdvözöljük a K-9 Mail beállításokban. A K-9 egy nyílt forráskódú levelezőprogram Androidra, a sima mail kliens alapjaira helyezve.
K-9 továbbfejlesztett funkciói:
* Push mail using IMAP IDLE
* Jobb teljesítmény
* Message refiling
* E-mail aláírások
* Titkos másolat
* Mappa-előfizetések
* Minden mappa szinkronizálása
* Válasz cím beállítása
* Gyorsbillentyűk
* Jobb IMAP támogatás
* Mellékletek mentése a memóriakártyára
* Kuka ürítése
* Üzenetek válogatás
<string name="accounts_welcome">"Üdvözöljük a K-9 Mail beállításokban. A K-9 egy nyílt forráskódú levelezőprogram Androidra, a sima mail kliens alapjaira helyezve.
K-9 továbbfejlesztett funkciói:
* Push mail using IMAP IDLE
* Jobb teljesítmény
* Message refiling
* E-mail aláírások
* Titkos másolat
* Mappa-előfizetések
* Minden mappa szinkronizálása
* Válasz cím beállítása
* Gyorsbillentyűk
* Jobb IMAP támogatás
* Mellékletek mentése a memóriakártyára
* Kuka ürítése
* Üzenetek válogatás
* ...és még sok más
Magyarította: Deák Tamás (maya98) és RootRulez
Magyarította: Deák Tamás (maya98) és RootRulez
Vegye figyelembe, hogy a K-9 nem támogatja a legtöbb ingyenes hotmail fiókot és még sok más klienst. Történnek furcsaságok, ha Microsoft Exchange-el kommunikál.
Hibajelentéseivel hozzájárul az újabb verziók tökéletesítéséhez, kérdéseit itt teheti fel http://k9mail.googlecode.com/"</string>
<string name="debug_version_fmt">Verzió: %s</string>
@ -218,7 +218,7 @@ Vegye figyelembe, hogy a K-9 nem támogatja a legtöbb ingyenes hotmail fiókot
<string name="message_compose_quoted_text_label">Idézet</string>
<string name="message_compose_error_no_recipients">Legalább egy címzetted adjon meg.</string>
<string name="error_contact_address_not_found">E-mail cím nem található.</string>
<string name="message_compose_downloading_attachments_toast">Néhány melléklet nem lett letöltve. Levélküldés előtt automatikusan letöltődnek.</string>
<string name="message_compose_downloading_attachments_toast">Néhány melléklet nem lett letöltve. Levélküldés előtt automatikusan letöltődnek.</string>
<string name="message_compose_attachments_skipped_toast">Néhány mellékletet nem lehet továbbítani, mert nem lettek letöltve.</string>
<string name="message_view_from_format" formatted="false">Feladó: %s &lt;%s></string>
<string name="message_to_label">Címzett:</string>
@ -278,7 +278,7 @@ Vegye figyelembe, hogy a K-9 nem támogatja a legtöbb ingyenes hotmail fiókot
<string name="global_settings_confirm_action_delete">Törlés (csak üzenetek nézet)</string>
<string name="global_settings_confirm_action_spam">Levélszemét</string>
<string name="global_settings_confirm_action_mark_all_as_read">Összes megjelölése olvasottként</string>
<string name="global_settings_confirm_action_send">Küldés</string>
<string name="global_settings_confirm_action_send">Küldés</string>
<string name="global_settings_privacy_mode_title">Képernyőzár értesítések</string>
<string name="global_settings_privacy_mode_summary">Lezárt képernyőnél ne mutassa a levelek tárgyát a állapotsoron</string>
<string name="quiet_time">Csendes mód</string>
@ -450,13 +450,8 @@ Levelek letöltése…"</string>
<string name="account_settings_notification_opens_unread_summary">Értesítésre kattintva megnyitja az olvasatlan üzeneteket</string>
<string name="account_settings_notification_unread_count_label">Olvasatlanok kijelzése</string>
<string name="account_settings_notification_unread_count_summary">Olvasatlan levelek száma az állapotsoron.</string>
<string name="account_settings_hide_buttons_label">Görgetés iránygombokkal</string>
<string name="account_settings_hide_buttons_never">Soha</string>
<string name="account_settings_hide_buttons_keyboard_avail">Ha van billentyűzet</string>
<string name="account_settings_hide_buttons_always">Mindig</string>
<string name="account_settings_enable_move_buttons_label">Művelet gombok megjelenítése</string>
<string name="account_settings_enable_move_buttons_summary">Mutassa a Mozgatás, Archív és Levélszemét gombokat</string>
<string name="account_settings_hide_move_buttons_label">Művelet gombok görgetése</string>
<string name="account_settings_show_pictures_label">Képek megjelenítése</string>
<string name="account_settings_show_pictures_never">Soha</string>
<string name="account_settings_show_pictures_only_from_contacts">Csak az ismerősökét</string>
@ -611,7 +606,7 @@ Levelek letöltése…"</string>
<string name="account_settings_signature_use_label">Aláírás használata</string>
<string name="account_settings_signature_label">Aláírás</string>
<string name="account_settings_signature_summary">Az aláírás hozzáfűzése minden elküldött levélhez</string>
<string name="default_signature">"--
<string name="default_signature">"--
Ezt a levelet mobiltelefonról küldtem, K-9 Mail-el. Elnézést a levél rövidségéért és az esetleges hibákért."</string>
<string name="default_identity_description">Elsődleges személyazonosságom</string>
<string name="choose_identity">Személyazonosság választása</string>
@ -654,7 +649,7 @@ Ezt a levelet mobiltelefonról küldtem, K-9 Mail-el. Elnézést a levél rövid
<string name="provider_note_hanmail">Ha POP3-at vagy IMAP-ot szeretne használni ehhez a szolgáltatóhoz, akkor engedélyeznie kell az IMAP vagy POP3 beállításokat a Hanmail(Daum) oldalán.</string>
<string name="provider_note_paran">Ha POP3-at vagy IMAP-ot szeretne használni ehhez a szolgáltatóhoz, akkor engedélyeznie kell az IMAP vagy POP3 beállításokat a Paran oldalán.</string>
<string name="provider_note_nate">Ha POP3-at vagy IMAP-ot szeretne használni ehhez a szolgáltatóhoz, akkor engedélyeznie kell az IMAP vagy POP3 beállításokat a Nate oldalán.</string>
<string name="account_setup_failed_dlg_invalid_certificate_title">Felismerhetetlen tanúsítvány</string>
<string name="account_setup_failed_dlg_invalid_certificate_title">Felismerhetetlen tanúsítvány</string>
<string name="account_setup_failed_dlg_invalid_certificate_accept">Kulcs elfogadva</string>
<string name="account_setup_failed_dlg_invalid_certificate_reject">Kulcs elutasítva</string>
<string name="message_help_key">"Del (or D) - Delete
@ -752,7 +747,7 @@ S - Select/deselect"</string>
<string name="gestures_summary">Engedélyezi a kézmozdulakkal való vezérlést.</string>
<string name="compact_layouts_title">Kompakt elrendezés</string>
<string name="compact_layouts_summary">Adjust layouts to display more on each page</string>
<string name="volume_navigation_title">Hangerő gomb vezérlés</string>
<string name="volume_navigation_title">Hangerő gomb vezérlés</string>
<string name="volume_navigation_summary">Léptetés az hangerő gombokkal</string>
<string name="volume_navigation_message">Leveleknél</string>
<string name="volume_navigation_list">Lista nézetek váltása</string>
@ -766,7 +761,7 @@ S - Select/deselect"</string>
<string name="count_search_summary">Kikcsapcsolva gyorsabb műkodés</string>
<string name="hide_special_accounts_title">Különleges fiókok elrejtése</string>
<string name="hide_special_accounts_summary">Egységesen elrejti a fiókok bejövő mappáit</string>
<string name="search_title" formatted="false">%s %s</string>
<string name="search_title" formatted="false">%s %s</string>
<string name="flagged_modifier">- Csillagos</string>
<string name="unread_modifier">- Olvasatlan</string>
<string name="search_all_messages_title">Minden levél</string>
@ -846,11 +841,11 @@ S - Select/deselect"</string>
<string name="dialog_confirm_spam_confirm_button">Igen</string>
<string name="dialog_confirm_spam_cancel_button">Nem</string>
<string name="dialog_attachment_progress_title">Csatolmányok letöltése</string>
<string name="debug_logging_enabled">Hibakereső naplózás bekapcsolva</string>
<string name="debug_logging_enabled">Hibakereső naplózás bekapcsolva</string>
<string name="messagelist_sent_to_me_sigil">»</string>
<string name="messagelist_sent_cc_me_sigil"></string>
<string name="error_unable_to_connect">Nem lehet kapcsolódni.</string>
<string name="account_unavailable"> \"%s\" fiók nem elérhető ellenőríze a tárhelyet</string>
<string name="account_unavailable"> \"%s\" fiók nem elérhető ellenőríze a tárhelyet</string>
<string name="settings_attachment_default_path">Csatolményok mentése ide:</string>
<string name="attachment_save_title">Csatolményok mentése</string>
<string name="attachment_save_desc">Nincs fájlkezelő. Hova szeretné mentni a csatolmányt?</string>

View File

@ -543,14 +543,8 @@ Benvenuto nella configurazione della posta di K-9. K-9 è un client di posta ope
<string name="account_settings_notification_unread_count_label">Vedi numero messaggi non letti</string>
<string name="account_settings_notification_unread_count_summary">Mostra il numero dei messaggi non letti nella barra di notifica.</string>
<string name="account_settings_hide_buttons_label">Scorri pulsanti navigazione</string>
<string name="account_settings_hide_buttons_never">Mai</string>
<string name="account_settings_hide_buttons_keyboard_avail">Quando la tastiera è disponibile</string>
<string name="account_settings_hide_buttons_always">Sempre</string>
<string name="account_settings_enable_move_buttons_label">Abilita pulsanti archiviazione</string>
<string name="account_settings_enable_move_buttons_summary">Mostra i pulsanti Archivia, Sposta e Spam.</string>
<string name="account_settings_hide_move_buttons_label">Scorri pulsanti archiviazione</string>
<string name="account_settings_show_pictures_label">Mostra sempre le immagini</string>
<string name="account_settings_show_pictures_never">No</string>

View File

@ -71,6 +71,7 @@
<string name="send_messages_action">メール送信</string>
<string name="list_folders_action">フォルダ一覧</string>
<string name="refresh_folders_action">フォルダ再読込</string>
<string name="filter_folders_action">フォルダを探す</string>
<string name="mark_all_as_read_action">すべてのメールを既読にする</string>
<string name="add_account_action">アカウント追加</string>
<string name="compose_action">作成</string>
@ -544,14 +545,8 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール
<string name="account_settings_notification_unread_count_label">未読件数の表示</string>
<string name="account_settings_notification_unread_count_summary">通知バーに未読メッセージの件数を表示する</string>
<string name="account_settings_hide_buttons_label">ナビゲーションボタンのスクロール</string>
<string name="account_settings_hide_buttons_never">しない</string>
<string name="account_settings_hide_buttons_keyboard_avail">キーボード利用時</string>
<string name="account_settings_hide_buttons_always">常に</string>
<string name="account_settings_enable_move_buttons_label">メール整理ボタンを有効にする</string>
<string name="account_settings_enable_move_buttons_summary">アーカイブ、移動、迷惑メールボタンを表示</string>
<string name="account_settings_hide_move_buttons_label">メール整理ボタンをスクロール</string>
<string name="account_settings_show_pictures_label">画像を自動で表示</string>
<string name="account_settings_show_pictures_never">しない</string>
@ -822,6 +817,8 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール
Q - アカウント設定に戻る\u000A
S - アカウント設定編集</string>
<string name="folder_list_filter_hint">フォルダ名に含まれる文字</string>
<string name="folder_list_display_mode_label">フォルダ表示</string>
<string name="folder_list_display_mode_all">全フォルダ表示</string>
<string name="folder_list_display_mode_first_class">1st クラスフォルダ表示</string>
@ -973,6 +970,9 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール
<string name="font_size_message_view_date">日付</string>
<string name="font_size_message_view_content">本文</string>
<string name="font_size_message_compose">メッセージ作成</string>
<string name="font_size_message_compose_input">入力テキスト</string>
<string name="font_size_tiniest">極小</string>
<string name="font_size_tiny">かなり小</string>
<string name="font_size_smaller">やや小</string>
@ -1014,6 +1014,9 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール
<string name="save_or_discard_draft_message_dlg_title">メッセージの下書き保存</string>
<string name="save_or_discard_draft_message_instructions_fmt">メッセージを保存しますか?</string>
<string name="confirm_discard_draft_message_title">メッセージ破棄?</string>
<string name="confirm_discard_draft_message">このメッセージを破棄しますか?</string>
<string name="refuse_to_save_draft_marked_encrypted_dlg_title">下書き保存の拒否</string>
<string name="refuse_to_save_draft_marked_encrypted_instructions_fmt">暗号化したメッセージは下書き保存できません</string>
@ -1102,4 +1105,11 @@ K-9 Mail セットアップにようこそ。\nK-9 は標準のAndroidメール
<string name="manage_accounts_move_down_action">下に移動</string>
<string name="manage_accounts_moving_message">アカウントを移動しています</string>
<string name="unread_widget_label">未読件数</string>
<string name="unread_widget_select_account">アカウントの未読件数を表示</string>
<string name="import_dialog_error_title">ファイルマネージャがありません</string>
<string name="import_dialog_error_message">設定をインポートするためのアプリケーションがありません。Androidマーケットからファイルマネージャをインストールしてください。</string>
<string name="open_market">マーケット</string>
<string name="close">閉じる</string>
</resources>

View File

@ -542,14 +542,8 @@ K-9 메일 설치를 환영합니다. K-9은 표준 안드로이드 메일 클
<string name="account_settings_notification_unread_count_label">읽지 않은 메일 수 세기</string>
<string name="account_settings_notification_unread_count_summary">읽지 않은 메시지의 수를 상태바에 보여줍니다.</string>
<string name="account_settings_hide_buttons_label">네비게이션 버튼을 스크롤</string>
<string name="account_settings_hide_buttons_never">하지않음</string>
<string name="account_settings_hide_buttons_keyboard_avail">키보드를 이용가능할 경우</string>
<string name="account_settings_hide_buttons_always">항상</string>
<string name="account_settings_enable_move_buttons_label">재정리(refile) 버튼 활성화</string>
<string name="account_settings_enable_move_buttons_summary">보관, 이동, 스팸 버튼을 보이기</string>
<string name="account_settings_hide_move_buttons_label">재정리(refile) 보튼을 스크롤</string>
<string name="account_settings_show_pictures_label">항상 그림 보기</string>
<string name="account_settings_show_pictures_never">아니오</string>

View File

@ -541,14 +541,8 @@ Welkom bij K-9 Mail setup. K-9 is een open source mail cliënt voor Android, ge
<string name="account_settings_notification_unread_count_label">Toon aantal ongelezen</string>
<string name="account_settings_notification_unread_count_summary">Toon het aantal ongelezen berichten in de \'notification bar\'.</string>
<string name="account_settings_hide_buttons_label">Scroll navigatie knoppen</string>
<string name="account_settings_hide_buttons_never">Nooit</string>
<string name="account_settings_hide_buttons_keyboard_avail">Wanneer toetsenbord beschikbaar is</string>
<string name="account_settings_hide_buttons_always">Altijd</string>
<string name="account_settings_enable_move_buttons_label">Inschakelen verplaats knoppen</string>
<string name="account_settings_enable_move_buttons_summary">Laat de Archief, Verplaats, en Spam knoppen zien.</string>
<string name="account_settings_hide_move_buttons_label">Scroll verplaats knoppen</string>
<string name="account_settings_show_pictures_label">Laat afbeeldingen automatisch zien</string>
<string name="account_settings_show_pictures_never">Nooit</string>

View File

@ -553,14 +553,8 @@ Witaj w K-9 Mail, darmowym programie pocztowym dla systemu Android. Najistotniej
<string name="account_settings_notification_unread_count_label">Pokaż liczbę nieprzeczytanych</string>
<string name="account_settings_notification_unread_count_summary">Pokaż liczbę nieprzeczytanych wiadomości w pasku powiadomień.</string>
<string name="account_settings_hide_buttons_label">Przyciski nawigacyjne</string>
<string name="account_settings_hide_buttons_never">Przyciski nie są nigdy przesuwalne</string>
<string name="account_settings_hide_buttons_keyboard_avail">Przesuwalne, gdy jest klawiatura</string>
<string name="account_settings_hide_buttons_always">Przyciski są zawsze przesuwalne</string>
<string name="account_settings_enable_move_buttons_label">Użyj przycisków refile </string> <!-- FIXME -->
<string name="account_settings_enable_move_buttons_summary">Pokaż przyciski Archiwum, Przenieś, Spam.</string>
<string name="account_settings_hide_move_buttons_label">Przewijaj przyciski refile </string> <!-- FIXME -->
<string name="account_settings_show_pictures_label">Zawsze pokazuj obrazki</string>
<string name="account_settings_show_pictures_never">Nie</string>

View File

@ -539,14 +539,8 @@ Bem-vindo à configuração do K-9 Mail. K-9 é um cliente de e-mail com código
<string name="account_settings_notification_unread_count_label">Mostrar contagem de não lidas</string>
<string name="account_settings_notification_unread_count_summary">Mostrar o número de mensagens não lidas na barra de notificação.</string>
<string name="account_settings_hide_buttons_label">Navegação com botões de scroll</string>
<string name="account_settings_hide_buttons_never">Nunca</string>
<string name="account_settings_hide_buttons_keyboard_avail">Quando teclado estiver disponível</string>
<string name="account_settings_hide_buttons_always">Sempre</string>
<string name="account_settings_enable_move_buttons_label">Habilitar botão de ações</string>
<string name="account_settings_enable_move_buttons_summary">Mostrar botões de Arquivar, Mover e Span.</string>
<string name="account_settings_hide_move_buttons_label">Scroll para botões de ação </string>
<string name="account_settings_show_pictures_label">Sempre mostrar imagens</string>
<string name="account_settings_show_pictures_never">Não</string>

View File

@ -533,14 +533,8 @@
<string name="account_settings_notification_unread_count_label">Показать количество непрочитанных</string>
<string name="account_settings_notification_unread_count_summary">Показать количество непрочитанных в строке уведомлений.</string>
<string name="account_settings_hide_buttons_label">Прокрутка навигационных кнопок</string>
<string name="account_settings_hide_buttons_never">Никогда</string>
<string name="account_settings_hide_buttons_keyboard_avail">Когда присутствует клавиатура</string>
<string name="account_settings_hide_buttons_always">Всегда</string>
<string name="account_settings_enable_move_buttons_label">Разрешить кнопки переноса сообщений</string>
<string name="account_settings_enable_move_buttons_summary">Показывает кнопки: Архив, Переместить, Спам.</string>
<string name="account_settings_hide_move_buttons_label">Спрятать кнопки перемещения</string>
<string name="account_settings_show_pictures_label">Показывать изображения</string>
<string name="account_settings_show_pictures_never">Никогда</string>

View File

@ -543,14 +543,8 @@ Välkommen till installationen av K-9 E-post. K-9 är en e-postklient med öppen
<string name="account_settings_notification_unread_count_label">Visa antal olästa</string>
<string name="account_settings_notification_unread_count_summary">Visar antalet olästa brev i notifieringsytan.</string>
<string name="account_settings_hide_buttons_label">Scrolla navigationsknappar</string>
<string name="account_settings_hide_buttons_never">Aldrig</string>
<string name="account_settings_hide_buttons_keyboard_avail">När ett tangentbord är tillgängligt</string>
<string name="account_settings_hide_buttons_always">Alltid</string>
<string name="account_settings_enable_move_buttons_label">Aktivera flyttknappar</string>
<string name="account_settings_enable_move_buttons_summary">Visa knappar för att arkivera, flytta och spam-markera e-post.</string>
<string name="account_settings_hide_move_buttons_label">Scrolla flyttknappar</string>
<string name="account_settings_show_pictures_label">Visa bilder automatiskt</string>
<string name="account_settings_show_pictures_never">Aldrig</string>

View File

@ -516,14 +516,8 @@
<string name="account_settings_notification_unread_count_label">Okunmamış sayısını göster</string>
<string name="account_settings_notification_unread_count_summary">Bildirim çubuğunda okunmamış mesaj numarasını göster.</string>
<string name="account_settings_hide_buttons_label">Gezinme tuşlarını kaydırma</string>
<string name="account_settings_hide_buttons_never">Asla</string>
<string name="account_settings_hide_buttons_keyboard_avail">Klavye olduğu zaman</string>
<string name="account_settings_hide_buttons_always">Daima</string>
<string name="account_settings_enable_move_buttons_label">İşaretleme düğmelerini etkinleştir</string>
<string name="account_settings_enable_move_buttons_summary">Arşiv, Taşıma ve Spam düğmelerini göster.</string>
<string name="account_settings_hide_move_buttons_label">İşaretleme düğmelerini kaydır</string>
<string name="account_settings_show_pictures_label">Daima imajları göster</string>
<string name="account_settings_show_pictures_never">Hayır</string>

View File

@ -530,14 +530,8 @@
<!-- NEW: <string name="account_settings_notification_unread_count_label">Show unread count</string>-->
<!-- NEW: <string name="account_settings_notification_unread_count_summary">Show the number of unread messages in the notification bar.</string>-->
<string name="account_settings_hide_buttons_label">滚动导航按钮</string>
<string name="account_settings_hide_buttons_never">从不</string>
<string name="account_settings_hide_buttons_keyboard_avail">使用键盘时</string>
<string name="account_settings_hide_buttons_always">总是</string>
<string name="account_settings_enable_move_buttons_label">启用整理按钮</string>
<string name="account_settings_enable_move_buttons_summary">显示归档、移动和标记为垃圾按钮</string>
<string name="account_settings_hide_move_buttons_label">滚动整理按钮</string>
<string name="account_settings_show_pictures_label">显示图片</string>
<string name="account_settings_show_pictures_never">从不</string>

View File

@ -539,14 +539,8 @@
<string name="account_settings_notification_unread_count_label">顯示未讀郵件數</string>
<string name="account_settings_notification_unread_count_summary">在通知欄上顯示未讀郵件數</string>
<string name="account_settings_hide_buttons_label">滾動導航按鈕</string>
<string name="account_settings_hide_buttons_never">從不</string>
<string name="account_settings_hide_buttons_keyboard_avail">使用鍵盤時</string>
<string name="account_settings_hide_buttons_always">總是</string>
<string name="account_settings_enable_move_buttons_label">啟用整理按鈕</string>
<string name="account_settings_enable_move_buttons_summary">顯示歸檔、移動和標記為垃圾按鈕</string>
<string name="account_settings_hide_move_buttons_label">滾動整理按鈕</string>
<string name="account_settings_show_pictures_label">顯示圖片</string>
<string name="account_settings_show_pictures_never">從不</string>
@ -799,7 +793,7 @@
<string name="provider_note_hanmail">要使用此提供者的IMAP或POP3請先至Hanmail(Daum)郵箱設置頁設定允許使用IMAP或POP3。</string>
<string name="provider_note_paran">要使用此提供者的IMAP或POP3請先至Paran郵箱設置頁設定允許使用IMAP或POP3。</string>
<string name="provider_note_nate">要使用此提供者的IMAP或POP3請先至Nate郵箱設置頁設定允許使用IMAP或POP3。</string>
<string name="account_setup_failed_dlg_invalid_certificate_title">無法識別的證書訊息</string>
<string name="account_setup_failed_dlg_invalid_certificate_accept">接收密鑰</string>
<string name="account_setup_failed_dlg_invalid_certificate_reject">拒絕密鑰</string>
@ -1060,5 +1054,5 @@
<string name="manage_accounts_move_up_action">上移</string>
<string name="manage_accounts_move_down_action">下移</string>
</resources>

View File

@ -149,30 +149,6 @@
<item>NOT_SECOND_CLASS</item>
</string-array>
<string-array name="account_settings_hide_buttons_entries">
<item>@string/account_settings_hide_buttons_never</item>
<item>@string/account_settings_hide_buttons_keyboard_avail</item>
<item>@string/account_settings_hide_buttons_always</item>
</string-array>
<string-array name="account_settings_hide_buttons_values">
<item>NEVER</item>
<item>KEYBOARD_AVAILABLE</item>
<item>ALWAYS</item>
</string-array>
<string-array name="account_settings_hide_move_buttons_entries">
<item>@string/account_settings_hide_buttons_never</item>
<item>@string/account_settings_hide_buttons_keyboard_avail</item>
<item>@string/account_settings_hide_buttons_always</item>
</string-array>
<string-array name="account_settings_hide_move_buttons_values">
<item>NEVER</item>
<item>KEYBOARD_AVAILABLE</item>
<item>ALWAYS</item>
</string-array>
<string-array name="account_settings_show_pictures_entries">
<item>@string/account_settings_show_pictures_never</item>
<item>@string/account_settings_show_pictures_only_from_contacts</item>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="message_list_item_background">#ffffff</color>
<color name="message_list_item_background">#ffffff</color>
<color name="message_list_item_footer_background">#eeeeee</color>
<color name="message_view_header_background">#1a080808</color>
</resources>

View File

@ -297,6 +297,9 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
<string name="message_view_status_attachment_not_saved">Unable to save attachment to SD card.</string>
<string name="message_view_show_pictures_instructions">Select \"Show pictures\" to display embedded pictures.</string>
<string name="message_view_show_pictures_action">Show pictures</string>
<string name="message_view_show_message_action">Show message</string>
<string name="message_view_show_attachments_action">Show attachments</string>
<string name="message_view_show_more_attachments_action">More&#8230;</string>
<string name="message_view_fetching_attachment_toast">Fetching attachment.</string>
<string name="message_view_no_viewer">Unable to find viewer for <xliff:g id="mimetype">%s</xliff:g>.</string>
@ -559,14 +562,8 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
<string name="account_settings_notification_unread_count_label">Show unread count</string>
<string name="account_settings_notification_unread_count_summary">Show the number of unread messages in the notification bar.</string>
<string name="account_settings_hide_buttons_label">Scroll navigation buttons</string>
<string name="account_settings_hide_buttons_never">Never</string>
<string name="account_settings_hide_buttons_keyboard_avail">When keyboard is available</string>
<string name="account_settings_hide_buttons_always">Always</string>
<string name="account_settings_enable_move_buttons_label">Enable refile buttons</string>
<string name="account_settings_enable_move_buttons_summary">Show the Archive, Move, and Spam buttons.</string>
<string name="account_settings_hide_move_buttons_label">Scroll refile buttons</string>
<string name="account_settings_show_pictures_label">Always show images</string>
<string name="account_settings_show_pictures_never">No</string>

View File

@ -70,14 +70,6 @@
android:entryValues="@array/account_settings_show_pictures_values"
android:dialogTitle="@string/account_settings_show_pictures_label" />
<ListPreference
android:persistent="false"
android:key="hide_buttons_enum"
android:title="@string/account_settings_hide_buttons_label"
android:entries="@array/account_settings_hide_buttons_entries"
android:entryValues="@array/account_settings_hide_buttons_values"
android:dialogTitle="@string/account_settings_hide_buttons_label" />
<CheckBoxPreference
android:persistent="false"
android:key="enable_move_buttons"
@ -85,15 +77,6 @@
android:defaultValue="true"
android:summary="@string/account_settings_enable_move_buttons_summary" />
<ListPreference
android:persistent="false"
android:key="hide_move_buttons_enum"
android:dependency="enable_move_buttons"
android:title="@string/account_settings_hide_move_buttons_label"
android:entries="@array/account_settings_hide_move_buttons_entries"
android:entryValues="@array/account_settings_hide_move_buttons_values"
android:dialogTitle="@string/account_settings_hide_move_buttons_label" />
</PreferenceCategory>
</PreferenceScreen>
@ -239,10 +222,10 @@
android:entryValues="@array/account_settings_message_format_values" />
<CheckBoxPreference
android:persistent="false"
android:key="message_read_receipt"
android:title="@string/account_settings_message_read_receipt_label"
android:summary="@string/account_settings_message_read_receipt_summary" />
android:persistent="false"
android:key="message_read_receipt"
android:title="@string/account_settings_message_read_receipt_label"
android:summary="@string/account_settings_message_read_receipt_summary" />
<ListPreference
android:persistent="false"

View File

@ -174,6 +174,10 @@
<incoming uri="imap+ssl+://mail.montclair.edu" username="$user" />
<outgoing uri="smtp+tls+://smtp.montclair.edu" username="$user" />
</provider>
<provider id="gmx.com" label="GMX" domain="gmx.com">
<incoming uri="imap+ssl+://imap.gmx.com" username="$email" />
<outgoing uri="smtp+ssl+://mail.gmx.com" username="$email" />
</provider>
<!-- Yahoo! Mail Variants -->
<provider id="yahoo" label="Yahoo" domain="yahoo.com">

View File

@ -124,8 +124,6 @@ public class Account implements BaseAccount {
private boolean mAutoUploadOnMove;
private boolean mPushPollOnConnect;
private boolean mNotifySync;
private ScrollButtons mScrollMessageViewButtons;
private ScrollButtons mScrollMessageViewMoveButtons;
private ShowPictures mShowPictures;
private boolean mEnableMoveButtons;
private boolean mIsSignatureBeforeQuotedText;
@ -183,10 +181,6 @@ public class Account implements BaseAccount {
NONE, ALL, FIRST_CLASS, FIRST_AND_SECOND_CLASS, NOT_SECOND_CLASS
}
public enum ScrollButtons {
NEVER, ALWAYS, KEYBOARD_AVAILABLE
}
public enum ShowPictures {
NEVER, ALWAYS, ONLY_FROM_CONTACTS
}
@ -220,8 +214,6 @@ public class Account implements BaseAccount {
mFolderSyncMode = FolderMode.FIRST_CLASS;
mFolderPushMode = FolderMode.FIRST_CLASS;
mFolderTargetMode = FolderMode.NOT_SECOND_CLASS;
mScrollMessageViewButtons = ScrollButtons.NEVER;
mScrollMessageViewMoveButtons = ScrollButtons.NEVER;
mShowPictures = ShowPictures.NEVER;
mEnableMoveButtons = false;
mIsSignatureBeforeQuotedText = false;
@ -344,20 +336,6 @@ public class Account implements BaseAccount {
(random.nextInt(0x70) * 0xffff) +
0xff000000);
try {
mScrollMessageViewButtons = ScrollButtons.valueOf(prefs.getString(mUuid + ".hideButtonsEnum",
ScrollButtons.NEVER.name()));
} catch (Exception e) {
mScrollMessageViewButtons = ScrollButtons.NEVER;
}
try {
mScrollMessageViewMoveButtons = ScrollButtons.valueOf(prefs.getString(mUuid + ".hideMoveButtonsEnum",
ScrollButtons.NEVER.name()));
} catch (Exception e) {
mScrollMessageViewMoveButtons = ScrollButtons.NEVER;
}
try {
mShowPictures = ShowPictures.valueOf(prefs.getString(mUuid + ".showPicturesEnum",
ShowPictures.NEVER.name()));
@ -624,8 +602,6 @@ public class Account implements BaseAccount {
editor.putString(mUuid + ".spamFolderName", mSpamFolderName);
editor.putString(mUuid + ".autoExpandFolderName", mAutoExpandFolderName);
editor.putInt(mUuid + ".accountNumber", mAccountNumber);
editor.putString(mUuid + ".hideButtonsEnum", mScrollMessageViewButtons.name());
editor.putString(mUuid + ".hideMoveButtonsEnum", mScrollMessageViewMoveButtons.name());
editor.putString(mUuid + ".showPicturesEnum", mShowPictures.name());
editor.putBoolean(mUuid + ".enableMoveButtons", mEnableMoveButtons);
editor.putString(mUuid + ".folderDisplayMode", mFolderDisplayMode.name());
@ -1073,22 +1049,6 @@ Log.d("ASH", "setTrashFolderName() attempting change of folder.setLocalOnly()");
this.mNotifySync = showOngoing;
}
public synchronized ScrollButtons getScrollMessageViewButtons() {
return mScrollMessageViewButtons;
}
public synchronized void setScrollMessageViewButtons(ScrollButtons scrollMessageViewButtons) {
mScrollMessageViewButtons = scrollMessageViewButtons;
}
public synchronized ScrollButtons getScrollMessageViewMoveButtons() {
return mScrollMessageViewMoveButtons;
}
public synchronized void setScrollMessageViewMoveButtons(ScrollButtons scrollMessageViewButtons) {
mScrollMessageViewMoveButtons = scrollMessageViewButtons;
}
public synchronized ShowPictures getShowPictures() {
return mShowPictures;
}

View File

@ -988,6 +988,14 @@ public class FolderList extends K9ListActivity {
menu.findItem(R.id.expunge).setVisible(false);
}
if (!MessagingController.getInstance(getApplication()).isMoveCapable(mAccount)) {
// FIXME: Really we want to do this for all local-only folders
if (!mAccount.getInboxFolderName().equals(folder.name)) {
menu.findItem(R.id.check_mail).setVisible(false);
}
menu.findItem(R.id.expunge).setVisible(false);
}
if (folder.name.equalsIgnoreCase(mAccount.getInboxFolderName()) ||
folder.name.equals(mAccount.getOutboxFolderName()) ||
folder.name.equals(mAccount.getErrorFolderName())) {

View File

@ -6,24 +6,21 @@ import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import com.fsck.k9.K9;
import com.fsck.k9.view.ToggleScrollView;
public class K9Activity extends Activity {
private GestureDetector gestureDetector;
protected ToggleScrollView mTopView;
@Override
public void onCreate(Bundle icicle) {
onCreate(icicle, true);
@ -144,22 +141,6 @@ public class K9Activity extends Activity {
private static final float SWIPE_MAX_OFF_PATH_DIP = 250f;
private static final float SWIPE_THRESHOLD_VELOCITY_DIP = 325f;
@Override
public boolean onDoubleTap(MotionEvent ev) {
super.onDoubleTap(ev);
if (mTopView != null) {
int height = getResources().getDisplayMetrics().heightPixels;
if (ev.getRawY() < (height / 4)) {
mTopView.fullScroll(View.FOCUS_UP);
} else if (ev.getRawY() > (height - height / 4)) {
mTopView.fullScroll(View.FOCUS_DOWN);
}
}
return false;
}
@Override
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.
@ -169,11 +150,11 @@ public class K9Activity extends Activity {
final float mGestureScale = getResources().getDisplayMetrics().density;
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);
@ -216,4 +197,14 @@ public class K9Activity extends Activity {
return false;
}
}
public int getThemeBackgroundColor() {
TypedArray array = getTheme().obtainStyledAttributes(new int[] {
android.R.attr.colorBackground,
});
int backgroundColor = array.getColor(0, 0xFF00FF);
array.recycle();
return backgroundColor;
}
}

View File

@ -2709,7 +2709,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
if (part != null) {
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "getBodyTextFromMessage: HTML requested, text found.");
return HtmlConverter.textToHtml(MimeUtility.getTextFromPart(part));
return HtmlConverter.textToHtml(MimeUtility.getTextFromPart(part), true);
}
} else if (format == MessageFormat.TEXT) {
// Text takes precedence, then html.

View File

@ -1633,6 +1633,19 @@ public class MessageList
if (K9.FOLDER_NONE.equalsIgnoreCase(mAccount.getSpamFolderName())) {
menu.findItem(R.id.batch_spam_op).setVisible(false);
}
if (!mController.isMoveCapable(mAccount)) {
// FIXME: Really we want to do this for all local-only folders
if (mCurrentFolder != null &&
!mAccount.getInboxFolderName().equals(mCurrentFolder.name)) {
menu.findItem(R.id.check_mail).setVisible(false);
}
menu.findItem(R.id.batch_archive_op).setVisible(false);
menu.findItem(R.id.batch_spam_op).setVisible(false);
menu.findItem(R.id.batch_move_op).setVisible(false);
menu.findItem(R.id.batch_copy_op).setVisible(false);
menu.findItem(R.id.expunge).setVisible(false);
}
try {
if (((com.fsck.k9.mail.store.LocalStore.LocalFolder)mCurrentFolder.folder).isLocalOnly() ||
!mAccount.getRemoteStore().isAppendCapable()) {

View File

@ -4,11 +4,9 @@ import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Config;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
@ -20,9 +18,9 @@ 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;
import com.fsck.k9.view.SingleMessageView;
import com.fsck.k9.view.AttachmentView.AttachmentFileDownloadCallback;
@ -34,8 +32,6 @@ public class MessageView extends K9Activity implements OnClickListener {
private static final String EXTRA_MESSAGE_REFERENCES = "com.fsck.k9.MessageView_messageReferences";
private static final String EXTRA_NEXT = "com.fsck.k9.MessageView_next";
private static final String EXTRA_MESSAGE_LIST_EXTRAS = "com.fsck.k9.MessageView_messageListExtras";
private static final String EXTRA_SCROLL_PERCENTAGE = "com.fsck.k9.MessageView_scrollPercentage";
private static final String SHOW_PICTURES = "showPictures";
private static final String STATE_PGP_DATA = "pgpData";
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
@ -45,7 +41,6 @@ public class MessageView extends K9Activity implements OnClickListener {
private PgpData mPgpData;
private View mNext;
private View mPrevious;
private View mDelete;
@ -104,24 +99,6 @@ public class MessageView extends K9Activity implements OnClickListener {
public void onMount(String providerId) { /* no-op */ }
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
// Text selection is finished. Allow scrolling again.
mTopView.setScrolling(true);
} else if (K9.zoomControlsEnabled()) {
// If we have system zoom controls enabled, disable scrolling so the screen isn't wiggling around while
// trying to zoom.
if (ev.getAction() == MotionEvent.ACTION_POINTER_2_DOWN) {
mTopView.setScrolling(false);
} else if (ev.getAction() == MotionEvent.ACTION_POINTER_2_UP) {
mTopView.setScrolling(true);
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
boolean ret = false;
@ -165,15 +142,6 @@ public class MessageView extends K9Activity implements OnClickListener {
}
break;
}
case KeyEvent.KEYCODE_SHIFT_LEFT:
case KeyEvent.KEYCODE_SHIFT_RIGHT: {
/*
* Selecting text started via shift key. Disable scrolling as
* this causes problems when selecting text.
*/
mTopView.setScrolling(false);
break;
}
case KeyEvent.KEYCODE_DEL: {
onDelete();
return true;
@ -324,7 +292,6 @@ public class MessageView extends K9Activity implements OnClickListener {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.message_view);
mTopView = (ToggleScrollView) findViewById(R.id.top_view);
mMessageView = (SingleMessageView) findViewById(R.id.message_view);
//set a callback for the attachment view. With this callback the attachmentview
@ -356,10 +323,6 @@ public class MessageView extends K9Activity implements OnClickListener {
mMessageView.initialize(this);
// Register the ScrollView's listener to handle scrolling to last known location on resume.
mController.addListener(mTopView.getListener());
mMessageView.setListeners(mController.getListeners());
setTitle("");
final Intent intent = getIntent();
@ -431,57 +394,29 @@ public class MessageView extends K9Activity implements OnClickListener {
setOnClickListener(R.id.archive);
setOnClickListener(R.id.move);
setOnClickListener(R.id.spam);
// To show full header
setOnClickListener(R.id.header_container);
setOnClickListener(R.id.reply_scrolling);
// setOnClickListener(R.id.reply_all_scrolling);
setOnClickListener(R.id.delete_scrolling);
setOnClickListener(R.id.forward_scrolling);
setOnClickListener(R.id.next_scrolling);
setOnClickListener(R.id.previous_scrolling);
setOnClickListener(R.id.archive_scrolling);
setOnClickListener(R.id.move_scrolling);
setOnClickListener(R.id.spam_scrolling);
setOnClickListener(R.id.show_pictures);
setOnClickListener(R.id.download_remainder);
// Perhaps the ScrollButtons should be global, instead of account-specific
Account.ScrollButtons scrollButtons = mAccount.getScrollMessageViewButtons();
if ((Account.ScrollButtons.ALWAYS == scrollButtons)
|| (Account.ScrollButtons.KEYBOARD_AVAILABLE == scrollButtons &&
(this.getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO))) {
scrollButtons();
} else { // never or the keyboard is open
staticButtons();
}
Account.ScrollButtons scrollMoveButtons = mAccount.getScrollMessageViewMoveButtons();
if ((Account.ScrollButtons.ALWAYS == scrollMoveButtons)
|| (Account.ScrollButtons.KEYBOARD_AVAILABLE == scrollMoveButtons &&
(this.getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO))) {
scrollMoveButtons();
} else {
staticMoveButtons();
}
mNext = findViewById(R.id.next);
mPrevious = findViewById(R.id.previous);
mDelete = findViewById(R.id.delete);
mArchive = findViewById(R.id.archive);
mMove = findViewById(R.id.move);
mSpam = findViewById(R.id.spam);
if (!mAccount.getEnableMoveButtons()) {
View buttons = findViewById(R.id.move_buttons);
if (buttons != null) {
buttons.setVisibility(View.GONE);
}
buttons = findViewById(R.id.scrolling_move_buttons);
if (buttons != null) {
buttons.setVisibility(View.GONE);
}
buttons.setVisibility(View.GONE);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(EXTRA_MESSAGE_REFERENCE, mMessageReference);
outState.putParcelableArrayList(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
outState.putSerializable(STATE_PGP_DATA, mPgpData);
outState.putBoolean(SHOW_PICTURES, mMessageView.showPictures());
outState.putDouble(EXTRA_SCROLL_PERCENTAGE, mTopView.getScrollPercentage());
}
@Override
@ -489,8 +424,6 @@ public class MessageView extends K9Activity implements OnClickListener {
super.onRestoreInstanceState(savedInstanceState);
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage);
mMessageView.setLoadPictures(savedInstanceState.getBoolean(SHOW_PICTURES));
mTopView.setScrollPercentage(savedInstanceState.getDouble(EXTRA_SCROLL_PERCENTAGE));
}
private void displayMessage(MessageReference ref) {
@ -498,22 +431,18 @@ public class MessageView extends K9Activity implements OnClickListener {
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "MessageView displaying message " + mMessageReference);
mAccount = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid);
clearMessageDisplay();
findSurroundingMessagesUid();
// start with fresh, empty PGP data
mPgpData = new PgpData();
mTopView.setVisibility(View.VISIBLE);
// Clear previous message
mMessageView.resetView();
mMessageView.resetHeaderView();
mController.loadMessageForView(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
setupDisplayMessageButtons();
}
private void clearMessageDisplay() {
mTopView.setVisibility(View.GONE);
mTopView.scrollTo(0, 0);
mMessageView.resetView();
}
private void setupDisplayMessageButtons() {
mDelete.setEnabled(true);
mNext.setEnabled(mNextMessage != null);
@ -526,45 +455,6 @@ public class MessageView extends K9Activity implements OnClickListener {
!K9.FOLDER_NONE.equalsIgnoreCase(mAccount.getSpamFolderName()));
mMove.setEnabled(true);
}
private void staticButtons() {
View buttons = findViewById(R.id.scrolling_buttons);
if (buttons != null) {
buttons.setVisibility(View.GONE);
}
mNext = findViewById(R.id.next);
mPrevious = findViewById(R.id.previous);
mDelete = findViewById(R.id.delete);
}
private void scrollButtons() {
View buttons = findViewById(R.id.bottom_buttons);
if (buttons != null) {
buttons.setVisibility(View.GONE);
}
mNext = findViewById(R.id.next_scrolling);
mPrevious = findViewById(R.id.previous_scrolling);
mDelete = findViewById(R.id.delete_scrolling);
}
private void staticMoveButtons() {
View buttons = findViewById(R.id.scrolling_move_buttons);
if (buttons != null) {
buttons.setVisibility(View.GONE);
}
mArchive = findViewById(R.id.archive);
mMove = findViewById(R.id.move);
mSpam = findViewById(R.id.spam);
}
private void scrollMoveButtons() {
View buttons = findViewById(R.id.move_buttons);
if (buttons != null) {
buttons.setVisibility(View.GONE);
}
mArchive = findViewById(R.id.archive_scrolling);
mMove = findViewById(R.id.move_scrolling);
mSpam = findViewById(R.id.spam_scrolling);
}
private void disableButtons() {
mMessageView.setLoadPictures(false);
@ -605,13 +495,11 @@ public class MessageView extends K9Activity implements OnClickListener {
onAccountUnavailable();
return;
}
mController.addListener(mTopView.getListener());
StorageManager.getInstance(getApplication()).addListener(mStorageListener);
}
@Override
protected void onPause() {
mController.removeListener(mTopView.getListener());
StorageManager.getInstance(getApplication()).removeListener(mStorageListener);
super.onPause();
}
@ -815,7 +703,6 @@ public class MessageView extends K9Activity implements OnClickListener {
protected void onNext() {
// Reset scroll percentage when we change messages
mTopView.setScrollPercentage(0);
if (mNextMessage == null) {
Toast.makeText(this, getString(R.string.end_of_folder), Toast.LENGTH_SHORT).show();
return;
@ -823,7 +710,7 @@ public class MessageView extends K9Activity implements OnClickListener {
mLastDirection = NEXT;
disableButtons();
if (K9.showAnimations()) {
mTopView.startAnimation(outToLeftAnimation());
mMessageView.startAnimation(outToLeftAnimation());
}
displayMessage(mNextMessage);
mNext.requestFocus();
@ -831,7 +718,6 @@ public class MessageView extends K9Activity implements OnClickListener {
protected void onPrevious() {
// Reset scroll percentage when we change messages
mTopView.setScrollPercentage(0);
if (mPreviousMessage == null) {
Toast.makeText(this, getString(R.string.end_of_folder), Toast.LENGTH_SHORT).show();
return;
@ -839,7 +725,7 @@ public class MessageView extends K9Activity implements OnClickListener {
mLastDirection = PREVIOUS;
disableButtons();
if (K9.showAnimations()) {
mTopView.startAnimation(inFromRightAnimation());
mMessageView.startAnimation(inFromRightAnimation());
}
displayMessage(mPreviousMessage);
mPrevious.requestFocus();
@ -868,46 +754,35 @@ public class MessageView extends K9Activity implements OnClickListener {
public void onClick(View view) {
switch (view.getId()) {
case R.id.reply:
case R.id.reply_scrolling:
onReply();
break;
case R.id.reply_all:
onReplyAll();
break;
case R.id.delete:
case R.id.delete_scrolling:
onDelete();
break;
case R.id.forward:
case R.id.forward_scrolling:
onForward();
break;
case R.id.archive:
case R.id.archive_scrolling:
onRefile(mAccount.getArchiveFolderName());
break;
case R.id.spam:
case R.id.spam_scrolling:
onRefile(mAccount.getSpamFolderName());
break;
case R.id.move:
case R.id.move_scrolling:
onMove();
break;
case R.id.next:
case R.id.next_scrolling:
onNext();
break;
case R.id.previous:
case R.id.previous_scrolling:
onPrevious();
break;
case R.id.download:
((AttachmentView)view).saveFile();
break;
case R.id.show_pictures:
mMessageView.setLoadPictures(true);
break;
case R.id.download_remainder:
onDownloadRemainder();
break;
@ -962,7 +837,6 @@ public class MessageView extends K9Activity implements OnClickListener {
});
break;
case R.id.select_text:
mTopView.setScrolling(false);
mMessageView.beginSelectingText();
break;
default:
@ -1053,30 +927,6 @@ public class MessageView extends K9Activity implements OnClickListener {
return super.onPrepareOptionsMenu(menu);
}
public void displayMessageBody(final Account account, final String folder, final String uid, final Message message) {
Log.d("ASH", MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL) + " " + MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_FULL));
Log.d("ASH", message.isSet(Flag.X_DOWNLOADED_PARTIAL) + " " + message.isSet(Flag.X_DOWNLOADED_FULL));
runOnUiThread(new Runnable() {
public void run() {
mTopView.scrollTo(0, 0);
try {
if (MessageView.this.mMessage != null
&& MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
&& message.isSet(Flag.X_DOWNLOADED_FULL)) {
mMessageView.setHeaders(message, account);
}
MessageView.this.mMessage = message;
mMessageView.displayMessageBody(account, folder, uid, message, mPgpData);
mMessageView.renderAttachments(mMessage, 0, mMessage, mAccount, mController, mListener);
} catch (MessagingException e) {
if (Config.LOGV) {
Log.v(K9.LOG_TAG, "loadMessageForViewBodyAvailable", e);
}
}
}
});
}
class Listener extends MessagingListener {
@Override
public void loadMessageForViewHeadersAvailable(final Account account, String folder, String uid,
@ -1085,7 +935,6 @@ Log.d("ASH", message.isSet(Flag.X_DOWNLOADED_PARTIAL) + " " + message.isSet(Fla
|| !mMessageReference.accountUuid.equals(account.getUuid())) {
return;
}
MessageView.this.mMessage = message;
/*
* Clone the message object because the original could be modified by
@ -1119,17 +968,28 @@ Log.d("ASH", message.isSet(Flag.X_DOWNLOADED_PARTIAL) + " " + message.isSet(Fla
}
@Override
public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
Message message) {
if (!mMessageReference.uid.equals(uid) || !mMessageReference.folderName.equals(folder)
|| !mMessageReference.accountUuid.equals(account.getUuid())) {
public void loadMessageForViewBodyAvailable(final Account account, String folder,
String uid, final Message message) {
if (!mMessageReference.uid.equals(uid) ||
!mMessageReference.folderName.equals(folder) ||
!mMessageReference.accountUuid.equals(account.getUuid())) {
return;
}
displayMessageBody(account, folder, uid, message);
}//loadMessageForViewBodyAvailable
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
mMessage = message;
mMessageView.setMessage(account, (LocalMessage) message, mPgpData,
mController, mListener);
} catch (MessagingException e) {
Log.v(K9.LOG_TAG, "loadMessageForViewBodyAvailable", e);
}
}
});
}
@Override
public void loadMessageForViewFailed(Account account, String folder, String uid, final Throwable t) {
@ -1234,8 +1094,14 @@ Log.d("ASH", message.isSet(Flag.X_DOWNLOADED_PARTIAL) + " " + message.isSet(Fla
// This REALLY should be in MessageCryptoView
public void onDecryptDone(PgpData pgpData) {
// TODO: this might not be enough if the orientation was changed while in APG,
// sometimes shows the original encrypted content
mMessageView.loadBodyFromText(mAccount.getCryptoProvider(), mPgpData, mMessage, mPgpData.getDecryptedData(), "text/plain");
Account account = mAccount;
LocalMessage message = (LocalMessage) mMessage;
MessagingController controller = mController;
Listener listener = mListener;
try {
mMessageView.setMessage(account, message, pgpData, controller, listener);
} catch (MessagingException e) {
Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
}
}
}

View File

@ -18,7 +18,6 @@ import java.util.List;
import com.fsck.k9.Account;
import com.fsck.k9.Account.FolderMode;
import com.fsck.k9.Account.QuoteStyle;
import com.fsck.k9.Account.ScrollButtons;
import com.fsck.k9.K9;
import com.fsck.k9.NotificationSetting;
import com.fsck.k9.Preferences;
@ -54,8 +53,6 @@ public class AccountSettings extends K9PreferenceActivity {
private static final String PREFERENCE_FREQUENCY = "account_check_frequency";
private static final String PREFERENCE_DISPLAY_COUNT = "account_display_count";
private static final String PREFERENCE_DEFAULT = "account_default";
private static final String PREFERENCE_HIDE_BUTTONS = "hide_buttons_enum";
private static final String PREFERENCE_HIDE_MOVE_BUTTONS = "hide_move_buttons_enum";
private static final String PREFERENCE_SHOW_PICTURES = "show_pictures_enum";
private static final String PREFERENCE_ENABLE_MOVE_BUTTONS = "enable_move_buttons";
private static final String PREFERENCE_NOTIFY = "account_notify";
@ -101,7 +98,7 @@ public class AccountSettings extends K9PreferenceActivity {
private static final String PREFERENCE_LOCAL_STORAGE_PROVIDER = "local_storage_provider";
private static final String PREFERENCE_CATEGORY_FOLDERS = "folders";
private static final String PREFERENCE_ARCHIVE_FOLDER = "archive_folder";
private static final String PREFERENCE_DRAFTS_FOLDER = "drafts_folder";
private static final String PREFERENCE_SENT_FOLDER = "sent_folder";
@ -111,6 +108,7 @@ public class AccountSettings extends K9PreferenceActivity {
private Account mAccount;
private boolean mIsMoveCapable = false; // ASH i seem to have removed this, or renamed it to mIsAppendCapable
private boolean mIsPushCapable = false;
private boolean mIsExpungeCapable = false;
private boolean mIsAppendCapable = false;
@ -125,8 +123,6 @@ public class AccountSettings extends K9PreferenceActivity {
private CheckBoxPreference mAccountDefault;
private CheckBoxPreference mAccountNotify;
private CheckBoxPreference mAccountNotifySelf;
private ListPreference mAccountScrollButtons;
private ListPreference mAccountScrollMoveButtons;
private ListPreference mAccountShowPictures;
private CheckBoxPreference mAccountEnableMoveButtons;
private CheckBoxPreference mAccountNotifySync;
@ -344,17 +340,17 @@ public class AccountSettings extends K9PreferenceActivity {
mExpungePolicy = (ListPreference) findPreference(PREFERENCE_EXPUNGE_POLICY);
if (mIsExpungeCapable) {
mExpungePolicy.setValue(mAccount.getExpungePolicy());
mExpungePolicy.setSummary(mExpungePolicy.getEntry());
mExpungePolicy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mExpungePolicy.findIndexOfValue(summary);
mExpungePolicy.setSummary(mExpungePolicy.getEntries()[index]);
mExpungePolicy.setValue(summary);
return false;
}
});
mExpungePolicy.setValue(mAccount.getExpungePolicy());
mExpungePolicy.setSummary(mExpungePolicy.getEntry());
mExpungePolicy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mExpungePolicy.findIndexOfValue(summary);
mExpungePolicy.setSummary(mExpungePolicy.getEntries()[index]);
mExpungePolicy.setValue(summary);
return false;
}
});
} else {
((PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING)).removePreference(mExpungePolicy);
}
@ -399,25 +395,25 @@ public class AccountSettings extends K9PreferenceActivity {
}
});
mMessageAge = (ListPreference) findPreference(PREFERENCE_MESSAGE_AGE);
if (!mAccount.isSearchByDateCapable()) {
((PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING)).removePreference(mMessageAge);
} else {
mMessageAge.setValue(String.valueOf(mAccount.getMaximumPolledMessageAge()));
mMessageAge.setSummary(mMessageAge.getEntry());
mMessageAge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mMessageAge.findIndexOfValue(summary);
mMessageAge.setSummary(mMessageAge.getEntries()[index]);
mMessageAge.setValue(summary);
return false;
}
});
mMessageAge.setValue(String.valueOf(mAccount.getMaximumPolledMessageAge()));
mMessageAge.setSummary(mMessageAge.getEntry());
mMessageAge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mMessageAge.findIndexOfValue(summary);
mMessageAge.setSummary(mMessageAge.getEntries()[index]);
mMessageAge.setValue(summary);
return false;
}
});
}
mMessageSize = (ListPreference) findPreference(PREFERENCE_MESSAGE_SIZE);
@ -437,35 +433,9 @@ public class AccountSettings extends K9PreferenceActivity {
mAccountDefault.setChecked(
mAccount.equals(Preferences.getPreferences(this).getDefaultAccount()));
mAccountScrollButtons = (ListPreference) findPreference(PREFERENCE_HIDE_BUTTONS);
mAccountScrollButtons.setValue("" + mAccount.getScrollMessageViewButtons());
mAccountScrollButtons.setSummary(mAccountScrollButtons.getEntry());
mAccountScrollButtons.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mAccountScrollButtons.findIndexOfValue(summary);
mAccountScrollButtons.setSummary(mAccountScrollButtons.getEntries()[index]);
mAccountScrollButtons.setValue(summary);
return false;
}
});
mAccountEnableMoveButtons = (CheckBoxPreference) findPreference(PREFERENCE_ENABLE_MOVE_BUTTONS);
mAccountEnableMoveButtons.setChecked(mAccount.getEnableMoveButtons());
mAccountScrollMoveButtons = (ListPreference) findPreference(PREFERENCE_HIDE_MOVE_BUTTONS);
mAccountScrollMoveButtons.setValue("" + mAccount.getScrollMessageViewMoveButtons());
mAccountScrollMoveButtons.setSummary(mAccountScrollMoveButtons.getEntry());
mAccountScrollMoveButtons.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mAccountScrollMoveButtons.findIndexOfValue(summary);
mAccountScrollMoveButtons.setSummary(mAccountScrollMoveButtons.getEntries()[index]);
mAccountScrollMoveButtons.setValue(summary);
return false;
}
});
mAccountShowPictures = (ListPreference) findPreference(PREFERENCE_SHOW_PICTURES);
mAccountShowPictures.setValue("" + mAccount.getShowPictures());
mAccountShowPictures.setSummary(mAccountShowPictures.getEntry());
@ -535,18 +505,18 @@ public class AccountSettings extends K9PreferenceActivity {
return false;
}
});
mPushMode = (ListPreference) findPreference(PREFERENCE_PUSH_MODE);
mPushMode.setValue(mAccount.getFolderPushMode().name());
mPushMode.setSummary(mPushMode.getEntry());
mPushMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mPushMode.findIndexOfValue(summary);
mPushMode.setSummary(mPushMode.getEntries()[index]);
mPushMode.setValue(summary);
return false;
}
});
mPushMode = (ListPreference) findPreference(PREFERENCE_PUSH_MODE);
mPushMode.setValue(mAccount.getFolderPushMode().name());
mPushMode.setSummary(mPushMode.getEntry());
mPushMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
int index = mPushMode.findIndexOfValue(summary);
mPushMode.setSummary(mPushMode.getEntries()[index]);
mPushMode.setValue(summary);
return false;
}
});
} else {
PreferenceScreen incomingPrefs = (PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING);
incomingPrefs.removePreference( (PreferenceScreen) findPreference(PREFERENCE_SCREEN_PUSH_ADVANCED));
@ -755,11 +725,13 @@ Log.d("ASH", "Have set delete policy to " + mAccount.getDeletePolicy());
else
mAccount.setAutoExpandFolderName(reverseTranslateFolder(mAutoExpandFolder.getValue()));
mAccount.setArchiveFolderName(mArchiveFolder.getValue());
mAccount.setDraftsFolderName(mDraftsFolder.getValue());
mAccount.setSentFolderName(mSentFolder.getValue());
mAccount.setSpamFolderName(mSpamFolder.getValue());
mAccount.setTrashFolderName(mTrashFolder.getValue());
if (mIsMoveCapable) {
mAccount.setArchiveFolderName(mArchiveFolder.getValue());
mAccount.setDraftsFolderName(mDraftsFolder.getValue());
mAccount.setSentFolderName(mSentFolder.getValue());
mAccount.setSpamFolderName(mSpamFolder.getValue());
mAccount.setTrashFolderName(mTrashFolder.getValue());
}
if (mIsPushCapable) {
@ -768,8 +740,11 @@ Log.d("ASH", "Have set delete policy to " + mAccount.getDeletePolicy());
mAccount.setMaxPushFolders(Integer.parseInt(mMaxPushFolders.getValue()));
}
mAccount.setEnableMoveButtons(mAccountEnableMoveButtons.isChecked());
mAccount.setScrollMessageViewMoveButtons(Account.ScrollButtons.valueOf(mAccountScrollMoveButtons.getValue()));
if (!mIsMoveCapable) {
mAccount.setEnableMoveButtons(false);
} else {
mAccount.setEnableMoveButtons(mAccountEnableMoveButtons.isChecked());
}
boolean needsRefresh = mAccount.setAutomaticCheckIntervalMinutes(Integer.parseInt(mCheckFrequency.getValue()));
needsRefresh |= mAccount.setFolderSyncMode(Account.FolderMode.valueOf(mSyncMode.getValue()));
@ -787,24 +762,23 @@ Log.d("ASH", "Have set delete policy to " + mAccount.getDeletePolicy());
}
}
mAccount.setScrollMessageViewButtons(Account.ScrollButtons.valueOf(mAccountScrollButtons.getValue()));
mAccount.setShowPictures(Account.ShowPictures.valueOf(mAccountShowPictures.getValue()));
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));
}
@ -951,22 +925,33 @@ Log.d("ASH", "Have set delete policy to " + mAccount.getDeletePolicy());
mTrashFolder = (ListPreference)findPreference(PREFERENCE_TRASH_FOLDER);
mTrashFolder.setEnabled(false);
if (!mIsMoveCapable) {
PreferenceScreen foldersCategory =
(PreferenceScreen) findPreference(PREFERENCE_CATEGORY_FOLDERS);
foldersCategory.removePreference(mArchiveFolder);
foldersCategory.removePreference(mSpamFolder);
foldersCategory.removePreference(mDraftsFolder);
foldersCategory.removePreference(mSentFolder);
foldersCategory.removePreference(mTrashFolder);
}
}
@Override
protected void onPostExecute(Void res) {
initListPreference(mAutoExpandFolder, mAccount.getAutoExpandFolderName(), allFolderLabels, allFolderValues);
initListPreference(mArchiveFolder, mAccount.getArchiveFolderName(), allFolderLabels, allFolderValues);
initListPreference(mDraftsFolder, mAccount.getDraftsFolderName(), allFolderLabels, allFolderValues);
initListPreference(mSentFolder, mAccount.getSentFolderName(), allFolderLabels, allFolderValues);
initListPreference(mSpamFolder, mAccount.getSpamFolderName(), allFolderLabels, allFolderValues);
initListPreference(mTrashFolder, mAccount.getTrashFolderName(), allFolderLabels, allFolderValues);
mAutoExpandFolder.setEnabled(true);
mArchiveFolder.setEnabled(true);
mDraftsFolder.setEnabled(true);
mSentFolder.setEnabled(true);
mSpamFolder.setEnabled(true);
mTrashFolder.setEnabled(true);
if (mIsMoveCapable) {
initListPreference(mArchiveFolder, mAccount.getArchiveFolderName(), allFolderLabels, allFolderValues);
initListPreference(mDraftsFolder, mAccount.getDraftsFolderName(), allFolderLabels, allFolderValues);
initListPreference(mSentFolder, mAccount.getSentFolderName(), allFolderLabels, allFolderValues);
initListPreference(mSpamFolder, mAccount.getSpamFolderName(), allFolderLabels, allFolderValues);
initListPreference(mTrashFolder, mAccount.getTrashFolderName(), allFolderLabels, allFolderValues);
mArchiveFolder.setEnabled(true);
mSpamFolder.setEnabled(true);
mDraftsFolder.setEnabled(true);
mSentFolder.setEnabled(true);
mTrashFolder.setEnabled(true);
}
}
}
}

View File

@ -1727,9 +1727,7 @@ public class MessagingController implements Runnable {
* right now, attachments will be left for later.
*/
ArrayList<Part> viewables = new ArrayList<Part>();
ArrayList<Part> attachments = new ArrayList<Part>();
MimeUtility.collectParts(message, viewables, attachments);
Set<Part> viewables = MimeUtility.collectTextParts(message);
/*
* Now download the parts we're interested in storing.
@ -2943,9 +2941,7 @@ public class MessagingController implements Runnable {
try {
LocalStore localStore = account.getLocalStore();
ArrayList<Part> viewables = new ArrayList<Part>();
ArrayList<Part> attachments = new ArrayList<Part>();
MimeUtility.collectParts(message, viewables, attachments);
List<Part> attachments = MimeUtility.collectAttachments(message);
for (Part attachment : attachments) {
attachment.setBody(null);
}
@ -3349,6 +3345,36 @@ public class MessagingController implements Runnable {
put("getFolderUnread:" + account.getDescription() + ":" + folderName, l, unreadRunnable);
}
// ASH i seem to have deleted the four below isMoveCapable/isCopyCapable methods:
public boolean isMoveCapable(Message message) {
return !message.getUid().startsWith(K9.LOCAL_UID_PREFIX);
}/*
public boolean isCopyCapable(Message message) {
return isMoveCapable(message);
}*/
public boolean isMoveCapable(final Account account) {
try {
Store localStore = account.getLocalStore();
Store remoteStore = account.getRemoteStore();
return localStore.isMoveCapable() && remoteStore.isMoveCapable();
} catch (MessagingException me) {
Log.e(K9.LOG_TAG, "Exception while ascertaining move capability", me);
return false;
}
}/*
public boolean isCopyCapable(final Account account) {
try {
Store localStore = account.getLocalStore();
Store remoteStore = account.getRemoteStore();
return localStore.isCopyCapable() && remoteStore.isCopyCapable();
} catch (MessagingException me) {
Log.e(K9.LOG_TAG, "Exception while ascertaining copy capability", me);
return false;
}
}*/
public void moveMessages(final Account account, final String srcFolder, final Message[] messages, final String destFolder,
final MessagingListener listener) {
for (Message message : messages) {

View File

@ -125,19 +125,41 @@ public class HtmlConverter {
private static final int MAX_SMART_HTMLIFY_MESSAGE_LENGTH = 1024 * 256 ;
public static final String getHtmlHeader() {
return "<html><head/><body>";
}
public static final String getHtmlFooter() {
return "</body></html>";
}
/**
* Naively convert a text string into an HTML document. This method avoids using regular expressions on the entire
* message body to save memory.
* @param text Plain text string.
* Naively convert a text string into an HTML document.
*
* <p>
* This method avoids using regular expressions on the entire message body to save memory.
* </p>
*
* @param text
* Plain text string.
* @param useHtmlTag
* If {@code true} this method adds headers and footers to create a proper HTML
* document.
*
* @return HTML string.
*/
private static String simpleTextToHtml(String text) {
private static String simpleTextToHtml(String text, boolean useHtmlTag) {
// Encode HTML entities to make sure we don't display something evil.
text = TextUtils.htmlEncode(text);
StringReader reader = new StringReader(text);
StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);
buff.append("<html><head/><body>");
if (useHtmlTag) {
buff.append(getHtmlHeader());
}
buff.append(htmlifyMessageHeader());
int c;
try {
@ -159,25 +181,39 @@ public class HtmlConverter {
Log.e(K9.LOG_TAG, "Could not read string to convert text to HTML:", e);
}
buff.append("</body></html>");
buff.append(htmlifyMessageFooter());
if (useHtmlTag) {
buff.append(getHtmlFooter());
}
return buff.toString();
}
/**
* Convert a text string into an HTML document. Attempts to do smart replacement for large
* documents to prevent OOM errors. This method adds headers and footers to create a proper HTML
* document. To convert to a fragment, use {@link #textToHtmlFragment(String)}.
* @param text Plain text string.
* Convert a text string into an HTML document.
*
* <p>
* Attempts to do smart replacement for large documents to prevent OOM errors. This method
* optionally adds headers and footers to create a proper HTML document. To convert to a
* fragment, use {@link #textToHtmlFragment(String)}.
* </p>
*
* @param text
* Plain text string.
* @param useHtmlTag
* If {@code true} this method adds headers and footers to create a proper HTML
* document.
*
* @return HTML string.
*/
public static String textToHtml(String text) {
public static String textToHtml(String text, boolean useHtmlTag) {
// Our HTMLification code is somewhat memory intensive
// and was causing lots of OOM errors on the market
// if the message is big and plain text, just do
// a trivial htmlification
if (text.length() > MAX_SMART_HTMLIFY_MESSAGE_LENGTH) {
return simpleTextToHtml(text);
return simpleTextToHtml(text, useHtmlTag);
}
StringReader reader = new StringReader(text);
StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);
@ -221,11 +257,19 @@ public class HtmlConverter {
text = text.replaceAll("(?m)(\r\n|\n|\r){4,}", "\n\n");
StringBuffer sb = new StringBuffer(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);
sb.append("<html><head></head><body>");
if (useHtmlTag) {
sb.append(getHtmlHeader());
}
sb.append(htmlifyMessageHeader());
linkifyText(text, sb);
sb.append(htmlifyMessageFooter());
sb.append("</body></html>");
if (useHtmlTag) {
sb.append(getHtmlFooter());
}
text = sb.toString();
return text;

View File

@ -1,9 +1,14 @@
package com.fsck.k9.mail.internet;
import android.content.Context;
import android.util.Log;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.helper.HtmlConverter;
import com.fsck.k9.mail.*;
import com.fsck.k9.mail.Message.RecipientType;
import org.apache.commons.io.IOUtils;
import org.apache.james.mime4j.codec.Base64InputStream;
import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
@ -12,7 +17,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
@ -23,6 +32,9 @@ public class MimeUtility {
public static final String K9_SETTINGS_MIME_TYPE = "application/x-k9settings";
private static final String TEXT_DIVIDER =
"------------------------------------------------------------------------";
/*
* http://www.w3schools.com/media/media_mimeref.asp
* +
@ -1100,49 +1112,867 @@ public class MimeUtility {
return tempBody;
}
/**
* An unfortunately named method that makes decisions about a Part (usually a Message)
* as to which of it's children will be "viewable" and which will be attachments.
* The method recursively sorts the viewables and attachments into seperate
* lists for further processing.
* @param part
* @param viewables
* @param attachments
* @throws MessagingException
* Empty base class for the class hierarchy used by
* {@link MimeUtility#extractTextAndAttachments(Context, Message)}.
*
* @see Text
* @see Html
* @see MessageHeader
* @see Alternative
*/
public static void collectParts(Part part, ArrayList<Part> viewables,
ArrayList<Part> attachments) throws MessagingException {
/*
* If the part is Multipart but not alternative it's either mixed or
* something we don't know about, which means we treat it as mixed
* per the spec. We just process it's pieces recursively.
static abstract class Viewable { /* empty */ }
/**
* Class representing textual parts of a message that aren't marked as attachments.
*
* @see MimeUtility#isPartTextualBody(Part)
*/
static abstract class Textual extends Viewable {
private Part mPart;
public Textual(Part part) {
mPart = part;
}
public Part getPart() {
return mPart;
}
}
/**
* Class representing a {@code text/plain} part of a message.
*/
static class Text extends Textual {
public Text(Part part) {
super(part);
}
}
/**
* Class representing a {@code text/html} part of a message.
*/
static class Html extends Textual {
public Html(Part part) {
super(part);
}
}
/**
* Class representing a {@code message/rfc822} part of a message.
*
* <p>
* This is used to extract basic header information when the message contents are displayed
* inline.
* </p>
*/
static class MessageHeader extends Viewable {
private Part mContainerPart;
private Message mMessage;
public MessageHeader(Part containerPart, Message message) {
mContainerPart = containerPart;
mMessage = message;
}
public Part getContainerPart() {
return mContainerPart;
}
public Message getMessage() {
return mMessage;
}
}
/**
* Class representing a {@code multipart/alternative} part of a message.
*
* <p>
* Only relevant {@code text/plain} and {@code text/html} children are stored in this container
* class.
* </p>
*/
static class Alternative extends Viewable {
private List<Viewable> mText;
private List<Viewable> mHtml;
public Alternative(List<Viewable> text, List<Viewable> html) {
mText = text;
mHtml = html;
}
public List<Viewable> getText() {
return mText;
}
public List<Viewable> getHtml() {
return mHtml;
}
}
/**
* Store viewable text of a message as plain text and HTML, and the parts considered
* attachments.
*
* @see MimeUtility#extractTextAndAttachments(Context, Message)
*/
public static class ViewableContainer {
/**
* The viewable text of the message in plain text.
*/
if (part.getBody() instanceof Multipart) {
Multipart mp = (Multipart)part.getBody();
for (int i = 0; i < mp.getCount(); i++) {
collectParts(mp.getBodyPart(i), viewables, attachments);
public final String text;
/**
* The viewable text of the message in HTML.
*/
public final String html;
/**
* The parts of the message considered attachments (everything not viewable).
*/
public final List<Part> attachments;
ViewableContainer(String text, String html, List<Part> attachments) {
this.text = text;
this.html = html;
this.attachments = attachments;
}
}
/**
* Collect attachment parts of a message.
*
* @param message
* The message to collect the attachment parts from.
*
* @return A list of parts regarded as attachments.
*
* @throws MessagingException
* In case of an error.
*/
public static List<Part> collectAttachments(Message message)
throws MessagingException {
try {
List<Part> attachments = new ArrayList<Part>();
getViewables(message, attachments);
return attachments;
} catch (Exception e) {
throw new MessagingException("Couldn't collect attachment parts", e);
}
}
/**
* Collect the viewable textual parts of a message.
*
* @param message
* The message to extract the viewable parts from.
*
* @return A set of viewable parts of the message.
*
* @throws MessagingException
* In case of an error.
*/
public static Set<Part> collectTextParts(Message message)
throws MessagingException {
try {
List<Part> attachments = new ArrayList<Part>();
// Collect all viewable parts
List<Viewable> viewables = getViewables(message, attachments);
// Extract the Part references
return getParts(viewables);
} catch (Exception e) {
throw new MessagingException("Couldn't extract viewable parts", e);
}
}
/**
* Extract the viewable textual parts of a message and return the rest as attachments.
*
* @param context
* A {@link Context} instance that will be used to get localized strings.
* @param message
* The message to extract the text and attachments from.
*
* @return A {@link ViewableContainer} instance containing the textual parts of the message as
* plain text and HTML, and a list of message parts considered attachments.
*
* @throws MessagingException
* In case of an error.
*/
public static ViewableContainer extractTextAndAttachments(Context context, Message message)
throws MessagingException {
try {
List<Part> attachments = new ArrayList<Part>();
// Collect all viewable parts
List<Viewable> viewables = getViewables(message, attachments);
/*
* Convert the tree of viewable parts into text and HTML
*/
// Used to suppress the divider for the first viewable part
boolean hideDivider = true;
StringBuilder text = new StringBuilder();
StringBuilder html = new StringBuilder();
html.append(HtmlConverter.getHtmlHeader());
for (Viewable viewable : viewables) {
if (viewable instanceof Textual) {
// This is either a text/plain or text/html part. Fill the variables 'text' and
// 'html', converting between plain text and HTML as necessary.
text.append(buildText(viewable, !hideDivider));
html.append(buildHtml(viewable, !hideDivider));
hideDivider = false;
} else if (viewable instanceof MessageHeader) {
MessageHeader header = (MessageHeader) viewable;
Part containerPart = header.getContainerPart();
Message innerMessage = header.getMessage();
addTextDivider(text, containerPart, !hideDivider);
addMessageHeaderText(context, text, innerMessage);
addHtmlDivider(html, containerPart, !hideDivider);
addMessageHeaderHtml(context, html, innerMessage);
hideDivider = true;
} else if (viewable instanceof Alternative) {
// Handle multipart/alternative contents
Alternative alternative = (Alternative) viewable;
/*
* We made sure at least one of text/plain or text/html is present when
* creating the Alternative object. If one part is not present we convert the
* other one to make sure 'text' and 'html' always contain the same text.
*/
List<Viewable> textAlternative = alternative.getText().isEmpty() ?
alternative.getHtml() : alternative.getText();
List<Viewable> htmlAlternative = alternative.getHtml().isEmpty() ?
alternative.getText() : alternative.getHtml();
// Fill the 'text' variable
boolean divider = !hideDivider;
for (Viewable textViewable : textAlternative) {
text.append(buildText(textViewable, divider));
divider = true;
}
// Fill the 'html' variable
divider = !hideDivider;
for (Viewable htmlViewable : htmlAlternative) {
html.append(buildHtml(htmlViewable, divider));
divider = true;
}
hideDivider = false;
}
}
html.append(HtmlConverter.getHtmlFooter());
return new ViewableContainer(text.toString(), html.toString(), attachments);
} catch (Exception e) {
throw new MessagingException("Couldn't extract viewable parts", e);
}
/*
* If the part is an embedded message we just continue to process
* it, pulling any viewables or attachments into the running list.
*/
else if (part.getBody() instanceof Message) {
Message message = (Message)part.getBody();
collectParts(message, viewables, attachments);
}
/*
* If the part is HTML and it got this far it's part of a mixed (et
* al) and should be rendered inline.
*/
else if (isPartTextualBody(part)) {
viewables.add(part);
}
/**
* Traverse the MIME tree of a message an extract viewable parts.
*
* @param part
* The message part to start from.
* @param attachments
* A list that will receive the parts that are considered attachments.
*
* @return A list of {@link Viewable}s.
*
* @throws MessagingException
* In case of an error.
*/
public static List<Viewable> getViewables(Part part, List<Part> attachments) throws MessagingException {
List<Viewable> viewables = new ArrayList<Viewable>();
Body body = part.getBody();
if (body instanceof Multipart) {
Multipart multipart = (Multipart) body;
if (part.getMimeType().equalsIgnoreCase("multipart/alternative")) {
/*
* For multipart/alternative parts we try to find a text/plain and a text/html
* child. Everything else we find is put into 'attachments'.
*/
List<Viewable> text = findTextPart(multipart, true);
Set<Part> knownTextParts = getParts(text);
List<Viewable> html = findHtmlPart(multipart, knownTextParts, attachments, true);
if (!text.isEmpty() || !html.isEmpty()) {
Alternative alternative = new Alternative(text, html);
viewables.add(alternative);
}
} else {
// For all other multipart parts we recurse to grab all viewable children.
int childCount = multipart.getCount();
for (int i = 0; i < childCount; i++) {
Part bodyPart = multipart.getBodyPart(i);
viewables.addAll(getViewables(bodyPart, attachments));
}
}
} else if (body instanceof Message &&
!("attachment".equalsIgnoreCase(getContentDisposition(part)))) {
/*
* We only care about message/rfc822 parts whose Content-Disposition header has a value
* other than "attachment".
*/
Message message = (Message) body;
// We add the Message object so we can extract the filename later.
viewables.add(new MessageHeader(part, message));
// Recurse to grab all viewable parts and attachments from that message.
viewables.addAll(getViewables(message, attachments));
} else if (isPartTextualBody(part)) {
/*
* Save text/plain and text/html
*/
String mimeType = part.getMimeType();
if (mimeType.equalsIgnoreCase("text/plain")) {
Text text = new Text(part);
viewables.add(text);
} else {
Html html = new Html(part);
viewables.add(html);
}
} else {
// Everything else is treated as attachment.
attachments.add(part);
}
return viewables;
}
/**
* Search the children of a {@link Multipart} for {@code text/plain} parts.
*
* @param multipart
* The {@code Multipart} to search through.
* @param directChild
* If {@code true}, this method will return after the first {@code text/plain} was
* found.
*
* @return A list of {@link Text} viewables.
*
* @throws MessagingException
* In case of an error.
*/
private static List<Viewable> findTextPart(Multipart multipart, boolean directChild)
throws MessagingException {
List<Viewable> viewables = new ArrayList<Viewable>();
int childCount = multipart.getCount();
for (int i = 0; i < childCount; i++) {
Part part = multipart.getBodyPart(i);
Body body = part.getBody();
if (body instanceof Multipart) {
Multipart innerMultipart = (Multipart) body;
/*
* Recurse to find text parts. Since this is a multipart that is a child of a
* multipart/alternative we don't want to stop after the first text/plain part
* we find. This will allow to get all text parts for constructions like this:
*
* 1. multipart/alternative
* 1.1. multipart/mixed
* 1.1.1. text/plain
* 1.1.2. text/plain
* 1.2. text/html
*/
List<Viewable> textViewables = findTextPart(innerMultipart, false);
if (!textViewables.isEmpty()) {
viewables.addAll(textViewables);
if (directChild) {
break;
}
}
} else if (isPartTextualBody(part) && part.getMimeType().equalsIgnoreCase("text/plain")) {
Text text = new Text(part);
viewables.add(text);
if (directChild) {
break;
}
}
}
return viewables;
}
/**
* Search the children of a {@link Multipart} for {@code text/html} parts.
*
* <p>
* Every part that is not a {@code text/html} we want to display, we add to 'attachments'.
* </p>
*
* @param multipart
* The {@code Multipart} to search through.
* @param knownTextParts
* A set of {@code text/plain} parts that shouldn't be added to 'attachments'.
* @param attachments
* A list that will receive the parts that are considered attachments.
* @param directChild
* If {@code true}, this method will add all {@code text/html} parts except the first
* found to 'attachments'.
*
* @return A list of {@link Text} viewables.
*
* @throws MessagingException
* In case of an error.
*/
private static List<Viewable> findHtmlPart(Multipart multipart, Set<Part> knownTextParts,
List<Part> attachments, boolean directChild) throws MessagingException {
List<Viewable> viewables = new ArrayList<Viewable>();
boolean partFound = false;
int childCount = multipart.getCount();
for (int i = 0; i < childCount; i++) {
Part part = multipart.getBodyPart(i);
Body body = part.getBody();
if (body instanceof Multipart) {
Multipart innerMultipart = (Multipart) body;
if (directChild && partFound) {
// We already found our text/html part. Now we're only looking for attachments.
findAttachments(innerMultipart, knownTextParts, attachments);
} else {
/*
* Recurse to find HTML parts. Since this is a multipart that is a child of a
* multipart/alternative we don't want to stop after the first text/html part
* we find. This will allow to get all text parts for constructions like this:
*
* 1. multipart/alternative
* 1.1. text/plain
* 1.2. multipart/mixed
* 1.2.1. text/html
* 1.2.2. text/html
* 1.3. image/jpeg
*/
List<Viewable> htmlViewables = findHtmlPart(innerMultipart, knownTextParts,
attachments, false);
if (!htmlViewables.isEmpty()) {
partFound = true;
viewables.addAll(htmlViewables);
}
}
} else if (!(directChild && partFound) && isPartTextualBody(part) &&
part.getMimeType().equalsIgnoreCase("text/html")) {
Html html = new Html(part);
viewables.add(html);
partFound = true;
} else if (!knownTextParts.contains(part)) {
// Only add this part as attachment if it's not a viewable text/plain part found
// earlier.
attachments.add(part);
}
}
return viewables;
}
/**
* Build a set of message parts for fast lookups.
*
* @param viewables
* A list of {@link Viewable}s containing references to the message parts to include in
* the set.
*
* @return The set of viewable {@code Part}s.
*
* @see MimeUtility#findHtmlPart(Multipart, Set, List, boolean)
* @see MimeUtility#findAttachments(Multipart, Set, List)
*/
private static Set<Part> getParts(List<Viewable> viewables) {
Set<Part> parts = new HashSet<Part>();
for (Viewable viewable : viewables) {
if (viewable instanceof Textual) {
parts.add(((Textual) viewable).getPart());
} else if (viewable instanceof Alternative) {
Alternative alternative = (Alternative) viewable;
parts.addAll(getParts(alternative.getText()));
parts.addAll(getParts(alternative.getHtml()));
}
}
return parts;
}
/**
* Traverse the MIME tree and add everything that's not a known text part to 'attachments'.
*
* @param multipart
* The {@link Multipart} to start from.
* @param knownTextParts
* A set of known text parts we don't want to end up in 'attachments'.
* @param attachments
* A list that will receive the parts that are considered attachments.
*/
private static void findAttachments(Multipart multipart, Set<Part> knownTextParts,
List<Part> attachments) {
int childCount = multipart.getCount();
for (int i = 0; i < childCount; i++) {
Part part = multipart.getBodyPart(i);
Body body = part.getBody();
if (body instanceof Multipart) {
Multipart innerMultipart = (Multipart) body;
findAttachments(innerMultipart, knownTextParts, attachments);
} else if (!knownTextParts.contains(part)) {
attachments.add(part);
}
}
}
/**
* Extract important header values from a message to display inline (plain text version).
*
* @param context
* A {@link Context} instance that will be used to get localized strings.
* @param text
* The {@link StringBuilder} that will receive the (plain text) output.
* @param message
* The message to extract the header values from.
*
* @throws MessagingException
* In case of an error.
*/
private static void addMessageHeaderText(Context context, StringBuilder text, Message message)
throws MessagingException {
// From: <sender>
Address[] from = message.getFrom();
if (from != null && from.length > 0) {
text.append(context.getString(R.string.message_compose_quote_header_from));
text.append(' ');
text.append(Address.toString(from));
text.append("\n");
}
// To: <recipients>
Address[] to = message.getRecipients(RecipientType.TO);
if (to != null && to.length > 0) {
text.append(context.getString(R.string.message_compose_quote_header_to));
text.append(' ');
text.append(Address.toString(to));
text.append("\n");
}
// Cc: <recipients>
Address[] cc = message.getRecipients(RecipientType.CC);
if (cc != null && cc.length > 0) {
text.append(context.getString(R.string.message_compose_quote_header_cc));
text.append(' ');
text.append(Address.toString(cc));
text.append("\n");
}
// Date: <date>
Date date = message.getSentDate();
if (date != null) {
text.append(context.getString(R.string.message_compose_quote_header_send_date));
text.append(' ');
text.append(date.toString());
text.append("\n");
}
// Subject: <subject>
String subject = message.getSubject();
text.append(context.getString(R.string.message_compose_quote_header_subject));
text.append(' ');
if (subject == null) {
text.append(context.getString(R.string.general_no_subject));
} else {
text.append(subject);
}
text.append("\n\n");
}
/**
* Extract important header values from a message to display inline (HTML version).
*
* @param context
* A {@link Context} instance that will be used to get localized strings.
* @param html
* The {@link StringBuilder} that will receive the (HTML) output.
* @param message
* The message to extract the header values from.
*
* @throws MessagingException
* In case of an error.
*/
private static void addMessageHeaderHtml(Context context, StringBuilder html, Message message)
throws MessagingException {
html.append("<table style=\"border: 0\">");
// From: <sender>
Address[] from = message.getFrom();
if (from != null && from.length > 0) {
addTableRow(html, context.getString(R.string.message_compose_quote_header_from),
Address.toString(from));
}
// To: <recipients>
Address[] to = message.getRecipients(RecipientType.TO);
if (to != null && to.length > 0) {
addTableRow(html, context.getString(R.string.message_compose_quote_header_to),
Address.toString(to));
}
// Cc: <recipients>
Address[] cc = message.getRecipients(RecipientType.CC);
if (cc != null && cc.length > 0) {
addTableRow(html, context.getString(R.string.message_compose_quote_header_cc),
Address.toString(cc));
}
// Date: <date>
Date date = message.getSentDate();
if (date != null) {
addTableRow(html, context.getString(R.string.message_compose_quote_header_send_date),
date.toString());
}
// Subject: <subject>
String subject = message.getSubject();
addTableRow(html, context.getString(R.string.message_compose_quote_header_subject),
(subject == null) ? context.getString(R.string.general_no_subject) : subject);
html.append("</table>");
}
/**
* Output an HTML table two column row with some hardcoded style.
*
* @param html
* The {@link StringBuilder} that will receive the output.
* @param header
* The string to be put in the {@code TH} element.
* @param value
* The string to be put in the {@code TD} element.
*/
private static void addTableRow(StringBuilder html, String header, String value) {
html.append("<tr><th style=\"text-align: left; vertical-align: top;\">");
html.append(header);
html.append("</th>");
html.append("<td>");
html.append(value);
html.append("</td></tr>");
}
/**
* Use the contents of a {@link Viewable} to create the plain text to be displayed.
*
* <p>
* This will use {@link HtmlConverter#htmlToText(String)} to convert HTML parts to plain text
* if necessary.
* </p>
*
* @param viewable
* The viewable part to build the text from.
* @param prependDivider
* {@code true}, if the text divider should be inserted as first element.
* {@code false}, otherwise.
*
* @return The contents of the supplied viewable instance as plain text.
*/
private static StringBuilder buildText(Viewable viewable, boolean prependDivider)
{
StringBuilder text = new StringBuilder();
if (viewable instanceof Textual) {
Part part = ((Textual)viewable).getPart();
addTextDivider(text, part, prependDivider);
String t = getTextFromPart(part);
if (t == null) {
t = "";
} else if (viewable instanceof Html) {
t = HtmlConverter.htmlToText(t);
}
text.append(t);
} else if (viewable instanceof Alternative) {
// That's odd - an Alternative as child of an Alternative; go ahead and try to use the
// text/plain child; fall-back to the text/html part.
Alternative alternative = (Alternative) viewable;
List<Viewable> textAlternative = alternative.getText().isEmpty() ?
alternative.getHtml() : alternative.getText();
boolean divider = prependDivider;
for (Viewable textViewable : textAlternative) {
text.append(buildText(textViewable, divider));
divider = true;
}
}
return text;
}
/*
* Some constants that are used by addTextDivider() below.
*/
private static final int TEXT_DIVIDER_LENGTH = TEXT_DIVIDER.length();
private static final String FILENAME_PREFIX = "----- ";
private static final int FILENAME_PREFIX_LENGTH = FILENAME_PREFIX.length();
private static final String FILENAME_SUFFIX = " ";
private static final int FILENAME_SUFFIX_LENGTH = FILENAME_SUFFIX.length();
/**
* Add a plain text divider between two plain text message parts.
*
* @param text
* The {@link StringBuilder} to append the divider to.
* @param part
* The message part that will follow after the divider. This is used to extract the
* part's name.
* @param prependDivider
* {@code true}, if the divider should be appended. {@code false}, otherwise.
*/
private static void addTextDivider(StringBuilder text, Part part, boolean prependDivider) {
if (prependDivider) {
String filename = getPartName(part);
text.append("\n\n");
int len = filename.length();
if (len > 0) {
if (len > TEXT_DIVIDER_LENGTH - FILENAME_PREFIX_LENGTH - FILENAME_SUFFIX_LENGTH) {
filename = filename.substring(0, TEXT_DIVIDER_LENGTH - FILENAME_PREFIX_LENGTH -
FILENAME_SUFFIX_LENGTH - 3) + "...";
}
text.append(FILENAME_PREFIX);
text.append(filename);
text.append(FILENAME_SUFFIX);
text.append(TEXT_DIVIDER.substring(0, TEXT_DIVIDER_LENGTH -
FILENAME_PREFIX_LENGTH - filename.length() - FILENAME_SUFFIX_LENGTH));
} else {
text.append(TEXT_DIVIDER);
}
text.append("\n\n");
}
}
/**
* Use the contents of a {@link Viewable} to create the HTML to be displayed.
*
* <p>
* This will use {@link HtmlConverter#textToHtml(String, boolean)} to convert plain text parts
* to HTML if necessary.
* </p>
*
* @param viewable
* The viewable part to build the HTML from.
* @param prependDivider
* {@code true}, if the HTML divider should be inserted as first element.
* {@code false}, otherwise.
*
* @return The contents of the supplied viewable instance as HTML.
*/
private static StringBuilder buildHtml(Viewable viewable, boolean prependDivider)
{
StringBuilder html = new StringBuilder();
if (viewable instanceof Textual) {
Part part = ((Textual)viewable).getPart();
addHtmlDivider(html, part, prependDivider);
String t = getTextFromPart(part);
if (t == null) {
t = "";
} else if (viewable instanceof Text) {
t = HtmlConverter.textToHtml(t, false);
}
html.append(t);
} else if (viewable instanceof Alternative) {
// That's odd - an Alternative as child of an Alternative; go ahead and try to use the
// text/html child; fall-back to the text/plain part.
Alternative alternative = (Alternative) viewable;
List<Viewable> htmlAlternative = alternative.getHtml().isEmpty() ?
alternative.getText() : alternative.getHtml();
boolean divider = prependDivider;
for (Viewable htmlViewable : htmlAlternative) {
html.append(buildHtml(htmlViewable, divider));
divider = true;
}
}
return html;
}
/**
* Add an HTML divider between two HTML message parts.
*
* @param html
* The {@link StringBuilder} to append the divider to.
* @param part
* The message part that will follow after the divider. This is used to extract the
* part's name.
* @param prependDivider
* {@code true}, if the divider should be appended. {@code false}, otherwise.
*/
private static void addHtmlDivider(StringBuilder html, Part part, boolean prependDivider) {
if (prependDivider) {
String filename = getPartName(part);
html.append("<p style=\"margin-top: 2.5em; margin-bottom: 1em; border-bottom: 1px solid #000\">");
html.append(filename);
html.append("</p>");
}
}
/**
* Get the name of the message part.
*
* @param part
* The part to get the name for.
*
* @return The (file)name of the part if available. An empty string, otherwise.
*/
private static String getPartName(Part part) {
try {
String disposition = part.getDisposition();
if (disposition != null) {
String name = MimeUtility.getHeaderParameter(disposition, "filename");
return (name == null) ? "" : name;
}
}
catch (MessagingException e) { /* ignore */ }
return "";
}
/**
* Get the value of the {@code Content-Disposition} header.
*
* @param part
* The message part to read the header from.
*
* @return The value of the {@code Content-Disposition} header if available. {@code null},
* otherwise.
*/
private static String getContentDisposition(Part part) {
try {
String disposition = part.getDisposition();
if (disposition != null) {
return MimeUtility.getHeaderParameter(disposition, null);
}
}
catch (MessagingException e) { /* ignore */ }
return null;
}
public static Boolean isPartTextualBody(Part part) throws MessagingException {
String disposition = part.getDisposition();

View File

@ -2000,7 +2000,7 @@ public class ImapStore extends Store {
List<ImapResponse> responses =
executeSimpleCommand(
String.format("UID SEARCH HEADER MESSAGE-ID %s", messageId));
String.format("UID SEARCH HEADER MESSAGE-ID %s", encodeString(messageId)));
for (ImapResponse response1 : responses) {
if (response1.mTag == null && ImapResponseParser.equalsIgnoreCase(response1.get(0), "SEARCH")
&& response1.size() > 1) {

View File

@ -56,6 +56,7 @@ import com.fsck.k9.mail.internet.MimeHeader;
import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.internet.MimeMultipart;
import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.internet.MimeUtility.ViewableContainer;
import com.fsck.k9.mail.internet.TextBody;
import com.fsck.k9.mail.store.LockableDatabase.DbCallback;
import com.fsck.k9.mail.store.LockableDatabase.WrappedException;
@ -2291,45 +2292,14 @@ Log.v("ASH", mAccount.getDescription() + ":" + name + " is " + (localOnly == 1 ?
deleteAttachments(message.getUid());
}
ArrayList<Part> viewables = new ArrayList<Part>();
ArrayList<Part> attachments = new ArrayList<Part>();
MimeUtility.collectParts(message, viewables, attachments);
ViewableContainer container =
MimeUtility.extractTextAndAttachments(mApplication, message);
StringBuilder sbHtml = new StringBuilder();
StringBuilder sbText = new StringBuilder();
for (Part viewable : viewables) {
try {
String text = MimeUtility.getTextFromPart(viewable);
List<Part> attachments = container.attachments;
String text = container.text;
String html = HtmlConverter.convertEmoji2Img(container.html);
/*
* Small hack to make sure the string "null" doesn't end up
* in one of the StringBuilders.
*/
if (text == null) {
text = "";
}
/*
* Anything with MIME type text/html will be stored as such. Anything
* else will be stored as text/plain.
*/
if (viewable.getMimeType().equalsIgnoreCase("text/html")) {
sbHtml.append(text);
} else {
sbText.append(text);
}
} catch (Exception e) {
throw new MessagingException("Unable to get text for message part", e);
}
}
String text = sbText.toString();
String html = markupContent(text, sbHtml.toString());
String preview = calculateContentPreview(text);
// If we couldn't generate a reasonable preview from the text part, try doing it with the HTML part.
if (preview == null || preview.length() == 0) {
preview = calculateContentPreview(HtmlConverter.htmlToText(html));
}
try {
ContentValues cv = new ContentValues();
@ -2407,49 +2377,17 @@ Log.v("ASH", mAccount.getDescription() + ":" + name + " is " + (localOnly == 1 ?
@Override
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
try {
ArrayList<Part> viewables = new ArrayList<Part>();
ArrayList<Part> attachments = new ArrayList<Part>();
message.buildMimeRepresentation();
MimeUtility.collectParts(message, viewables, attachments);
ViewableContainer container =
MimeUtility.extractTextAndAttachments(mApplication, message);
StringBuilder sbHtml = new StringBuilder();
StringBuilder sbText = new StringBuilder();
for (int i = 0, count = viewables.size(); i < count; i++) {
Part viewable = viewables.get(i);
try {
String text = MimeUtility.getTextFromPart(viewable);
List<Part> attachments = container.attachments;
String text = container.text;
String html = HtmlConverter.convertEmoji2Img(container.html);
/*
* Small hack to make sure the string "null" doesn't end up
* in one of the StringBuilders.
*/
if (text == null) {
text = "";
}
/*
* Anything with MIME type text/html will be stored as such. Anything
* else will be stored as text/plain.
*/
if (viewable.getMimeType().equalsIgnoreCase("text/html")) {
sbHtml.append(text);
} else {
sbText.append(text);
}
} catch (Exception e) {
throw new MessagingException("Unable to get text for message part", e);
}
}
String text = sbText.toString();
String html = markupContent(text, sbHtml.toString());
String preview = calculateContentPreview(text);
// If we couldn't generate a reasonable preview from the text part, try doing it with the HTML part.
if (preview == null || preview.length() == 0) {
preview = calculateContentPreview(HtmlConverter.htmlToText(html));
}
try {
db.execSQL("UPDATE messages SET "
+ "uid = ?, subject = ?, sender_list = ?, date = ?, flags = ?, "
@ -2583,6 +2521,18 @@ Log.v("ASH", mAccount.getDescription() + ":" + name + " is " + (localOnly == 1 ?
Body body = attachment.getBody();
if (body instanceof LocalAttachmentBody) {
contentUri = ((LocalAttachmentBody) body).getContentUri();
} else if (body instanceof Message) {
// It's a message, so use Message.writeTo() to output the
// message including all children.
Message message = (Message) body;
tempAttachmentFile = File.createTempFile("att", null, attachmentDirectory);
FileOutputStream out = new FileOutputStream(tempAttachmentFile);
try {
message.writeTo(out);
} finally {
out.close();
}
size = (int) (tempAttachmentFile.length() & 0x7FFFFFFFL);
} else {
/*
* If the attachment has a body we're expected to save it into the local store
@ -2997,17 +2947,6 @@ Log.v("ASH", mAccount.getDescription() + ":" + name + " is " + (localOnly == 1 ?
}
public String markupContent(String text, String html) {
if (text.length() > 0 && html.length() == 0) {
html = HtmlConverter.textToHtml(text);
}
html = HtmlConverter.convertEmoji2Img(html);
return html;
}
@Override
public boolean isInTopGroup() {
return mInTopGroup;

View File

@ -12,7 +12,6 @@ import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.Account.FolderMode;
import com.fsck.k9.Account.ScrollButtons;
import com.fsck.k9.crypto.Apg;
import com.fsck.k9.mail.store.StorageManager;
import com.fsck.k9.preferences.Settings.*;
@ -82,12 +81,6 @@ public class AccountSettings {
s.put("goToUnreadMessageSearch", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("hideButtonsEnum", Settings.versions(
new V(1, new EnumSetting(ScrollButtons.class, ScrollButtons.NEVER))
));
s.put("hideMoveButtonsEnum", Settings.versions(
new V(1, new EnumSetting(ScrollButtons.class, ScrollButtons.NEVER))
));
s.put("idleRefreshMinutes", Settings.versions(
new V(1, new IntegerResourceSetting(24, R.array.idle_refresh_period_values))
));

View File

@ -35,7 +35,7 @@ public class Settings {
*
* @see SettingsExporter
*/
public static final int VERSION = 5;
public static final int VERSION = 6;
public static Map<String, Object> validate(int version, Map<String,
TreeMap<Integer, SettingsDescription>> settings,

View File

@ -2,6 +2,8 @@ package com.fsck.k9.view;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
@ -10,7 +12,10 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -25,14 +30,14 @@ import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.store.LocalStore;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.text.DateFormat;
public class MessageHeader extends LinearLayout {
public class MessageHeader extends ScrollView implements OnClickListener {
private Context mContext;
private TextView mFromView;
private TextView mDateView;
@ -44,16 +49,18 @@ public class MessageHeader extends LinearLayout {
private DateFormat mTimeFormat;
private View mChip;
private View mChip2;
private CheckBox mFlagged;
private LinearLayout mToContainerView;
private LinearLayout mCcContainerView;
private TextView mAdditionalHeadersView;
private View mAttachmentIcon;
private View mAnsweredIcon;
private Message mMessage;
private Account mAccount;
private FontSizes mFontSizes = K9.getFontSizes();
private Contacts mContacts;
private ImageView mShowAdditionalHeadersIcon;
private SavedState mSavedState;
/**
* Pair class is only available since API Level 5, so we need
@ -78,7 +85,6 @@ public class MessageHeader extends LinearLayout {
}
private void initializeLayout() {
mAttachmentIcon = findViewById(R.id.attachment);
mAnsweredIcon = findViewById(R.id.answered);
mFromView = (TextView) findViewById(R.id.from);
mToView = (TextView) findViewById(R.id.to);
@ -88,16 +94,19 @@ public class MessageHeader extends LinearLayout {
mSubjectView = (TextView) findViewById(R.id.subject);
mAdditionalHeadersView = (TextView) findViewById(R.id.additional_headers_view);
mChip = findViewById(R.id.chip);
mChip2 = findViewById(R.id.chip2);
mDateView = (TextView) findViewById(R.id.date);
mTimeView = (TextView) findViewById(R.id.time);
mFlagged = (CheckBox) findViewById(R.id.flagged);
mShowAdditionalHeadersIcon = (ImageView) findViewById(R.id.show_additional_headers_icon);
mSubjectView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewSubject());
mTimeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTime());
mDateView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewDate());
mAdditionalHeadersView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewAdditionalHeaders());
mAdditionalHeadersView.setVisibility(View.GONE);
mAttachmentIcon.setVisibility(View.GONE);
hideAdditionalHeaders();
mAnsweredIcon.setVisibility(View.GONE);
mFromView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewSender());
mToView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTo());
@ -105,39 +114,45 @@ public class MessageHeader extends LinearLayout {
((TextView) findViewById(R.id.to_label)).setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewTo());
((TextView) findViewById(R.id.cc_label)).setTextSize(TypedValue.COMPLEX_UNIT_SP, mFontSizes.getMessageViewCC());
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onShowAdditionalHeaders();
}
});
findViewById(R.id.show_additional_headers_area).setOnClickListener(this);
mFromView.setOnClickListener(this);
}
mFromView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mMessage != null) {
try {
final Address senderEmail = mMessage.getFrom()[0];
mContacts.createContact(senderEmail);
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Couldn't create contact", e);
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.show_additional_headers_area: {
onShowAdditionalHeaders();
break;
}
});
case R.id.from: {
onAddSenderToContacts();
break;
}
}
}
private void onAddSenderToContacts() {
if (mMessage != null) {
try {
final Address senderEmail = mMessage.getFrom()[0];
mContacts.createContact(senderEmail);
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Couldn't create contact", e);
}
}
}
public void setOnFlagListener(OnClickListener listener) {
if (mFlagged == null)
return;
mFlagged.setOnClickListener(listener);
}
public boolean additionalHeadersVisible() {
if (mAdditionalHeadersView != null && mAdditionalHeadersView.getVisibility() == View.VISIBLE) {
return true;
} else {
return false;
}
return (mAdditionalHeadersView != null &&
mAdditionalHeadersView.getVisibility() == View.VISIBLE);
}
/**
@ -147,7 +162,7 @@ public class MessageHeader extends LinearLayout {
private void hideAdditionalHeaders() {
mAdditionalHeadersView.setVisibility(View.GONE);
mAdditionalHeadersView.setText("");
mShowAdditionalHeadersIcon.setImageResource(R.drawable.show_more);
}
@ -166,6 +181,7 @@ public class MessageHeader extends LinearLayout {
// Show the additional headers that we have got.
populateAdditionalHeadersView(additionalHeaders);
mAdditionalHeadersView.setVisibility(View.VISIBLE);
mShowAdditionalHeadersIcon.setImageResource(R.drawable.show_less);
}
if (!allHeadersDownloaded) {
/*
@ -229,14 +245,25 @@ public class MessageHeader extends LinearLayout {
mToView.setText(to);
mCcContainerView.setVisibility((cc != null && cc.length() > 0) ? View.VISIBLE : View.GONE);
mCcView.setText(cc);
mAttachmentIcon.setVisibility(((LocalStore.LocalMessage) message).hasAttachments() ? View.VISIBLE : View.GONE);
mAnsweredIcon.setVisibility(message.isSet(Flag.ANSWERED) ? View.VISIBLE : View.GONE);
mFlagged.setChecked(message.isSet(Flag.FLAGGED));
mChip.setBackgroundDrawable(mAccount.generateColorChip().drawable());
mChip.getBackground().setAlpha(!message.isSet(Flag.SEEN) ? 255 : 127);
int chipColor = mAccount.getChipColor();
int chipColorAlpha = (!message.isSet(Flag.SEEN)) ? 255 : 127;
mChip.setBackgroundColor(chipColor);
mChip.getBackground().setAlpha(chipColorAlpha);
mChip2.setBackgroundColor(chipColor);
mChip2.getBackground().setAlpha(chipColorAlpha);
setVisibility(View.VISIBLE);
if (mAdditionalHeadersView.getVisibility() == View.VISIBLE) {
showAdditionalHeaders();
if (mSavedState != null) {
if (mSavedState.additionalHeadersVisible) {
showAdditionalHeaders();
}
mSavedState = null;
} else {
hideAdditionalHeaders();
}
}
@ -296,4 +323,61 @@ public class MessageHeader extends LinearLayout {
mAdditionalHeadersView.setText(sb);
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.additionalHeadersVisible = additionalHeadersVisible();
return savedState;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if(!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState savedState = (SavedState)state;
super.onRestoreInstanceState(savedState.getSuperState());
mSavedState = savedState;
}
static class SavedState extends BaseSavedState {
boolean additionalHeadersVisible;
@SuppressWarnings("hiding")
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.additionalHeadersVisible = (in.readInt() != 0);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt((this.additionalHeadersVisible) ? 1 : 0);
}
}
}

View File

@ -1,25 +1,20 @@
package com.fsck.k9.view;
import android.content.Context;
import android.graphics.Picture;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Toast;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.controller.MessagingListener;
import java.lang.reflect.Method;
import java.util.Set;
public class MessageWebView extends WebView {
// Store a reference to the listeners in MessagingController. We can't fetch it directly since
// we don't know the application name.
private Set<MessagingListener> mListeners = null;
/**
* We use WebSettings.getBlockNetworkLoads() to prevent the WebView that displays email
@ -75,7 +70,7 @@ public class MessageWebView extends WebView {
this.setVerticalScrollBarEnabled(true);
this.setVerticalScrollbarOverlay(true);
this.setScrollBarStyle(SCROLLBARS_INSIDE_OVERLAY);
this.setLongClickable(true);
final WebSettings webSettings = this.getSettings();
@ -97,22 +92,16 @@ public class MessageWebView extends WebView {
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
}
if (Integer.parseInt(Build.VERSION.SDK) >= 9 ) {
setOverScrollMode(OVER_SCROLL_NEVER);
}
webSettings.setTextSize(K9.getFontSizes().getMessageViewContent());
// Disable network images by default. This is overridden by preferences.
blockNetworkData(true);
// Listen for when the screen has finished drawing.
setPictureListener(new PictureListener() {
@Override
public void onNewPicture(WebView webView, Picture picture) {
if (mListeners != null) {
for (MessagingListener l : mListeners) {
l.messageViewFinished();
}
}
}
});
}
/*
@ -132,7 +121,15 @@ public class MessageWebView extends WebView {
}
}
public void setListeners(final Set<MessagingListener> listeners) {
this.mListeners = listeners;
public void wrapSetTitleBar(final View title) {
try {
Class<?> webViewClass = Class.forName("android.webkit.WebView");
Method setEmbeddedTitleBar = webViewClass.getMethod("setEmbeddedTitleBar", View.class);
setEmbeddedTitleBar.invoke(this, title);
}
catch (Exception e) {
Log.v(K9.LOG_TAG, "failed to find the setEmbeddedTitleBar method",e);
}
}
}

View File

@ -7,16 +7,20 @@ import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.controller.MessagingController;
import com.fsck.k9.controller.MessagingListener;
import com.fsck.k9.crypto.CryptoProvider;
@ -24,49 +28,67 @@ import com.fsck.k9.crypto.PgpData;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.*;
import com.fsck.k9.mail.internet.MimeHeader;
import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.store.LocalStore;
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
import java.util.List;
import java.util.Set;
/**
*/
public class SingleMessageView extends LinearLayout {
public class SingleMessageView extends LinearLayout implements OnClickListener {
private boolean mScreenReaderEnabled;
private MessageCryptoView mCryptoView;
private MessageWebView mMessageContentView;
private AccessibleWebView mAccessibleMessageContentView;
private MessageHeader mHeaderContainer;
private LinearLayout mAttachments;
private View mShowPicturesSection;
private Button mShowHiddenAttachments;
private LinearLayout mHiddenAttachments;
private View mShowPicturesAction;
private View mShowMessageAction;
private View mShowAttachmentsAction;
private boolean mShowPictures;
private boolean mHasAttachments;
private Button mDownloadRemainder;
private LayoutInflater mInflater;
private Contacts mContacts;
private AttachmentView.AttachmentFileDownloadCallback attachmentCallback;
private LinearLayout mHeaderPlaceHolder;
private LinearLayout mTitleBarHeaderContainer;
private View mAttachmentsContainer;
private LinearLayout mInsideAttachmentsContainer;
private SavedState mSavedState;
public void initialize(Activity activity) {
mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
mAccessibleMessageContentView = (AccessibleWebView) findViewById(R.id.accessible_message_content);
mAttachments = (LinearLayout) findViewById(R.id.attachments);
mMessageContentView.configure();
mHeaderPlaceHolder = (LinearLayout) findViewById(R.id.message_view_header_container);
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
mAttachmentsContainer = findViewById(R.id.attachments_container);
mInsideAttachmentsContainer = (LinearLayout) findViewById(R.id.inside_attachments_container);
mAttachments = (LinearLayout) findViewById(R.id.attachments);
mHiddenAttachments = (LinearLayout) findViewById(R.id.hidden_attachments);
mHiddenAttachments.setVisibility(View.GONE);
mShowHiddenAttachments = (Button) findViewById(R.id.show_hidden_attachments);
mShowHiddenAttachments.setVisibility(View.GONE);
mCryptoView = (MessageCryptoView) findViewById(R.id.layout_decrypt);
mCryptoView.setActivity(activity);
mCryptoView.setupChildViews();
mShowPicturesSection = findViewById(R.id.show_pictures_section);
mShowPicturesAction = findViewById(R.id.show_pictures);
mShowMessageAction = findViewById(R.id.show_message);
mShowAttachmentsAction = findViewById(R.id.show_attachments);
mShowPictures = false;
mContacts = Contacts.getInstance(activity);
mInflater = activity.getLayoutInflater();
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
mMessageContentView.configure();
mAttachments.setVisibility(View.GONE);
mDownloadRemainder.setVisibility(View.GONE);
mAttachmentsContainer.setVisibility(View.GONE);
if (isScreenReaderActive(activity)) {
mAccessibleMessageContentView.setVisibility(View.VISIBLE);
mMessageContentView.setVisibility(View.GONE);
@ -75,8 +97,62 @@ public class SingleMessageView extends LinearLayout {
mAccessibleMessageContentView.setVisibility(View.GONE);
mMessageContentView.setVisibility(View.VISIBLE);
mScreenReaderEnabled = false;
mHeaderPlaceHolder.removeView(mHeaderContainer);
// the HTC version of WebView tries to force the background of the
// titlebar, which is really unfair.
mHeaderContainer.setBackgroundColor(((K9Activity)activity).getThemeBackgroundColor());
mTitleBarHeaderContainer = new LinearLayout(activity);
mTitleBarHeaderContainer.addView(mHeaderContainer);
mMessageContentView.wrapSetTitleBar(mTitleBarHeaderContainer);
}
mShowHiddenAttachments.setOnClickListener(this);
mShowMessageAction.setOnClickListener(this);
mShowAttachmentsAction.setOnClickListener(this);
mShowPicturesAction.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.show_hidden_attachments: {
onShowHiddenAttachments();
break;
}
case R.id.show_message: {
onShowMessage();
break;
}
case R.id.show_attachments: {
onShowAttachments();
break;
}
case R.id.show_pictures: {
setLoadPictures(true);
break;
}
}
}
private void onShowHiddenAttachments() {
mShowHiddenAttachments.setVisibility(View.GONE);
mHiddenAttachments.setVisibility(View.VISIBLE);
}
public void onShowMessage() {
showShowMessageAction(false);
showAttachments(false);
showShowAttachmentsAction(mHasAttachments);
showMessageWebView(true);
}
public void onShowAttachments() {
showMessageWebView(false);
showShowAttachmentsAction(false);
showShowMessageAction(true);
showAttachments(true);
}
public SingleMessageView(Context context, AttributeSet attrs) {
@ -139,20 +215,27 @@ public class SingleMessageView extends LinearLayout {
public void setLoadPictures(boolean enable) {
mMessageContentView.blockNetworkData(!enable);
setShowPictures(enable);
showShowPicturesSection(false);
showShowPicturesAction(false);
}
public Button downloadRemainderButton() {
return mDownloadRemainder;
}
public void showShowPicturesSection(boolean show) {
mShowPicturesSection.setVisibility(show ? View.VISIBLE : View.GONE);
public void showShowPicturesAction(boolean show) {
mShowPicturesAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showShowMessageAction(boolean show) {
mShowMessageAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void showShowAttachmentsAction(boolean show) {
mShowAttachmentsAction.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void setHeaders(final Message message, Account account) {
try {
mHeaderContainer.populate(message, account);
mHeaderContainer.setVisibility(View.VISIBLE);
} catch (Exception me) {
@ -181,9 +264,9 @@ public class SingleMessageView extends LinearLayout {
return mHeaderContainer.additionalHeadersVisible();
}
public void displayMessageBody(Account account, String folder, String uid, Message message, PgpData pgpData) throws MessagingException {
// TODO - really this code path? this is an odd place to put it
removeAllAttachments();
public void setMessage(Account account, LocalMessage message, PgpData pgpData,
MessagingController controller, MessagingListener listener) throws MessagingException {
resetView();
String type;
String text = pgpData.getDecryptedData();
@ -191,13 +274,49 @@ public class SingleMessageView extends LinearLayout {
type = "text/plain";
} else {
// getTextForDisplay() always returns HTML-ified content.
text = ((LocalStore.LocalMessage) message).getTextForDisplay();
text = message.getTextForDisplay();
type = "text/html";
}
if (text != null) {
final String emailText = text;
final String contentType = type;
loadBodyFromText(account.getCryptoProvider(), pgpData, message, emailText, contentType);
loadBodyFromText(emailText, contentType);
updateCryptoLayout(account.getCryptoProvider(), pgpData, message);
} else {
loadBodyFromUrl("file:///android_asset/empty.html");
}
mHasAttachments = message.hasAttachments();
if (mHasAttachments) {
renderAttachments(message, 0, message, account, controller, listener);
}
mHiddenAttachments.setVisibility(View.GONE);
boolean lookForImages = true;
if (mSavedState != null) {
if (mSavedState.showPictures) {
setLoadPictures(true);
lookForImages = false;
}
if (mSavedState.attachmentViewVisible) {
onShowAttachments();
} else {
onShowMessage();
}
if (mSavedState.hiddenAttachmentsVisible) {
onShowHiddenAttachments();
}
mSavedState = null;
} else {
onShowMessage();
}
if (text != null && lookForImages) {
// If the message contains external pictures and the "Show pictures"
// button wasn't already pressed, see if the user's preferences has us
// showing them anyway.
@ -210,11 +329,9 @@ public class SingleMessageView extends LinearLayout {
mContacts.isInContacts(from[0].getAddress()))) {
setLoadPictures(true);
} else {
showShowPicturesSection(true);
showShowPicturesAction(true);
}
}
} else {
loadBodyFromUrl("file:///android_asset/empty.html");
}
}
@ -224,14 +341,13 @@ public class SingleMessageView extends LinearLayout {
}
public void loadBodyFromText(CryptoProvider cryptoProvider, PgpData pgpData, Message message, String emailText, String contentType) {
private void loadBodyFromText(String emailText, String contentType) {
if (mScreenReaderEnabled) {
mAccessibleMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
} else {
mMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
mMessageContentView.scrollTo(0, 0);
}
updateCryptoLayout(cryptoProvider, pgpData, message);
}
@ -239,6 +355,23 @@ public class SingleMessageView extends LinearLayout {
mCryptoView.updateLayout(cp, pgpData, message);
}
public void showAttachments(boolean show) {
mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE);
boolean showHidden = (show && mHiddenAttachments.getVisibility() == View.GONE &&
mHiddenAttachments.getChildCount() > 0);
mShowHiddenAttachments.setVisibility(showHidden ? View.VISIBLE : View.GONE);
if (show) {
moveHeaderToLayout();
} else {
moveHeaderToWebViewTitleBar();
}
}
public void showMessageWebView(boolean show) {
mMessageContentView.setVisibility(show ? View.VISIBLE : View.GONE);
}
public void setAttachmentsEnabled(boolean enabled) {
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
AttachmentView attachment = (AttachmentView) mAttachments.getChildAt(i);
@ -247,7 +380,6 @@ public class SingleMessageView extends LinearLayout {
}
}
public void removeAllAttachments() {
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
mAttachments.removeView(mAttachments.getChildAt(i));
@ -263,25 +395,23 @@ public class SingleMessageView extends LinearLayout {
renderAttachments(mp.getBodyPart(i), depth + 1, message, account, controller, listener);
}
} else if (part instanceof LocalStore.LocalAttachmentBodyPart) {
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
// Inline parts with a content-id are almost certainly components of an HTML message
// not attachments. Don't show attachment download buttons for them.
if (contentDisposition != null &&
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
&& part.getHeader(MimeHeader.HEADER_CONTENT_ID) != null) {
return;
}
AttachmentView view = (AttachmentView)mInflater.inflate(R.layout.message_view_attachment, null);
view.setCallback(attachmentCallback);
if (view.populateFromPart(part, message, account, controller, listener)) {
addAttachment(view);
} else {
addHiddenAttachment(view);
}
}
}
public void addAttachment(View attachmentView) {
mAttachments.addView(attachmentView);
mAttachments.setVisibility(View.VISIBLE);
}
public void addHiddenAttachment(View attachmentView) {
mHiddenAttachments.addView(attachmentView);
}
public void zoom(KeyEvent event) {
@ -301,11 +431,26 @@ public class SingleMessageView extends LinearLayout {
}
public void resetView() {
mDownloadRemainder.setVisibility(View.GONE);
setLoadPictures(false);
mMessageContentView.scrollTo(0, 0);
mHeaderContainer.setVisibility(View.GONE);
mMessageContentView.clearView();
showShowAttachmentsAction(false);
showShowMessageAction(false);
showShowPicturesAction(false);
mAttachments.removeAllViews();
mHiddenAttachments.removeAllViews();
/*
* Clear the WebView content
*
* For some reason WebView.clearView() doesn't clear the contents when the WebView changes
* its size because the button to download the complete message was previously shown and
* is now hidden.
*/
loadBodyFromText("", "text/plain");
}
public void resetHeaderView() {
mHeaderContainer.setVisibility(View.GONE);
}
public AttachmentView.AttachmentFileDownloadCallback getAttachmentCallback() {
@ -317,20 +462,85 @@ public class SingleMessageView extends LinearLayout {
this.attachmentCallback = attachmentCallback;
}
/**
* Save a copy of the {@link com.fsck.k9.controller.MessagingController#getListeners()}. This method will also
* pass along these listeners to the underlying views.
* @param listeners Set of listeners.
*/
public void setListeners(final Set<MessagingListener> listeners) {
if(!mScreenReaderEnabled) {
if(mMessageContentView != null) {
mMessageContentView.setListeners(listeners);
private void moveHeaderToLayout() {
if (mTitleBarHeaderContainer != null && mTitleBarHeaderContainer.getChildCount() != 0) {
mTitleBarHeaderContainer.removeView(mHeaderContainer);
mInsideAttachmentsContainer.addView(mHeaderContainer, 0);
}
}
private void moveHeaderToWebViewTitleBar() {
if (mTitleBarHeaderContainer != null && mTitleBarHeaderContainer.getChildCount() == 0) {
mInsideAttachmentsContainer.removeView(mHeaderContainer);
mTitleBarHeaderContainer.addView(mHeaderContainer);
}
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.attachmentViewVisible = (mAttachmentsContainer != null &&
mAttachmentsContainer.getVisibility() == View.VISIBLE);
savedState.hiddenAttachmentsVisible = (mHiddenAttachments != null &&
mHiddenAttachments.getVisibility() == View.VISIBLE);
savedState.showPictures = mShowPictures;
return savedState;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if(!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState savedState = (SavedState)state;
super.onRestoreInstanceState(savedState.getSuperState());
mSavedState = savedState;
}
static class SavedState extends BaseSavedState {
boolean attachmentViewVisible;
boolean hiddenAttachmentsVisible;
boolean showPictures;
@SuppressWarnings("hiding")
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
} else {
if(mAccessibleMessageContentView != null) {
mAccessibleMessageContentView.setListeners(listeners);
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.attachmentViewVisible = (in.readInt() != 0);
this.hiddenAttachmentsVisible = (in.readInt() != 0);
this.showPictures = (in.readInt() != 0);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt((this.attachmentViewVisible) ? 1 : 0);
out.writeInt((this.hiddenAttachmentsVisible) ? 1 : 0);
out.writeInt((this.showPictures) ? 1 : 0);
}
}
}

View File

@ -0,0 +1,188 @@
package com.fsck.k9.mail.internet;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import android.test.AndroidTestCase;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.mail.internet.MimeUtility.ViewableContainer;
public class ViewablesTest extends AndroidTestCase {
public void testSimplePlainTextMessage() throws MessagingException {
String bodyText = "K-9 Mail rocks :>";
// Create text/plain body
TextBody body = new TextBody(bodyText);
// Create message
MimeMessage message = new MimeMessage();
message.setBody(body);
// Extract text
ViewableContainer container = MimeUtility.extractTextAndAttachments(getContext(), message);
String expectedText = bodyText;
String expectedHtml =
"<html><head/><body>" +
"<pre style=\"white-space: pre-wrap; word-wrap:break-word; " +
"font-family: sans-serif\">" +
"K-9 Mail rocks :&gt;" +
"</pre>" +
"</body></html>";
assertEquals(expectedText, container.text);
assertEquals(expectedHtml, container.html);
}
public void testSimpleHtmlMessage() throws MessagingException {
String bodyText = "<strong>K-9 Mail</strong> rocks :&gt;";
// Create text/plain body
TextBody body = new TextBody(bodyText);
// Create message
MimeMessage message = new MimeMessage();
message.setHeader("Content-Type", "text/html");
message.setBody(body);
// Extract text
ViewableContainer container = MimeUtility.extractTextAndAttachments(getContext(), message);
String expectedText = "K-9 Mail rocks :>";
String expectedHtml =
"<html><head/><body>" +
bodyText +
"</body></html>";
assertEquals(expectedText, container.text);
assertEquals(expectedHtml, container.html);
}
public void testMultipartPlainTextMessage() throws MessagingException {
String bodyText1 = "text body 1";
String bodyText2 = "text body 2";
// Create text/plain bodies
TextBody body1 = new TextBody(bodyText1);
TextBody body2 = new TextBody(bodyText2);
// Create multipart/mixed part
MimeMultipart multipart = new MimeMultipart();
MimeBodyPart bodyPart1 = new MimeBodyPart(body1, "text/plain");
MimeBodyPart bodyPart2 = new MimeBodyPart(body2, "text/plain");
multipart.addBodyPart(bodyPart1);
multipart.addBodyPart(bodyPart2);
// Create message
MimeMessage message = new MimeMessage();
message.setBody(multipart);
// Extract text
ViewableContainer container = MimeUtility.extractTextAndAttachments(getContext(), message);
String expectedText =
bodyText1 + "\n\n" +
"------------------------------------------------------------------------\n\n" +
bodyText2;
String expectedHtml =
"<html><head/><body>" +
"<pre style=\"white-space: pre-wrap; word-wrap:break-word; " +
"font-family: sans-serif\">" +
bodyText1 +
"</pre>" +
"<p style=\"margin-top: 2.5em; margin-bottom: 1em; " +
"border-bottom: 1px solid #000\"></p>" +
"<pre style=\"white-space: pre-wrap; word-wrap:break-word; " +
"font-family: sans-serif\">" +
bodyText2 +
"</pre>" +
"</body></html>";
assertEquals(expectedText, container.text);
assertEquals(expectedHtml, container.html);
}
public void testTextPlusRfc822Message() throws MessagingException {
Locale.setDefault(Locale.US);
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
String bodyText = "Some text here";
String innerBodyText = "Hey there. I'm inside a message/rfc822 (inline) attachment.";
// Create text/plain body
TextBody textBody = new TextBody(bodyText);
// Create inner text/plain body
TextBody innerBody = new TextBody(innerBodyText);
// Create message/rfc822 body
MimeMessage innerMessage = new MimeMessage();
innerMessage.addSentDate(new Date(112, 02, 17));
innerMessage.setRecipients(RecipientType.TO, new Address[] { new Address("to@example.com") });
innerMessage.setSubject("Subject");
innerMessage.setFrom(new Address("from@example.com"));
innerMessage.setBody(innerBody);
// Create multipart/mixed part
MimeMultipart multipart = new MimeMultipart();
MimeBodyPart bodyPart1 = new MimeBodyPart(textBody, "text/plain");
MimeBodyPart bodyPart2 = new MimeBodyPart(innerMessage, "message/rfc822");
bodyPart2.setHeader("Content-Disposition", "inline; filename=\"message.eml\"");
multipart.addBodyPart(bodyPart1);
multipart.addBodyPart(bodyPart2);
// Create message
MimeMessage message = new MimeMessage();
message.setBody(multipart);
// Extract text
ViewableContainer container = MimeUtility.extractTextAndAttachments(getContext(), message);
String expectedText =
bodyText +
"\n\n" +
"----- message.eml ------------------------------------------------------" +
"\n\n" +
"From: from@example.com" + "\n" +
"To: to@example.com" + "\n" +
"Sent: Sat Mar 17 00:00:00 GMT+00:00 2012" + "\n" +
"Subject: Subject" + "\n" +
"\n" +
innerBodyText;
String expectedHtml =
"<html><head/><body>" +
"<pre style=\"white-space: pre-wrap; word-wrap:break-word; " +
"font-family: sans-serif\">" +
bodyText +
"</pre>" +
"<p style=\"margin-top: 2.5em; margin-bottom: 1em; border-bottom: " +
"1px solid #000\">message.eml</p>" +
"<table style=\"border: 0\">" +
"<tr>" +
"<th style=\"text-align: left; vertical-align: top;\">From:</th>" +
"<td>from@example.com</td>" +
"</tr><tr>" +
"<th style=\"text-align: left; vertical-align: top;\">To:</th>" +
"<td>to@example.com</td>" +
"</tr><tr>" +
"<th style=\"text-align: left; vertical-align: top;\">Sent:</th>" +
"<td>Sat Mar 17 00:00:00 GMT+00:00 2012</td>" +
"</tr><tr>" +
"<th style=\"text-align: left; vertical-align: top;\">Subject:</th>" +
"<td>Subject</td>" +
"</tr>" +
"</table>" +
"<pre style=\"white-space: pre-wrap; word-wrap:break-word; " +
"font-family: sans-serif\">" +
innerBodyText +
"</pre>" +
"</body></html>";
assertEquals(expectedText, container.text);
assertEquals(expectedHtml, container.html);
}
}