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:
commit
a62a5babca
@ -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"
|
||||
|
20
images/show_more_indicator.svg
Normal file
20
images/show_more_indicator.svg
Normal 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 |
BIN
res/drawable-hdpi/show_less.png
Normal file
BIN
res/drawable-hdpi/show_less.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 393 B |
BIN
res/drawable-hdpi/show_more.png
Normal file
BIN
res/drawable-hdpi/show_more.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 389 B |
14
res/drawable/separator_area_background.xml
Normal file
14
res/drawable/separator_area_background.xml
Normal 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
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
BIN
res/drawable/show_more.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 299 B |
@ -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>
|
@ -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>
|
||||
|
@ -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>
|
||||
|
289
res/layout/message_view_header.xml
Normal file
289
res/layout/message_view_header.xml
Normal 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>
|
@ -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>
|
@ -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 d’Arxiu, 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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 & 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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 <%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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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…</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>
|
||||
|
@ -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"
|
||||
|
@ -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">
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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())) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
));
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
188
tests/src/com/fsck/k9/mail/internet/ViewablesTest.java
Normal file
188
tests/src/com/fsck/k9/mail/internet/ViewablesTest.java
Normal 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 :>" +
|
||||
"</pre>" +
|
||||
"</body></html>";
|
||||
|
||||
assertEquals(expectedText, container.text);
|
||||
assertEquals(expectedHtml, container.html);
|
||||
}
|
||||
|
||||
public void testSimpleHtmlMessage() throws MessagingException {
|
||||
String bodyText = "<strong>K-9 Mail</strong> rocks :>";
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user