Merge branch 'main' into message-view-redesign
This commit is contained in:
commit
32f4b34e93
145 changed files with 1831 additions and 1245 deletions
|
@ -21,6 +21,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.autodiscovery.providersxml'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.fsck.k9.autodiscovery.providersxml" />
|
|
@ -43,6 +43,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.core'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.fsck.k9.core">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||
|
|
|
@ -123,7 +123,7 @@ object K9 : EarlyInit {
|
|||
val fontSizes = FontSizes()
|
||||
|
||||
@JvmStatic
|
||||
var backgroundOps = BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC
|
||||
var backgroundOps = BACKGROUND_OPS.ALWAYS
|
||||
|
||||
@JvmStatic
|
||||
var isShowAnimations = true
|
||||
|
@ -188,9 +188,6 @@ object K9 : EarlyInit {
|
|||
@JvmStatic
|
||||
var isUseVolumeKeysForNavigation = false
|
||||
|
||||
@JvmStatic
|
||||
var isUseVolumeKeysForListNavigation = false
|
||||
|
||||
@JvmStatic
|
||||
var isShowUnifiedInbox = true
|
||||
|
||||
|
@ -253,6 +250,12 @@ object K9 : EarlyInit {
|
|||
@JvmStatic
|
||||
var pgpSignOnlyDialogCounter: Int = 0
|
||||
|
||||
@JvmStatic
|
||||
var swipeRightAction: SwipeAction = SwipeAction.ToggleSelection
|
||||
|
||||
@JvmStatic
|
||||
var swipeLeftAction: SwipeAction = SwipeAction.ToggleRead
|
||||
|
||||
val isQuietTime: Boolean
|
||||
get() {
|
||||
if (!isQuietTimeEnabled) {
|
||||
|
@ -298,7 +301,6 @@ object K9 : EarlyInit {
|
|||
isSensitiveDebugLoggingEnabled = storage.getBoolean("enableSensitiveLogging", false)
|
||||
isShowAnimations = storage.getBoolean("animations", true)
|
||||
isUseVolumeKeysForNavigation = storage.getBoolean("useVolumeKeysForNavigation", false)
|
||||
isUseVolumeKeysForListNavigation = storage.getBoolean("useVolumeKeysForListNavigation", false)
|
||||
isShowUnifiedInbox = storage.getBoolean("showUnifiedInbox", true)
|
||||
isShowStarredCount = storage.getBoolean("showStarredCount", false)
|
||||
isMessageListSenderAboveSubject = storage.getBoolean("messageListSenderAboveSubject", false)
|
||||
|
@ -348,7 +350,7 @@ object K9 : EarlyInit {
|
|||
isThreadedViewEnabled = storage.getBoolean("threadedView", true)
|
||||
fontSizes.load(storage)
|
||||
|
||||
backgroundOps = storage.getEnum("backgroundOperations", BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC)
|
||||
backgroundOps = storage.getEnum("backgroundOperations", BACKGROUND_OPS.ALWAYS)
|
||||
|
||||
isColorizeMissingContactPictures = storage.getBoolean("colorizeMissingContactPictures", true)
|
||||
|
||||
|
@ -362,6 +364,9 @@ object K9 : EarlyInit {
|
|||
pgpSignOnlyDialogCounter = storage.getInt("pgpSignOnlyDialogCounter", 0)
|
||||
|
||||
k9Language = storage.getString("language", "")
|
||||
|
||||
swipeRightAction = storage.getEnum("swipeRightAction", SwipeAction.ToggleSelection)
|
||||
swipeLeftAction = storage.getEnum("swipeLeftAction", SwipeAction.ToggleRead)
|
||||
}
|
||||
|
||||
internal fun save(editor: StorageEditor) {
|
||||
|
@ -370,7 +375,6 @@ object K9 : EarlyInit {
|
|||
editor.putEnum("backgroundOperations", backgroundOps)
|
||||
editor.putBoolean("animations", isShowAnimations)
|
||||
editor.putBoolean("useVolumeKeysForNavigation", isUseVolumeKeysForNavigation)
|
||||
editor.putBoolean("useVolumeKeysForListNavigation", isUseVolumeKeysForListNavigation)
|
||||
editor.putBoolean("autofitWidth", isAutoFitWidth)
|
||||
editor.putBoolean("quietTimeEnabled", isQuietTimeEnabled)
|
||||
editor.putBoolean("notificationDuringQuietTimeEnabled", isNotificationDuringQuietTimeEnabled)
|
||||
|
@ -422,6 +426,9 @@ object K9 : EarlyInit {
|
|||
editor.putInt("pgpInlineDialogCounter", pgpInlineDialogCounter)
|
||||
editor.putInt("pgpSignOnlyDialogCounter", pgpSignOnlyDialogCounter)
|
||||
|
||||
editor.putEnum("swipeRightAction", swipeRightAction)
|
||||
editor.putEnum("swipeLeftAction", swipeLeftAction)
|
||||
|
||||
fontSizes.save(editor)
|
||||
}
|
||||
|
||||
|
|
12
app/core/src/main/java/com/fsck/k9/SwipeAction.kt
Normal file
12
app/core/src/main/java/com/fsck/k9/SwipeAction.kt
Normal file
|
@ -0,0 +1,12 @@
|
|||
package com.fsck.k9
|
||||
|
||||
enum class SwipeAction {
|
||||
None,
|
||||
ToggleSelection,
|
||||
ToggleRead,
|
||||
ToggleStar,
|
||||
Archive,
|
||||
Delete,
|
||||
Spam,
|
||||
Move
|
||||
}
|
|
@ -58,6 +58,11 @@ class NotifierMessageStore(
|
|||
notifyChange()
|
||||
}
|
||||
|
||||
override fun setMoreMessages(folderId: Long, moreMessages: MoreMessages) {
|
||||
messageStore.setMoreMessages(folderId, moreMessages)
|
||||
notifyChange()
|
||||
}
|
||||
|
||||
private fun notifyChange() {
|
||||
localStore.notifyChange()
|
||||
}
|
||||
|
|
|
@ -10,15 +10,16 @@ import java.util.Set;
|
|||
import java.util.TreeMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.Account.SortType;
|
||||
import com.fsck.k9.DI;
|
||||
import com.fsck.k9.FontSizes;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.K9.BACKGROUND_OPS;
|
||||
import com.fsck.k9.K9.NotificationQuickDelete;
|
||||
import com.fsck.k9.K9.SplitViewMode;
|
||||
import com.fsck.k9.SwipeAction;
|
||||
import com.fsck.k9.core.R;
|
||||
import com.fsck.k9.preferences.Settings.BooleanSetting;
|
||||
import com.fsck.k9.preferences.Settings.ColorSetting;
|
||||
|
@ -51,7 +52,8 @@ public class GeneralSettingsDescriptions {
|
|||
new V(1, new BooleanSetting(false))
|
||||
));
|
||||
s.put("backgroundOperations", Settings.versions(
|
||||
new V(1, new EnumSetting<>(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC))
|
||||
new V(1, new EnumSetting<>(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC)),
|
||||
new V(83, new EnumSetting<>(K9.BACKGROUND_OPS.class, BACKGROUND_OPS.ALWAYS))
|
||||
));
|
||||
s.put("changeRegisteredNameColor", Settings.versions(
|
||||
new V(1, new BooleanSetting(false))
|
||||
|
@ -184,9 +186,6 @@ public class GeneralSettingsDescriptions {
|
|||
new V(16, new LegacyThemeSetting(AppTheme.LIGHT)),
|
||||
new V(24, new SubThemeSetting(SubTheme.USE_GLOBAL))
|
||||
));
|
||||
s.put("useVolumeKeysForListNavigation", Settings.versions(
|
||||
new V(1, new BooleanSetting(false))
|
||||
));
|
||||
s.put("useVolumeKeysForNavigation", Settings.versions(
|
||||
new V(1, new BooleanSetting(false))
|
||||
));
|
||||
|
@ -278,6 +277,12 @@ public class GeneralSettingsDescriptions {
|
|||
s.put("showStarredCount", Settings.versions(
|
||||
new V(75, new BooleanSetting(false))
|
||||
));
|
||||
s.put("swipeRightAction", Settings.versions(
|
||||
new V(83, new EnumSetting<>(SwipeAction.class, SwipeAction.ToggleSelection))
|
||||
));
|
||||
s.put("swipeLeftAction", Settings.versions(
|
||||
new V(83, new EnumSetting<>(SwipeAction.class, SwipeAction.ToggleRead))
|
||||
));
|
||||
|
||||
SETTINGS = Collections.unmodifiableMap(s);
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ internal class RealGeneralSettingsManager(
|
|||
}
|
||||
|
||||
override fun getSettingsFlow(): Flow<GeneralSettings> {
|
||||
// Make sure to load settings now if they haven't been loaded already. This will also update settingsFlow.
|
||||
getSettings()
|
||||
|
||||
return settingsFlow.distinctUntilChanged()
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class Settings {
|
|||
*
|
||||
* @see SettingsExporter
|
||||
*/
|
||||
public static final int VERSION = 81;
|
||||
public static final int VERSION = 83;
|
||||
|
||||
static Map<String, Object> validate(int version, Map<String, TreeMap<Integer, SettingsDescription>> settings,
|
||||
Map<String, String> importedSettings, boolean useDefaultValues) {
|
||||
|
|
|
@ -3,25 +3,31 @@
|
|||
|
||||
<!-- Must be kept in sync with arrays_drawer.xml/drawer_account_accent_color_dark_theme -->
|
||||
<integer-array name="account_colors">
|
||||
<item>0xFFFFB300</item> <!-- Amber 600 -->
|
||||
<item>0xFFFB8C00</item> <!-- Orange 600 -->
|
||||
<item>0xFFF4511E</item> <!-- Deep orange 600 -->
|
||||
<item>0xFFE53935</item> <!-- Red 600 -->
|
||||
<item>@color/material_amber_600</item>
|
||||
<item>@color/material_orange_600</item>
|
||||
<item>@color/material_deep_orange_600</item>
|
||||
<item>@color/material_red_600</item>
|
||||
|
||||
<item>0xFFC0CA33</item> <!-- Lime 600 -->
|
||||
<item>0xFF7CB342</item> <!-- Light green 600 -->
|
||||
<item>0xFF388E3C</item> <!-- Green 700 -->
|
||||
<item>0xFF00897B</item> <!-- Teal 600 -->
|
||||
<item>@color/material_lime_600</item>
|
||||
<item>@color/material_light_green_600</item>
|
||||
<item>@color/material_green_700</item>
|
||||
<item>@color/material_teal_600</item>
|
||||
|
||||
<item>0xFF00ACC1</item> <!-- Cyan 600 -->
|
||||
<item>0xFF039BE5</item> <!-- Light blue 600 -->
|
||||
<item>0xFF1976D2</item> <!-- Blue 700 -->
|
||||
<item>0xFF3949AB</item> <!-- Indigo 600 -->
|
||||
<item>@color/material_cyan_600</item>
|
||||
<item>@color/material_light_blue_600</item>
|
||||
<item>@color/material_blue_700</item>
|
||||
<item>@color/material_indigo_600</item>
|
||||
|
||||
<item>0xFFE91E63</item> <!-- Pink 500 -->
|
||||
<item>0xFF8E24AA</item> <!-- Purple 600 -->
|
||||
<item>0xFF5E35B1</item> <!-- Deep purple 600 -->
|
||||
<item>0xFF455A64</item> <!-- Blue gray 700 -->
|
||||
<item>@color/material_pink_500</item>
|
||||
<item>@color/material_purple_600</item>
|
||||
<item>@color/material_deep_purple_600</item>
|
||||
<item>@color/material_blue_gray_700</item>
|
||||
</integer-array>
|
||||
|
||||
<integer-array name="default_account_colors">
|
||||
<item>@color/material_blue_700</item>
|
||||
<item>@color/material_pink_500</item>
|
||||
<item>@color/material_amber_600</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="check_frequency_values" translatable="false">
|
||||
|
|
|
@ -3,25 +3,25 @@
|
|||
|
||||
<!-- Must be kept in sync with arrays_account_settings_values.xml/account_colors -->
|
||||
<integer-array name="drawer_account_accent_color_dark_theme">
|
||||
<item>0xFFFFB300</item> <!-- Amber 600 -->
|
||||
<item>0xFFFF9800</item> <!-- Orange 500 -->
|
||||
<item>0xFFFF7043</item> <!-- Deep orange 400 -->
|
||||
<item>0xFFEF5350</item> <!-- Red 400 -->
|
||||
<item>@color/material_amber_600</item>
|
||||
<item>@color/material_orange_500</item>
|
||||
<item>@color/material_deep_orange_400</item>
|
||||
<item>@color/material_red_400</item>
|
||||
|
||||
<item>0xFFC0CA33</item> <!-- Lime 600 -->
|
||||
<item>0xFF7CB342</item> <!-- Light green 600 -->
|
||||
<item>0xFF4CAF50</item> <!-- Green 500 -->
|
||||
<item>0xFF4DB6AC</item> <!-- Teal 300 -->
|
||||
<item>@color/material_lime_600</item>
|
||||
<item>@color/material_light_green_600</item>
|
||||
<item>@color/material_green_500</item>
|
||||
<item>@color/material_teal_300</item>
|
||||
|
||||
<item>0xFF00ACC1</item> <!-- Cyan 600 -->
|
||||
<item>0xFF03A9F4</item> <!-- Light blue 500 -->
|
||||
<item>0xFF42A5F5</item> <!-- Blue 400 -->
|
||||
<item>0xFF9FA8DA</item> <!-- Indigo 200 -->
|
||||
<item>@color/material_cyan_600</item>
|
||||
<item>@color/material_light_blue_500</item>
|
||||
<item>@color/material_blue_400</item>
|
||||
<item>@color/material_indigo_200</item>
|
||||
|
||||
<item>0xFFF48FB1</item> <!-- Pink 200 -->
|
||||
<item>0xFFCE93D8</item> <!-- Purple 200 -->
|
||||
<item>0xFFB39DDB</item> <!-- Deep purple 200 -->
|
||||
<item>0xFF90A4AE</item> <!-- Blue gray 300 -->
|
||||
<item>@color/material_pink_200</item>
|
||||
<item>@color/material_purple_200</item>
|
||||
<item>@color/material_deep_purple_200</item>
|
||||
<item>@color/material_blue_gray_300</item>
|
||||
</integer-array>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -210,9 +210,15 @@
|
|||
<item>spam</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="volume_navigation_values" translatable="false">
|
||||
<item>message</item>
|
||||
<item>list</item>
|
||||
<string-array name="swipe_action_values" translatable="false">
|
||||
<item>none</item>
|
||||
<item>toggle_selection</item>
|
||||
<item>toggle_read</item>
|
||||
<item>toggle_star</item>
|
||||
<item>archive</item>
|
||||
<item>delete</item>
|
||||
<item>spam</item>
|
||||
<item>move</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
|
211
app/core/src/main/res/values/material_colors.xml
Normal file
211
app/core/src/main/res/values/material_colors.xml
Normal file
|
@ -0,0 +1,211 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="material_red_50">#FFEBEE</color>
|
||||
<color name="material_red_100">#FFCDD2</color>
|
||||
<color name="material_red_200">#EF9A9A</color>
|
||||
<color name="material_red_300">#E57373</color>
|
||||
<color name="material_red_400">#EF5350</color>
|
||||
<color name="material_red_500">#F44336</color>
|
||||
<color name="material_red_600">#E53935</color>
|
||||
<color name="material_red_700">#D32F2F</color>
|
||||
<color name="material_red_800">#C62828</color>
|
||||
<color name="material_red_900">#B71C1C</color>
|
||||
|
||||
<color name="material_deep_purple_50">#EDE7F6</color>
|
||||
<color name="material_deep_purple_100">#D1C4E9</color>
|
||||
<color name="material_deep_purple_200">#B39DDB</color>
|
||||
<color name="material_deep_purple_300">#9575CD</color>
|
||||
<color name="material_deep_purple_400">#7E57C2</color>
|
||||
<color name="material_deep_purple_500">#673AB7</color>
|
||||
<color name="material_deep_purple_600">#5E35B1</color>
|
||||
<color name="material_deep_purple_700">#512DA8</color>
|
||||
<color name="material_deep_purple_800">#4527A0</color>
|
||||
<color name="material_deep_purple_900">#311B92</color>
|
||||
|
||||
<color name="material_light_blue_50">#E1F5FE</color>
|
||||
<color name="material_light_blue_100">#B3E5FC</color>
|
||||
<color name="material_light_blue_200">#81D4FA</color>
|
||||
<color name="material_light_blue_300">#4FC3F7</color>
|
||||
<color name="material_light_blue_400">#29B6F6</color>
|
||||
<color name="material_light_blue_500">#03A9F4</color>
|
||||
<color name="material_light_blue_600">#039BE5</color>
|
||||
<color name="material_light_blue_700">#0288D1</color>
|
||||
<color name="material_light_blue_800">#0277BD</color>
|
||||
<color name="material_light_blue_900">#01579B</color>
|
||||
|
||||
<color name="material_green_50">#E8F5E9</color>
|
||||
<color name="material_green_100">#C8E6C9</color>
|
||||
<color name="material_green_200">#A5D6A7</color>
|
||||
<color name="material_green_300">#81C784</color>
|
||||
<color name="material_green_400">#66BB6A</color>
|
||||
<color name="material_green_500">#4CAF50</color>
|
||||
<color name="material_green_600">#43A047</color>
|
||||
<color name="material_green_700">#388E3C</color>
|
||||
<color name="material_green_800">#2E7D32</color>
|
||||
<color name="material_green_900">#1B5E20</color>
|
||||
|
||||
<color name="material_yellow_50">#FFFDE7</color>
|
||||
<color name="material_yellow_100">#FFF9C4</color>
|
||||
<color name="material_yellow_200">#FFF59D</color>
|
||||
<color name="material_yellow_300">#FFF176</color>
|
||||
<color name="material_yellow_400">#FFEE58</color>
|
||||
<color name="material_yellow_500">#FFEB3B</color>
|
||||
<color name="material_yellow_600">#FDD835</color>
|
||||
<color name="material_yellow_700">#FBC02D</color>
|
||||
<color name="material_yellow_800">#F9A825</color>
|
||||
<color name="material_yellow_900">#F57F17</color>
|
||||
|
||||
<color name="material_deep_orange_50">#FBE9E7</color>
|
||||
<color name="material_deep_orange_100">#FFCCBC</color>
|
||||
<color name="material_deep_orange_200">#FFAB91</color>
|
||||
<color name="material_deep_orange_300">#FF8A65</color>
|
||||
<color name="material_deep_orange_400">#FF7043</color>
|
||||
<color name="material_deep_orange_500">#FF5722</color>
|
||||
<color name="material_deep_orange_600">#F4511E</color>
|
||||
<color name="material_deep_orange_700">#E64A19</color>
|
||||
<color name="material_deep_orange_800">#D84315</color>
|
||||
<color name="material_deep_orange_900">#BF360C</color>
|
||||
|
||||
<color name="material_blue_gray_50">#ECEFF1</color>
|
||||
<color name="material_blue_gray_100">#CFD8DC</color>
|
||||
<color name="material_blue_gray_200">#B0BEC5</color>
|
||||
<color name="material_blue_gray_300">#90A4AE</color>
|
||||
<color name="material_blue_gray_400">#78909C</color>
|
||||
<color name="material_blue_gray_500">#607D8B</color>
|
||||
<color name="material_blue_gray_600">#546E7A</color>
|
||||
<color name="material_blue_gray_700">#455A64</color>
|
||||
<color name="material_blue_gray_800">#37474F</color>
|
||||
<color name="material_blue_gray_900">#263238</color>
|
||||
|
||||
<color name="material_pink_50">#FCE4EC</color>
|
||||
<color name="material_pink_100">#F8BBD0</color>
|
||||
<color name="material_pink_200">#F48FB1</color>
|
||||
<color name="material_pink_300">#F06292</color>
|
||||
<color name="material_pink_400">#EC407A</color>
|
||||
<color name="material_pink_500">#E91E63</color>
|
||||
<color name="material_pink_600">#D81B60</color>
|
||||
<color name="material_pink_700">#C2185B</color>
|
||||
<color name="material_pink_800">#AD1457</color>
|
||||
<color name="material_pink_900">#880E4F</color>
|
||||
|
||||
<color name="material_indigo_50">#E8EAF6</color>
|
||||
<color name="material_indigo_100">#C5CAE9</color>
|
||||
<color name="material_indigo_200">#9FA8DA</color>
|
||||
<color name="material_indigo_300">#7986CB</color>
|
||||
<color name="material_indigo_400">#5C6BC0</color>
|
||||
<color name="material_indigo_500">#3F51B5</color>
|
||||
<color name="material_indigo_600">#3949AB</color>
|
||||
<color name="material_indigo_700">#303F9F</color>
|
||||
<color name="material_indigo_800">#283593</color>
|
||||
<color name="material_indigo_900">#1A237E</color>
|
||||
|
||||
<color name="material_cyan_50">#E0F7FA</color>
|
||||
<color name="material_cyan_100">#B2EBF2</color>
|
||||
<color name="material_cyan_200">#80DEEA</color>
|
||||
<color name="material_cyan_300">#4DD0E1</color>
|
||||
<color name="material_cyan_400">#26C6DA</color>
|
||||
<color name="material_cyan_500">#00BCD4</color>
|
||||
<color name="material_cyan_600">#00ACC1</color>
|
||||
<color name="material_cyan_700">#0097A7</color>
|
||||
<color name="material_cyan_800">#00838F</color>
|
||||
<color name="material_cyan_900">#006064</color>
|
||||
|
||||
<color name="material_light_green_50">#F1F8E9</color>
|
||||
<color name="material_light_green_100">#DCEDC8</color>
|
||||
<color name="material_light_green_200">#C5E1A5</color>
|
||||
<color name="material_light_green_300">#AED581</color>
|
||||
<color name="material_light_green_400">#9CCC65</color>
|
||||
<color name="material_light_green_500">#8BC34A</color>
|
||||
<color name="material_light_green_600">#7CB342</color>
|
||||
<color name="material_light_green_700">#689F38</color>
|
||||
<color name="material_light_green_800">#558B2F</color>
|
||||
<color name="material_light_green_900">#33691E</color>
|
||||
|
||||
<color name="material_amber_50">#FFF8E1</color>
|
||||
<color name="material_amber_100">#FFECB3</color>
|
||||
<color name="material_amber_200">#FFE082</color>
|
||||
<color name="material_amber_300">#FFD54F</color>
|
||||
<color name="material_amber_400">#FFCA28</color>
|
||||
<color name="material_amber_500">#FFC107</color>
|
||||
<color name="material_amber_600">#FFB300</color>
|
||||
<color name="material_amber_700">#FFA000</color>
|
||||
<color name="material_amber_800">#FF8F00</color>
|
||||
<color name="material_amber_900">#FF6F00</color>
|
||||
|
||||
<color name="material_brown_50">#EFEBE9</color>
|
||||
<color name="material_brown_100">#D7CCC8</color>
|
||||
<color name="material_brown_200">#BCAAA4</color>
|
||||
<color name="material_brown_300">#A1887F</color>
|
||||
<color name="material_brown_400">#8D6E63</color>
|
||||
<color name="material_brown_500">#795548</color>
|
||||
<color name="material_brown_600">#6D4C41</color>
|
||||
<color name="material_brown_700">#5D4037</color>
|
||||
<color name="material_brown_800">#4E342E</color>
|
||||
<color name="material_brown_900">#3E2723</color>
|
||||
|
||||
<color name="material_purple_50">#F3E5F5</color>
|
||||
<color name="material_purple_100">#E1BEE7</color>
|
||||
<color name="material_purple_200">#CE93D8</color>
|
||||
<color name="material_purple_300">#BA68C8</color>
|
||||
<color name="material_purple_400">#AB47BC</color>
|
||||
<color name="material_purple_500">#9C27B0</color>
|
||||
<color name="material_purple_600">#8E24AA</color>
|
||||
<color name="material_purple_700">#7B1FA2</color>
|
||||
<color name="material_purple_800">#6A1B9A</color>
|
||||
<color name="material_purple_900">#4A148C</color>
|
||||
|
||||
<color name="material_blue_50">#E3F2FD</color>
|
||||
<color name="material_blue_100">#BBDEFB</color>
|
||||
<color name="material_blue_200">#90CAF9</color>
|
||||
<color name="material_blue_300">#64B5F6</color>
|
||||
<color name="material_blue_400">#42A5F5</color>
|
||||
<color name="material_blue_500">#2196F3</color>
|
||||
<color name="material_blue_600">#1E88E5</color>
|
||||
<color name="material_blue_700">#1976D2</color>
|
||||
<color name="material_blue_800">#1565C0</color>
|
||||
<color name="material_blue_900">#0D47A1</color>
|
||||
|
||||
<color name="material_teal_50">#E0F2F1</color>
|
||||
<color name="material_teal_100">#B2DFDB</color>
|
||||
<color name="material_teal_200">#80CBC4</color>
|
||||
<color name="material_teal_300">#4DB6AC</color>
|
||||
<color name="material_teal_400">#26A69A</color>
|
||||
<color name="material_teal_500">#009688</color>
|
||||
<color name="material_teal_600">#00897B</color>
|
||||
<color name="material_teal_700">#00796B</color>
|
||||
<color name="material_teal_800">#00695C</color>
|
||||
<color name="material_teal_900">#004D40</color>
|
||||
|
||||
<color name="material_lime_50">#F9FBE7</color>
|
||||
<color name="material_lime_100">#F0F4C3</color>
|
||||
<color name="material_lime_200">#E6EE9C</color>
|
||||
<color name="material_lime_300">#DCE775</color>
|
||||
<color name="material_lime_400">#D4E157</color>
|
||||
<color name="material_lime_500">#CDDC39</color>
|
||||
<color name="material_lime_600">#C0CA33</color>
|
||||
<color name="material_lime_700">#AFB42B</color>
|
||||
<color name="material_lime_800">#9E9D24</color>
|
||||
<color name="material_lime_900">#827717</color>
|
||||
|
||||
<color name="material_orange_50">#FFF3E0</color>
|
||||
<color name="material_orange_100">#FFE0B2</color>
|
||||
<color name="material_orange_200">#FFCC80</color>
|
||||
<color name="material_orange_300">#FFB74D</color>
|
||||
<color name="material_orange_400">#FFA726</color>
|
||||
<color name="material_orange_500">#FF9800</color>
|
||||
<color name="material_orange_600">#FB8C00</color>
|
||||
<color name="material_orange_700">#F57C00</color>
|
||||
<color name="material_orange_800">#EF6C00</color>
|
||||
<color name="material_orange_900">#E65100</color>
|
||||
|
||||
<color name="material_gray_50">#FAFAFA</color>
|
||||
<color name="material_gray_100">#F5F5F5</color>
|
||||
<color name="material_gray_200">#EEEEEE</color>
|
||||
<color name="material_gray_300">#E0E0E0</color>
|
||||
<color name="material_gray_400">#BDBDBD</color>
|
||||
<color name="material_gray_500">#9E9E9E</color>
|
||||
<color name="material_gray_600">#757575</color>
|
||||
<color name="material_gray_700">#616161</color>
|
||||
<color name="material_gray_800">#424242</color>
|
||||
<color name="material_gray_900">#212121</color>
|
||||
</resources>
|
|
@ -9,6 +9,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.crypto.openpgp'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.fsck.k9.crypto.openpgp" />
|
|
@ -41,6 +41,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
@ -48,8 +50,8 @@ android {
|
|||
applicationId "com.fsck.k9"
|
||||
testApplicationId "com.fsck.k9.tests"
|
||||
|
||||
versionCode 33005
|
||||
versionName '6.306-SNAPSHOT'
|
||||
versionCode 33008
|
||||
versionName '6.309-SNAPSHOT'
|
||||
|
||||
// Keep in sync with the resource string array 'supported_languages'
|
||||
resConfigs "in", "br", "ca", "cs", "cy", "da", "de", "et", "en", "en_GB", "es", "eo", "eu", "fr", "gd", "gl",
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="auto"
|
||||
package="com.fsck.k9">
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.fsck.k9.external;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -7,13 +8,13 @@ import android.text.SpannableStringBuilder;
|
|||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.helper.MessageHelper;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Message.RecipientType;
|
||||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.ui.R;
|
||||
|
||||
class MessageInfoHolder {
|
||||
public Date compareDate;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.fsck.k9.notification
|
||||
|
||||
import android.content.Context
|
||||
import com.fsck.k9.R
|
||||
import com.fsck.k9.ui.R
|
||||
|
||||
class K9NotificationResourceProvider(private val context: Context) : NotificationResourceProvider {
|
||||
override val iconWarning: Int = R.drawable.notification_icon_warning
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package com.fsck.k9.resources
|
||||
|
||||
import android.content.Context
|
||||
import com.fsck.k9.R
|
||||
import com.fsck.k9.autocrypt.AutocryptStringProvider
|
||||
import com.fsck.k9.ui.R
|
||||
|
||||
class K9AutocryptStringProvider(private val context: Context) : AutocryptStringProvider {
|
||||
override fun transferMessageSubject(): String = context.getString(R.string.ac_transfer_msg_subject)
|
||||
|
|
|
@ -2,8 +2,8 @@ package com.fsck.k9.resources
|
|||
|
||||
import android.content.Context
|
||||
import com.fsck.k9.CoreResourceProvider
|
||||
import com.fsck.k9.R
|
||||
import com.fsck.k9.notification.PushNotificationState
|
||||
import com.fsck.k9.ui.R
|
||||
|
||||
class K9CoreResourceProvider(private val context: Context) : CoreResourceProvider {
|
||||
override fun defaultSignature(): String = context.getString(R.string.default_signature)
|
||||
|
|
|
@ -147,7 +147,7 @@ public class MessageListRemoteViewFactory implements RemoteViewsService.RemoteVi
|
|||
@Override
|
||||
public RemoteViews getLoadingView() {
|
||||
RemoteViews loadingView = new RemoteViews(context.getPackageName(), R.layout.message_list_widget_loading);
|
||||
loadingView.setTextViewText(R.id.loadingText, context.getString(R.string.mail_list_widget_loading));
|
||||
loadingView.setTextViewText(R.id.loadingText, context.getString(com.fsck.k9.ui.R.string.mail_list_widget_loading));
|
||||
loadingView.setViewVisibility(R.id.loadingText, View.VISIBLE);
|
||||
return loadingView;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MessageListWidgetProvider extends AppWidgetProvider {
|
|||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.message_list_widget_layout);
|
||||
|
||||
views.setTextViewText(R.id.folder, context.getString(R.string.integrated_inbox_title));
|
||||
views.setTextViewText(R.id.folder, context.getString(com.fsck.k9.ui.R.string.integrated_inbox_title));
|
||||
|
||||
Intent intent = new Intent(context, MessageListWidgetService.class);
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.fsck.k9.R
|
|||
import com.fsck.k9.ui.base.K9Activity
|
||||
import com.fsck.k9.ui.fragmentTransaction
|
||||
import timber.log.Timber
|
||||
import com.fsck.k9.ui.R as UiR
|
||||
|
||||
/**
|
||||
* Activity to select an account for the unread widget.
|
||||
|
@ -15,7 +16,7 @@ class UnreadWidgetConfigurationActivity : K9Activity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setLayout(R.layout.activity_unread_widget_configuration)
|
||||
setTitle(R.string.unread_widget_select_account)
|
||||
setTitle(UiR.string.unread_widget_select_account)
|
||||
|
||||
var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
val extras = intent.extras
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.fsck.k9.search.SearchAccount
|
|||
import com.fsck.k9.ui.choosefolder.ChooseFolderActivity
|
||||
import com.takisoft.preferencex.PreferenceFragmentCompat
|
||||
import org.koin.android.ext.android.inject
|
||||
import com.fsck.k9.ui.R as UiR
|
||||
|
||||
class UnreadWidgetConfigurationFragment : PreferenceFragmentCompat() {
|
||||
private val preferences: Preferences by inject()
|
||||
|
@ -48,7 +49,7 @@ class UnreadWidgetConfigurationFragment : PreferenceFragmentCompat() {
|
|||
|
||||
unreadFolderEnabled = findPreference(PREFERENCE_UNREAD_FOLDER_ENABLED)!!
|
||||
unreadFolderEnabled.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, _ ->
|
||||
unreadFolder.summary = getString(R.string.unread_widget_folder_summary)
|
||||
unreadFolder.summary = getString(UiR.string.unread_widget_folder_summary)
|
||||
selectedFolderId = null
|
||||
selectedFolderDisplayName = null
|
||||
true
|
||||
|
@ -116,7 +117,7 @@ class UnreadWidgetConfigurationFragment : PreferenceFragmentCompat() {
|
|||
selectedAccountUuid = accountUuid
|
||||
selectedFolderId = null
|
||||
selectedFolderDisplayName = null
|
||||
unreadFolder.summary = getString(R.string.unread_widget_folder_summary)
|
||||
unreadFolder.summary = getString(UiR.string.unread_widget_folder_summary)
|
||||
if (SearchAccount.UNIFIED_INBOX == selectedAccountUuid) {
|
||||
handleSearchAccount()
|
||||
} else {
|
||||
|
@ -126,7 +127,7 @@ class UnreadWidgetConfigurationFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun handleSearchAccount() {
|
||||
if (SearchAccount.UNIFIED_INBOX == selectedAccountUuid) {
|
||||
unreadAccount.setSummary(R.string.unread_widget_unified_inbox_account_summary)
|
||||
unreadAccount.setSummary(UiR.string.unread_widget_unified_inbox_account_summary)
|
||||
}
|
||||
unreadFolderEnabled.isEnabled = false
|
||||
unreadFolderEnabled.isChecked = false
|
||||
|
@ -168,10 +169,10 @@ class UnreadWidgetConfigurationFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun validateWidget(): Boolean {
|
||||
if (selectedAccountUuid == null) {
|
||||
Toast.makeText(requireContext(), R.string.unread_widget_account_not_selected, Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(requireContext(), UiR.string.unread_widget_account_not_selected, Toast.LENGTH_LONG).show()
|
||||
return false
|
||||
} else if (unreadFolderEnabled.isChecked && selectedFolderId == null) {
|
||||
Toast.makeText(requireContext(), R.string.unread_widget_folder_not_selected, Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(requireContext(), UiR.string.unread_widget_folder_not_selected, Toast.LENGTH_LONG).show()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.R
|
||||
import com.fsck.k9.activity.MessageList
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.mailstore.FolderRepository
|
||||
|
@ -13,6 +12,7 @@ import com.fsck.k9.search.SearchAccount
|
|||
import com.fsck.k9.ui.folders.FolderNameFormatterFactory
|
||||
import com.fsck.k9.ui.messagelist.DefaultFolderProvider
|
||||
import timber.log.Timber
|
||||
import com.fsck.k9.ui.R as UiR
|
||||
|
||||
class UnreadWidgetDataProvider(
|
||||
private val context: Context,
|
||||
|
@ -68,7 +68,7 @@ class UnreadWidgetDataProvider(
|
|||
|
||||
val accountName = account.displayName
|
||||
val folderDisplayName = getFolderDisplayName(account, folderId)
|
||||
val title = context.getString(R.string.unread_widget_title, accountName, folderDisplayName)
|
||||
val title = context.getString(UiR.string.unread_widget_title, accountName, folderDisplayName)
|
||||
|
||||
val unreadCount = messagingController.getFolderUnreadMessageCount(account, folderId)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
android:initialLayout="@layout/message_list_widget_layout"
|
||||
android:minHeight="180dp"
|
||||
android:minWidth="250dp"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:previewImage="@drawable/message_list_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
|
|
|
@ -24,6 +24,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.storage'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.fsck.k9.storage" />
|
|
@ -70,30 +70,30 @@ internal class CopyMessageOperations(
|
|||
private fun copyMessageParts(database: SQLiteDatabase, messageId: Long): Long {
|
||||
return database.rawQuery(
|
||||
"""
|
||||
SELECT
|
||||
message_parts.id,
|
||||
message_parts.type,
|
||||
message_parts.root,
|
||||
message_parts.parent,
|
||||
message_parts.seq,
|
||||
message_parts.mime_type,
|
||||
message_parts.decoded_body_size,
|
||||
message_parts.display_name,
|
||||
message_parts.header,
|
||||
message_parts.encoding,
|
||||
message_parts.charset,
|
||||
message_parts.data_location,
|
||||
message_parts.data,
|
||||
message_parts.preamble,
|
||||
message_parts.epilogue,
|
||||
message_parts.boundary,
|
||||
message_parts.content_id,
|
||||
message_parts.server_extra
|
||||
FROM messages
|
||||
JOIN message_parts ON (message_parts.root = messages.message_part_id)
|
||||
WHERE messages.id = ?
|
||||
ORDER BY message_parts.seq
|
||||
""".trimIndent(),
|
||||
SELECT
|
||||
message_parts.id,
|
||||
message_parts.type,
|
||||
message_parts.root,
|
||||
message_parts.parent,
|
||||
message_parts.seq,
|
||||
message_parts.mime_type,
|
||||
message_parts.decoded_body_size,
|
||||
message_parts.display_name,
|
||||
message_parts.header,
|
||||
message_parts.encoding,
|
||||
message_parts.charset,
|
||||
message_parts.data_location,
|
||||
message_parts.data,
|
||||
message_parts.preamble,
|
||||
message_parts.epilogue,
|
||||
message_parts.boundary,
|
||||
message_parts.content_id,
|
||||
message_parts.server_extra
|
||||
FROM messages
|
||||
JOIN message_parts ON (message_parts.root = messages.message_part_id)
|
||||
WHERE messages.id = ?
|
||||
ORDER BY message_parts.seq
|
||||
""",
|
||||
arrayOf(messageId.toString())
|
||||
).use { cursor ->
|
||||
if (!cursor.moveToNext()) error("No message part found for message with ID $messageId")
|
||||
|
@ -201,10 +201,8 @@ internal class CopyMessageOperations(
|
|||
|
||||
private fun copyFulltextEntry(database: SQLiteDatabase, newMessageId: Long, messageId: Long) {
|
||||
database.execSQL(
|
||||
"""
|
||||
INSERT OR REPLACE INTO messages_fulltext (docid, fulltext)
|
||||
SELECT ?, fulltext FROM messages_fulltext WHERE docid = ?
|
||||
""".trimIndent(),
|
||||
"INSERT OR REPLACE INTO messages_fulltext (docid, fulltext) " +
|
||||
"SELECT ?, fulltext FROM messages_fulltext WHERE docid = ?",
|
||||
arrayOf(newMessageId.toString(), messageId.toString())
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,16 +19,16 @@ internal class DeleteFolderOperations(
|
|||
private fun SQLiteDatabase.deleteMessagePartFiles(folderServerId: String) {
|
||||
rawQuery(
|
||||
"""
|
||||
SELECT message_parts.id
|
||||
FROM folders
|
||||
JOIN messages ON (messages.folder_id = folders.id)
|
||||
JOIN message_parts ON (
|
||||
message_parts.root = messages.message_part_id
|
||||
AND
|
||||
message_parts.data_location = $DATA_LOCATION_ON_DISK
|
||||
)
|
||||
WHERE folders.server_id = ?
|
||||
""".trimIndent(),
|
||||
SELECT message_parts.id
|
||||
FROM folders
|
||||
JOIN messages ON (messages.folder_id = folders.id)
|
||||
JOIN message_parts ON (
|
||||
message_parts.root = messages.message_part_id
|
||||
AND
|
||||
message_parts.data_location = $DATA_LOCATION_ON_DISK
|
||||
)
|
||||
WHERE folders.server_id = ?
|
||||
""",
|
||||
arrayOf(folderServerId)
|
||||
).use { cursor ->
|
||||
while (cursor.moveToNext()) {
|
||||
|
|
|
@ -38,12 +38,12 @@ internal class DeleteMessageOperations(
|
|||
return lockableDatabase.execute(false) { database ->
|
||||
database.rawQuery(
|
||||
"""
|
||||
SELECT messages.id, messages.message_part_id, COUNT(threads2.id)
|
||||
FROM messages
|
||||
LEFT JOIN threads threads1 ON (threads1.message_id = messages.id)
|
||||
LEFT JOIN threads threads2 ON (threads2.parent = threads1.id)
|
||||
WHERE folder_id = ? AND uid = ?
|
||||
""".trimIndent(),
|
||||
SELECT messages.id, messages.message_part_id, COUNT(threads2.id)
|
||||
FROM messages
|
||||
LEFT JOIN threads threads1 ON (threads1.message_id = messages.id)
|
||||
LEFT JOIN threads threads2 ON (threads2.parent = threads1.id)
|
||||
WHERE folder_id = ? AND uid = ?
|
||||
""",
|
||||
arrayOf(folderId.toString(), messageServerId)
|
||||
).use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
|
@ -128,12 +128,12 @@ internal class DeleteMessageOperations(
|
|||
private fun SQLiteDatabase.getEmptyThreadParent(messageId: Long): Long? {
|
||||
return rawQuery(
|
||||
"""
|
||||
SELECT messages.id
|
||||
FROM threads threads1
|
||||
JOIN threads threads2 ON (threads1.parent = threads2.id)
|
||||
JOIN messages ON (threads2.message_id = messages.id AND messages.empty = 1)
|
||||
WHERE threads1.message_id = ?
|
||||
""".trimIndent(),
|
||||
SELECT messages.id
|
||||
FROM threads threads1
|
||||
JOIN threads threads2 ON (threads1.parent = threads2.id)
|
||||
JOIN messages ON (threads2.message_id = messages.id AND messages.empty = 1)
|
||||
WHERE threads1.message_id = ?
|
||||
""",
|
||||
arrayOf(messageId.toString())
|
||||
).use { cursor ->
|
||||
if (cursor.moveToFirst() && !cursor.isNull(0)) {
|
||||
|
@ -151,11 +151,11 @@ internal class DeleteMessageOperations(
|
|||
private fun SQLiteDatabase.hasThreadChildren(messageId: Long): Boolean {
|
||||
return rawQuery(
|
||||
"""
|
||||
SELECT COUNT(threads2.id)
|
||||
FROM threads threads1
|
||||
JOIN threads threads2 ON (threads2.parent = threads1.id)
|
||||
WHERE threads1.message_id = ?
|
||||
""".trimIndent(),
|
||||
SELECT COUNT(threads2.id)
|
||||
FROM threads threads1
|
||||
JOIN threads threads2 ON (threads2.parent = threads1.id)
|
||||
WHERE threads1.message_id = ?
|
||||
""",
|
||||
arrayOf(messageId.toString())
|
||||
).use { cursor ->
|
||||
cursor.moveToFirst() && !cursor.isNull(0) && cursor.getLong(0) > 0L
|
||||
|
|
|
@ -70,22 +70,22 @@ internal class RetrieveFolderOperations(private val lockableDatabase: LockableDa
|
|||
|
||||
val query =
|
||||
"""
|
||||
SELECT ${FOLDER_COLUMNS.joinToString()}, (
|
||||
SELECT COUNT(messages.id)
|
||||
FROM messages
|
||||
WHERE messages.folder_id = folders.id
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
AND (messages.read = 0 OR folders.id = ?)
|
||||
), (
|
||||
SELECT COUNT(messages.id)
|
||||
FROM messages
|
||||
WHERE messages.folder_id = folders.id
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
AND messages.flagged = 1
|
||||
)
|
||||
FROM folders
|
||||
$displayModeSelection
|
||||
""".trimIndent()
|
||||
SELECT ${FOLDER_COLUMNS.joinToString()}, (
|
||||
SELECT COUNT(messages.id)
|
||||
FROM messages
|
||||
WHERE messages.folder_id = folders.id
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
AND (messages.read = 0 OR folders.id = ?)
|
||||
), (
|
||||
SELECT COUNT(messages.id)
|
||||
FROM messages
|
||||
WHERE messages.folder_id = folders.id
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
AND messages.flagged = 1
|
||||
)
|
||||
FROM folders
|
||||
$displayModeSelection
|
||||
"""
|
||||
|
||||
db.rawQuery(query, arrayOf(outboxFolderIdOrZero.toString())).use { cursor ->
|
||||
val cursorFolderAccessor = CursorFolderAccessor(cursor)
|
||||
|
|
|
@ -20,32 +20,32 @@ internal class RetrieveMessageListOperations(private val lockableDatabase: Locka
|
|||
return lockableDatabase.execute(false) { database ->
|
||||
database.rawQuery(
|
||||
"""
|
||||
SELECT
|
||||
messages.id AS id,
|
||||
uid,
|
||||
folder_id,
|
||||
sender_list,
|
||||
to_list,
|
||||
cc_list,
|
||||
date,
|
||||
internal_date,
|
||||
subject,
|
||||
preview_type,
|
||||
preview,
|
||||
read,
|
||||
flagged,
|
||||
answered,
|
||||
forwarded,
|
||||
attachment_count,
|
||||
root
|
||||
FROM messages
|
||||
JOIN threads ON (threads.message_id = messages.id)
|
||||
LEFT JOIN FOLDERS ON (folders.id = messages.folder_id)
|
||||
WHERE
|
||||
($selection)
|
||||
AND empty = 0 AND deleted = 0
|
||||
ORDER BY $sortOrder
|
||||
""".trimIndent(),
|
||||
SELECT
|
||||
messages.id AS id,
|
||||
uid,
|
||||
folder_id,
|
||||
sender_list,
|
||||
to_list,
|
||||
cc_list,
|
||||
date,
|
||||
internal_date,
|
||||
subject,
|
||||
preview_type,
|
||||
preview,
|
||||
read,
|
||||
flagged,
|
||||
answered,
|
||||
forwarded,
|
||||
attachment_count,
|
||||
root
|
||||
FROM messages
|
||||
JOIN threads ON (threads.message_id = messages.id)
|
||||
LEFT JOIN FOLDERS ON (folders.id = messages.folder_id)
|
||||
WHERE
|
||||
($selection)
|
||||
AND empty = 0 AND deleted = 0
|
||||
ORDER BY $sortOrder
|
||||
""",
|
||||
selectionArgs,
|
||||
).use { cursor ->
|
||||
val cursorMessageAccessor = CursorMessageAccessor(cursor, includesThreadCount = false)
|
||||
|
@ -72,60 +72,60 @@ internal class RetrieveMessageListOperations(private val lockableDatabase: Locka
|
|||
return lockableDatabase.execute(false) { database ->
|
||||
database.rawQuery(
|
||||
"""
|
||||
SELECT
|
||||
messages.id AS id,
|
||||
uid,
|
||||
folder_id,
|
||||
sender_list,
|
||||
to_list,
|
||||
cc_list,
|
||||
aggregated.date AS date,
|
||||
aggregated.internal_date AS internal_date,
|
||||
subject,
|
||||
preview_type,
|
||||
preview,
|
||||
aggregated.read AS read,
|
||||
aggregated.flagged AS flagged,
|
||||
aggregated.answered AS answered,
|
||||
aggregated.forwarded AS forwarded,
|
||||
aggregated.attachment_count AS attachment_count,
|
||||
root,
|
||||
aggregated.thread_count AS thread_count
|
||||
FROM (
|
||||
SELECT
|
||||
threads.root AS thread_root,
|
||||
MAX(date) AS date,
|
||||
MAX(internal_date) AS internal_date,
|
||||
MIN(read) AS read,
|
||||
MAX(flagged) AS flagged,
|
||||
MIN(answered) AS answered,
|
||||
MIN(forwarded) AS forwarded,
|
||||
SUM(attachment_count) AS attachment_count,
|
||||
COUNT(threads.root) AS thread_count
|
||||
FROM messages
|
||||
JOIN threads ON (threads.message_id = messages.id)
|
||||
JOIN folders ON (folders.id = messages.folder_id)
|
||||
WHERE
|
||||
threads.root IN (
|
||||
SELECT threads.root
|
||||
FROM messages
|
||||
JOIN threads ON (threads.message_id = messages.id)
|
||||
WHERE messages.empty = 0 AND messages.deleted = 0
|
||||
)
|
||||
AND ($selection)
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
GROUP BY threads.root
|
||||
) aggregated
|
||||
JOIN threads ON (threads.root = aggregated.thread_root)
|
||||
JOIN messages ON (
|
||||
messages.id = threads.message_id
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
AND messages.date = aggregated.date
|
||||
)
|
||||
JOIN folders ON (folders.id = messages.folder_id)
|
||||
GROUP BY threads.root
|
||||
ORDER BY $orderBy
|
||||
""".trimIndent(),
|
||||
SELECT
|
||||
messages.id AS id,
|
||||
uid,
|
||||
folder_id,
|
||||
sender_list,
|
||||
to_list,
|
||||
cc_list,
|
||||
aggregated.date AS date,
|
||||
aggregated.internal_date AS internal_date,
|
||||
subject,
|
||||
preview_type,
|
||||
preview,
|
||||
aggregated.read AS read,
|
||||
aggregated.flagged AS flagged,
|
||||
aggregated.answered AS answered,
|
||||
aggregated.forwarded AS forwarded,
|
||||
aggregated.attachment_count AS attachment_count,
|
||||
root,
|
||||
aggregated.thread_count AS thread_count
|
||||
FROM (
|
||||
SELECT
|
||||
threads.root AS thread_root,
|
||||
MAX(date) AS date,
|
||||
MAX(internal_date) AS internal_date,
|
||||
MIN(read) AS read,
|
||||
MAX(flagged) AS flagged,
|
||||
MIN(answered) AS answered,
|
||||
MIN(forwarded) AS forwarded,
|
||||
SUM(attachment_count) AS attachment_count,
|
||||
COUNT(threads.root) AS thread_count
|
||||
FROM messages
|
||||
JOIN threads ON (threads.message_id = messages.id)
|
||||
JOIN folders ON (folders.id = messages.folder_id)
|
||||
WHERE
|
||||
threads.root IN (
|
||||
SELECT threads.root
|
||||
FROM messages
|
||||
JOIN threads ON (threads.message_id = messages.id)
|
||||
WHERE messages.empty = 0 AND messages.deleted = 0
|
||||
)
|
||||
AND ($selection)
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
GROUP BY threads.root
|
||||
) aggregated
|
||||
JOIN threads ON (threads.root = aggregated.thread_root)
|
||||
JOIN messages ON (
|
||||
messages.id = threads.message_id
|
||||
AND messages.empty = 0 AND messages.deleted = 0
|
||||
AND messages.date = aggregated.date
|
||||
)
|
||||
JOIN folders ON (folders.id = messages.folder_id)
|
||||
GROUP BY threads.root
|
||||
ORDER BY $orderBy
|
||||
""",
|
||||
selectionArgs,
|
||||
).use { cursor ->
|
||||
val cursorMessageAccessor = CursorMessageAccessor(cursor, includesThreadCount = true)
|
||||
|
@ -145,32 +145,32 @@ internal class RetrieveMessageListOperations(private val lockableDatabase: Locka
|
|||
return lockableDatabase.execute(false) { database ->
|
||||
database.rawQuery(
|
||||
"""
|
||||
SELECT
|
||||
messages.id AS id,
|
||||
uid,
|
||||
folder_id,
|
||||
sender_list,
|
||||
to_list,
|
||||
cc_list,
|
||||
date,
|
||||
internal_date,
|
||||
subject,
|
||||
preview_type,
|
||||
preview,
|
||||
read,
|
||||
flagged,
|
||||
answered,
|
||||
forwarded,
|
||||
attachment_count,
|
||||
root
|
||||
FROM threads
|
||||
JOIN messages ON (messages.id = threads.message_id)
|
||||
LEFT JOIN FOLDERS ON (folders.id = messages.folder_id)
|
||||
WHERE
|
||||
root = ?
|
||||
AND empty = 0 AND deleted = 0
|
||||
ORDER BY $sortOrder
|
||||
""".trimIndent(),
|
||||
SELECT
|
||||
messages.id AS id,
|
||||
uid,
|
||||
folder_id,
|
||||
sender_list,
|
||||
to_list,
|
||||
cc_list,
|
||||
date,
|
||||
internal_date,
|
||||
subject,
|
||||
preview_type,
|
||||
preview,
|
||||
read,
|
||||
flagged,
|
||||
answered,
|
||||
forwarded,
|
||||
attachment_count,
|
||||
root
|
||||
FROM threads
|
||||
JOIN messages ON (messages.id = threads.message_id)
|
||||
LEFT JOIN FOLDERS ON (folders.id = messages.folder_id)
|
||||
WHERE
|
||||
root = ?
|
||||
AND empty = 0 AND deleted = 0
|
||||
ORDER BY $sortOrder
|
||||
""",
|
||||
arrayOf(threadId.toString()),
|
||||
).use { cursor ->
|
||||
val cursorMessageAccessor = CursorMessageAccessor(cursor, includesThreadCount = false)
|
||||
|
|
|
@ -20,11 +20,11 @@ internal class ThreadMessageOperations {
|
|||
fun getMessageThreadHeaders(database: SQLiteDatabase, messageId: Long): ThreadHeaders {
|
||||
return database.rawQuery(
|
||||
"""
|
||||
SELECT messages.message_id, message_parts.header
|
||||
FROM messages
|
||||
LEFT JOIN message_parts ON (messages.message_part_id = message_parts.id)
|
||||
WHERE messages.id = ?
|
||||
""".trimIndent(),
|
||||
SELECT messages.message_id, message_parts.header
|
||||
FROM messages
|
||||
LEFT JOIN message_parts ON (messages.message_part_id = message_parts.id)
|
||||
WHERE messages.id = ?
|
||||
""",
|
||||
arrayOf(messageId.toString()),
|
||||
).use { cursor ->
|
||||
if (!cursor.moveToFirst()) error("Message not found: $messageId")
|
||||
|
@ -157,14 +157,14 @@ internal class ThreadMessageOperations {
|
|||
|
||||
return db.rawQuery(
|
||||
"""
|
||||
SELECT t.id, t.message_id, t.root, t.parent
|
||||
FROM messages m
|
||||
LEFT JOIN threads t ON (t.message_id = m.id)
|
||||
WHERE m.folder_id = ? AND m.message_id = ?
|
||||
${if (onlyEmpty) "AND m.empty = 1 " else ""}
|
||||
ORDER BY m.id
|
||||
LIMIT 1
|
||||
""".trimIndent(),
|
||||
SELECT t.id, t.message_id, t.root, t.parent
|
||||
FROM messages m
|
||||
LEFT JOIN threads t ON (t.message_id = m.id)
|
||||
WHERE m.folder_id = ? AND m.message_id = ?
|
||||
${if (onlyEmpty) "AND m.empty = 1 " else ""}
|
||||
ORDER BY m.id
|
||||
LIMIT 1
|
||||
""",
|
||||
arrayOf(folderId.toString(), messageIdHeader)
|
||||
).use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
|
|
|
@ -12,6 +12,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.testing'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.fsck.k9.testing" />
|
|
@ -18,6 +18,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.ui.base'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.fsck.k9.ui.base">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ class ThemeManager(
|
|||
.onEach {
|
||||
updateAppTheme(it)
|
||||
}
|
||||
.launchIn(appCoroutineScope + Dispatchers.Main)
|
||||
.launchIn(appCoroutineScope + Dispatchers.Main.immediate)
|
||||
}
|
||||
|
||||
private fun updateAppTheme(appTheme: AppTheme) {
|
||||
|
|
|
@ -33,9 +33,7 @@ dependencies {
|
|||
implementation "com.splitwise:tokenautocomplete:4.0.0-beta01"
|
||||
implementation "de.cketti.safecontentresolver:safe-content-resolver-v21:1.0.0"
|
||||
implementation 'com.mikepenz:materialdrawer:8.4.5'
|
||||
implementation 'com.mikepenz:materialdrawer-iconics:8.4.5'
|
||||
implementation 'com.mikepenz:fontawesome-typeface:5.9.0.0-kotlin@aar'
|
||||
implementation 'com.github.ByteHamster:SearchPreference:v2.2.1'
|
||||
implementation 'com.github.ByteHamster:SearchPreference:v2.3.0'
|
||||
implementation "com.mikepenz:fastadapter:${versions.fastAdapter}"
|
||||
implementation "com.mikepenz:fastadapter-extensions-drag:${versions.fastAdapter}"
|
||||
implementation "com.mikepenz:fastadapter-extensions-utils:${versions.fastAdapter}"
|
||||
|
@ -70,6 +68,8 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace 'com.fsck.k9.ui'
|
||||
|
||||
compileSdkVersion buildConfig.compileSdk
|
||||
buildToolsVersion buildConfig.buildTools
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.fsck.k9.ui">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.fsck.k9.account.accountModule
|
|||
import com.fsck.k9.activity.activityModule
|
||||
import com.fsck.k9.autodiscovery.providersxml.autodiscoveryProvidersXmlModule
|
||||
import com.fsck.k9.contacts.contactsModule
|
||||
import com.fsck.k9.fragment.fragmentModule
|
||||
import com.fsck.k9.ui.account.accountUiModule
|
||||
import com.fsck.k9.ui.base.uiBaseModule
|
||||
import com.fsck.k9.ui.changelog.changelogUiModule
|
||||
|
@ -28,7 +27,6 @@ val uiModules = listOf(
|
|||
messageListUiModule,
|
||||
manageFoldersUiModule,
|
||||
chooseFolderUiModule,
|
||||
fragmentModule,
|
||||
contactsModule,
|
||||
accountModule,
|
||||
autodiscoveryProvidersXmlModule,
|
||||
|
|
|
@ -3,10 +3,9 @@ package com.fsck.k9.account
|
|||
import android.content.res.Resources
|
||||
import com.fsck.k9.Account.DeletePolicy
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.core.R
|
||||
import com.fsck.k9.mail.ConnectionSecurity
|
||||
import com.fsck.k9.preferences.Protocols
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.helper.MaterialColors
|
||||
|
||||
/**
|
||||
* Deals with logic surrounding account creation.
|
||||
|
@ -53,7 +52,7 @@ class AccountCreator(private val preferences: Preferences, private val resources
|
|||
|
||||
fun pickColor(): Int {
|
||||
val accounts = preferences.accounts
|
||||
val usedAccountColors = accounts.map { it.chipColor }
|
||||
val usedAccountColors = accounts.map { it.chipColor }.toSet()
|
||||
val accountColors = resources.getIntArray(R.array.account_colors).toList()
|
||||
|
||||
val availableColors = accountColors - usedAccountColors
|
||||
|
@ -61,17 +60,10 @@ class AccountCreator(private val preferences: Preferences, private val resources
|
|||
return accountColors.random()
|
||||
}
|
||||
|
||||
val defaultAccountColors = resources.getIntArray(R.array.default_account_colors)
|
||||
return availableColors.shuffled().minByOrNull { color ->
|
||||
val index = DEFAULT_COLORS.indexOf(color)
|
||||
if (index != -1) index else DEFAULT_COLORS.size
|
||||
val index = defaultAccountColors.indexOf(color)
|
||||
if (index != -1) index else defaultAccountColors.size
|
||||
} ?: error("availableColors must not be empty")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DEFAULT_COLORS = intArrayOf(
|
||||
MaterialColors.BLUE_700,
|
||||
MaterialColors.PINK_500,
|
||||
MaterialColors.AMBER_600
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package com.fsck.k9.activity;
|
||||
|
||||
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.ui.base.K9Activity;
|
||||
|
||||
|
||||
|
@ -15,45 +12,6 @@ public abstract class K9ListActivity extends K9Activity {
|
|||
protected ListAdapter adapter;
|
||||
protected ListView list;
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
// Shortcuts that work no matter what is selected
|
||||
if (K9.isUseVolumeKeysForListNavigation() &&
|
||||
(keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
|
||||
keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
|
||||
|
||||
final ListView listView = getListView();
|
||||
|
||||
int currentPosition = listView.getSelectedItemPosition();
|
||||
if (currentPosition == AdapterView.INVALID_POSITION || listView.isInTouchMode()) {
|
||||
currentPosition = listView.getFirstVisiblePosition();
|
||||
}
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && currentPosition > 0) {
|
||||
listView.setSelection(currentPosition - 1);
|
||||
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN &&
|
||||
currentPosition < listView.getCount()) {
|
||||
listView.setSelection(currentPosition + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
// Swallow these events too to avoid the audible notification of a volume change
|
||||
if (K9.isUseVolumeKeysForListNavigation() &&
|
||||
(keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
|
||||
keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
protected ListView getListView() {
|
||||
if (list == null) {
|
||||
list = findViewById(android.R.id.list);
|
||||
|
|
|
@ -15,7 +15,6 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.appcompat.widget.SearchView
|
||||
|
@ -35,8 +34,6 @@ import com.fsck.k9.account.BackgroundAccountRemover
|
|||
import com.fsck.k9.activity.compose.MessageActions
|
||||
import com.fsck.k9.controller.MessageReference
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.fragment.MessageListFragment
|
||||
import com.fsck.k9.fragment.MessageListFragment.MessageListFragmentListener
|
||||
import com.fsck.k9.helper.Contacts
|
||||
import com.fsck.k9.helper.ParcelableUtil
|
||||
import com.fsck.k9.mailstore.SearchStatusManager
|
||||
|
@ -55,6 +52,8 @@ import com.fsck.k9.ui.changelog.RecentChangesActivity
|
|||
import com.fsck.k9.ui.changelog.RecentChangesViewModel
|
||||
import com.fsck.k9.ui.managefolders.ManageFoldersActivity
|
||||
import com.fsck.k9.ui.messagelist.DefaultFolderProvider
|
||||
import com.fsck.k9.ui.messagelist.MessageListFragment
|
||||
import com.fsck.k9.ui.messagelist.MessageListFragment.MessageListFragmentListener
|
||||
import com.fsck.k9.ui.messageview.Direction
|
||||
import com.fsck.k9.ui.messageview.MessageViewContainerFragment
|
||||
import com.fsck.k9.ui.messageview.MessageViewContainerFragment.MessageViewContainerListener
|
||||
|
@ -120,7 +119,7 @@ open class MessageList :
|
|||
?: if (K9.isMessageViewShowNext) Direction.NEXT else Direction.PREVIOUS
|
||||
}
|
||||
|
||||
private var messageListActivityAppearance: MessageListActivityAppearance? = null
|
||||
private var messageListActivityConfig: MessageListActivityConfig? = null
|
||||
|
||||
/**
|
||||
* `true` if the message list should be displayed as flat list (i.e. no threading)
|
||||
|
@ -552,9 +551,9 @@ open class MessageList :
|
|||
public override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
if (messageListActivityAppearance == null) {
|
||||
messageListActivityAppearance = MessageListActivityAppearance.create(generalSettingsManager)
|
||||
} else if (messageListActivityAppearance != MessageListActivityAppearance.create(generalSettingsManager)) {
|
||||
if (messageListActivityConfig == null) {
|
||||
messageListActivityConfig = MessageListActivityConfig.create(generalSettingsManager)
|
||||
} else if (messageListActivityConfig != MessageListActivityConfig.create(generalSettingsManager)) {
|
||||
recreateCompat()
|
||||
}
|
||||
|
||||
|
@ -591,7 +590,7 @@ open class MessageList :
|
|||
|
||||
messageViewOnly = savedInstanceState.getBoolean(STATE_MESSAGE_VIEW_ONLY)
|
||||
messageListWasDisplayed = savedInstanceState.getBoolean(STATE_MESSAGE_LIST_WAS_DISPLAYED)
|
||||
initialSearchViewIconified = savedInstanceState.getBoolean(STATE_SEARCH_VIEW_ICONIFIED)
|
||||
initialSearchViewIconified = savedInstanceState.getBoolean(STATE_SEARCH_VIEW_ICONIFIED, true)
|
||||
initialSearchViewQuery = savedInstanceState.getString(STATE_SEARCH_VIEW_QUERY)
|
||||
}
|
||||
|
||||
|
@ -620,7 +619,10 @@ open class MessageList :
|
|||
|
||||
override fun onDrawerStateChanged(newState: Int) = Unit
|
||||
|
||||
override fun onDrawerOpened(drawerView: View) = Unit
|
||||
override fun onDrawerOpened(drawerView: View) {
|
||||
collapseSearchView()
|
||||
messageListFragment?.finishActionMode()
|
||||
}
|
||||
|
||||
override fun onDrawerSlide(drawerView: View, slideOffset: Float) = Unit
|
||||
}
|
||||
|
@ -762,9 +764,6 @@ open class MessageList :
|
|||
) {
|
||||
showPreviousMessage()
|
||||
return true
|
||||
} else if (displayMode != DisplayMode.MESSAGE_VIEW && K9.isUseVolumeKeysForListNavigation) {
|
||||
messageListFragment!!.onMoveUp()
|
||||
return true
|
||||
}
|
||||
}
|
||||
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
||||
|
@ -773,9 +772,6 @@ open class MessageList :
|
|||
) {
|
||||
showNextMessage()
|
||||
return true
|
||||
} else if (displayMode != DisplayMode.MESSAGE_VIEW && K9.isUseVolumeKeysForListNavigation) {
|
||||
messageListFragment!!.onMoveDown()
|
||||
return true
|
||||
}
|
||||
}
|
||||
KeyEvent.KEYCODE_DEL -> {
|
||||
|
@ -889,15 +885,6 @@ open class MessageList :
|
|||
}
|
||||
return true
|
||||
}
|
||||
'h' -> {
|
||||
val toast = if (displayMode == DisplayMode.MESSAGE_LIST) {
|
||||
Toast.makeText(this, R.string.message_list_help_key, Toast.LENGTH_LONG)
|
||||
} else {
|
||||
Toast.makeText(this, R.string.message_view_help_key, Toast.LENGTH_LONG)
|
||||
}
|
||||
toast.show()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -913,7 +900,7 @@ open class MessageList :
|
|||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
||||
// Swallow these events too to avoid the audible notification of a volume change
|
||||
if (K9.isUseVolumeKeysForListNavigation) {
|
||||
if (K9.isUseVolumeKeysForNavigation) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
Timber.v("Swallowed key up.")
|
||||
return true
|
||||
|
@ -931,7 +918,6 @@ open class MessageList :
|
|||
if (drawer!!.isOpen) {
|
||||
drawer!!.close()
|
||||
} else {
|
||||
collapseSearchView()
|
||||
drawer!!.open()
|
||||
}
|
||||
} else {
|
||||
|
@ -979,8 +965,8 @@ open class MessageList :
|
|||
}
|
||||
})
|
||||
|
||||
searchView.isIconified = initialSearchViewIconified
|
||||
searchView.setQuery(initialSearchViewQuery, false)
|
||||
searchView.isIconified = initialSearchViewIconified
|
||||
|
||||
this.searchView = searchView
|
||||
}
|
||||
|
@ -1080,6 +1066,8 @@ open class MessageList :
|
|||
}
|
||||
|
||||
private fun addMessageListFragment(fragment: MessageListFragment) {
|
||||
messageListFragment?.isActive = false
|
||||
|
||||
supportFragmentManager.commit {
|
||||
replace(R.id.message_list_container, fragment)
|
||||
|
||||
|
@ -1207,10 +1195,16 @@ open class MessageList :
|
|||
}
|
||||
|
||||
private fun showLogicalNextMessage(): Boolean {
|
||||
return when (lastDirection) {
|
||||
val couldMoveInLastDirection = when (lastDirection) {
|
||||
Direction.NEXT -> showNextMessage()
|
||||
Direction.PREVIOUS -> showPreviousMessage()
|
||||
}
|
||||
|
||||
return if (couldMoveInLastDirection) {
|
||||
true
|
||||
} else {
|
||||
showNextMessage() || showPreviousMessage()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setProgress(enable: Boolean) {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.fsck.k9.activity
|
||||
|
||||
import com.fsck.k9.K9
|
||||
import com.fsck.k9.SwipeAction
|
||||
import com.fsck.k9.preferences.AppTheme
|
||||
import com.fsck.k9.preferences.GeneralSettingsManager
|
||||
import com.fsck.k9.preferences.SubTheme
|
||||
|
||||
data class MessageListActivityAppearance(
|
||||
data class MessageListActivityConfig(
|
||||
val appTheme: AppTheme,
|
||||
val isShowUnifiedInbox: Boolean,
|
||||
val isShowMessageListStars: Boolean,
|
||||
|
@ -31,13 +32,15 @@ data class MessageListActivityAppearance(
|
|||
val fontSizeMessageViewAdditionalHeaders: Int,
|
||||
val fontSizeMessageViewSubject: Int,
|
||||
val fontSizeMessageViewDate: Int,
|
||||
val fontSizeMessageViewContentAsPercent: Int
|
||||
val fontSizeMessageViewContentAsPercent: Int,
|
||||
val swipeRightAction: SwipeAction,
|
||||
val swipeLeftAction: SwipeAction,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun create(generalSettingsManager: GeneralSettingsManager): MessageListActivityAppearance {
|
||||
fun create(generalSettingsManager: GeneralSettingsManager): MessageListActivityConfig {
|
||||
val settings = generalSettingsManager.getSettings()
|
||||
return MessageListActivityAppearance(
|
||||
return MessageListActivityConfig(
|
||||
appTheme = settings.appTheme,
|
||||
isShowUnifiedInbox = K9.isShowUnifiedInbox,
|
||||
isShowMessageListStars = K9.isShowMessageListStars,
|
||||
|
@ -63,7 +66,9 @@ data class MessageListActivityAppearance(
|
|||
fontSizeMessageViewAdditionalHeaders = K9.fontSizes.messageViewAdditionalHeaders,
|
||||
fontSizeMessageViewSubject = K9.fontSizes.messageViewSubject,
|
||||
fontSizeMessageViewDate = K9.fontSizes.messageViewDate,
|
||||
fontSizeMessageViewContentAsPercent = K9.fontSizes.messageViewContentAsPercent
|
||||
fontSizeMessageViewContentAsPercent = K9.fontSizes.messageViewContentAsPercent,
|
||||
swipeRightAction = K9.swipeRightAction,
|
||||
swipeLeftAction = K9.swipeLeftAction,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,26 +1,28 @@
|
|||
package com.fsck.k9.contacts
|
||||
|
||||
import android.content.Context
|
||||
import android.util.TypedValue
|
||||
import android.view.ContextThemeWrapper
|
||||
import com.fsck.k9.K9
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.base.Theme
|
||||
import com.fsck.k9.ui.base.ThemeManager
|
||||
import com.fsck.k9.ui.getIntArray
|
||||
import com.fsck.k9.ui.resolveColorAttribute
|
||||
|
||||
class ContactLetterBitmapConfig(context: Context, themeManager: ThemeManager) {
|
||||
val hasDefaultBackgroundColor: Boolean = !K9.isColorizeMissingContactPictures
|
||||
val useDarkTheme = themeManager.appTheme == Theme.DARK
|
||||
val defaultBackgroundColor: Int
|
||||
val backgroundColors: IntArray
|
||||
|
||||
init {
|
||||
defaultBackgroundColor = if (hasDefaultBackgroundColor) {
|
||||
val outValue = TypedValue()
|
||||
val themedContext = ContextThemeWrapper(context, themeManager.appThemeResourceId)
|
||||
themedContext.theme.resolveAttribute(R.attr.contactPictureFallbackDefaultBackgroundColor, outValue, true)
|
||||
outValue.data
|
||||
val themedContext = ContextThemeWrapper(context, themeManager.appThemeResourceId)
|
||||
val theme = themedContext.theme
|
||||
|
||||
if (hasDefaultBackgroundColor) {
|
||||
defaultBackgroundColor = theme.resolveColorAttribute(R.attr.contactPictureFallbackDefaultBackgroundColor)
|
||||
backgroundColors = intArrayOf()
|
||||
} else {
|
||||
0
|
||||
defaultBackgroundColor = 0
|
||||
backgroundColors = theme.getIntArray(R.attr.contactPictureFallbackBackgroundColors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.graphics.Canvas
|
|||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import com.fsck.k9.mail.Address
|
||||
import com.fsck.k9.ui.helper.MaterialColors
|
||||
|
||||
/**
|
||||
* Draw a `Bitmap` containing the "contact letter" obtained by [ContactLetterExtractor].
|
||||
|
@ -48,54 +47,12 @@ class ContactLetterBitmapCreator(
|
|||
}
|
||||
|
||||
val hash = address.hashCode()
|
||||
if (config.useDarkTheme) {
|
||||
val colorIndex = (hash and Integer.MAX_VALUE) % BACKGROUND_COLORS_DARK.size
|
||||
return BACKGROUND_COLORS_DARK[colorIndex]
|
||||
} else {
|
||||
val colorIndex = (hash and Integer.MAX_VALUE) % BACKGROUND_COLORS_LIGHT.size
|
||||
return BACKGROUND_COLORS_LIGHT[colorIndex]
|
||||
}
|
||||
val backgroundColors = config.backgroundColors
|
||||
val colorIndex = (hash and Integer.MAX_VALUE) % backgroundColors.size
|
||||
return backgroundColors[colorIndex]
|
||||
}
|
||||
|
||||
fun signatureOf(address: Address): String {
|
||||
return calcUnknownContactColor(address).toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val BACKGROUND_COLORS_LIGHT = intArrayOf(
|
||||
MaterialColors.RED_300,
|
||||
MaterialColors.DEEP_PURPLE_300,
|
||||
MaterialColors.LIGHT_BLUE_300,
|
||||
MaterialColors.GREEN_300,
|
||||
MaterialColors.DEEP_ORANGE_300,
|
||||
MaterialColors.BLUE_GREY_300,
|
||||
MaterialColors.PINK_300,
|
||||
MaterialColors.INDIGO_300,
|
||||
MaterialColors.CYAN_300,
|
||||
MaterialColors.AMBER_400,
|
||||
MaterialColors.BROWN_300,
|
||||
MaterialColors.PURPLE_300,
|
||||
MaterialColors.BLUE_300,
|
||||
MaterialColors.TEAL_300,
|
||||
MaterialColors.ORANGE_400
|
||||
)
|
||||
|
||||
private val BACKGROUND_COLORS_DARK = intArrayOf(
|
||||
MaterialColors.RED_600,
|
||||
MaterialColors.DEEP_PURPLE_600,
|
||||
MaterialColors.LIGHT_BLUE_600,
|
||||
MaterialColors.GREEN_600,
|
||||
MaterialColors.DEEP_ORANGE_600,
|
||||
MaterialColors.BLUE_GREY_600,
|
||||
MaterialColors.PINK_600,
|
||||
MaterialColors.INDIGO_600,
|
||||
MaterialColors.CYAN_600,
|
||||
MaterialColors.AMBER_600,
|
||||
MaterialColors.BROWN_600,
|
||||
MaterialColors.PURPLE_600,
|
||||
MaterialColors.BLUE_600,
|
||||
MaterialColors.TEAL_600,
|
||||
MaterialColors.ORANGE_600
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package com.fsck.k9.fragment
|
||||
|
||||
import org.koin.dsl.module
|
||||
|
||||
val fragmentModule = module {
|
||||
single { SortTypeToastProvider() }
|
||||
}
|
|
@ -56,6 +56,8 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
|||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import com.fsck.k9.core.R as CoreR
|
||||
import com.mikepenz.materialdrawer.R as MaterialDrawerR
|
||||
|
||||
private const val UNREAD_SYMBOL = "\u2B24"
|
||||
private const val STARRED_SYMBOL = "\u2605"
|
||||
|
@ -466,8 +468,8 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
}
|
||||
|
||||
private fun getDarkThemeAccentColor(color: Int): Int {
|
||||
val lightColors = resources.getIntArray(R.array.account_colors)
|
||||
val darkColors = resources.getIntArray(R.array.drawer_account_accent_color_dark_theme)
|
||||
val lightColors = resources.getIntArray(CoreR.array.account_colors)
|
||||
val darkColors = resources.getIntArray(CoreR.array.drawer_account_accent_color_dark_theme)
|
||||
val index = lightColors.indexOf(color)
|
||||
return if (index == -1) color else darkColors[index]
|
||||
}
|
||||
|
@ -537,11 +539,11 @@ class K9Drawer(private val parent: MessageList, savedInstanceState: Bundle?) : K
|
|||
private fun Context.obtainDrawerTextColor(): Int {
|
||||
val styledAttributes = obtainStyledAttributes(
|
||||
null,
|
||||
R.styleable.MaterialDrawerSliderView,
|
||||
R.attr.materialDrawerStyle,
|
||||
R.style.Widget_MaterialDrawerStyle
|
||||
MaterialDrawerR.styleable.MaterialDrawerSliderView,
|
||||
MaterialDrawerR.attr.materialDrawerStyle,
|
||||
MaterialDrawerR.style.Widget_MaterialDrawerStyle
|
||||
)
|
||||
val textColor = styledAttributes.getColor(R.styleable.MaterialDrawerSliderView_materialDrawerPrimaryText, 0)
|
||||
val textColor = styledAttributes.getColor(MaterialDrawerR.styleable.MaterialDrawerSliderView_materialDrawerPrimaryText, 0)
|
||||
styledAttributes.recycle()
|
||||
|
||||
return textColor
|
||||
|
|
|
@ -25,3 +25,14 @@ fun Theme.resolveDrawableAttribute(attrId: Int): Drawable {
|
|||
|
||||
return getDrawable(typedValue.resourceId)
|
||||
}
|
||||
|
||||
fun Theme.getIntArray(attrId: Int): IntArray {
|
||||
val typedValue = TypedValue()
|
||||
|
||||
val found = resolveAttribute(attrId, typedValue, true)
|
||||
if (!found) {
|
||||
throw IllegalStateException("Couldn't resolve attribute ($attrId)")
|
||||
}
|
||||
|
||||
return resources.getIntArray(typedValue.resourceId)
|
||||
}
|
||||
|
|
|
@ -2,24 +2,21 @@ package com.fsck.k9.ui.account
|
|||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat
|
||||
import androidx.core.graphics.BlendModeCompat
|
||||
import com.fsck.k9.ui.R
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.fontawesome.FontAwesome
|
||||
import com.mikepenz.iconics.utils.backgroundColorInt
|
||||
import com.mikepenz.iconics.utils.colorRes
|
||||
import com.mikepenz.iconics.utils.paddingDp
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
|
||||
/**
|
||||
* Provides a [Drawable] for the account using the account's color as background color.
|
||||
*/
|
||||
class AccountFallbackImageProvider(private val context: Context) {
|
||||
fun getDrawable(color: Int): Drawable {
|
||||
return IconicsDrawable(context, FontAwesome.Icon.faw_user_alt).apply {
|
||||
colorRes = R.color.material_drawer_profile_icon
|
||||
backgroundColorInt = color
|
||||
sizeDp = 56
|
||||
paddingDp = 12
|
||||
val drawable = ContextCompat.getDrawable(context, R.drawable.drawer_account_fallback)
|
||||
?: error("Error loading drawable")
|
||||
|
||||
return drawable.mutate().apply {
|
||||
colorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.DST_OVER)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,216 +0,0 @@
|
|||
package com.fsck.k9.ui.helper
|
||||
|
||||
@Suppress("unused")
|
||||
object MaterialColors {
|
||||
/*
|
||||
* Heavily modified version of https://gist.github.com/kalehv/bae765c756e94455ed88
|
||||
*/
|
||||
const val RED_50 = 0xFFFFEBEE.toInt()
|
||||
const val RED_100 = 0xFFFFCDD2.toInt()
|
||||
const val RED_200 = 0xFFEF9A9A.toInt()
|
||||
const val RED_300 = 0xFFE57373.toInt()
|
||||
const val RED_400 = 0xFFEF5350.toInt()
|
||||
const val RED_500 = 0xFFF44336.toInt()
|
||||
const val RED_600 = 0xFFE53935.toInt()
|
||||
const val RED_700 = 0xFFD32F2F.toInt()
|
||||
const val RED_800 = 0xFFC62828.toInt()
|
||||
const val RED_900 = 0xFFB71C1C.toInt()
|
||||
|
||||
const val DEEP_PURPLE_50 = 0xFFEDE7F6.toInt()
|
||||
const val DEEP_PURPLE_100 = 0xFFD1C4E9.toInt()
|
||||
const val DEEP_PURPLE_200 = 0xFFB39DDB.toInt()
|
||||
const val DEEP_PURPLE_300 = 0xFF9575CD.toInt()
|
||||
const val DEEP_PURPLE_400 = 0xFF7E57C2.toInt()
|
||||
const val DEEP_PURPLE_500 = 0xFF673AB7.toInt()
|
||||
const val DEEP_PURPLE_600 = 0xFF5E35B1.toInt()
|
||||
const val DEEP_PURPLE_700 = 0xFF512DA8.toInt()
|
||||
const val DEEP_PURPLE_800 = 0xFF4527A0.toInt()
|
||||
const val DEEP_PURPLE_900 = 0xFF311B92.toInt()
|
||||
|
||||
const val LIGHT_BLUE_50 = 0xFFE1F5FE.toInt()
|
||||
const val LIGHT_BLUE_100 = 0xFFB3E5FC.toInt()
|
||||
const val LIGHT_BLUE_200 = 0xFF81D4FA.toInt()
|
||||
const val LIGHT_BLUE_300 = 0xFF4FC3F7.toInt()
|
||||
const val LIGHT_BLUE_400 = 0xFF29B6F6.toInt()
|
||||
const val LIGHT_BLUE_500 = 0xFF03A9F4.toInt()
|
||||
const val LIGHT_BLUE_600 = 0xFF039BE5.toInt()
|
||||
const val LIGHT_BLUE_700 = 0xFF0288D1.toInt()
|
||||
const val LIGHT_BLUE_800 = 0xFF0277BD.toInt()
|
||||
const val LIGHT_BLUE_900 = 0xFF01579B.toInt()
|
||||
|
||||
const val GREEN_50 = 0xFFE8F5E9.toInt()
|
||||
const val GREEN_100 = 0xFFC8E6C9.toInt()
|
||||
const val GREEN_200 = 0xFFA5D6A7.toInt()
|
||||
const val GREEN_300 = 0xFF81C784.toInt()
|
||||
const val GREEN_400 = 0xFF66BB6A.toInt()
|
||||
const val GREEN_500 = 0xFF4CAF50.toInt()
|
||||
const val GREEN_600 = 0xFF43A047.toInt()
|
||||
const val GREEN_700 = 0xFF388E3C.toInt()
|
||||
const val GREEN_800 = 0xFF2E7D32.toInt()
|
||||
const val GREEN_900 = 0xFF1B5E20.toInt()
|
||||
|
||||
const val YELLOW_50 = 0xFFFFFDE7.toInt()
|
||||
const val YELLOW_100 = 0xFFFFF9C4.toInt()
|
||||
const val YELLOW_200 = 0xFFFFF59D.toInt()
|
||||
const val YELLOW_300 = 0xFFFFF176.toInt()
|
||||
const val YELLOW_400 = 0xFFFFEE58.toInt()
|
||||
const val YELLOW_500 = 0xFFFFEB3B.toInt()
|
||||
const val YELLOW_600 = 0xFFFDD835.toInt()
|
||||
const val YELLOW_700 = 0xFFFBC02D.toInt()
|
||||
const val YELLOW_800 = 0xFFF9A825.toInt()
|
||||
const val YELLOW_900 = 0xFFF57F17.toInt()
|
||||
|
||||
const val DEEP_ORANGE_50 = 0xFFFBE9E7.toInt()
|
||||
const val DEEP_ORANGE_100 = 0xFFFFCCBC.toInt()
|
||||
const val DEEP_ORANGE_200 = 0xFFFFAB91.toInt()
|
||||
const val DEEP_ORANGE_300 = 0xFFFF8A65.toInt()
|
||||
const val DEEP_ORANGE_400 = 0xFFFF7043.toInt()
|
||||
const val DEEP_ORANGE_500 = 0xFFFF5722.toInt()
|
||||
const val DEEP_ORANGE_600 = 0xFFF4511E.toInt()
|
||||
const val DEEP_ORANGE_700 = 0xFFE64A19.toInt()
|
||||
const val DEEP_ORANGE_800 = 0xFFD84315.toInt()
|
||||
const val DEEP_ORANGE_900 = 0xFFBF360C.toInt()
|
||||
|
||||
const val BLUE_GREY_50 = 0xFFECEFF1.toInt()
|
||||
const val BLUE_GREY_100 = 0xFFCFD8DC.toInt()
|
||||
const val BLUE_GREY_200 = 0xFFB0BEC5.toInt()
|
||||
const val BLUE_GREY_300 = 0xFF90A4AE.toInt()
|
||||
const val BLUE_GREY_400 = 0xFF78909C.toInt()
|
||||
const val BLUE_GREY_500 = 0xFF607D8B.toInt()
|
||||
const val BLUE_GREY_600 = 0xFF546E7A.toInt()
|
||||
const val BLUE_GREY_700 = 0xFF455A64.toInt()
|
||||
const val BLUE_GREY_800 = 0xFF37474F.toInt()
|
||||
const val BLUE_GREY_900 = 0xFF263238.toInt()
|
||||
|
||||
const val PINK_50 = 0xFFFCE4EC.toInt()
|
||||
const val PINK_100 = 0xFFF8BBD0.toInt()
|
||||
const val PINK_200 = 0xFFF48FB1.toInt()
|
||||
const val PINK_300 = 0xFFF06292.toInt()
|
||||
const val PINK_400 = 0xFFEC407A.toInt()
|
||||
const val PINK_500 = 0xFFE91E63.toInt()
|
||||
const val PINK_600 = 0xFFD81B60.toInt()
|
||||
const val PINK_700 = 0xFFC2185B.toInt()
|
||||
const val PINK_800 = 0xFFAD1457.toInt()
|
||||
const val PINK_900 = 0xFF880E4F.toInt()
|
||||
|
||||
const val INDIGO_50 = 0xFFE8EAF6.toInt()
|
||||
const val INDIGO_100 = 0xFFC5CAE9.toInt()
|
||||
const val INDIGO_200 = 0xFF9FA8DA.toInt()
|
||||
const val INDIGO_300 = 0xFF7986CB.toInt()
|
||||
const val INDIGO_400 = 0xFF5C6BC0.toInt()
|
||||
const val INDIGO_500 = 0xFF3F51B5.toInt()
|
||||
const val INDIGO_600 = 0xFF3949AB.toInt()
|
||||
const val INDIGO_700 = 0xFF303F9F.toInt()
|
||||
const val INDIGO_800 = 0xFF283593.toInt()
|
||||
const val INDIGO_900 = 0xFF1A237E.toInt()
|
||||
|
||||
const val CYAN_50 = 0xFFE0F7FA.toInt()
|
||||
const val CYAN_100 = 0xFFB2EBF2.toInt()
|
||||
const val CYAN_200 = 0xFF80DEEA.toInt()
|
||||
const val CYAN_300 = 0xFF4DD0E1.toInt()
|
||||
const val CYAN_400 = 0xFF26C6DA.toInt()
|
||||
const val CYAN_500 = 0xFF00BCD4.toInt()
|
||||
const val CYAN_600 = 0xFF00ACC1.toInt()
|
||||
const val CYAN_700 = 0xFF0097A7.toInt()
|
||||
const val CYAN_800 = 0xFF00838F.toInt()
|
||||
const val CYAN_900 = 0xFF006064.toInt()
|
||||
|
||||
const val LIGHT_GREEN_50 = 0xFFF1F8E9.toInt()
|
||||
const val LIGHT_GREEN_100 = 0xFFDCEDC8.toInt()
|
||||
const val LIGHT_GREEN_200 = 0xFFC5E1A5.toInt()
|
||||
const val LIGHT_GREEN_300 = 0xFFAED581.toInt()
|
||||
const val LIGHT_GREEN_400 = 0xFF9CCC65.toInt()
|
||||
const val LIGHT_GREEN_500 = 0xFF8BC34A.toInt()
|
||||
const val LIGHT_GREEN_600 = 0xFF7CB342.toInt()
|
||||
const val LIGHT_GREEN_700 = 0xFF689F38.toInt()
|
||||
const val LIGHT_GREEN_800 = 0xFF558B2F.toInt()
|
||||
const val LIGHT_GREEN_900 = 0xFF33691E.toInt()
|
||||
|
||||
const val AMBER_50 = 0xFFFFF8E1.toInt()
|
||||
const val AMBER_100 = 0xFFFFECB3.toInt()
|
||||
const val AMBER_200 = 0xFFFFE082.toInt()
|
||||
const val AMBER_300 = 0xFFFFD54F.toInt()
|
||||
const val AMBER_400 = 0xFFFFCA28.toInt()
|
||||
const val AMBER_500 = 0xFFFFC107.toInt()
|
||||
const val AMBER_600 = 0xFFFFB300.toInt()
|
||||
const val AMBER_700 = 0xFFFFA000.toInt()
|
||||
const val AMBER_800 = 0xFFFF8F00.toInt()
|
||||
const val AMBER_900 = 0xFFFF6F00.toInt()
|
||||
|
||||
const val BROWN_50 = 0xFFEFEBE9.toInt()
|
||||
const val BROWN_100 = 0xFFD7CCC8.toInt()
|
||||
const val BROWN_200 = 0xFFBCAAA4.toInt()
|
||||
const val BROWN_300 = 0xFFA1887F.toInt()
|
||||
const val BROWN_400 = 0xFF8D6E63.toInt()
|
||||
const val BROWN_500 = 0xFF795548.toInt()
|
||||
const val BROWN_600 = 0xFF6D4C41.toInt()
|
||||
const val BROWN_700 = 0xFF5D4037.toInt()
|
||||
const val BROWN_800 = 0xFF4E342E.toInt()
|
||||
const val BROWN_900 = 0xFF3E2723.toInt()
|
||||
|
||||
const val PURPLE_50 = 0xFFF3E5F5.toInt()
|
||||
const val PURPLE_100 = 0xFFE1BEE7.toInt()
|
||||
const val PURPLE_200 = 0xFFCE93D8.toInt()
|
||||
const val PURPLE_300 = 0xFFBA68C8.toInt()
|
||||
const val PURPLE_400 = 0xFFAB47BC.toInt()
|
||||
const val PURPLE_500 = 0xFF9C27B0.toInt()
|
||||
const val PURPLE_600 = 0xFF8E24AA.toInt()
|
||||
const val PURPLE_700 = 0xFF7B1FA2.toInt()
|
||||
const val PURPLE_800 = 0xFF6A1B9A.toInt()
|
||||
const val PURPLE_900 = 0xFF4A148C.toInt()
|
||||
|
||||
const val BLUE_50 = 0xFFE3F2FD.toInt()
|
||||
const val BLUE_100 = 0xFFBBDEFB.toInt()
|
||||
const val BLUE_200 = 0xFF90CAF9.toInt()
|
||||
const val BLUE_300 = 0xFF64B5F6.toInt()
|
||||
const val BLUE_400 = 0xFF42A5F5.toInt()
|
||||
const val BLUE_500 = 0xFF2196F3.toInt()
|
||||
const val BLUE_600 = 0xFF1E88E5.toInt()
|
||||
const val BLUE_700 = 0xFF1976D2.toInt()
|
||||
const val BLUE_800 = 0xFF1565C0.toInt()
|
||||
const val BLUE_900 = 0xFF0D47A1.toInt()
|
||||
|
||||
const val TEAL_50 = 0xFFE0F2F1.toInt()
|
||||
const val TEAL_100 = 0xFFB2DFDB.toInt()
|
||||
const val TEAL_200 = 0xFF80CBC4.toInt()
|
||||
const val TEAL_300 = 0xFF4DB6AC.toInt()
|
||||
const val TEAL_400 = 0xFF26A69A.toInt()
|
||||
const val TEAL_500 = 0xFF009688.toInt()
|
||||
const val TEAL_600 = 0xFF00897B.toInt()
|
||||
const val TEAL_700 = 0xFF00796B.toInt()
|
||||
const val TEAL_800 = 0xFF00695C.toInt()
|
||||
const val TEAL_900 = 0xFF004D40.toInt()
|
||||
|
||||
const val LIME_50 = 0xFFF9FBE7.toInt()
|
||||
const val LIME_100 = 0xFFF0F4C3.toInt()
|
||||
const val LIME_200 = 0xFFE6EE9C.toInt()
|
||||
const val LIME_300 = 0xFFDCE775.toInt()
|
||||
const val LIME_400 = 0xFFD4E157.toInt()
|
||||
const val LIME_500 = 0xFFCDDC39.toInt()
|
||||
const val LIME_600 = 0xFFC0CA33.toInt()
|
||||
const val LIME_700 = 0xFFAFB42B.toInt()
|
||||
const val LIME_800 = 0xFF9E9D24.toInt()
|
||||
const val LIME_900 = 0xFF827717.toInt()
|
||||
|
||||
const val ORANGE_50 = 0xFFFFF3E0.toInt()
|
||||
const val ORANGE_100 = 0xFFFFE0B2.toInt()
|
||||
const val ORANGE_200 = 0xFFFFCC80.toInt()
|
||||
const val ORANGE_300 = 0xFFFFB74D.toInt()
|
||||
const val ORANGE_400 = 0xFFFFA726.toInt()
|
||||
const val ORANGE_500 = 0xFFFF9800.toInt()
|
||||
const val ORANGE_600 = 0xFFFB8C00.toInt()
|
||||
const val ORANGE_700 = 0xFFF57C00.toInt()
|
||||
const val ORANGE_800 = 0xFFEF6C00.toInt()
|
||||
const val ORANGE_900 = 0xFFE65100.toInt()
|
||||
|
||||
const val GREY_50 = 0xFFFAFAFA.toInt()
|
||||
const val GREY_100 = 0xFFF5F5F5.toInt()
|
||||
const val GREY_200 = 0xFFEEEEEE.toInt()
|
||||
const val GREY_300 = 0xFFE0E0E0.toInt()
|
||||
const val GREY_400 = 0xFFBDBDBD.toInt()
|
||||
const val GREY_500 = 0xFF9E9E9E.toInt()
|
||||
const val GREY_600 = 0xFF757575.toInt()
|
||||
const val GREY_700 = 0xFF616161.toInt()
|
||||
const val GREY_800 = 0xFF424242.toInt()
|
||||
const val GREY_900 = 0xFF212121.toInt()
|
||||
}
|
|
@ -17,4 +17,5 @@ val messageListUiModule = module {
|
|||
factory {
|
||||
MessageListLiveDataFactory(messageListLoader = get(), preferences = get(), messageListRepository = get())
|
||||
}
|
||||
single { SortTypeToastProvider() }
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package com.fsck.k9.fragment
|
||||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import android.content.Context
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Resources
|
||||
import android.content.res.Resources.Theme
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.Spannable
|
||||
|
@ -14,26 +13,31 @@ import android.text.style.StyleSpan
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.OnClickListener
|
||||
import android.view.View.OnLongClickListener
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.NO_POSITION
|
||||
import com.fsck.k9.FontSizes
|
||||
import com.fsck.k9.contacts.ContactPictureLoader
|
||||
import com.fsck.k9.controller.MessageReference
|
||||
import com.fsck.k9.mail.Address
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.helper.RelativeDateTimeFormatter
|
||||
import com.fsck.k9.ui.messagelist.MessageListAppearance
|
||||
import com.fsck.k9.ui.messagelist.MessageListItem
|
||||
import com.fsck.k9.ui.resolveColorAttribute
|
||||
import com.fsck.k9.ui.resolveDrawableAttribute
|
||||
import kotlin.math.max
|
||||
|
||||
private const val FOOTER_ID = 1L
|
||||
|
||||
private const val TYPE_MESSAGE = 0
|
||||
private const val TYPE_FOOTER = 1
|
||||
|
||||
class MessageListAdapter internal constructor(
|
||||
private val context: Context,
|
||||
theme: Theme,
|
||||
private val res: Resources,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
|
@ -41,7 +45,7 @@ class MessageListAdapter internal constructor(
|
|||
private val listItemListener: MessageListItemActionListener,
|
||||
private val appearance: MessageListAppearance,
|
||||
private val relativeDateTimeFormatter: RelativeDateTimeFormatter
|
||||
) : BaseAdapter() {
|
||||
) : RecyclerView.Adapter<MessageListViewHolder>() {
|
||||
|
||||
private val forwardedIcon: Drawable = theme.resolveDrawableAttribute(R.attr.messageListForwarded)
|
||||
private val answeredIcon: Drawable = theme.resolveDrawableAttribute(R.attr.messageListAnswered)
|
||||
|
@ -49,11 +53,15 @@ class MessageListAdapter internal constructor(
|
|||
private val previewTextColor: Int = theme.resolveColorAttribute(R.attr.messageListPreviewTextColor)
|
||||
private val activeItemBackgroundColor: Int = theme.resolveColorAttribute(R.attr.messageListActiveItemBackgroundColor)
|
||||
private val selectedItemBackgroundColor: Int = theme.resolveColorAttribute(R.attr.messageListSelectedBackgroundColor)
|
||||
private val regularItemBackgroundColor: Int = theme.resolveColorAttribute(R.attr.messageListRegularItemBackgroundColor)
|
||||
private val readItemBackgroundColor: Int = theme.resolveColorAttribute(R.attr.messageListReadItemBackgroundColor)
|
||||
private val unreadItemBackgroundColor: Int = theme.resolveColorAttribute(R.attr.messageListUnreadItemBackgroundColor)
|
||||
|
||||
var messages: List<MessageListItem> = emptyList()
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
set(value) {
|
||||
val oldMessageList = field
|
||||
|
||||
field = value
|
||||
messagesMap = value.associateBy { it.uniqueId }
|
||||
|
||||
|
@ -62,18 +70,57 @@ class MessageListAdapter internal constructor(
|
|||
selected = selected.intersect(uniqueIds)
|
||||
}
|
||||
|
||||
notifyDataSetChanged()
|
||||
if (oldMessageList.isEmpty()) {
|
||||
// While loading, only the footer view is showing. If we used DiffUtil, the footer view would be used as
|
||||
// anchor element and the updated list would be scrolled all the way down.
|
||||
notifyDataSetChanged()
|
||||
} else {
|
||||
val diffResult = DiffUtil.calculateDiff(
|
||||
MessageListDiffCallback(oldMessageList = oldMessageList, newMessageList = value)
|
||||
)
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
}
|
||||
|
||||
private var messagesMap = emptyMap<Long, MessageListItem>()
|
||||
|
||||
var activeMessage: MessageReference? = null
|
||||
set(value) {
|
||||
if (value == field) return
|
||||
|
||||
val oldPosition = getPosition(field)
|
||||
val newPosition = getPosition(value)
|
||||
|
||||
field = value
|
||||
|
||||
oldPosition?.let { position -> notifyItemChanged(position) }
|
||||
newPosition?.let { position -> notifyItemChanged(position) }
|
||||
}
|
||||
|
||||
var selected: Set<Long> = emptySet()
|
||||
private set(value) {
|
||||
if (value == field) return
|
||||
|
||||
// Selection removed
|
||||
field.asSequence()
|
||||
.filter { uniqueId -> uniqueId !in value }
|
||||
.mapNotNull { uniqueId -> messagesMap[uniqueId] }
|
||||
.mapNotNull { messageListItem -> getPosition(messageListItem) }
|
||||
.forEach { position ->
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
||||
// Selection added
|
||||
value.asSequence()
|
||||
.filter { uniqueId -> uniqueId !in field }
|
||||
.mapNotNull { uniqueId -> messagesMap[uniqueId] }
|
||||
.mapNotNull { messageListItem -> getPosition(messageListItem) }
|
||||
.forEach { position ->
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
||||
field = value
|
||||
selectedCount = calculateSelectionCount()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
val selectedMessages: List<MessageListItem>
|
||||
|
@ -85,6 +132,34 @@ class MessageListAdapter internal constructor(
|
|||
var selectedCount: Int = 0
|
||||
private set
|
||||
|
||||
var footerText: String? = null
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
|
||||
val hadFooterText = field != null
|
||||
val previousFooterPosition = footerPosition
|
||||
field = value
|
||||
|
||||
if (hadFooterText) {
|
||||
if (value == null) {
|
||||
notifyItemRemoved(previousFooterPosition)
|
||||
} else {
|
||||
notifyItemChanged(footerPosition)
|
||||
}
|
||||
} else {
|
||||
notifyItemInserted(footerPosition)
|
||||
}
|
||||
}
|
||||
|
||||
private val hasFooter: Boolean
|
||||
get() = footerText != null
|
||||
|
||||
private val lastMessagePosition: Int
|
||||
get() = messages.lastIndex
|
||||
|
||||
private val footerPosition: Int
|
||||
get() = if (hasFooter) lastMessagePosition + 1 else NO_POSITION
|
||||
|
||||
private inline val subjectViewFontSize: Int
|
||||
get() = if (appearance.senderAboveSubject) {
|
||||
appearance.fontSizes.messageListSender
|
||||
|
@ -92,35 +167,60 @@ class MessageListAdapter internal constructor(
|
|||
appearance.fontSizes.messageListSubject
|
||||
}
|
||||
|
||||
private val messageClickedListener = OnClickListener { view: View ->
|
||||
val messageListItem = getItemFromView(view)
|
||||
listItemListener.onMessageClicked(messageListItem)
|
||||
}
|
||||
|
||||
private val messageLongClickedListener = OnLongClickListener { view: View ->
|
||||
val messageListItem = getItemFromView(view)
|
||||
listItemListener.onToggleMessageSelection(messageListItem)
|
||||
true
|
||||
}
|
||||
|
||||
private val footerClickListener = OnClickListener {
|
||||
listItemListener.onFooterClicked()
|
||||
}
|
||||
|
||||
private val flagClickListener = OnClickListener { view: View ->
|
||||
val messageViewHolder = view.tag as MessageViewHolder
|
||||
val messageListItem = getItemById(messageViewHolder.uniqueId)
|
||||
val messageListItem = getItemFromView(view)
|
||||
listItemListener.onToggleMessageFlag(messageListItem)
|
||||
}
|
||||
|
||||
private val contactPictureClickListener = OnClickListener { view: View ->
|
||||
val parentView = view.parent.parent as View
|
||||
val messageViewHolder = parentView.tag as MessageViewHolder
|
||||
val messageListItem = getItemById(messageViewHolder.uniqueId)
|
||||
val messageListItem = getItemFromView(parentView)
|
||||
listItemListener.onToggleMessageSelection(messageListItem)
|
||||
}
|
||||
|
||||
init {
|
||||
setHasStableIds(true)
|
||||
}
|
||||
|
||||
private fun recipientSigil(toMe: Boolean, ccMe: Boolean) = when {
|
||||
toMe -> res.getString(R.string.messagelist_sent_to_me_sigil) + " "
|
||||
ccMe -> res.getString(R.string.messagelist_sent_cc_me_sigil) + " "
|
||||
else -> ""
|
||||
}
|
||||
|
||||
override fun hasStableIds(): Boolean = true
|
||||
override fun getItemCount(): Int = messages.size + if (hasFooter) 1 else 0
|
||||
|
||||
override fun getCount(): Int = messages.size
|
||||
override fun getItemId(position: Int): Long {
|
||||
return if (position <= lastMessagePosition) {
|
||||
messages[position].uniqueId
|
||||
} else {
|
||||
FOOTER_ID
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long = messages[position].uniqueId
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position <= lastMessagePosition) TYPE_MESSAGE else TYPE_FOOTER
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): MessageListItem = messages[position]
|
||||
private fun getItem(position: Int): MessageListItem = messages[position]
|
||||
|
||||
private fun getItemById(uniqueId: Long): MessageListItem {
|
||||
return messagesMap[uniqueId]!!
|
||||
fun getItemById(uniqueId: Long): MessageListItem? {
|
||||
return messagesMap[uniqueId]
|
||||
}
|
||||
|
||||
fun getItem(messageReference: MessageReference): MessageListItem? {
|
||||
|
@ -135,16 +235,26 @@ class MessageListAdapter internal constructor(
|
|||
return messages.indexOf(messageListItem).takeIf { it != -1 }
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
val message = getItem(position)
|
||||
val view: View = convertView ?: newView(parent)
|
||||
bindView(view, context, message)
|
||||
private fun getPosition(messageReference: MessageReference?): Int? {
|
||||
if (messageReference == null) return null
|
||||
|
||||
return view
|
||||
return messages.indexOfFirst {
|
||||
messageReference.equals(it.account.uuid, it.folderId, it.messageUid)
|
||||
}.takeIf { it != -1 }
|
||||
}
|
||||
|
||||
private fun newView(parent: ViewGroup?): View {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageListViewHolder {
|
||||
return when (viewType) {
|
||||
TYPE_MESSAGE -> createMessageViewHolder(parent)
|
||||
TYPE_FOOTER -> createFooterViewHolder(parent)
|
||||
else -> error("Unsupported type: $viewType")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMessageViewHolder(parent: ViewGroup?): MessageViewHolder {
|
||||
val view = layoutInflater.inflate(R.layout.message_list_item, parent, false)
|
||||
view.setOnClickListener(messageClickedListener)
|
||||
view.setOnLongClickListener(messageLongClickedListener)
|
||||
|
||||
val holder = MessageViewHolder(view)
|
||||
|
||||
|
@ -168,14 +278,33 @@ class MessageListAdapter internal constructor(
|
|||
|
||||
view.tag = holder
|
||||
|
||||
return view
|
||||
return holder
|
||||
}
|
||||
|
||||
private fun bindView(view: View, context: Context, message: MessageListItem) {
|
||||
val isSelected = selected.contains(message.uniqueId)
|
||||
val isActive = isActiveMessage(message)
|
||||
private fun createFooterViewHolder(parent: ViewGroup): MessageListViewHolder {
|
||||
val view = layoutInflater.inflate(R.layout.message_list_item_footer, parent, false)
|
||||
view.setOnClickListener(footerClickListener)
|
||||
return FooterViewHolder(view)
|
||||
}
|
||||
|
||||
val holder = view.tag as MessageViewHolder
|
||||
override fun onBindViewHolder(holder: MessageListViewHolder, position: Int) {
|
||||
when (val viewType = getItemViewType(position)) {
|
||||
TYPE_MESSAGE -> {
|
||||
val messageListItem = getItem(position)
|
||||
bindMessageViewHolder(holder as MessageViewHolder, messageListItem)
|
||||
}
|
||||
TYPE_FOOTER -> {
|
||||
bindFooterViewHolder(holder as FooterViewHolder)
|
||||
}
|
||||
else -> {
|
||||
error("Unsupported type: $viewType")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindMessageViewHolder(holder: MessageViewHolder, messageListItem: MessageListItem) {
|
||||
val isSelected = selected.contains(messageListItem.uniqueId)
|
||||
val isActive = isActiveMessage(messageListItem)
|
||||
|
||||
if (appearance.showContactPicture) {
|
||||
if (isSelected) {
|
||||
|
@ -187,7 +316,7 @@ class MessageListAdapter internal constructor(
|
|||
}
|
||||
}
|
||||
|
||||
with(message) {
|
||||
with(messageListItem) {
|
||||
val maybeBoldTypeface = if (isRead) Typeface.NORMAL else Typeface.BOLD
|
||||
val displayDate = relativeDateTimeFormatter.formatDate(messageDate)
|
||||
val displayThreadCount = if (appearance.showingThreadedList) threadCount else 0
|
||||
|
@ -206,7 +335,7 @@ class MessageListAdapter internal constructor(
|
|||
if (appearance.showContactPicture && holder.contactPicture.isVisible) {
|
||||
setContactPicture(holder.contactPicture, displayAddress)
|
||||
}
|
||||
setBackgroundColor(view, isSelected, isRead, isActive)
|
||||
setBackgroundColor(holder.itemView, isSelected, isRead, isActive)
|
||||
updateWithThreadCount(holder, displayThreadCount)
|
||||
val beforePreviewText = if (appearance.senderAboveSubject) subject else displayName
|
||||
val sigil = recipientSigil(toMe, ccMe)
|
||||
|
@ -240,6 +369,10 @@ class MessageListAdapter internal constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun bindFooterViewHolder(holder: FooterViewHolder) {
|
||||
holder.text.text = footerText
|
||||
}
|
||||
|
||||
private fun formatPreviewText(
|
||||
preview: TextView,
|
||||
beforePreviewText: CharSequence,
|
||||
|
@ -304,7 +437,7 @@ class MessageListAdapter internal constructor(
|
|||
selected -> selectedItemBackgroundColor
|
||||
backGroundAsReadIndicator && read -> readItemBackgroundColor
|
||||
backGroundAsReadIndicator && !read -> unreadItemBackgroundColor
|
||||
else -> Color.TRANSPARENT
|
||||
else -> regularItemBackgroundColor
|
||||
}
|
||||
|
||||
view.setBackgroundColor(backgroundColor)
|
||||
|
@ -388,9 +521,33 @@ class MessageListAdapter internal constructor(
|
|||
.filter { it.uniqueId in selected }
|
||||
.sumOf { it.threadCount.coerceAtLeast(1) }
|
||||
}
|
||||
|
||||
private fun getItemFromView(view: View): MessageListItem {
|
||||
val messageViewHolder = view.tag as MessageViewHolder
|
||||
return getItemById(messageViewHolder.uniqueId) ?: error("Couldn't find MessageListItem by View")
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageListDiffCallback(
|
||||
private val oldMessageList: List<MessageListItem>,
|
||||
private val newMessageList: List<MessageListItem>
|
||||
) : DiffUtil.Callback() {
|
||||
override fun getOldListSize(): Int = oldMessageList.size
|
||||
|
||||
override fun getNewListSize(): Int = newMessageList.size
|
||||
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
return oldMessageList[oldItemPosition].uniqueId == newMessageList[newItemPosition].uniqueId
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
return oldMessageList[oldItemPosition] == newMessageList[newItemPosition]
|
||||
}
|
||||
}
|
||||
|
||||
interface MessageListItemActionListener {
|
||||
fun onMessageClicked(messageListItem: MessageListItem)
|
||||
fun onToggleMessageSelection(item: MessageListItem)
|
||||
fun onToggleMessageFlag(item: MessageListItem)
|
||||
fun onFooterClicked()
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.fsck.k9.fragment
|
||||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.SearchManager
|
||||
|
@ -6,20 +6,19 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.AdapterView.OnItemClickListener
|
||||
import android.widget.AdapterView.OnItemLongClickListener
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.Account.Expunge
|
||||
|
@ -27,14 +26,15 @@ import com.fsck.k9.Account.SortType
|
|||
import com.fsck.k9.Clock
|
||||
import com.fsck.k9.K9
|
||||
import com.fsck.k9.Preferences
|
||||
import com.fsck.k9.SwipeAction
|
||||
import com.fsck.k9.activity.FolderInfoHolder
|
||||
import com.fsck.k9.activity.Search
|
||||
import com.fsck.k9.activity.misc.ContactPicture
|
||||
import com.fsck.k9.controller.MessageReference
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.controller.SimpleMessagingListener
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener
|
||||
import com.fsck.k9.fragment.MessageListFragment.MessageListFragmentListener.Companion.MAX_PROGRESS
|
||||
import com.fsck.k9.helper.Utility
|
||||
import com.fsck.k9.helper.mapToSet
|
||||
import com.fsck.k9.mail.Flag
|
||||
|
@ -47,12 +47,7 @@ import com.fsck.k9.ui.choosefolder.ChooseFolderActivity
|
|||
import com.fsck.k9.ui.folders.FolderNameFormatter
|
||||
import com.fsck.k9.ui.folders.FolderNameFormatterFactory
|
||||
import com.fsck.k9.ui.helper.RelativeDateTimeFormatter
|
||||
import com.fsck.k9.ui.messagelist.MessageListAppearance
|
||||
import com.fsck.k9.ui.messagelist.MessageListConfig
|
||||
import com.fsck.k9.ui.messagelist.MessageListInfo
|
||||
import com.fsck.k9.ui.messagelist.MessageListItem
|
||||
import com.fsck.k9.ui.messagelist.MessageListViewModel
|
||||
import com.fsck.k9.ui.messagelist.MessageSortOverride
|
||||
import com.fsck.k9.ui.messagelist.MessageListFragment.MessageListFragmentListener.Companion.MAX_PROGRESS
|
||||
import java.util.concurrent.Future
|
||||
import net.jcip.annotations.GuardedBy
|
||||
import org.koin.android.ext.android.inject
|
||||
|
@ -60,11 +55,10 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
|||
import timber.log.Timber
|
||||
|
||||
private const val MAXIMUM_MESSAGE_SORT_OVERRIDES = 3
|
||||
private const val MINIMUM_CLICK_INTERVAL = 200L
|
||||
|
||||
class MessageListFragment :
|
||||
Fragment(),
|
||||
OnItemClickListener,
|
||||
OnItemLongClickListener,
|
||||
ConfirmationDialogFragmentListener,
|
||||
MessageListItemActionListener {
|
||||
|
||||
|
@ -82,12 +76,9 @@ class MessageListFragment :
|
|||
|
||||
private lateinit var fragmentListener: MessageListFragmentListener
|
||||
|
||||
private lateinit var listView: ListView
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
private lateinit var adapter: MessageListAdapter
|
||||
private var footerView: View? = null
|
||||
|
||||
private var savedListState: Parcelable? = null
|
||||
|
||||
private lateinit var accountUuids: Array<String>
|
||||
private var account: Account? = null
|
||||
|
@ -111,6 +102,7 @@ class MessageListFragment :
|
|||
private var isThreadDisplay = false
|
||||
private var activeMessage: MessageReference? = null
|
||||
private var rememberedSelected: Set<Long>? = null
|
||||
private var lastMessageClick = 0L
|
||||
|
||||
lateinit var localSearch: LocalSearch
|
||||
private set
|
||||
|
@ -118,6 +110,7 @@ class MessageListFragment :
|
|||
private set
|
||||
private var isSingleFolderMode = false
|
||||
private var isRemoteSearch = false
|
||||
private var initialMessageListLoad = true
|
||||
|
||||
private val isUnifiedInbox: Boolean
|
||||
get() = localSearch.id == SearchAccount.UNIFIED_INBOX
|
||||
|
@ -176,7 +169,6 @@ class MessageListFragment :
|
|||
activeMessages = savedInstanceState.getStringArray(STATE_ACTIVE_MESSAGES)?.map { MessageReference.parse(it)!! }
|
||||
restoreSelectedMessages(savedInstanceState)
|
||||
isRemoteSearch = savedInstanceState.getBoolean(STATE_REMOTE_SEARCH_PERFORMED)
|
||||
savedListState = savedInstanceState.getParcelable(STATE_MESSAGE_LIST)
|
||||
val messageReferenceString = savedInstanceState.getString(STATE_ACTIVE_MESSAGE)
|
||||
activeMessage = MessageReference.parse(messageReferenceString)
|
||||
}
|
||||
|
@ -186,7 +178,7 @@ class MessageListFragment :
|
|||
}
|
||||
|
||||
fun restoreListState(savedListState: Parcelable) {
|
||||
listView.onRestoreInstanceState(savedListState)
|
||||
recyclerView.layoutManager?.onRestoreInstanceState(savedListState)
|
||||
}
|
||||
|
||||
private fun decodeArguments(): MessageListFragment? {
|
||||
|
@ -226,7 +218,7 @@ class MessageListFragment :
|
|||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.message_list_fragment, container, false).apply {
|
||||
initializeSwipeRefreshLayout(this)
|
||||
initializeListView(this)
|
||||
initializeRecyclerView(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,17 +235,13 @@ class MessageListFragment :
|
|||
swipeRefreshLayout.isEnabled = false
|
||||
}
|
||||
|
||||
private fun initializeListView(view: View) {
|
||||
listView = view.findViewById(R.id.message_list)
|
||||
with(listView) {
|
||||
scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY
|
||||
isLongClickable = true
|
||||
isFastScrollEnabled = true
|
||||
isVerticalFadingEdgeEnabled = false
|
||||
isScrollingCacheEnabled = false
|
||||
onItemClickListener = this@MessageListFragment
|
||||
onItemLongClickListener = this@MessageListFragment
|
||||
}
|
||||
private fun initializeRecyclerView(view: View) {
|
||||
recyclerView = view.findViewById(R.id.message_list)
|
||||
|
||||
val itemDecoration = MessageListItemDecoration(requireContext())
|
||||
recyclerView.addItemDecoration(itemDecoration)
|
||||
|
||||
recyclerView.itemAnimator = MessageListItemAnimator()
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
|
@ -267,9 +255,10 @@ class MessageListFragment :
|
|||
}
|
||||
|
||||
private fun initializeMessageList() {
|
||||
val theme = requireActivity().theme
|
||||
|
||||
adapter = MessageListAdapter(
|
||||
context = requireContext(),
|
||||
theme = requireActivity().theme,
|
||||
theme = theme,
|
||||
res = resources,
|
||||
layoutInflater = layoutInflater,
|
||||
contactsPictureLoader = ContactPicture.getContactPictureLoader(),
|
||||
|
@ -280,12 +269,20 @@ class MessageListFragment :
|
|||
|
||||
adapter.activeMessage = activeMessage
|
||||
|
||||
if (isSingleFolderMode) {
|
||||
listView.addFooterView(getFooterView(listView))
|
||||
updateFooter(null)
|
||||
}
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
listView.adapter = adapter
|
||||
val itemTouchHelper = ItemTouchHelper(
|
||||
MessageListSwipeCallback(
|
||||
resources,
|
||||
resourceProvider = SwipeResourceProvider(theme),
|
||||
swipeActionSupportProvider,
|
||||
swipeRightAction = K9.swipeRightAction,
|
||||
swipeLeftAction = K9.swipeLeftAction,
|
||||
adapter,
|
||||
swipeListener
|
||||
)
|
||||
)
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
}
|
||||
|
||||
private fun initializeSortSettings() {
|
||||
|
@ -318,10 +315,9 @@ class MessageListFragment :
|
|||
currentFolder?.let {
|
||||
if (it.databaseId == folderId) {
|
||||
it.loading = loading
|
||||
updateFooterText()
|
||||
}
|
||||
}
|
||||
|
||||
updateFooterView()
|
||||
}
|
||||
|
||||
fun updateTitle() {
|
||||
|
@ -375,16 +371,7 @@ class MessageListFragment :
|
|||
fragmentListener.setMessageListProgressEnabled(progress)
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||
if (view === footerView) {
|
||||
handleFooterClick()
|
||||
} else {
|
||||
val messageListItem = adapter.getItem(position)
|
||||
handleListItemClick(messageListItem)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleFooterClick() {
|
||||
override fun onFooterClicked() {
|
||||
val currentFolder = this.currentFolder ?: return
|
||||
|
||||
if (currentFolder.moreMessages && !localSearch.isManualSearch) {
|
||||
|
@ -403,7 +390,7 @@ class MessageListFragment :
|
|||
} else {
|
||||
extraSearchResults = null
|
||||
loadSearchResults = additionalSearchResults
|
||||
updateFooter(null)
|
||||
updateFooterText(null)
|
||||
}
|
||||
|
||||
messagingController.loadSearchResults(
|
||||
|
@ -415,10 +402,20 @@ class MessageListFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleListItemClick(messageListItem: MessageListItem) {
|
||||
override fun onMessageClicked(messageListItem: MessageListItem) {
|
||||
if (!isActive) {
|
||||
// Ignore click events that are delivered after the Fragment is no longer active. This could happen when
|
||||
// the user taps two messages at almost the same time and the first tap opens a new MessageListFragment.
|
||||
return
|
||||
}
|
||||
|
||||
val clickTime = SystemClock.elapsedRealtime()
|
||||
if (clickTime - lastMessageClick < MINIMUM_CLICK_INTERVAL) return
|
||||
|
||||
if (adapter.selectedCount > 0) {
|
||||
toggleMessageSelect(messageListItem)
|
||||
} else {
|
||||
lastMessageClick = clickTime
|
||||
if (showingThreadedList && messageListItem.threadCount > 1) {
|
||||
fragmentListener.showThread(messageListItem.account, messageListItem.threadRoot)
|
||||
} else {
|
||||
|
@ -427,28 +424,17 @@ class MessageListFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onItemLongClick(parent: AdapterView<*>?, view: View, position: Int, id: Long): Boolean {
|
||||
if (view === footerView) return false
|
||||
|
||||
val messageListItem = adapter.getItem(position)
|
||||
toggleMessageSelect(messageListItem)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
if (isNewMessagesView && !requireActivity().isChangingConfigurations) {
|
||||
messagingController.clearNewMessages(account)
|
||||
}
|
||||
|
||||
savedListState = listView.onSaveInstanceState()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
|
||||
saveListState(outState)
|
||||
outState.putLongArray(STATE_SELECTED_MESSAGES, adapter.selected.toLongArray())
|
||||
outState.putBoolean(STATE_REMOTE_SEARCH_PERFORMED, isRemoteSearch)
|
||||
outState.putStringArray(
|
||||
|
@ -460,15 +446,6 @@ class MessageListFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveListState(outState: Bundle) {
|
||||
if (savedListState != null) {
|
||||
// The previously saved state was never restored, so just use that.
|
||||
outState.putParcelable(STATE_MESSAGE_LIST, savedListState)
|
||||
} else {
|
||||
outState.putParcelable(STATE_MESSAGE_LIST, listView.onSaveInstanceState())
|
||||
}
|
||||
}
|
||||
|
||||
private val messageListAppearance: MessageListAppearance
|
||||
get() = MessageListAppearance(
|
||||
fontSizes = K9.fontSizes,
|
||||
|
@ -792,26 +769,15 @@ class MessageListFragment :
|
|||
messagingController.sendPendingMessages(account, null)
|
||||
}
|
||||
|
||||
private fun getFooterView(parent: ViewGroup?): View? {
|
||||
return footerView ?: createFooterView(parent).also { footerView = it }
|
||||
}
|
||||
|
||||
private fun createFooterView(parent: ViewGroup?): View {
|
||||
return layoutInflater.inflate(R.layout.message_list_item_footer, parent, false).apply {
|
||||
tag = FooterViewHolder(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFooterView() {
|
||||
private fun updateFooterText() {
|
||||
val currentFolder = this.currentFolder
|
||||
val account = this.account
|
||||
|
||||
if (localSearch.isManualSearch || currentFolder == null || account == null) {
|
||||
updateFooter(null)
|
||||
return
|
||||
}
|
||||
|
||||
val footerText = if (currentFolder.loading) {
|
||||
val footerText = if (initialMessageListLoad) {
|
||||
null
|
||||
} else if (localSearch.isManualSearch || currentFolder == null || account == null) {
|
||||
null
|
||||
} else if (currentFolder.loading) {
|
||||
getString(R.string.status_loading_more)
|
||||
} else if (!currentFolder.moreMessages) {
|
||||
null
|
||||
|
@ -821,24 +787,11 @@ class MessageListFragment :
|
|||
getString(R.string.load_more_messages_fmt, account.displayCount)
|
||||
}
|
||||
|
||||
updateFooter(footerText)
|
||||
updateFooterText(footerText)
|
||||
}
|
||||
|
||||
fun updateFooter(text: String?) {
|
||||
val footerView = this.footerView ?: return
|
||||
|
||||
val shouldHideFooter = text == null
|
||||
if (shouldHideFooter) {
|
||||
listView.removeFooterView(footerView)
|
||||
} else {
|
||||
val isFooterViewAddedToListView = listView.footerViewsCount > 0
|
||||
if (!isFooterViewAddedToListView) {
|
||||
listView.addFooterView(footerView)
|
||||
}
|
||||
}
|
||||
|
||||
val holder = footerView.tag as FooterViewHolder
|
||||
holder.main.text = text
|
||||
fun updateFooterText(text: String?) {
|
||||
adapter.footerText = text
|
||||
}
|
||||
|
||||
private fun selectAll() {
|
||||
|
@ -1195,28 +1148,6 @@ class MessageListFragment :
|
|||
super.onStop()
|
||||
}
|
||||
|
||||
fun onMoveUp() {
|
||||
var currentPosition = listView.selectedItemPosition
|
||||
if (currentPosition == AdapterView.INVALID_POSITION || listView.isInTouchMode) {
|
||||
currentPosition = listView.firstVisiblePosition
|
||||
}
|
||||
|
||||
if (currentPosition > 0) {
|
||||
listView.setSelection(currentPosition - 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun onMoveDown() {
|
||||
var currentPosition = listView.selectedItemPosition
|
||||
if (currentPosition == AdapterView.INVALID_POSITION || listView.isInTouchMode) {
|
||||
currentPosition = listView.firstVisiblePosition
|
||||
}
|
||||
|
||||
if (currentPosition < listView.count) {
|
||||
listView.setSelection(currentPosition + 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun openMessage(messageReference: MessageReference) {
|
||||
fragmentListener.openMessage(messageReference)
|
||||
}
|
||||
|
@ -1230,8 +1161,9 @@ class MessageListFragment :
|
|||
|
||||
private val selectedMessageListItem: MessageListItem?
|
||||
get() {
|
||||
val position = listView.selectedItemPosition
|
||||
return if (position !in 0 until adapter.count) null else adapter.getItem(position)
|
||||
val focusedView = recyclerView.focusedChild ?: return null
|
||||
val viewHolder = recyclerView.findContainingViewHolder(focusedView) as? MessageViewHolder ?: return null
|
||||
return adapter.getItemById(viewHolder.uniqueId)
|
||||
}
|
||||
|
||||
private val selectedMessages: List<MessageReference>
|
||||
|
@ -1368,16 +1300,13 @@ class MessageListFragment :
|
|||
resetActionMode()
|
||||
computeBatchDirection()
|
||||
|
||||
if (savedListState != null) {
|
||||
handler.restoreListPosition(savedListState)
|
||||
savedListState = null
|
||||
}
|
||||
|
||||
invalidateMenu()
|
||||
|
||||
initialMessageListLoad = false
|
||||
|
||||
currentFolder?.let { currentFolder ->
|
||||
currentFolder.moreMessages = messageListInfo.hasMoreMessages
|
||||
updateFooterView()
|
||||
updateFooterText()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1402,6 +1331,10 @@ class MessageListFragment :
|
|||
actionMode?.invalidate()
|
||||
}
|
||||
|
||||
fun finishActionMode() {
|
||||
actionMode?.finish()
|
||||
}
|
||||
|
||||
fun remoteSearchFinished() {
|
||||
remoteSearchFuture = null
|
||||
}
|
||||
|
@ -1419,7 +1352,6 @@ class MessageListFragment :
|
|||
// Redraw list immediately
|
||||
if (::adapter.isInitialized) {
|
||||
adapter.activeMessage = activeMessage
|
||||
adapter.notifyDataSetChanged()
|
||||
|
||||
if (messageReference != null) {
|
||||
scrollToMessage(messageReference)
|
||||
|
@ -1462,8 +1394,11 @@ class MessageListFragment :
|
|||
val messageListItem = adapter.getItem(messageReference) ?: return
|
||||
val position = adapter.getPosition(messageListItem) ?: return
|
||||
|
||||
if (position <= listView.firstVisiblePosition || position >= listView.lastVisiblePosition) {
|
||||
listView.smoothScrollToPosition(position)
|
||||
val linearLayoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
val firstVisiblePosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition()
|
||||
val lastVisiblePosition = linearLayoutManager.findLastCompletelyVisibleItemPosition()
|
||||
if (position !in firstVisiblePosition..lastVisiblePosition) {
|
||||
recyclerView.smoothScrollToPosition(position)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1497,6 +1432,58 @@ class MessageListFragment :
|
|||
private val isPullToRefreshAllowed: Boolean
|
||||
get() = isRemoteSearchAllowed || isCheckMailAllowed
|
||||
|
||||
private val swipeListener = MessageListSwipeListener { item, action ->
|
||||
when (action) {
|
||||
SwipeAction.None -> Unit
|
||||
SwipeAction.ToggleSelection -> {
|
||||
toggleMessageSelect(item)
|
||||
}
|
||||
SwipeAction.ToggleRead -> {
|
||||
setFlag(item, Flag.SEEN, !item.isRead)
|
||||
}
|
||||
SwipeAction.ToggleStar -> {
|
||||
setFlag(item, Flag.FLAGGED, !item.isStarred)
|
||||
}
|
||||
SwipeAction.Archive -> {
|
||||
onArchive(item.messageReference)
|
||||
}
|
||||
SwipeAction.Delete -> {
|
||||
if (K9.isConfirmDelete) {
|
||||
notifyItemChanged(item)
|
||||
}
|
||||
onDelete(listOf(item.messageReference))
|
||||
}
|
||||
SwipeAction.Spam -> {
|
||||
if (K9.isConfirmSpam) {
|
||||
notifyItemChanged(item)
|
||||
}
|
||||
onSpam(listOf(item.messageReference))
|
||||
}
|
||||
SwipeAction.Move -> {
|
||||
notifyItemChanged(item)
|
||||
onMove(item.messageReference)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyItemChanged(item: MessageListItem) {
|
||||
val position = adapter.getPosition(item) ?: return
|
||||
adapter.notifyItemChanged(position)
|
||||
}
|
||||
|
||||
private val swipeActionSupportProvider = SwipeActionSupportProvider { item, action ->
|
||||
when (action) {
|
||||
SwipeAction.None -> false
|
||||
SwipeAction.ToggleSelection -> true
|
||||
SwipeAction.ToggleRead -> !isOutbox
|
||||
SwipeAction.ToggleStar -> !isOutbox
|
||||
SwipeAction.Archive -> !isOutbox && item.account.hasArchiveFolder()
|
||||
SwipeAction.Delete -> true
|
||||
SwipeAction.Move -> !isOutbox && messagingController.isMoveCapable(item.account)
|
||||
SwipeAction.Spam -> !isOutbox && item.account.hasSpamFolder() && item.folderId != item.account.spamFolderId
|
||||
}
|
||||
}
|
||||
|
||||
internal inner class MessageListActivityListener : SimpleMessagingListener() {
|
||||
private val lock = Any()
|
||||
|
||||
|
@ -1839,10 +1826,6 @@ class MessageListFragment :
|
|||
}
|
||||
}
|
||||
|
||||
internal class FooterViewHolder(view: View) {
|
||||
val main: TextView = view.findViewById(R.id.main_text)
|
||||
}
|
||||
|
||||
private enum class FolderOperation {
|
||||
COPY, MOVE
|
||||
}
|
||||
|
@ -1876,7 +1859,6 @@ class MessageListFragment :
|
|||
private const val STATE_ACTIVE_MESSAGES = "activeMessages"
|
||||
private const val STATE_ACTIVE_MESSAGE = "activeMessage"
|
||||
private const val STATE_REMOTE_SEARCH_PERFORMED = "remoteSearchPerformed"
|
||||
private const val STATE_MESSAGE_LIST = "listState"
|
||||
|
||||
fun newInstance(search: LocalSearch, isThreadDisplay: Boolean, threadedList: Boolean): MessageListFragment {
|
||||
return MessageListFragment().apply {
|
|
@ -1,4 +1,4 @@
|
|||
package com.fsck.k9.fragment;
|
||||
package com.fsck.k9.ui.messagelist;
|
||||
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -57,7 +57,7 @@ public class MessageListHandler extends Handler {
|
|||
public void run() {
|
||||
MessageListFragment fragment = mFragment.get();
|
||||
if (fragment != null) {
|
||||
fragment.updateFooter(message);
|
||||
fragment.updateFooterText(message);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
|
||||
class MessageListItemAnimator : DefaultItemAnimator() {
|
||||
init {
|
||||
supportsChangeAnimations = false
|
||||
changeDuration = 120
|
||||
}
|
||||
|
||||
override fun canReuseUpdatedViewHolder(viewHolder: ViewHolder, payloads: MutableList<Any>): Boolean {
|
||||
// ItemTouchHelper expects swiped views to be removed from the view hierarchy. So we don't reuse views that are
|
||||
// marked as having been swiped.
|
||||
return !viewHolder.wasSwiped && super.canReuseUpdatedViewHolder(viewHolder, payloads)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import androidx.core.graphics.withSave
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
|
||||
import com.fsck.k9.ui.resolveDrawableAttribute
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* An [ItemDecoration] that uses the alpha and visibility values of a view when drawing the divider.
|
||||
*
|
||||
* Based on [androidx.recyclerview.widget.DividerItemDecoration].
|
||||
*/
|
||||
class MessageListItemDecoration(context: Context) : ItemDecoration() {
|
||||
private val divider: Drawable = context.theme.resolveDrawableAttribute(android.R.attr.listDivider)
|
||||
private val bounds = Rect()
|
||||
|
||||
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||
if (parent.layoutManager == null) return
|
||||
|
||||
canvas.withSave {
|
||||
val childCount = parent.childCount
|
||||
for (i in 0 until childCount) {
|
||||
val child = parent.getChildAt(i)
|
||||
if (!child.isVisible) {
|
||||
continue
|
||||
}
|
||||
|
||||
parent.getDecoratedBoundsWithMargins(child, bounds)
|
||||
|
||||
val left = 0
|
||||
val right = parent.width
|
||||
val bottom = bounds.bottom + child.translationY.roundToInt()
|
||||
val top = bottom - divider.intrinsicHeight
|
||||
|
||||
divider.setBounds(left, top, right, bottom)
|
||||
divider.alpha = (child.alpha * 255).toInt()
|
||||
divider.draw(canvas)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
||||
outRect.set(0, 0, 0, divider.intrinsicHeight)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.view.View
|
||||
import androidx.core.graphics.withSave
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.fsck.k9.SwipeAction
|
||||
import com.fsck.k9.ui.R
|
||||
import kotlin.math.abs
|
||||
|
||||
class MessageListSwipeCallback(
|
||||
resources: Resources,
|
||||
private val resourceProvider: SwipeResourceProvider,
|
||||
private val swipeActionSupportProvider: SwipeActionSupportProvider,
|
||||
private val swipeRightAction: SwipeAction,
|
||||
private val swipeLeftAction: SwipeAction,
|
||||
private val adapter: MessageListAdapter,
|
||||
private val listener: MessageListSwipeListener
|
||||
) : ItemTouchHelper.Callback() {
|
||||
private val iconPadding = resources.getDimension(R.dimen.messageListSwipeIconPadding).toInt()
|
||||
private val swipeThreshold = resources.getDimension(R.dimen.messageListSwipeThreshold)
|
||||
private val backgroundColorPaint = Paint()
|
||||
|
||||
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: ViewHolder): Int {
|
||||
if (viewHolder !is MessageViewHolder) return 0
|
||||
|
||||
val item = adapter.getItemById(viewHolder.uniqueId) ?: return 0
|
||||
|
||||
var swipeFlags = 0
|
||||
if (swipeActionSupportProvider.isActionSupported(item, swipeRightAction)) {
|
||||
swipeFlags = swipeFlags or ItemTouchHelper.RIGHT
|
||||
}
|
||||
if (swipeActionSupportProvider.isActionSupported(item, swipeLeftAction)) {
|
||||
swipeFlags = swipeFlags or ItemTouchHelper.LEFT
|
||||
}
|
||||
|
||||
return makeMovementFlags(0, swipeFlags)
|
||||
}
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: ViewHolder,
|
||||
target: ViewHolder
|
||||
): Boolean {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: ViewHolder, direction: Int) {
|
||||
val holder = viewHolder as MessageViewHolder
|
||||
val item = adapter.getItemById(holder.uniqueId) ?: error("Couldn't find MessageListItem")
|
||||
|
||||
// ItemTouchHelper expects swiped views to be removed from the view hierarchy. We mark this ViewHolder so that
|
||||
// MessageListItemAnimator knows not to reuse it during an animation.
|
||||
viewHolder.markAsSwiped(true)
|
||||
|
||||
when (direction) {
|
||||
ItemTouchHelper.RIGHT -> listener.onSwipeAction(item, swipeRightAction)
|
||||
ItemTouchHelper.LEFT -> listener.onSwipeAction(item, swipeLeftAction)
|
||||
else -> error("Unsupported direction: $direction")
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearView(recyclerView: RecyclerView, viewHolder: ViewHolder) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
viewHolder.markAsSwiped(false)
|
||||
}
|
||||
|
||||
override fun getSwipeThreshold(viewHolder: ViewHolder): Float {
|
||||
return swipeThreshold / viewHolder.itemView.width
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
canvas: Canvas,
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: ViewHolder,
|
||||
dX: Float,
|
||||
dY: Float,
|
||||
actionState: Int,
|
||||
isCurrentlyActive: Boolean
|
||||
) {
|
||||
canvas.withSave {
|
||||
val view = viewHolder.itemView
|
||||
|
||||
val holder = viewHolder as MessageViewHolder
|
||||
val item = adapter.getItemById(holder.uniqueId) ?: return@withSave
|
||||
|
||||
val swipeThreshold = recyclerView.width * getSwipeThreshold(holder)
|
||||
val swipeThresholdReached = abs(dX) > swipeThreshold
|
||||
if (swipeThresholdReached) {
|
||||
val action = if (dX > 0) swipeRightAction else swipeLeftAction
|
||||
val backgroundColor = resourceProvider.getBackgroundColor(item, action)
|
||||
drawBackground(view, backgroundColor)
|
||||
} else {
|
||||
val backgroundColor = resourceProvider.getBackgroundColor(item, SwipeAction.None)
|
||||
drawBackground(view, backgroundColor)
|
||||
}
|
||||
|
||||
// Stop drawing the icon when the view has been animated all the way off the screen by ItemTouchHelper.
|
||||
// We do this so the icon doesn't switch state when RecyclerView's ItemAnimator animates the view back after
|
||||
// a toggle action (mark as read/unread, add/remove star) was used.
|
||||
if (isCurrentlyActive || abs(dX).toInt() < view.width) {
|
||||
drawIcon(dX, view, item, swipeThresholdReached)
|
||||
}
|
||||
}
|
||||
|
||||
super.onChildDraw(canvas, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
||||
}
|
||||
|
||||
private fun Canvas.drawBackground(view: View, color: Int) {
|
||||
backgroundColorPaint.color = color
|
||||
drawRect(
|
||||
view.left.toFloat(),
|
||||
view.top.toFloat(),
|
||||
view.right.toFloat(),
|
||||
view.bottom.toFloat(),
|
||||
backgroundColorPaint
|
||||
)
|
||||
}
|
||||
|
||||
private fun Canvas.drawIcon(dX: Float, view: View, item: MessageListItem, swipeThresholdReached: Boolean) {
|
||||
if (dX > 0) {
|
||||
drawSwipeRightIcon(view, item, swipeThresholdReached)
|
||||
} else {
|
||||
drawSwipeLeftIcon(view, item, swipeThresholdReached)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Canvas.drawSwipeRightIcon(view: View, item: MessageListItem, swipeThresholdReached: Boolean) {
|
||||
resourceProvider.getIcon(item, swipeRightAction)?.let { icon ->
|
||||
val iconLeft = iconPadding
|
||||
val iconTop = view.top + ((view.height - icon.intrinsicHeight) / 2)
|
||||
val iconRight = iconLeft + icon.intrinsicWidth
|
||||
val iconBottom = iconTop + icon.intrinsicHeight
|
||||
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||
|
||||
icon.setTint(resourceProvider.getIconTint(item, swipeRightAction, swipeThresholdReached))
|
||||
icon.draw(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Canvas.drawSwipeLeftIcon(view: View, item: MessageListItem, swipeThresholdReached: Boolean) {
|
||||
resourceProvider.getIcon(item, swipeLeftAction)?.let { icon ->
|
||||
val iconRight = view.right - iconPadding
|
||||
val iconLeft = iconRight - icon.intrinsicWidth
|
||||
val iconTop = view.top + ((view.height - icon.intrinsicHeight) / 2)
|
||||
val iconBottom = iconTop + icon.intrinsicHeight
|
||||
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||
|
||||
icon.setTint(resourceProvider.getIconTint(item, swipeLeftAction, swipeThresholdReached))
|
||||
icon.draw(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun interface SwipeActionSupportProvider {
|
||||
fun isActionSupported(item: MessageListItem, action: SwipeAction): Boolean
|
||||
}
|
||||
|
||||
fun interface MessageListSwipeListener {
|
||||
fun onSwipeAction(item: MessageListItem, action: SwipeAction)
|
||||
}
|
||||
|
||||
private fun ViewHolder.markAsSwiped(value: Boolean) {
|
||||
itemView.setTag(R.id.message_list_swipe_tag, if (value) true else null)
|
||||
}
|
||||
|
||||
val ViewHolder.wasSwiped
|
||||
get() = itemView.getTag(R.id.message_list_swipe_tag) == true
|
|
@ -1,12 +1,15 @@
|
|||
package com.fsck.k9.fragment
|
||||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.fsck.k9.ui.R
|
||||
|
||||
class MessageViewHolder(view: View) {
|
||||
sealed class MessageListViewHolder(view: View) : ViewHolder(view)
|
||||
|
||||
class MessageViewHolder(view: View) : MessageListViewHolder(view) {
|
||||
var uniqueId: Long = -1L
|
||||
|
||||
val selected: View = view.findViewById(R.id.selected)
|
||||
|
@ -20,3 +23,7 @@ class MessageViewHolder(view: View) {
|
|||
val attachment: ImageView = view.findViewById(R.id.attachment)
|
||||
val status: ImageView = view.findViewById(R.id.status)
|
||||
}
|
||||
|
||||
class FooterViewHolder(view: View) : MessageListViewHolder(view) {
|
||||
val text: TextView = view.findViewById(R.id.main_text)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.fsck.k9.fragment;
|
||||
package com.fsck.k9.ui.messagelist;
|
||||
|
||||
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package com.fsck.k9.fragment
|
||||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import com.fsck.k9.Account.SortType
|
||||
import com.fsck.k9.Account.SortType.SORT_ARRIVAL
|
|
@ -0,0 +1,72 @@
|
|||
package com.fsck.k9.ui.messagelist
|
||||
|
||||
import android.content.res.Resources.Theme
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.AttrRes
|
||||
import com.fsck.k9.SwipeAction
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.resolveColorAttribute
|
||||
import com.fsck.k9.ui.resolveDrawableAttribute
|
||||
|
||||
class SwipeResourceProvider(val theme: Theme) {
|
||||
private val iconTint = theme.resolveColorAttribute(R.attr.messageListSwipeIconTint)
|
||||
|
||||
private val selectIcon = theme.loadDrawable(R.attr.messageListSwipeSelectIcon)
|
||||
private val markAsReadIcon = theme.loadDrawable(R.attr.messageListSwipeMarkAsReadIcon)
|
||||
private val markAsUnreadIcon = theme.loadDrawable(R.attr.messageListSwipeMarkAsUnreadIcon)
|
||||
private val addStarIcon = theme.loadDrawable(R.attr.messageListSwipeAddStarIcon)
|
||||
private val removeStarIcon = theme.loadDrawable(R.attr.messageListSwipeRemoveStarIcon)
|
||||
private val archiveIcon = theme.loadDrawable(R.attr.messageListSwipeArchiveIcon)
|
||||
private val deleteIcon = theme.loadDrawable(R.attr.messageListSwipeDeleteIcon)
|
||||
private val spamIcon = theme.loadDrawable(R.attr.messageListSwipeSpamIcon)
|
||||
private val moveIcon = theme.loadDrawable(R.attr.messageListSwipeMoveIcon)
|
||||
|
||||
private val noActionColor = theme.resolveColorAttribute(R.attr.messageListSwipeDisabledBackgroundColor)
|
||||
private val selectColor = theme.resolveColorAttribute(R.attr.messageListSwipeSelectBackgroundColor)
|
||||
private val markAsReadColor = theme.resolveColorAttribute(R.attr.messageListSwipeMarkAsReadBackgroundColor)
|
||||
private val markAsUnreadColor = theme.resolveColorAttribute(R.attr.messageListSwipeMarkAsUnreadBackgroundColor)
|
||||
private val addStarColor = theme.resolveColorAttribute(R.attr.messageListSwipeAddStarBackgroundColor)
|
||||
private val removeStarColor = theme.resolveColorAttribute(R.attr.messageListSwipeRemoveStarBackgroundColor)
|
||||
private val archiveColor = theme.resolveColorAttribute(R.attr.messageListSwipeArchiveBackgroundColor)
|
||||
private val deleteColor = theme.resolveColorAttribute(R.attr.messageListSwipeDeleteBackgroundColor)
|
||||
private val spamColor = theme.resolveColorAttribute(R.attr.messageListSwipeSpamBackgroundColor)
|
||||
private val moveColor = theme.resolveColorAttribute(R.attr.messageListSwipeMoveBackgroundColor)
|
||||
|
||||
fun getIconTint(item: MessageListItem, action: SwipeAction, swipeThresholdReached: Boolean): Int {
|
||||
return if (swipeThresholdReached) {
|
||||
iconTint
|
||||
} else {
|
||||
getBackgroundColor(item, action)
|
||||
}
|
||||
}
|
||||
|
||||
fun getIcon(item: MessageListItem, action: SwipeAction): Drawable? {
|
||||
return when (action) {
|
||||
SwipeAction.None -> null
|
||||
SwipeAction.ToggleSelection -> selectIcon
|
||||
SwipeAction.ToggleRead -> if (item.isRead) markAsUnreadIcon else markAsReadIcon
|
||||
SwipeAction.ToggleStar -> if (item.isStarred) removeStarIcon else addStarIcon
|
||||
SwipeAction.Archive -> archiveIcon
|
||||
SwipeAction.Delete -> deleteIcon
|
||||
SwipeAction.Spam -> spamIcon
|
||||
SwipeAction.Move -> moveIcon
|
||||
}
|
||||
}
|
||||
|
||||
fun getBackgroundColor(item: MessageListItem, action: SwipeAction): Int {
|
||||
return when (action) {
|
||||
SwipeAction.None -> noActionColor
|
||||
SwipeAction.ToggleSelection -> selectColor
|
||||
SwipeAction.ToggleRead -> if (item.isRead) markAsUnreadColor else markAsReadColor
|
||||
SwipeAction.ToggleStar -> if (item.isStarred) removeStarColor else addStarColor
|
||||
SwipeAction.Archive -> archiveColor
|
||||
SwipeAction.Delete -> deleteColor
|
||||
SwipeAction.Spam -> spamColor
|
||||
SwipeAction.Move -> moveColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Theme.loadDrawable(@AttrRes attributeId: Int): Drawable {
|
||||
return resolveDrawableAttribute(attributeId).mutate()
|
||||
}
|
|
@ -110,8 +110,8 @@ public class OpenPgpAppSelectDialog extends K9Activity {
|
|||
Context context = getActivity();
|
||||
|
||||
OpenPgpProviderEntry noneEntry = new OpenPgpProviderEntry(null,
|
||||
context.getString(R.string.openpgp_list_preference_none),
|
||||
getResources().getDrawable(R.drawable.ic_action_cancel_launchersize_light));
|
||||
context.getString(org.openintents.openpgp.R.string.openpgp_list_preference_none),
|
||||
getResources().getDrawable(org.openintents.openpgp.R.drawable.ic_action_cancel_launchersize_light));
|
||||
openPgpProviderList.add(noneEntry);
|
||||
|
||||
// search for OpenPGP providers...
|
||||
|
@ -144,8 +144,9 @@ public class OpenPgpAppSelectDialog extends K9Activity {
|
|||
Drawable icon = resolveInfo.activityInfo.loadIcon(context.getPackageManager());
|
||||
String marketName = String.valueOf(resolveInfo.activityInfo.applicationInfo
|
||||
.loadLabel(context.getPackageManager()));
|
||||
String simpleName = String.format(context.getString(R.string
|
||||
.openpgp_install_openkeychain_via), marketName);
|
||||
String simpleName = String.format(
|
||||
context.getString(org.openintents.openpgp.R.string.openpgp_install_openkeychain_via),
|
||||
marketName);
|
||||
openPgpProviderList.add(new OpenPgpProviderEntry(OPENKEYCHAIN_PACKAGE, simpleName,
|
||||
icon, marketIntent));
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.fsck.k9.ui.settings.general
|
|||
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import com.fsck.k9.K9
|
||||
import com.fsck.k9.SwipeAction
|
||||
import com.fsck.k9.job.K9JobManager
|
||||
import com.fsck.k9.preferences.AppTheme
|
||||
import com.fsck.k9.preferences.GeneralSettingsManager
|
||||
|
@ -41,6 +42,7 @@ class GeneralSettingsDataStore(
|
|||
"privacy_hide_timezone" -> K9.isHideTimeZone
|
||||
"debug_logging" -> K9.isDebugLoggingEnabled
|
||||
"sensitive_logging" -> K9.isSensitiveDebugLoggingEnabled
|
||||
"volume_navigation" -> K9.isUseVolumeKeysForNavigation
|
||||
else -> defValue
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +72,7 @@ class GeneralSettingsDataStore(
|
|||
"privacy_hide_timezone" -> K9.isHideTimeZone = value
|
||||
"debug_logging" -> K9.isDebugLoggingEnabled = value
|
||||
"sensitive_logging" -> K9.isSensitiveDebugLoggingEnabled = value
|
||||
"volume_navigation" -> K9.isUseVolumeKeysForNavigation = value
|
||||
else -> return
|
||||
}
|
||||
|
||||
|
@ -123,6 +126,8 @@ class GeneralSettingsDataStore(
|
|||
"message_view_date_font" -> K9.fontSizes.messageViewDate.toString()
|
||||
"message_view_additional_headers_font" -> K9.fontSizes.messageViewAdditionalHeaders.toString()
|
||||
"message_compose_input_font" -> K9.fontSizes.messageComposeInput.toString()
|
||||
"swipe_action_right" -> swipeActionToString(K9.swipeRightAction)
|
||||
"swipe_action_left" -> swipeActionToString(K9.swipeLeftAction)
|
||||
else -> defValue
|
||||
}
|
||||
}
|
||||
|
@ -162,6 +167,8 @@ class GeneralSettingsDataStore(
|
|||
"message_view_date_font" -> K9.fontSizes.messageViewDate = value.toInt()
|
||||
"message_view_additional_headers_font" -> K9.fontSizes.messageViewAdditionalHeaders = value.toInt()
|
||||
"message_compose_input_font" -> K9.fontSizes.messageComposeInput = value.toInt()
|
||||
"swipe_action_right" -> K9.swipeRightAction = stringToSwipeAction(value)
|
||||
"swipe_action_left" -> K9.swipeLeftAction = stringToSwipeAction(value)
|
||||
else -> return
|
||||
}
|
||||
|
||||
|
@ -189,12 +196,6 @@ class GeneralSettingsDataStore(
|
|||
if (K9.isMessageViewSpamActionVisible) add("spam")
|
||||
}
|
||||
}
|
||||
"volume_navigation" -> {
|
||||
mutableSetOf<String>().apply {
|
||||
if (K9.isUseVolumeKeysForNavigation) add("message")
|
||||
if (K9.isUseVolumeKeysForListNavigation) add("list")
|
||||
}
|
||||
}
|
||||
else -> defValues
|
||||
}
|
||||
}
|
||||
|
@ -217,10 +218,6 @@ class GeneralSettingsDataStore(
|
|||
K9.isMessageViewCopyActionVisible = "copy" in checkedValues
|
||||
K9.isMessageViewSpamActionVisible = "spam" in checkedValues
|
||||
}
|
||||
"volume_navigation" -> {
|
||||
K9.isUseVolumeKeysForNavigation = "message" in checkedValues
|
||||
K9.isUseVolumeKeysForListNavigation = "list" in checkedValues
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
|
||||
|
@ -288,4 +285,27 @@ class GeneralSettingsDataStore(
|
|||
jobManager.scheduleAllMailJobs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun swipeActionToString(action: SwipeAction) = when (action) {
|
||||
SwipeAction.None -> "none"
|
||||
SwipeAction.ToggleSelection -> "toggle_selection"
|
||||
SwipeAction.ToggleRead -> "toggle_read"
|
||||
SwipeAction.ToggleStar -> "toggle_star"
|
||||
SwipeAction.Archive -> "archive"
|
||||
SwipeAction.Delete -> "delete"
|
||||
SwipeAction.Spam -> "spam"
|
||||
SwipeAction.Move -> "move"
|
||||
}
|
||||
|
||||
private fun stringToSwipeAction(action: String) = when (action) {
|
||||
"none" -> SwipeAction.None
|
||||
"toggle_selection" -> SwipeAction.ToggleSelection
|
||||
"toggle_read" -> SwipeAction.ToggleRead
|
||||
"toggle_star" -> SwipeAction.ToggleStar
|
||||
"archive" -> SwipeAction.Archive
|
||||
"delete" -> SwipeAction.Delete
|
||||
"spam" -> SwipeAction.Spam
|
||||
"move" -> SwipeAction.Move
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.google.android.material.snackbar.Snackbar
|
|||
import com.takisoft.preferencex.PreferenceFragmentCompat
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import com.fsck.k9.core.R as CoreR
|
||||
|
||||
class GeneralSettingsFragment : PreferenceFragmentCompat() {
|
||||
private val viewModel: GeneralSettingsViewModel by viewModel()
|
||||
|
@ -74,7 +75,7 @@ class GeneralSettingsFragment : PreferenceFragmentCompat() {
|
|||
(findPreference(PREFERENCE_THEME) as? ListPreference)?.apply {
|
||||
if (Build.VERSION.SDK_INT < 28) {
|
||||
setEntries(R.array.theme_entries_legacy)
|
||||
setEntryValues(R.array.theme_values_legacy)
|
||||
setEntryValues(CoreR.array.theme_values_legacy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import android.content.Context
|
|||
import android.util.AttributeSet
|
||||
import androidx.core.content.res.TypedArrayUtils
|
||||
import androidx.preference.ListPreference
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.core.R
|
||||
|
||||
class LanguagePreference
|
||||
@JvmOverloads
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="56dp"
|
||||
android:height="56dp"
|
||||
android:viewportWidth="28"
|
||||
android:viewportHeight="28">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14,14c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM14,16c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z" />
|
||||
</vector>
|
11
app/ui/legacy/src/main/res/drawable/ic_move_to_folder.xml
Normal file
11
app/ui/legacy/src/main/res/drawable/ic_move_to_folder.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM14,18v-3h-4v-4h4L14,8l5,5 -5,5z" />
|
||||
</vector>
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_window_focused="false" android:state_selected="true"
|
||||
android:drawable="@color/message_list_item_footer_background" />
|
||||
<item android:state_selected="true"
|
||||
android:drawable="@android:color/transparent" />
|
||||
<item android:state_pressed="true" android:state_selected="false"
|
||||
android:drawable="@android:color/transparent" />
|
||||
<item android:state_selected="false"
|
||||
android:drawable="@android:color/transparent"
|
||||
/>
|
||||
</selector>
|
|
@ -1,18 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/swiperefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.fsck.k9.fragment.MessageListFragment">
|
||||
tools:context=".messagelist.MessageListFragment">
|
||||
|
||||
<ListView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/message_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="5"
|
||||
android:scrollbars="vertical"
|
||||
android:scrollbarStyle="insideOverlay"
|
||||
android:fadingEdge="none"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/message_list_item"/>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:layout_height="?android:attr/listPreferredItemHeight"
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:background="@drawable/message_list_item_footer_background"
|
||||
android:background="?attr/messageListRegularItemBackgroundColor"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
|
|
|
@ -5,6 +5,26 @@
|
|||
Locale-specific versions are kept in res/raw-<locale qualifier>/changelog.xml.
|
||||
-->
|
||||
<changelog>
|
||||
<release version="6.308" versioncode="33008" date="2022-10-06">
|
||||
<change>Added swipe actions to the message list screen</change>
|
||||
<change>Changed the minimum size of the message list widget to 2x2 cells</change>
|
||||
<change>Fixed a bug where the app would start using the light theme before switching to the dark theme resulting in a brief flash of white</change>
|
||||
<change>More minor bug fixes and improvements</change>
|
||||
<change>Updated translations</change>
|
||||
</release>
|
||||
<release version="6.307" versioncode="33007" date="2022-09-26">
|
||||
<change>Fixed the message list background color in the dark theme</change>
|
||||
<change>Fixed a small display issue where "Load up to X more" could have been displayed when it shouldn't have been</change>
|
||||
<change>Updated translations</change>
|
||||
</release>
|
||||
<release version="6.306" versioncode="33006" date="2022-09-23">
|
||||
<change>Added a monochromatic app icon for Android 13</change>
|
||||
<change>Changed the UI component used for the message list; now changes to the list will be animated</change>
|
||||
<change>Removed the volume key navigation for list views because it doesn't play nice with the above change</change>
|
||||
<change>Fixed a bug that lead to the search input field being focused on app start on some devices</change>
|
||||
<change>Restored the previous behavior of "show next message after delete"</change>
|
||||
<change>A lot of internal changes and some minor performance improvements</change>
|
||||
</release>
|
||||
<release version="6.305" versioncode="33005" date="2022-09-17">
|
||||
<change>Fixed a bug that could lead to a crash when opening the message list</change>
|
||||
</release>
|
||||
|
|
|
@ -567,7 +567,6 @@
|
|||
<string name="account_setup_push_limit_500">500 مجلد</string>
|
||||
<string name="account_setup_push_limit_1000">1000 مجلد</string>
|
||||
<string name="animations_title">الحركة</string>
|
||||
<string name="volume_navigation_title">التصفح عبر أزرار التحكم في الصوت</string>
|
||||
<string name="integrated_inbox_title">البريد الوارد الموحَّد</string>
|
||||
<string name="integrated_inbox_detail">كل الرسائل في مجلدات موحَّدة</string>
|
||||
<string name="folder_settings_include_in_integrated_inbox_label">التوحيد</string>
|
||||
|
|
|
@ -579,8 +579,6 @@ K-9 Mail - шматфункцыянальны свабодны паштовы к
|
|||
<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>
|
||||
<string name="message_view_help_key">Del (ці D) - Выдаліць\nR - Адказаць\nA - Адказаць усім\nC - Стварыць\nF - Пераслаць\nM - Перамясціць\nV - Адправіць у архіў\nY - Скапіяваць\nZ - Пазначыць (не)прачытаным\nG - Адзначыць\nO - Тып сартавання\nI - Парадак сартавання\nQ - Вярнуцца да каталогаў\nS - Абраць / Адкінуць выбар\nJ альбо P - Папярэдні ліст\nK альбо N - Наступны ліст</string>
|
||||
<string name="message_list_help_key">Del (ці D) - Выдаліць\nC - Стварыць\nF - Пераслаць\nM - Перамясціць\nV - Адправіць у архіў\nY - Скапіяваць\nZ - Пазначыць (не)прачытаным\nG - Адзначыць\nO - Тып сартавання\nI - Парадак сартавання\nQ - Вярнуцца да каталогаў\nS - Абраць / Адкінуць выбар</string>
|
||||
<string name="folder_list_filter_hint">Пошук каталога</string>
|
||||
<string name="folder_list_display_mode_label">Паказваць каталогі…</string>
|
||||
<string name="folder_list_display_mode_all">Усе каталогі</string>
|
||||
|
@ -628,9 +626,6 @@ K-9 Mail - шматфункцыянальны свабодны паштовы к
|
|||
<string name="account_setup_push_limit_1000">1000 каталогаў</string>
|
||||
<string name="animations_title">Анімацыя</string>
|
||||
<string name="animations_summary">Анімацыя інтэрфейсу</string>
|
||||
<string name="volume_navigation_title">Навігацыя клавішамі гучнасці</string>
|
||||
<string name="volume_navigation_message">У лісце</string>
|
||||
<string name="volume_navigation_list">У спісе</string>
|
||||
<string name="show_unified_inbox_title">Агульная скрыня ўваходных лістоў для ўсіх акаўнтаў</string>
|
||||
<string name="integrated_inbox_title">Усе атрыманыя</string>
|
||||
<string name="integrated_inbox_detail">Усе лісты са ўсіх каталогаў</string>
|
||||
|
|
|
@ -576,8 +576,6 @@ K-9 Mail е мощен, безплатен имейл клиент за Андр
|
|||
<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>
|
||||
<string name="message_view_help_key">Del (or D) - Изтриване\nR - Отговор\nA - Отговор на всички\nC - Създаване\nF - Препращане\nM - Премесване\nV - Архивиране\nY - Копиране\nZ - Отбелязване като (не)прочетно\nG - Звезда\nO - Сортиране\nI - Приоритет на сортиране\nQ - Обратно към папките\nS - Отбелязване/премахване на отбелязване\nJ или P - Предно съобщение\nK или N - Следващо съобщение</string>
|
||||
<string name="message_list_help_key">Del (or D) - Изтриване\nC - Създаване\nM - Премесване\nV - Архивиране\nC - Копиране\nZ - Отбелязване като (не)прочетно\nG - Звезда\nO - Сортиране\nI - Приоритет на сортиране\nQ - Обратно към папките\nS - Отбелязване/премахване на отбелязване</string>
|
||||
<string name="folder_list_filter_hint">Името на папката съдържа</string>
|
||||
<string name="folder_list_display_mode_label">Покажи папките…</string>
|
||||
<string name="folder_list_display_mode_all">Всички папки</string>
|
||||
|
@ -625,9 +623,6 @@ K-9 Mail е мощен, безплатен имейл клиент за Андр
|
|||
<string name="account_setup_push_limit_1000">1000 папки</string>
|
||||
<string name="animations_title">Анимация</string>
|
||||
<string name="animations_summary">Изплозване на ярки виулани ефекти</string>
|
||||
<string name="volume_navigation_title">Навигация с клавиш за звука</string>
|
||||
<string name="volume_navigation_message">В преглед на съобщението</string>
|
||||
<string name="volume_navigation_list">В списъка със съобщения</string>
|
||||
<string name="show_unified_inbox_title">Покажи унифицирана папка Входящи</string>
|
||||
<string name="integrated_inbox_title">Обща входяща кутия</string>
|
||||
<string name="integrated_inbox_detail">Всички съобщения в общата входяща кутия</string>
|
||||
|
|
|
@ -550,8 +550,6 @@ Danevellit beugoù, kenlabourit war keweriusterioù nevez ha savit goulennoù wa
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Testeni dianav</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Asantiñ an alc’hwez</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Nac’h an alc’hwez</string>
|
||||
<string name="message_view_help_key">Del (pe D) - Dilemel\nR - Respont\nA - Respont d’an holl\nC - Skridaozañ\nF - Treuzkas\nM - Dilec’hiañ\nV - Diellaouiñ\nY - Eilañ\nZ - Merkañ evel (An)lennet\nG - Steredenniñ\nO - Doare urzhiañ\nI - Tu an urzh\nQ - Distreiñ d’an teuliadoù\nS - (Di)ziuzañ\nJ or P - Kemennadenn gent\nK pe N - Kemennadenn da heul</string>
|
||||
<string name="message_list_help_key">Del (pe D) - Dilemel\nC - Skridaozañ\nM - Dilec’hiañ\nV - Diellaouiñ\nY - Eilañ\nZ - Merkañ evel (An)Lennet\nG - Steredenniñ\nO - Doare urzhiañ\nI - Tu an urzhiañ\nQ - Distreiñ d’an teuliadoù\nS - (Di)ziuzañ</string>
|
||||
<string name="folder_list_filter_hint">Anv an teuliad a endalc’h</string>
|
||||
<string name="folder_list_display_mode_label">Diskouez an teuliadoù</string>
|
||||
<string name="folder_list_display_mode_all">An holl deuliadoù</string>
|
||||
|
@ -597,9 +595,6 @@ Danevellit beugoù, kenlabourit war keweriusterioù nevez ha savit goulennoù wa
|
|||
<string name="account_setup_push_limit_1000">1000 teuliad</string>
|
||||
<string name="animations_title">Bliverezh</string>
|
||||
<string name="animations_summary">Ober gant efedoù gwel gaudy</string>
|
||||
<string name="volume_navigation_title">Merdeiñ dre afelloù an ampled</string>
|
||||
<string name="volume_navigation_message">Er gwel kemennadenn</string>
|
||||
<string name="volume_navigation_list">Er gwel roll</string>
|
||||
<string name="integrated_inbox_title">Boest degemer unanet</string>
|
||||
<string name="integrated_inbox_detail">Holl gemennadennoù an teuliadoù unanet</string>
|
||||
<string name="folder_settings_include_in_integrated_inbox_label">Unanañ</string>
|
||||
|
|
|
@ -633,8 +633,6 @@ Si us plau, envieu informes d\'errors, contribuïu-hi amb noves millores i feu p
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Certificat no reconegut</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Accepta la clau</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Rebutja la clau</string>
|
||||
<string name="message_view_help_key">Del (o D) - Elimina\nR - Respon\nA - Respon a tothom\nC - Escriu\nF - Reenvia\nM - Mou\nV - Arxiva\nY - Copia\nZ - Marca com a (no) llegit\nG - Estel\nO - Per tipus\nI - Per ordre\nQ - Torna a les carpetes\nS - Selecciona / desmarca\nJ o P - Missatge anterior n\K o N - Missatge següent</string>
|
||||
<string name="message_list_help_key">Del (o D) - Elimina\nC - Escriu\nM - Mou\nV - Arxiva\nY - Copia\nZ - Marca com a (no) llegit\nG - Estel\nO - Tipus de classificació\nI - Ordre de classificació\nQ - Torna a les carpetes\nS - Selecciona / desmarca</string>
|
||||
<string name="folder_list_filter_hint">El nom de carpeta conté</string>
|
||||
<string name="folder_list_display_mode_label">Carpetes…</string>
|
||||
<string name="folder_list_display_mode_all">Mostra totes les carpetes</string>
|
||||
|
@ -682,9 +680,7 @@ Si us plau, envieu informes d\'errors, contribuïu-hi amb noves millores i feu p
|
|||
<string name="account_setup_push_limit_1000">1000 carpetes</string>
|
||||
<string name="animations_title">Animació</string>
|
||||
<string name="animations_summary">Utilitza efectes visuals cridaners</string>
|
||||
<string name="volume_navigation_title">Navegació amb botons de volum</string>
|
||||
<string name="volume_navigation_message">Vista del missatge</string>
|
||||
<string name="volume_navigation_list">A la vista de llistes</string>
|
||||
<string name="volume_navigation_title">Navegació amb la tecla de volum a la vista de missatges</string>
|
||||
<string name="show_unified_inbox_title">Mostra la safata d\'entrada unificada</string>
|
||||
<string name="show_starred_count_title">Mostra el recompte de destacats.</string>
|
||||
<string name="integrated_inbox_title">Bústia unificada</string>
|
||||
|
|
|
@ -95,7 +95,7 @@ Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictví
|
|||
<string name="single_message_options_action">Odeslat…</string>
|
||||
<string name="refile_action">Přesměrovat…</string>
|
||||
<string name="done_action">Hotovo</string>
|
||||
<string name="discard_action">Zrušit</string>
|
||||
<string name="discard_action">Zahodit</string>
|
||||
<string name="save_draft_action">Uložit jako koncept</string>
|
||||
<string name="check_mail_action">Zkontrolovat poštu</string>
|
||||
<string name="send_messages_action">Odeslat zprávy</string>
|
||||
|
@ -637,8 +637,6 @@ Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictví
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Nerozpoznaný certifikát</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Přijmout klíč</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Odmítnout klíč</string>
|
||||
<string name="message_view_help_key">Delete (nebo D) – Smazat\nR – Odpovědět\nA – Odpovědět všem\nC – Vytvořit\nF – Přeposlat\nM – Přesunout\nV - Archivovat\nY – Kopírovat\nZ – Označit (Ne)přečtené\nG – Hvězdička\nO – Uspořádat podle typu\nI – Uspořádat podle pořadí\nQ – Zpět ke složkám\nS – Označit/odznačit\nJ nebo P – Předešlá zpráva\nK nebo N – Další zpráva</string>
|
||||
<string name="message_list_help_key">Delete (nebo D) – Smazat\nC – Vytvořit\nM – Přesunout\nV – Archivovat\nY – Zkopírovat\nZ – Označit jako (ne)přečtené\nG – Označit hvězdičkou\nO – Typ řazení\nI – Pořadí řazení\nQ – Návrat na složky\nS – Označit / zrušit označení</string>
|
||||
<string name="folder_list_filter_hint">Název složky obsahuje</string>
|
||||
<string name="folder_list_display_mode_label">Zobrazit složky…</string>
|
||||
<string name="folder_list_display_mode_all">Všechny složky</string>
|
||||
|
@ -686,9 +684,6 @@ Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictví
|
|||
<string name="account_setup_push_limit_1000">1000 složek</string>
|
||||
<string name="animations_title">Animace</string>
|
||||
<string name="animations_summary">Používat okázalé vizuální efekty</string>
|
||||
<string name="volume_navigation_title">Navigace tlačítky hlasitosti</string>
|
||||
<string name="volume_navigation_message">Zobrazení zpráv</string>
|
||||
<string name="volume_navigation_list">Různá zobrazení seznamů</string>
|
||||
<string name="show_unified_inbox_title">Ukázat sjednocený pohled na doručenou poštu</string>
|
||||
<string name="show_starred_count_title">Zobrazit počet označených hvězdičkou</string>
|
||||
<string name="integrated_inbox_title">Integrovaná doručená pošta</string>
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
<string name="app_license">Trwydded Apache, Fersiwn 2.0</string>
|
||||
<string name="about_project_title">Prosiect Cod Agored</string>
|
||||
<string name="about_website_title">Gwefan</string>
|
||||
<string name="user_manual_title">Llawlyfr defnyddiwr</string>
|
||||
<string name="get_help_title">Cael cymorth</string>
|
||||
<string name="user_forum_title">Fforwm defnyddiwyr</string>
|
||||
<string name="about_fediverse_title">Fediverse</string>
|
||||
<string name="about_twitter_title">Twitter</string>
|
||||
<string name="about_libraries">Llyfrgelloedd</string>
|
||||
<string name="license">Trwydded</string>
|
||||
|
@ -71,7 +74,7 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="choose_account_title">Dewis cyfrif</string>
|
||||
<string name="choose_folder_title">Dewis ffolder</string>
|
||||
<string name="choose_folder_move_title">Symud i...</string>
|
||||
<string name="choose_folder_copy_title">Copïo i...</string>
|
||||
<string name="choose_folder_copy_title">Copïo i…</string>
|
||||
<string name="actionbar_selected"><xliff:g id="selection_count">%d</xliff:g> wedi\'i dewis</string>
|
||||
<string name="next_action">Nesaf</string>
|
||||
<string name="previous_action">Blaenorol</string>
|
||||
|
@ -171,7 +174,9 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="notification_authentication_error_title">Methwyd a dilysu</string>
|
||||
<string name="notification_authentication_error_text">Methodd y dilysiad ar gyfer <xliff:g id="account">%s</xliff:g>. Diweddara dy osodiadau gweinydd.</string>
|
||||
<!--Title of an error notification that is displayed when creating a notification for a new message has failed-->
|
||||
<string name="notification_notify_error_title">Gwall hysbysiad</string>
|
||||
<!--Body of an error notification that is displayed when creating a notification for a new message has failed-->
|
||||
<string name="notification_notify_error_text">Bu gwall wrth geisio creu hysbysiad system am neges newydd. Mae\'n debyg mai\'r rheswm yw bod sain hysbysiad ar goll.\n\nTapia i agor gosodiadau hysbysiadau.</string>
|
||||
<string name="notification_bg_sync_ticker">Yn gwirio am negeseuon: <xliff:g id="account">%1$s</xliff:g>:<xliff:g id="folder">%2$s</xliff:g></string>
|
||||
<string name="notification_bg_sync_title">Yn gwirio am negeseuon</string>
|
||||
<string name="notification_bg_send_ticker">Yn anfon negeseuon: <xliff:g id="account">%s</xliff:g></string>
|
||||
|
@ -196,7 +201,7 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="debug_enable_sensitive_logging_summary">Gall dangos cyfrineiriau mewn logiau.</string>
|
||||
<string name="debug_export_logs_title">Allforio logiau</string>
|
||||
<string name="debug_export_logs_success">Allforiwyd yn llwyddiannus. Gall logiau gynnwys gwybodaeth sensitif. Byddwch yn ofalus gyda phwy rydych yn eu rhannu.</string>
|
||||
<string name="debug_export_logs_failure">Methwyd yr allforio.</string>
|
||||
<string name="debug_export_logs_failure">Methodd yr allforio.</string>
|
||||
<string name="message_list_load_more_messages_action">Llwytho rhagor o negeseuon</string>
|
||||
<string name="message_to_fmt">At:<xliff:g id="counterParty">%s</xliff:g></string>
|
||||
<string name="message_compose_subject_hint">Pwnc</string>
|
||||
|
@ -397,6 +402,7 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="account_setup_failed_dlg_server_message_fmt">Methwyd cysylltu gyda\'r gweinydd.\n(<xliff:g id="error">%s</xliff:g>)</string>
|
||||
<string name="account_setup_failed_dlg_oauth_flow_canceled">Diddymwyd awdurdodi</string>
|
||||
<string name="account_setup_failed_dlg_oauth_flow_failed">Methodd awdurdodi gyda\'r gwall hwn: <xliff:g id="error">%s</xliff:g></string>
|
||||
<string name="account_setup_failed_dlg_oauth_not_supported">Ni chefnogir OAuth 2.0 ar hyn o bryd gyda\'r darparydd hwn.</string>
|
||||
<string name="account_setup_failed_dlg_browser_not_found">Methodd yr ap hwn ddod o hyd i borwr i\'w ddefnyddio i roi mynediad at dy gyfrif.</string>
|
||||
<string name="account_setup_failed_dlg_edit_details_action">Golygu manylion</string>
|
||||
<string name="account_setup_failed_dlg_continue_action">Parhau</string>
|
||||
|
@ -538,6 +544,7 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="folder_settings_folder_push_mode_normal">Dim Rhenc</string>
|
||||
<string name="folder_settings_folder_push_mode_first_class">Rhenc 1af</string>
|
||||
<string name="folder_settings_folder_push_mode_second_class">2ail renc</string>
|
||||
<string name="folder_settings_folder_push_mode_inherited">Fel rhenc gwirio</string>
|
||||
<string name="folder_settings_folder_notify_mode_label">Rhenc hysbysiadau\'r ffolder</string>
|
||||
<string name="folder_settings_folder_notify_mode_normal">Dim rhenc</string>
|
||||
<string name="folder_settings_folder_notify_mode_first_class">Rhenc 1af</string>
|
||||
|
@ -631,8 +638,6 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Tystysgrif Ddiarth</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Derbyn Allwedd</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Gwrthod Allwedd</string>
|
||||
<string name="message_view_help_key">Del (neu D) - Dileu\nR - Ateb\nA - Ateb i bawb\nC - Cyfansoddi\nF - Anfon ymlaen\nM - Symud\nV - Archifo\nY - Copïo\nZ - Nodi heb/wedi ei darllen\nG - Serennu\nO - Math o drefn\nI - Trefn sortio\nQ - Nôl i\'r ffolderi\nS - Dewis/dad-ddewis\nJ neu P - Neges flaenorol\nK neu N - Neges nesaf</string>
|
||||
<string name="message_list_help_key">Del (neu D) - Dileu\nC - Cyfansoddi\nM - Symud\nV - Archive\nY - Copy\nZ -Nodi wedi/heb ei darllen\nG - Serennu\nO - Math o drefn\nI - Trefn\nQ - Nôl i\'r ffolderi\nS - Dewis/dad-ddewis</string>
|
||||
<string name="folder_list_filter_hint">Enw ffolder yn cynnwys</string>
|
||||
<string name="folder_list_display_mode_label">Dangos ffolderi…</string>
|
||||
<string name="folder_list_display_mode_all">Pob ffolder</string>
|
||||
|
@ -680,10 +685,9 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="account_setup_push_limit_1000">1000 o ffolderi</string>
|
||||
<string name="animations_title">Animeiddiad</string>
|
||||
<string name="animations_summary">Defnyddio effeithiau gweledol dros ben llestri</string>
|
||||
<string name="volume_navigation_title">Pori gyda\'r botymau sain</string>
|
||||
<string name="volume_navigation_message">Wrth edrych ar neges</string>
|
||||
<string name="volume_navigation_list">Wrth edrych ar restr</string>
|
||||
<string name="volume_navigation_title">Llywio gyda botymau sain ym modd golwg neges</string>
|
||||
<string name="show_unified_inbox_title">Dangos mewnflwch unedig</string>
|
||||
<string name="show_starred_count_title">Dangos cyfrif serennog</string>
|
||||
<string name="integrated_inbox_title">Mewnflwch Unedig</string>
|
||||
<string name="integrated_inbox_detail">Holl negeseuon pob cyfrif mewn un ffolder unedig</string>
|
||||
<string name="folder_settings_include_in_integrated_inbox_label">Uno</string>
|
||||
|
@ -766,7 +770,7 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
|
|||
<string name="messagelist_sent_cc_me_sigil">›</string>
|
||||
<string name="settings_list_backup_category">Copi wrth gefn</string>
|
||||
<string name="settings_list_miscellaneous_category">Amrywiol</string>
|
||||
<string name="settings_export_title">Archwilio gosodiadau</string>
|
||||
<string name="settings_export_title">Allforio gosodiadau</string>
|
||||
<string name="settings_export_button">Allforio</string>
|
||||
<string name="settings_export_share_button">Rhannu</string>
|
||||
<string name="settings_export_progress_text">Yn allforio gosodiadau…</string>
|
||||
|
@ -1039,10 +1043,16 @@ Mae\'n bosib i ti gadw\'r neges hon a\'i ddefnyddio wrth gefn fel dy allwedd gyf
|
|||
<string name="permission_contacts_rationale_title">Caniatáu mynediad at gysylltiadau</string>
|
||||
<string name="permission_contacts_rationale_message">Er mwyn medru awgrymu cysylltiadau a dangos lluniau ac enwau cysylltiadau, mae ar yr ap angen mynediad at dy gysylltiadau.</string>
|
||||
<string name="generic_loading_error">Bu gwall wrth lwytho\'r data</string>
|
||||
<string name="push_notification_state_initializing">Yn ymgychwyn…</string>
|
||||
<string name="push_notification_state_listening">Yn aros am negeseuon e-bost newydd</string>
|
||||
<string name="push_notification_state_wait_background_sync">Yn cysgu nes bod cysoni yn y cefndir wedi\'i ganiatáu</string>
|
||||
<string name="push_notification_state_wait_network">Yn cysgu nes bod rhwydwaith ar gael</string>
|
||||
<string name="push_notification_info">Tapiwch i ddysgu rhagor.</string>
|
||||
<string name="push_info_title">Gwybodaeth gwthio</string>
|
||||
<string name="push_info_notification_explanation_text">Pan yn defnyddio Gwthio, mae K-9 Mail yn cadw cysylltiad â\'r gweinydd ebost. Mae ar Android angen dangos hysbysiad parhaus tra bod yr ap yn weithredol yn y cefndir. %s</string>
|
||||
<string name="push_info_configure_notification_text">Fodd bynnag, mae Android hefyd yn eich galluogi i guddio\'r hysbysiad.</string>
|
||||
<string name="push_info_learn_more_text">Dysgu rhagor</string>
|
||||
<string name="push_info_configure_notification_action">Ffurfweddu hysbysiad</string>
|
||||
<string name="push_info_disable_push_text">Os nad wyt angen hysbysiadau ar unwaith am negeseuon newydd, analluoga Gwthio a defnyddio Gwirio. Mae Gwirio yn edrych am negeseuon newydd ar gyfnodau rheolaidd heb fod angen yr hysbysiad parhaus.</string>
|
||||
<string name="push_info_disable_push_action">Analluogi Gwthio</string>
|
||||
</resources>
|
||||
|
|
|
@ -605,8 +605,6 @@ Rapporter venligst fejl, forslag til nye funktioner eller stil spørgsmål på:
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Ukendt certificat</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Acceptér nøgle</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Afvis nøgle</string>
|
||||
<string name="message_view_help_key">Del (or D) - Slet\nR - Svar\nA - Svar alle\nC - Skriv besked\nF - Videresend\nM - Flyt\nV - Arkiver\nY - Kopier\nZ - Marker (U)læst\nG - Stjernemarker\nO - Sorteringstype\nI - Sortering\nQ - Tilbage til Mapper\nS - Marker/afmarker\nJ or P - Forrige meddelelse\nK or N - Næste Meddelelse</string>
|
||||
<string name="message_list_help_key">Del (or D) - Slet\nC - Skriv besked\nM - Flyt\nV - Arkiver\nY - Kopier\nZ - Marker (U)læst\nG - Stjernemarker\nO - Sorteringstype\nI - Sorteringsorden\nQ - Tilbage til mapper\nS - Marker/afmaker</string>
|
||||
<string name="folder_list_filter_hint">Mappenavn indeholder</string>
|
||||
<string name="folder_list_display_mode_label">Mapper</string>
|
||||
<string name="folder_list_display_mode_all">Vis alle mapper</string>
|
||||
|
@ -654,9 +652,6 @@ Rapporter venligst fejl, forslag til nye funktioner eller stil spørgsmål på:
|
|||
<string name="account_setup_push_limit_1000">1000 mapper</string>
|
||||
<string name="animations_title">Animation</string>
|
||||
<string name="animations_summary">Anvend visuelle effekter</string>
|
||||
<string name="volume_navigation_title">Volume-knap navigation</string>
|
||||
<string name="volume_navigation_message">Mail-visning</string>
|
||||
<string name="volume_navigation_list">Diverse listevisninger</string>
|
||||
<string name="show_unified_inbox_title">Vis Fælles Indbakke</string>
|
||||
<string name="integrated_inbox_title">Fælles indbakke</string>
|
||||
<string name="integrated_inbox_detail">Alle mails i fælles mapper</string>
|
||||
|
|
|
@ -633,8 +633,6 @@ Bitte senden Sie Fehlerberichte, Ideen für neue Funktionen und stellen Sie Frag
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Ungültiges Zertifikat</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Zertifikat akzeptieren</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Zertifikat ablehnen</string>
|
||||
<string name="message_view_help_key">Entf (oder D) - Löschen\nR - Antworten\nA - Allen Antworten\nC - Verfassen\nF - Weiterleiten\nM - Verschieben\nV - Archivieren\nY - Kopieren\nZ - Als (un)gelesen markieren\nG - Wichtig\nO - Sortiertyp\nI - Sortierreihenfolge\nQ - Zurück zu den Ordnern\nS - Auswählen/Abwählen\nJ oder P - Vorherige Nachricht\nK oder N - Nächste Nachricht</string>
|
||||
<string name="message_list_help_key">Entf (oder D) - Löschen\nC - Verfassen\nM - Verschieben\nV - Archivieren\nY - Kopieren\nZ - Als (un)gelesen markieren\nG - Wichtig\nO - Sortiertyp\nI - Sortierreihenfolge\nQ - Zurück zu den Ordnern\nS - Auswählen/Abwählen</string>
|
||||
<string name="folder_list_filter_hint">Ordnername enthält</string>
|
||||
<string name="folder_list_display_mode_label">Ordner</string>
|
||||
<string name="folder_list_display_mode_all">Alle Ordner anzeigen</string>
|
||||
|
@ -682,9 +680,7 @@ Bitte senden Sie Fehlerberichte, Ideen für neue Funktionen und stellen Sie Frag
|
|||
<string name="account_setup_push_limit_1000">1000 Ordner</string>
|
||||
<string name="animations_title">Animationen</string>
|
||||
<string name="animations_summary">Aufwendige visuelle Effekte benutzen</string>
|
||||
<string name="volume_navigation_title">Lauter/Leiser-Navigation</string>
|
||||
<string name="volume_navigation_message">Nachrichtenansicht</string>
|
||||
<string name="volume_navigation_list">Diverse Listenansichten</string>
|
||||
<string name="volume_navigation_title">Navigation per Lautstärketasten in der Nachrichtenansicht</string>
|
||||
<string name="show_unified_inbox_title">Gemeinsamen Posteingang anzeigen</string>
|
||||
<string name="show_starred_count_title">Anzahl der Sterne anzeigen</string>
|
||||
<string name="integrated_inbox_title">Gemeinsamer Posteingang</string>
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
<!--Used in the about dialog-->
|
||||
<string name="app_authors">The K-9 Dog Walkers</string>
|
||||
<string name="source_code">Πηγαίος κώδικας</string>
|
||||
<string name="app_license">Άδεια χρήσης Apache, έκδοση 2.0.</string>
|
||||
<string name="about_project_title">Έργο Ανοιχτού Κώδικα</string>
|
||||
<string name="app_license">Άδεια χρήσης Apache, έκδοση 2.0</string>
|
||||
<string name="about_project_title">Έργο ανοικτού κώδικα</string>
|
||||
<string name="about_website_title">Ιστότοπος</string>
|
||||
<string name="user_forum_title">Χώρος συζητήσεων χρηστών</string>
|
||||
<string name="user_manual_title">Οδηγός χρήστη</string>
|
||||
<string name="get_help_title">Λήψη βοήθειας</string>
|
||||
<string name="user_forum_title">Φόρουμ χρηστών</string>
|
||||
<string name="about_fediverse_title">Fediverse</string>
|
||||
<string name="about_twitter_title">Twitter</string>
|
||||
<string name="about_libraries">Βιβλιοθήκες</string>
|
||||
|
@ -71,12 +73,14 @@
|
|||
<string name="compose_title_forward_as_attachment">Προώθηση ως συνημμένο</string>
|
||||
<string name="choose_account_title">Επιλογή Λογαριασμού</string>
|
||||
<string name="choose_folder_title">Επιλογή φακέλου</string>
|
||||
<string name="choose_folder_move_title">Μετακίνηση σε…</string>
|
||||
<string name="choose_folder_copy_title">Αντιγραφή σε…</string>
|
||||
<string name="actionbar_selected"><xliff:g id="selection_count">%d</xliff:g> επιλέχθηκαν</string>
|
||||
<string name="next_action">Επόμενο</string>
|
||||
<string name="previous_action">Προηγούμενο</string>
|
||||
<!--Used to confirm acceptance of dialog boxes, warnings, errors, etc.-->
|
||||
<string name="okay_action">OK</string>
|
||||
<string name="cancel_action">Άκυρο</string>
|
||||
<string name="cancel_action">Ακύρωση</string>
|
||||
<string name="send_action">Αποστολή</string>
|
||||
<string name="empty_subject">Το θέμα είναι κενό, πατήστε επανάληψη για αποστολή</string>
|
||||
<string name="reply_action">Απάντηση</string>
|
||||
|
@ -103,17 +107,19 @@
|
|||
<string name="search_action">Αναζήτηση</string>
|
||||
<string name="search_everywhere_action">Αναζήτηση παντού</string>
|
||||
<string name="search_results">Αποτελέσματα αναζήτησης</string>
|
||||
<string name="new_messages_title">Νέα μηνύματα</string>
|
||||
<string name="preferences_action">Ρυθμίσεις</string>
|
||||
<string name="folders_action">Διαχείριση φακέλων</string>
|
||||
<string name="account_settings_action">Ρυθμίσεις λογαριασμού</string>
|
||||
<string name="remove_account_action">Διαγραφή λογαριασμού</string>
|
||||
<string name="mark_as_read_action">Σήμανση ως αναγνωσμένου</string>
|
||||
<string name="send_alternate_action">Διανομή</string>
|
||||
<string name="send_alternate_action">Κοινοποίηση</string>
|
||||
<string name="send_alternate_chooser_title">Επιλογή αποστολέα</string>
|
||||
<string name="flag_action">Προσθήκη αστεριού</string>
|
||||
<string name="unflag_action">Αφαίρεση αστεριού</string>
|
||||
<string name="copy_action">Αντιγραφή</string>
|
||||
<string name="show_headers_action">Προβολή επικεφαλίδων</string>
|
||||
<string name="unsubscribe_action">Κατάργηση συνδρομής</string>
|
||||
<string name="show_headers_action">Προβολή κεφαλίδων</string>
|
||||
<plurals name="copy_address_to_clipboard">
|
||||
<item quantity="one">Η διεύθυνση αντιγράφηκε στο πρόχειρο</item>
|
||||
<item quantity="other">Οι διευθύνσεις αντιγράφηκαν στο πρόχειρο </item>
|
||||
|
@ -126,19 +132,19 @@
|
|||
<string name="read_receipt_enabled">Θα ζητηθεί απόδειξη ανάγνωσης</string>
|
||||
<string name="read_receipt_disabled">Δε θα ζητηθεί αποδεικτικό ανάγνωσης</string>
|
||||
<string name="add_attachment_action">Προσθήκη συνημμένου</string>
|
||||
<string name="empty_trash_action">Άδειασμα σκουπιδιών</string>
|
||||
<string name="empty_trash_action">Άδειασμα απορριμμάτων</string>
|
||||
<string name="expunge_action">Εξάλειψη</string>
|
||||
<string name="about_action">Περί</string>
|
||||
<string name="about_action">Πληροφορίες</string>
|
||||
<string name="prefs_title">Ρυθμίσεις</string>
|
||||
<!--Shown in place of the subject when a message has no subject. Showing this in parentheses is customary.-->
|
||||
<string name="general_no_subject">(Χωρίς θέμα)</string>
|
||||
<string name="general_no_sender">Χωρίς αποστολέα</string>
|
||||
<string name="status_loading_more">Φόρτωση μηνυμάτων\u2026</string>
|
||||
<string name="status_network_error">Σφάλμα σύνδεσης</string>
|
||||
<string name="status_invalid_id_error">Δε βρέθηκε το μήνυμα</string>
|
||||
<string name="status_loading_error">Σφάλμα φόρτωση μηνύματος</string>
|
||||
<string name="load_more_messages_fmt">Φόρτωση
|
||||
έως <xliff:g id="messages_to_load">%d</xliff:g> περισσότερων</string>
|
||||
<string name="status_invalid_id_error">Δεν βρέθηκε το μήνυμα</string>
|
||||
<string name="status_loading_error">Σφάλμα φόρτωσης μηνύματος</string>
|
||||
<string name="load_more_messages_fmt">Φόρτωση έως
|
||||
<xliff:g id="messages_to_load">%d</xliff:g> περισσότερων</string>
|
||||
<string name="size_format_gigabytes">%.1f GB</string>
|
||||
<string name="size_format_megabytes">%.1f MB</string>
|
||||
<string name="size_format_kilobytes">%.1f kB</string>
|
||||
|
@ -151,19 +157,22 @@
|
|||
<string name="notification_new_one_account_fmt"><xliff:g id="unread_message_count">%1$d</xliff:g> μη αναγνωσμένα (<xliff:g id="account">%2$s</xliff:g>)</string>
|
||||
<string name="notification_additional_messages">+ <xliff:g id="additional_messages">%1$d</xliff:g> περισσότερα για <xliff:g id="account">%2$s</xliff:g></string>
|
||||
<string name="notification_action_reply">Απάντηση</string>
|
||||
<string name="notification_action_mark_as_read">Ανάγνωση</string>
|
||||
<string name="notification_action_mark_all_as_read">Σήμανση όλων των αναγνωσμένων</string>
|
||||
<string name="notification_action_mark_as_read">Σήμανση ως αναγνωσμένο</string>
|
||||
<string name="notification_action_mark_all_as_read">Σήμανση όλων ως αναγνωσμένων</string>
|
||||
<string name="notification_action_delete">Διαγραφή</string>
|
||||
<string name="notification_action_delete_all">Διαγραφή όλων</string>
|
||||
<string name="notification_action_archive">Αρχειοθήκη</string>
|
||||
<string name="notification_action_archive">Αρχειοθέτηση</string>
|
||||
<string name="notification_action_archive_all">Αρχειοθέτηση όλων</string>
|
||||
<string name="notification_action_spam">Ανεπιθύμητα</string>
|
||||
<string name="notification_certificate_error_public">Σφάλμα πιστοποιητικού</string>
|
||||
<string name="notification_certificate_error_title">Σφάλμα πιστοποιητικού για <xliff:g id="account">%s</xliff:g></string>
|
||||
<string name="notification_certificate_error_text">Ελέγξτε τις ρυθμίσεις του εξυπηρετητή</string>
|
||||
<string name="notification_certificate_error_text">Ελέγξτε τις ρυθμίσεις του διακομιστή σας</string>
|
||||
<string name="notification_authentication_error_title">Αποτυχία πιστοποίησης</string>
|
||||
<string name="notification_authentication_error_text">Αποτυχία πιστοποίησης <xliff:g id="account">%s</xliff:g>. Ενημερώστε τις ρυθμίσεις του εξυπηρετητή σας.</string>
|
||||
<!--Title of an error notification that is displayed when creating a notification for a new message has failed-->
|
||||
<string name="notification_notify_error_title">Σφάλμα ειδοποίησης</string>
|
||||
<!--Body of an error notification that is displayed when creating a notification for a new message has failed-->
|
||||
<string name="notification_notify_error_text">Σφάλμα στην προσπάθεια δημιουργίας ειδοποίησης συστήματος για νέο μήνυμα. Η ατία είναι μάλλον λείπει ο ήχος της ειδοπίησης.\n\nΠατήστε για να ανοίξετε τις ρυθμίσεων των ειδοποιήσεων.</string>
|
||||
<string name="notification_bg_sync_ticker">Έλεγχος μηνύματος: <xliff:g id="account">%1$s</xliff:g>:<xliff:g id="folder">%2$s</xliff:g></string>
|
||||
<string name="notification_bg_sync_title">Έλεγχος μηνύματος</string>
|
||||
<string name="notification_bg_send_ticker">Αποστολή μηνύματος: <xliff:g id="account">%s</xliff:g></string>
|
||||
|
@ -186,6 +195,9 @@
|
|||
<string name="debug_enable_debug_logging_summary">Καταγραφή πρόσθετων διαγνωστικών πληροφοριών</string>
|
||||
<string name="debug_enable_sensitive_logging_title">Καταγραφή ευαίσθητων πληροφοριών</string>
|
||||
<string name="debug_enable_sensitive_logging_summary">Συνθηματικά μπορεί να εμφανιστούν στις καταγραφές.</string>
|
||||
<string name="debug_export_logs_title">Καταγραφές εξαγωγών</string>
|
||||
<string name="debug_export_logs_success">Επιτυχής εξαγωγή. Οι καταγραφές ίσως περιέχουν ευαίσθητες πληροφορίες. Προσέχετε σε ποιον/ποια τις στέλνετε.</string>
|
||||
<string name="debug_export_logs_failure">Αποτυχία εξαγωγής</string>
|
||||
<string name="message_list_load_more_messages_action">Φόρτωση περισσότερων μηνυμάτων</string>
|
||||
<string name="message_to_fmt">Προς:<xliff:g id="counterParty">%s</xliff:g></string>
|
||||
<string name="message_compose_subject_hint">Θέμα</string>
|
||||
|
@ -197,11 +209,11 @@
|
|||
<string name="message_compose_quote_header_from">Από:</string>
|
||||
<string name="message_compose_quote_header_to">Προς:</string>
|
||||
<string name="message_compose_quote_header_cc">Κοιν:</string>
|
||||
<string name="message_compose_reply_header_fmt"><xliff:g id="sender">%s</xliff:g> έγραψε:</string>
|
||||
<string name="message_compose_reply_header_fmt">Ο/Η <xliff:g id="sender">%s</xliff:g> έγραψε:</string>
|
||||
<string name="message_compose_reply_header_fmt_with_date">Στις <xliff:g id="sent_date">%1$s</xliff:g>, ο/η <xliff:g id="sender">%2$s</xliff:g> έγραψε:</string>
|
||||
<string name="message_compose_error_no_recipients">Πρέπει να συμπεριλάβετε τουλάχιστον έναν παραλήπτη.</string>
|
||||
<string name="message_compose_error_no_recipients">Πρέπει να προσθέσετε τουλάχιστον έναν παραλήπτη.</string>
|
||||
<string name="compose_error_incomplete_recipient">Το πεδίο παραλήπτη περιέχει ελλιπή στοιχεία!</string>
|
||||
<string name="error_contact_address_not_found">Δε βρέθηκαν διευθύνσεις ηλεκτρονικού ταχυδρομείου.</string>
|
||||
<string name="error_contact_address_not_found">Δεν βρέθηκαν διευθύνσεις ηλεκτρονικού ταχυδρομείου.</string>
|
||||
<string name="message_compose_attachments_skipped_toast">Μερικά συνημμένα δεν μπορούν να προωθηθούν γιατί δεν έχουν ληφθεί.</string>
|
||||
<string name="message_compose_attachments_forward_toast">Το μήνυμα δεν μπορεί να προωθηθεί επειδή μερικά συνημμένα δεν έχουν ληφθεί.</string>
|
||||
<string name="message_compose_show_quoted_text_action">Συμπερίληψη του παραθετιμένου μηνύματος</string>
|
||||
|
@ -211,19 +223,19 @@
|
|||
<string name="message_view_from_format">Από: <xliff:g id="name">%1$s</xliff:g> <<xliff:g id="email">%2$s</xliff:g>></string>
|
||||
<string name="message_to_label">Προς:</string>
|
||||
<string name="message_view_cc_label">Κοιν:</string>
|
||||
<string name="message_view_bcc_label">Κρυφή Κοιν:</string>
|
||||
<string name="message_view_bcc_label">Κρυφή κοιν:</string>
|
||||
<string name="message_view_status_attachment_not_saved">Αδυναμία αποθήκευσης συνημμένου.</string>
|
||||
<string name="message_view_show_pictures_action">Προβολή εικόνων</string>
|
||||
<string name="message_view_show_pictures_action">Εμφάνιση εικόνων</string>
|
||||
<string name="message_view_no_viewer">Δεν υπάρχει πρόγραμμα προβολής για <xliff:g id="mimetype">%s</xliff:g>.</string>
|
||||
<string name="message_view_download_remainder">Λήψη πλήρους μηνύματος</string>
|
||||
<string name="message_view_sender_label">μέσω %1$s</string>
|
||||
<string name="from_same_sender">Από τον ίδιο αποστολέα</string>
|
||||
<string name="search_from_format">Από <xliff:g id="sender">%s</xliff:g></string>
|
||||
<string name="message_discarded_toast">Το μήνυμα αγνοήθηκε.</string>
|
||||
<string name="message_saved_toast">Το μήνυμα αποθηκεύτηκε στα πρόχειρα.</string>
|
||||
<string name="global_settings_flag_label">Προβολή αστεριών</string>
|
||||
<string name="message_discarded_toast">Το μήνυμα απορρίφθηκε</string>
|
||||
<string name="message_saved_toast">Το μήνυμα αποθηκεύτηκε ως πρόχειρο</string>
|
||||
<string name="global_settings_flag_label">Εμφάνιση αστεριών</string>
|
||||
<string name="global_settings_flag_summary">Τα αστέρια υποδηλώνουν σημαντικά μηνύματα</string>
|
||||
<string name="global_settings_preview_lines_label">Προεπισκόπηση μηνυμάτων</string>
|
||||
<string name="global_settings_preview_lines_label">Γραμμές προεπισκόπησης</string>
|
||||
<string name="global_settings_show_correspondent_names_label">Εμφάνιση ονομάτων επιστολογράφων</string>
|
||||
<string name="global_settings_show_correspondent_names_summary">Εμφάνιση των ονομάτων των επιστολογράφων αντί των διευθύνσεων ηλεκτρονικού ταχυδρομείου</string>
|
||||
<string name="global_settings_sender_above_subject_label">Αποστολέας πάνω από το θέμα</string>
|
||||
|
@ -232,14 +244,15 @@
|
|||
<string name="global_settings_show_contact_name_summary">Χρήση ονομάτων επιστολογράφων από Επαφές όταν είναι διαθέσιμο</string>
|
||||
<string name="global_settings_registered_name_color_label">Χρωματισμός Επαφών</string>
|
||||
<string name="global_settings_registered_name_color_changed">Να χρωματίζονται τα ονόματα στη λίστα επαφών</string>
|
||||
<string name="general_settings_contact_name_color_label">Χρώμα ονόματος επαφής</string>
|
||||
<string name="global_settings_messageview_fixedwidth_label">Γραμματοσειρά σταθερού πλάτους</string>
|
||||
<string name="global_settings_messageview_fixedwidth_summary">Να χρησιμοποιείται γραμματοσειρά σταθερού πλάτους όταν προβάλλονται μηνύματα απλού κειμένου</string>
|
||||
<string name="global_settings_messageview_autofit_width_label">Αυτόματη προσαρμογή</string>
|
||||
<string name="global_settings_messageview_autofit_width_summary">Ρύθμιση μεγέθους μηνύματος για να χωρά στην οθόνη</string>
|
||||
<string name="global_settings_messageview_return_to_list_label">Επιστροφή στη λίστα</string>
|
||||
<string name="global_settings_messageview_return_to_list_summary">Επιστροφή στη λίστα μηνυμάτων μετά τη διαγραφή ενός μηνύματος</string>
|
||||
<string name="global_settings_messageview_show_next_label">Προβολή επόμενου</string>
|
||||
<string name="global_settings_messageview_show_next_summary">Προβολή επόμενου μηνύματος μετά τη διαγραφή ενός μηνύματος</string>
|
||||
<string name="global_settings_messageview_show_next_label">Εμφάνιση επόμενου μηνύματος μετά τη διαγραφή</string>
|
||||
<string name="global_settings_messageview_show_next_summary">Εμφάνιση επόμενου μηνύματος μετά τη διαγραφή ενός μηνύματος</string>
|
||||
<string name="global_settings_confirm_actions_title">Επιβεβαίωση ενεργειών</string>
|
||||
<string name="global_settings_confirm_actions_summary">Προβολή διαλόγου όποτε εκτελούνται επιλεγμένες ενέργειες</string>
|
||||
<string name="global_settings_confirm_action_delete">Διαγραφή</string>
|
||||
|
@ -255,13 +268,14 @@
|
|||
<string name="global_settings_notification_quick_delete_title">Εμφάνιση κουμπιού «Διαγραφή»</string>
|
||||
<string name="global_settings_notification_quick_delete_never">Ποτέ</string>
|
||||
<string name="global_settings_notification_quick_delete_when_single_msg">Για ειδοποίηση ενός μηνύματος</string>
|
||||
<string name="global_settings_notification_quick_delete_always">Πάντοτε</string>
|
||||
<string name="global_settings_notification_quick_delete_always">Πάντα</string>
|
||||
<string name="global_settings_lock_screen_notification_visibility_title">Ειδοποιήσεις οθόνης κλειδώματος</string>
|
||||
<string name="global_settings_lock_screen_notification_visibility_nothing">Χωρίς ειδοποιήσεις οθόνης κλειδώματος</string>
|
||||
<string name="global_settings_lock_screen_notification_visibility_app_name">Όνομα εφαρμογής</string>
|
||||
<string name="global_settings_lock_screen_notification_visibility_message_count">Αριθμός νέων μηνυμάτων</string>
|
||||
<string name="global_settings_lock_screen_notification_visibility_senders">Αριθμός μηνυμάτων και αποστολείς</string>
|
||||
<string name="global_settings_lock_screen_notification_visibility_everything">Ομοίως με τότε που η οθόνη είναι ξεκλείδωτη</string>
|
||||
<string name="quiet_time">Ώρες Ησυχίας</string>
|
||||
<string name="quiet_time">Ώρες ησυχίας</string>
|
||||
<string name="quiet_time_description">Απενεργοποιηση κουδουνίσματος, βουητού και αναβοσβησίματος τη νύχτα</string>
|
||||
<string name="quiet_time_notification">Απενεργοποίηση ειδοποιήσεων</string>
|
||||
<string name="quiet_time_notification_description">Πλήρης απενεργοποίηση ειδοποιήσεων για όσο διαρκούν οι Ώρες Ησυχίας</string>
|
||||
|
@ -270,8 +284,11 @@
|
|||
<string name="account_setup_basics_title">Ρύθμιση νέου λογαριασμού</string>
|
||||
<string name="account_setup_basics_email_hint">Διεύθυνση ηλ. ταχυδρομείου</string>
|
||||
<string name="account_setup_basics_password_hint">Συνθηματικό</string>
|
||||
<string name="account_setup_oauth_description">Αν θέλετε να χρησιμοποιήσετε αυτόν τον λογαριασμό ηλεκτρονικού ταχυδρομείου με το K-9 Mail πρέπει να συνδεθείτε και να παραχωρήσετε στην εφαρμογή πρόσβαση στα ηλεκτρονικά μηνύματά σας.</string>
|
||||
<!--Displayed below the 'account_setup_oauth_description' text-->
|
||||
<string name="account_setup_oauth_sign_in">Σύνδεση</string>
|
||||
<!--Displayed below the 'account_setup_oauth_description' text-->
|
||||
<string name="account_setup_oauth_sign_in_with_google">Σύνδεση μέσω Google</string>
|
||||
<!--Please use the same translation for "screen lock" as is used in the 'Security' section in Android's settings app-->
|
||||
<string name="account_setup_basics_show_password_need_lock">Για να δείτε τον κωδικό σας εδώ, ενεργοποιήστε το κλείδωμα οθόνης σε αυτή την συσκευή.</string>
|
||||
<string name="account_setup_basics_show_password_biometrics_title">Επαλήθευση ταυτότητας</string>
|
||||
|
@ -295,6 +312,7 @@
|
|||
<string name="account_setup_auth_type_insecure_password">Συνθηματικό, μεταβιβασμένο χωρίς ασφάλεια</string>
|
||||
<string name="account_setup_auth_type_encrypted_password">Κρυπτογραφημένο συνθηματικό</string>
|
||||
<string name="account_setup_auth_type_tls_client_certificate">Πιστοποιητικό πελάτη</string>
|
||||
<string name="account_setup_auth_type_oauth2">OAuth 2.0</string>
|
||||
<string name="account_setup_incoming_title">Ρυθμίσεις εισερχόμενης αλληλογραφίας</string>
|
||||
<string name="account_setup_incoming_username_label">Όνομα χρήστη</string>
|
||||
<string name="account_setup_incoming_password_label">Συνθηματικό</string>
|
||||
|
@ -313,6 +331,7 @@
|
|||
<string name="account_setup_incoming_delete_policy_never_label">Να μη διαγράφεται στον εξυπηρετητή</string>
|
||||
<string name="account_setup_incoming_delete_policy_delete_label">Να διαγράφεται άμεσα από τον εξυπηρετητή</string>
|
||||
<string name="account_setup_incoming_delete_policy_markread_label">Επισήμανση ως αναγνωσμένο στον εξυπηρετητή</string>
|
||||
<string name="account_setup_incoming_use_compression">Χρήση συμπίεσης</string>
|
||||
<string name="account_setup_expunge_policy_label">Εξάλειψη διαγραμμένων μηνυμάτων</string>
|
||||
<string name="account_setup_expunge_policy_immediately">Αμέσως</string>
|
||||
<string name="account_setup_expunge_policy_on_poll">Κατά την ενημέρωση</string>
|
||||
|
@ -377,6 +396,10 @@
|
|||
<string name="account_setup_failed_dlg_auth_message_fmt">Το όνομα χρήστη ή ο κωδικός πρόσβασης δεν είναι σωστά.\n(<xliff:g id="error">%s</xliff:g>)</string>
|
||||
<string name="account_setup_failed_dlg_certificate_message_fmt">Ο εξυπηρετητής παρουσίασε ένα μη εγκυρο πιστοποιητικό SSL. Κάποιες φορές αυτό συμβαίνει λόγω κακής ρύθμισής του. Άλλες φορές γιατί κάποιος προσπαθεί να επιτεθεί σε εσάς ή τον εξυπηρετητή ταχυδρομείου σας. Αν δεν είστε βέβαιοι τι συμβαίνει, επιλέξτε Απόρριψη και επικοινωνήστε με τους διαχειριστές του εξυπηρετητή ταχυδρομείου σας.\n\n(<xliff:g id="error">%s</xliff:g>)</string>
|
||||
<string name="account_setup_failed_dlg_server_message_fmt">Αδύνατη η σύνδεση στον εξυπηρετητή.\n(<xliff:g id="error">%s</xliff:g>)</string>
|
||||
<string name="account_setup_failed_dlg_oauth_flow_canceled">Η εξακρίβωση ακυρώθηκε</string>
|
||||
<string name="account_setup_failed_dlg_oauth_flow_failed">Η εξακρίβωση απέτυχε με το εξής σφάλμα: <xliff:g id="error">%s</xliff:g></string>
|
||||
<string name="account_setup_failed_dlg_oauth_not_supported">Το πρωτόκολο OAuth 2.0 αυτή τη στιγμή δεν υποστηρίζεται από τον συγκεκριμένο πάροχο.</string>
|
||||
<string name="account_setup_failed_dlg_browser_not_found">Η εφαρμογή δεν βρήκε περιηγητή ιστού για να παράσχει πρόσβαση στον λογαριασμό σας.</string>
|
||||
<string name="account_setup_failed_dlg_edit_details_action">Διόρθωση λεπτομερειών</string>
|
||||
<string name="account_setup_failed_dlg_continue_action">Συνέχεια</string>
|
||||
<string name="account_settings_push_advanced_title">Προχωρημένα</string>
|
||||
|
@ -531,11 +554,29 @@
|
|||
<string name="account_settings_description_label">Όνομα λογαριασμού</string>
|
||||
<string name="account_settings_name_label">Το όνομά σου</string>
|
||||
<string name="notifications_title">Ειδοποιήσεις</string>
|
||||
<string name="account_settings_vibration">Δόνηση</string>
|
||||
<string name="account_settings_vibrate_enable">Δόνηση</string>
|
||||
<string name="account_settings_vibrate_pattern_label">Μοτίβο δόνησης</string>
|
||||
<string name="account_settings_vibrate_pattern_default">Εξ ορισμού</string>
|
||||
<string name="account_settings_vibrate_pattern_1">Μοτίβο 1</string>
|
||||
<string name="account_settings_vibrate_pattern_2">Μοτίβο 2</string>
|
||||
<string name="account_settings_vibrate_pattern_3">Μοτίβο 3</string>
|
||||
<string name="account_settings_vibrate_pattern_4">Μοτίβο 4</string>
|
||||
<string name="account_settings_vibrate_pattern_5">Μοτίβο 5</string>
|
||||
<string name="account_settings_vibrate_times">Επανάληψη δόνησης</string>
|
||||
<string name="account_settings_vibrate_summary_disabled">Απενεργοποιήθηκε</string>
|
||||
<string name="account_settings_ringtone">Κουδούνισμα με νέο μήνυμα</string>
|
||||
<string name="account_settings_notification_light_label">Φωτεινή ειδοποίηση</string>
|
||||
<string name="account_settings_notification_light_disabled">Απενεργοποιήθηκε</string>
|
||||
<string name="account_settings_notification_light_account_color">Χρώμα λογαριασμού</string>
|
||||
<string name="account_settings_notification_light_default_color">Προεπιλεγμένο χρώμα συστήματος</string>
|
||||
<string name="account_settings_notification_light_white">Λευκό</string>
|
||||
<string name="account_settings_notification_light_red">Κόκκινο</string>
|
||||
<string name="account_settings_notification_light_green">Πράσινο</string>
|
||||
<string name="account_settings_notification_light_blue">Μπλε</string>
|
||||
<string name="account_settings_notification_light_yellow">Κίτρινο</string>
|
||||
<string name="account_settings_notification_light_cyan">Μωβ</string>
|
||||
<string name="account_settings_notification_light_magenta">Ματζέντα</string>
|
||||
<string name="account_settings_composition_title">Επιλογές σύνθεσης μηνύματος</string>
|
||||
<string name="account_settings_composition_label">Εξ ορισμού σύνθεση</string>
|
||||
<string name="account_settings_composition_summary">Ορισμός εξ ορισμού Αποστολέα, Ιδιωτικής κοινοποίησης και υπογραφής</string>
|
||||
|
@ -593,8 +634,6 @@
|
|||
<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>
|
||||
<string name="message_view_help_key">Del (or D) - Διαγραφή\nR - Απάντηση\nA - Απάντηση Όλων\nC - Σύνθεση\nF - Προώθηση\nM - Μετακίνηση\nV - Αρχειοθέτηση\nY - Αντιγραφή\nZ - Σημείωση ως (μη) αναγνωσμένο\nG - Αστέρι\nO - Ταξινόμηση κατά τύπο\nI - Ταξινόμηση κατά σειρά\nQ - Επιστροφή στους Φακέλους\nS - Επιλογή/αποεπιλογή\nJ or P - Προηγούμενο Μήνυμα\nK or N - Επόμενο Μήνυμα</string>
|
||||
<string name="message_list_help_key">Del (or D) - Διαγραφή\nC - Σύνθεση\nM - Μετακίνηση\nV - Αρχειοθέτηση\nY - Αντιγραφή\nZ - Σημείωση ως (μη) αναγνωσμένο\nG - Αστέρι\nO - Ταξινόμηση κατά τύπο\nI - Ταξινόμηση κατά σειρά\nQ - Επιστροφή στους Φακέλους\nS - Επιλογή/αποεπιλογή</string>
|
||||
<string name="folder_list_filter_hint">Το όνομα του φακέλου περιέχει</string>
|
||||
<string name="folder_list_display_mode_label">Φάκελοι</string>
|
||||
<string name="folder_list_display_mode_all">Προβολή όλων</string>
|
||||
|
@ -642,9 +681,7 @@
|
|||
<string name="account_setup_push_limit_1000">1000 φάκελοι</string>
|
||||
<string name="animations_title">Κινούμενα σχέδια</string>
|
||||
<string name="animations_summary">Χρήση οπτικών εφέ gaudy</string>
|
||||
<string name="volume_navigation_title">Πλοήγηση με πλήκτρο έντασης</string>
|
||||
<string name="volume_navigation_message">Προβολή μηνύματος</string>
|
||||
<string name="volume_navigation_list">Διάφορες προβολές λίστας</string>
|
||||
<string name="volume_navigation_title">Πλοήγηση με τα πλήκτρα ήχου όταν προβάλεται μήνυμα</string>
|
||||
<string name="show_unified_inbox_title">Εμφάνιση Ενιαία Εισερχόμενα</string>
|
||||
<string name="show_starred_count_title">Εμφάνιση πλήθους επιλεγμένων</string>
|
||||
<string name="integrated_inbox_title">Ενιαία Εισερχόμενα</string>
|
||||
|
@ -738,13 +775,16 @@
|
|||
<!--Displayed after importing accounts when one or multiple accounts require entering a password-->
|
||||
<string name="settings_import_password_required">Παρακαλώ εισάγετε συνθηματικά</string>
|
||||
<!--Displayed after importing accounts when one or multiple accounts require to use the OAuth authorization flow-->
|
||||
<string name="settings_import_authorization_required">Παρακαλώ συνδεθείτε</string>
|
||||
<!--Displayed after importing accounts when some accounts require entering a password and some to use the OAuth authorization flow-->
|
||||
<string name="settings_import_authorization_and_password_required">Παρακαλώ συνδεθείτε και εισάγετε κωδικό</string>
|
||||
<string name="settings_import_failure">Αποτυχία εισαγωγής ρυθμίσεων</string>
|
||||
<string name="settings_import_read_failure">Αποτυχία ανάγνωσης αρχείου ρυθμίσεων</string>
|
||||
<string name="settings_import_partial_failure">Αποτυχία εισαγωγής ορισμένων ρυθμίσεων</string>
|
||||
<string name="settings_import_status_success">Η εισαγωγή ολοκληρώθηκε με επιτυχία</string>
|
||||
<string name="settings_import_status_password_required">Απαιτείται κωδικός πρόσβασης</string>
|
||||
<!--Content description for the icon that is displayed next to an imported account that requires sign-in-->
|
||||
<string name="settings_import_status_log_in_required">Απαιτείται σύνδεση</string>
|
||||
<string name="settings_import_status_not_imported">Δεν έχει εισαχθεί</string>
|
||||
<string name="settings_import_status_error">Αποτυχία εισαγωγής</string>
|
||||
<string name="settings_import_later_button">Αργότερα</string>
|
||||
|
@ -851,6 +891,7 @@
|
|||
<string name="recipient_bcc">Κρυφή Κοιν:</string>
|
||||
<string name="recipient_to">Προς</string>
|
||||
<string name="recipient_from">Από:</string>
|
||||
<string name="reply_to_label">Απάντηση σε</string>
|
||||
<string name="unknown_recipient"><Άγνωστος Παραλήπτης></string>
|
||||
<string name="unknown_sender"><Άγνωστος Αποστολέας></string>
|
||||
<string name="address_type_home">Οικία</string>
|
||||
|
|
|
@ -593,8 +593,6 @@ Bonvolu raporti erarojn, kontribui novajn eblojn kaj peti pri novaj funkcioj per
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Nekonata atestilo</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Akcepti ŝlosilon</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Rifuzi ŝlosilon</string>
|
||||
<string name="message_view_help_key">Del (aŭ D) - forigi\nR - respondi\nA - respondi al ĉiuj\nC - krei\nF - plusendi\nM - movi\nV - arĥivigi\nY - kopii\nZ - marki kiel (ne)legitan\nG - steletigi\nO - ordiga tipo\nI - ordigo\nQ - reveni al mesaĝujoj\nS - (mal)elekti\nJ aŭ P -antaŭa mesaĝo\nK aŭ N - sekva mesaĝo</string>
|
||||
<string name="message_list_help_key">Del (aŭ D) - forigi\nC - krei\nM - movi\nV - arĥivigi\nY - kopii\nZ - marki kiel (ne)legitan\nG - steletigi\nO - ordiga tipo\nI - ordigo\nQ - reveni al mesaĝujoj\nS - (mal)elekti</string>
|
||||
<string name="folder_list_filter_hint">Nomo de mesaĝujo enhavas</string>
|
||||
<string name="folder_list_display_mode_label">Montri mesaĝujojn…</string>
|
||||
<string name="folder_list_display_mode_all">Ĉiuj mesaĝujoj</string>
|
||||
|
@ -642,9 +640,6 @@ Bonvolu raporti erarojn, kontribui novajn eblojn kaj peti pri novaj funkcioj per
|
|||
<string name="account_setup_push_limit_1000">Maksimume 1000 mesaĝujoj</string>
|
||||
<string name="animations_title">Movbildoj</string>
|
||||
<string name="animations_summary">Uzas afablajn vidajn efektojn</string>
|
||||
<string name="volume_navigation_title">Navigado per sonfortecaj butonoj</string>
|
||||
<string name="volume_navigation_message">En vido de mesaĝoj</string>
|
||||
<string name="volume_navigation_list">En vidoj de listoj</string>
|
||||
<string name="show_unified_inbox_title">Montri unuigitan ricevujon</string>
|
||||
<string name="show_starred_count_title">Montri nombron da steletoj</string>
|
||||
<string name="integrated_inbox_title">Unuigita ricevujo</string>
|
||||
|
|
|
@ -633,8 +633,6 @@ Puedes informar de fallos, contribuir con su desarrollo y hacer preguntas en <a
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Certificado desconocido</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Aceptar clave</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Rechazar clave</string>
|
||||
<string name="message_view_help_key">Supr (o D) - Borrar\nR - Responder\nA - Responder a todos\nC - Redactar\nF - Reenviar\nM - Mover\nV - Archivar\nY - Copiar\nZ - Marcar como (no) leído\nG - Destacar\nO - Tipo de ordenación\nI - Invertir orden\nQ - Volver a las carpetas\nS - Des/marcar\nJ o P - Mensaje anterior\nK o N - Siguiente mensaje</string>
|
||||
<string name="message_list_help_key">Supr (o D) - Borrar\nC - Redactar\nM - Mover\nV - Archivar\nY - Copiar\nZ - Marcar como (no) leído\nG - Destacar\nO - Tipo de ordenación\nI - Invertir orden\nQ - Volver a las carpetas\nS - Des/marcar</string>
|
||||
<string name="folder_list_filter_hint">El nombre de la carpeta contiene</string>
|
||||
<string name="folder_list_display_mode_label">Mostrar carpetas…</string>
|
||||
<string name="folder_list_display_mode_all">Ver todas las carpetas</string>
|
||||
|
@ -682,9 +680,7 @@ Puedes informar de fallos, contribuir con su desarrollo y hacer preguntas en <a
|
|||
<string name="account_setup_push_limit_1000">1000 carpetas</string>
|
||||
<string name="animations_title">Animaciones</string>
|
||||
<string name="animations_summary">Utilizar animaciones</string>
|
||||
<string name="volume_navigation_title">Navegación con teclas de volumen</string>
|
||||
<string name="volume_navigation_message">Vista de mensaje</string>
|
||||
<string name="volume_navigation_list">Listas de mensajes</string>
|
||||
<string name="volume_navigation_title">Navegar con las teclas de volumen al leer el correo</string>
|
||||
<string name="show_unified_inbox_title">Mostrar bandeja de entrada unificada</string>
|
||||
<string name="show_starred_count_title">Mostrar número de mensajes destacados</string>
|
||||
<string name="integrated_inbox_title">Entrada unificada</string>
|
||||
|
|
|
@ -636,8 +636,6 @@ Veateated saad saata, kaastööd teha ning küsida teavet järgmisel lehel:
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Tunnustamata sertifikaat</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Aktsepteeri võti</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Keeldu võtmest</string>
|
||||
<string name="message_view_help_key">Del (või D) - Kustuta\nR - Vasta\nA - Vasta kõigile\nC - Koosta\nF - Saada edasi\nM - Teisalda\nV - Arhiveeri\nY - Kopeeri\nZ - Märgi (mitte)loetuks\nG - Tärn\nO - Sortimise tüüp\nI - Sorteerimise järjekord\nQ - Tagasi kaustadesse\nS - Vali/Tühista valik\nJ or P - Eelmine kiri\nK or N - Järgmine kiri</string>
|
||||
<string name="message_list_help_key">Del (või D) - Kustuta\nC - Koosta kiri\nM - Teisalda\nV - Arhiveri\nY - Kopeeri\nZ - Märgi (mitte)loetuks\nG - Märgi tärniga\nO - Sortimise tüüp\nI - Sortimise järjekord\nQ - Tagasi kasutade loendisse\nS - Vali/eemalda valik</string>
|
||||
<string name="folder_list_filter_hint">Kausta nimi sisaldab</string>
|
||||
<string name="folder_list_display_mode_label">Näita kaustu…</string>
|
||||
<string name="folder_list_display_mode_all">Kõik kaustad</string>
|
||||
|
@ -685,9 +683,6 @@ Veateated saad saata, kaastööd teha ning küsida teavet järgmisel lehel:
|
|||
<string name="account_setup_push_limit_1000">1000 kausta</string>
|
||||
<string name="animations_title">Animatsioon</string>
|
||||
<string name="animations_summary">Kasuta erinevaid visuaalseid efekte</string>
|
||||
<string name="volume_navigation_title">Helitugevuse nupuga liikumine</string>
|
||||
<string name="volume_navigation_message">Kirjade vaadetes</string>
|
||||
<string name="volume_navigation_list">Nimekirja vaadetes</string>
|
||||
<string name="show_unified_inbox_title">Näita koondsisendkausta</string>
|
||||
<string name="show_starred_count_title">Näita tärniga tähistatud kirjade arvu</string>
|
||||
<string name="integrated_inbox_title">Koondsisendkaust</string>
|
||||
|
|
|
@ -632,8 +632,6 @@ Mesedez akatsen berri emateko, ezaugarri berriak gehitzeko eta galderak egiteko
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Ziurtagiri ezezaguna</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Onartu gakoa</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Baztertu gakoa</string>
|
||||
<string name="message_view_help_key">Del (edo D) - Ezabatu\nR - Erantzun\nA - Erantzun denei\nC - Idatzi\nF - Birbidali\nM - Mugitu\nV - Artxibatu\nY - Kopiatu\nZ - Markatu irakurri (gabe) gisa\nG - Izarra\nO - Ordenatze mota\nI - Ordenatzeko irizpidea\nQ - Itzuli Karpetetara\nS - Hautatu/desautatu\nJ or P - Aurreko Mezua\nK or N - Hurrengo Mezua</string>
|
||||
<string name="message_list_help_key">Del (edo D) - Ezabatu\nC - Idatzi\nM - Mugitu\nV - Artxibatu\nY - Kopiatu\nZ - Markatu irakurri (gabe) gisa\nG - Izarra\nO - Ordenatze mota\nI - Ordenatzeko irizpidea\nQ - Itzuli Karpetetara\nS - Hautatu/desautatu</string>
|
||||
<string name="folder_list_filter_hint">Karpetaren izenak dauka</string>
|
||||
<string name="folder_list_display_mode_label">Erakutsi karpetak…</string>
|
||||
<string name="folder_list_display_mode_all">Karpeta guztiak</string>
|
||||
|
@ -681,9 +679,6 @@ Mesedez akatsen berri emateko, ezaugarri berriak gehitzeko eta galderak egiteko
|
|||
<string name="account_setup_push_limit_1000">1000 karpeta</string>
|
||||
<string name="animations_title">Animazioak</string>
|
||||
<string name="animations_summary">Erabili bistaratze efektu nabarmenak</string>
|
||||
<string name="volume_navigation_title">Bolumen teklekin nabigatu</string>
|
||||
<string name="volume_navigation_message">Mezu barruko ikuspegiak</string>
|
||||
<string name="volume_navigation_list">Zerrenda barruko ikuspegiak</string>
|
||||
<string name="show_unified_inbox_title">Erakutsi Sarrera Ontzi Bateratua</string>
|
||||
<string name="show_starred_count_title">Erakutsi kontu izardunak</string>
|
||||
<string name="integrated_inbox_title">Sarrerako ontzi bateratua</string>
|
||||
|
|
|
@ -633,8 +633,6 @@
|
|||
<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>
|
||||
<string name="message_view_help_key">Del (یا D) - حذف\nR - پاسخ\nA - پاسخ به همه\nC - نوشتن\nF - هدایت\nM - انتقال\nV - بایگانی\nY - کپی\nZ - نشان بزن که (نـ)خواندم\nG - ستاره\nO - نوع ترتیب\nI - ترتیب\nQ - بازگشت به پوشهها\nS - انتخاب (نـ)کردن\nJ یا P - پیام قبلی\nK یا N - پیام بعدی</string>
|
||||
<string name="message_list_help_key">Del (یا D) - حذف\nC - نوشتن\nM - انتقال\nV - بایگانی\nY - کپی\nZ - نشان بزن که (نـ)خواندم\nG - ستاره\nO - نوع ترتیب\nI - ترتیب\nQ - بازگشت به پوشهها\nS - انتخاب (نـ)کردن</string>
|
||||
<string name="folder_list_filter_hint">بخشی از نام پوشه</string>
|
||||
<string name="folder_list_display_mode_label">نمایش کدام پوشهها…</string>
|
||||
<string name="folder_list_display_mode_all">همهٔ پوشهها</string>
|
||||
|
@ -682,9 +680,6 @@
|
|||
<string name="account_setup_push_limit_1000">۱۰۰۰ پوشه</string>
|
||||
<string name="animations_title">پویانمایی</string>
|
||||
<string name="animations_summary">استفاده از جلوههای پُرزرقوبرق</string>
|
||||
<string name="volume_navigation_title">جابهجایی با کلیدهای تنظیم صدا</string>
|
||||
<string name="volume_navigation_message">در نماهای پیام</string>
|
||||
<string name="volume_navigation_list">در نماهای لیستی</string>
|
||||
<string name="show_unified_inbox_title">نمایش صندوق یکپارچه</string>
|
||||
<string name="show_starred_count_title">نمایش تعداد ستارهدارها</string>
|
||||
<string name="integrated_inbox_title">صندوق ورودی یکپارچه</string>
|
||||
|
|
|
@ -632,8 +632,6 @@ Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoittees
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Tunnistamaton varmenne</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Hyväksy-avain</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Hylkää-avain</string>
|
||||
<string name="message_view_help_key">Del (tai D) - Poista\nR - Vastaa\nA - Vastaa Kaikille\nC - Uusi viesti\nF - Välitä\nM - Siirrä\nV - Arkistoi\nY - Kopioi\nZ - Merkitse Lukemattomaksi(luetuksi)\nG - Merkitse tähdellä\nO - Lajittelun tyyppi\nI - Lajittelun järjestys\nQ - Palaa kansioihin\nS - Valitse/Poista valinta\nJ tai P - Edellinen viesti\nK or N - Seuraava viesti</string>
|
||||
<string name="message_list_help_key">Del (tai D) - Poista\nC - Uusi viesti\nM - Siirrä\nV - Arkistoi\nY - Kopioi\nZ - Merkitse (Lukemattomaksi)luetuksi\nG - Merkitse tähdellä\nO - Lajittelun tyyppi\nI - Lajittelun järjestys\nQ - Palaa kansioihin\nS - Valitse / poista valinta</string>
|
||||
<string name="folder_list_filter_hint">Kansion nimi sisältää</string>
|
||||
<string name="folder_list_display_mode_label">Kansiot</string>
|
||||
<string name="folder_list_display_mode_all">Näytä kaikki</string>
|
||||
|
@ -681,9 +679,7 @@ Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoittees
|
|||
<string name="account_setup_push_limit_1000">1000 kansiota</string>
|
||||
<string name="animations_title">Animaatio</string>
|
||||
<string name="animations_summary">Käytä koreita visuaalisia tehosteita</string>
|
||||
<string name="volume_navigation_title">Navigointi äänenvoimakkuusnäppäimillä</string>
|
||||
<string name="volume_navigation_message">Viestinäkymä</string>
|
||||
<string name="volume_navigation_list">Erilaisia listanäkymiä</string>
|
||||
<string name="volume_navigation_title">Liikkuminen äänipainikkeilla viestinäkymässä</string>
|
||||
<string name="show_unified_inbox_title">Näytä \"Yhdistetty saapuneet\"</string>
|
||||
<string name="show_starred_count_title">Näytä tähdellä merkittyjen viestien määrä</string>
|
||||
<string name="integrated_inbox_title">Yhdistetty saapuneet</string>
|
||||
|
|
|
@ -636,8 +636,6 @@ Rapportez les bogues, recommandez de nouvelles fonctions et posez vos questions
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Certificat non reconnu</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Accepter la clé</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Rejeter la clé</string>
|
||||
<string name="message_view_help_key">Suppr (ou D) - Supprimer\nR - Répondre\nA - Répondre à tous\nC - Rédiger\nF - Transférer\nM - Déplacer\nV - Archiver\nY - Copier\nZ - Marquer comme lu ou non\nG - Étoile\nO - Type de tri\nI - Ordre de tri\nQ - Retourner aux dossiers\nS - Sélectionner/dessélectionner\nJ ou P - Courriel précédent\nK ou N - Courriel suivant</string>
|
||||
<string name="message_list_help_key">Suppr (ou D) - Supprimer\nC - Rédiger\nM - Déplacer\nV - Archiver\nY - Copier\nZ - Marquer comme lu ou non\nG - Étoile\nO - Type de tri\nI - Ordre de tri\nQ - Retourner aux dossiers\nS - Sélectionner/dessélectionner</string>
|
||||
<string name="folder_list_filter_hint">Le nom de dossier comprend</string>
|
||||
<string name="folder_list_display_mode_label">Afficher les dossiers…</string>
|
||||
<string name="folder_list_display_mode_all">Tous les dossiers</string>
|
||||
|
@ -685,9 +683,6 @@ Rapportez les bogues, recommandez de nouvelles fonctions et posez vos questions
|
|||
<string name="account_setup_push_limit_1000">1 000 dossiers</string>
|
||||
<string name="animations_title">Animation</string>
|
||||
<string name="animations_summary">Utiliser des effets visuels voyants</string>
|
||||
<string name="volume_navigation_title">Navigation à l’aide de la touche de volume</string>
|
||||
<string name="volume_navigation_message">Dans les vues des courriels</string>
|
||||
<string name="volume_navigation_list">Dans les vues en liste</string>
|
||||
<string name="show_unified_inbox_title">Afficher la boîte de réception unifiée</string>
|
||||
<string name="show_starred_count_title">Afficher le compte d’étoilés</string>
|
||||
<string name="integrated_inbox_title">Boîte de réception unifiée</string>
|
||||
|
|
|
@ -628,8 +628,6 @@ Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Unbekend sertifikaat</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Kaai akseptearje</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Kaai wegerje</string>
|
||||
<string name="message_view_help_key">Del (of D) - Fuortsmite\nR - Beäntwurdzje\nA - Elkenien beäntwurdzje\nC - Opstelle\nF - Trochstjoere\nM - Ferpleatse\nV - Argivearje\nY - Kopiearje\nZ - (net)lêzen markearje\nG - Stjer\nO - Sorteartype\nI - Sortearfolchoarder\nQ - Tebek nei Mappen\nS - Selektearje/deselektearje\nJ of P - Foarich berjocht\nK of N - Folgjende berjocht</string>
|
||||
<string name="message_list_help_key">Del (of D) - Fuortsmite\nC - Opstelle\nM - Ferpleatse\nV - Argivearje\nY - Kopiearje\nZ - (net)lêzen markearje\nG - Stjer\nO - Sorteartype\nI - Sortearfolchoarder\nQ - Tebek nei Mappen\nS - Selektearje/deselektearje</string>
|
||||
<string name="folder_list_filter_hint">Mapnamme befettet</string>
|
||||
<string name="folder_list_display_mode_label">Mappen</string>
|
||||
<string name="folder_list_display_mode_all">Alle mappen</string>
|
||||
|
@ -677,9 +675,7 @@ Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op
|
|||
<string name="account_setup_push_limit_1000">1000 mappen</string>
|
||||
<string name="animations_title">Animaasje</string>
|
||||
<string name="animations_summary">Opsichtige fisuele effekten brûke</string>
|
||||
<string name="volume_navigation_title">Folumetoetsnavigaasje</string>
|
||||
<string name="volume_navigation_message">Berjochtbyld</string>
|
||||
<string name="volume_navigation_list">Fariabele listwerjefte</string>
|
||||
<string name="volume_navigation_title">Folumetoetsnavigaasje yn berjochtbyld</string>
|
||||
<string name="show_unified_inbox_title">Kombinearre Postfek Yn werjaan</string>
|
||||
<string name="show_starred_count_title">It oantal berjochten mei in stjer werjaan</string>
|
||||
<string name="integrated_inbox_title">Kombinearre Postfek Yn</string>
|
||||
|
|
|
@ -545,33 +545,6 @@
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Teisteanas nach aithne dhuinn</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Gabh ris an iuchair</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Diùlt an iuchair</string>
|
||||
<string name="message_view_help_key">Del (no D) – Sguab às
|
||||
\nR – Freagair
|
||||
\nA – Freagair a h-uile
|
||||
\nC – Sgrìobh
|
||||
\nF – Sìn air adhart
|
||||
\nM – Gluais
|
||||
\nV – Cuir san tasg-lann
|
||||
\nY – Dèan lethbhreac
|
||||
\nZ – Cuir comharra gun deach/nach deach a leughadh
|
||||
\nG – Cuir rionnag ris
|
||||
\nO – Seòrsa an t-seòrsachaidh
|
||||
\nI – Òrdugh an t-seòrsachaidh
|
||||
\nQ – Till dha na pasganan
|
||||
\nS – Tagh/Dì-thagh
|
||||
\nJ no P – An teachdaireachd roimhpe
|
||||
\nK no N – An ath-theachdaireachd</string>
|
||||
<string name="message_list_help_key">Del (no D) – Sguab às
|
||||
\nC – Sgrìobh
|
||||
\nM – Gluais
|
||||
\nV – Cuir san tasg-lann
|
||||
\nY – Dèan lethbhreac
|
||||
\nZ – Cuir comharra gun deach/nach deach a leughadh
|
||||
\nG – Cuir rionnag ris
|
||||
\nO – Seòrsa an t-seòrsachaidh
|
||||
\nI – Òrdugh an t-seòrsachaidh
|
||||
\nQ – Till dha na pasganan
|
||||
\nS – Tagh/Dì-thagh</string>
|
||||
<string name="folder_list_filter_hint">Ainm a’ phasgain anns a bheil</string>
|
||||
<string name="folder_list_display_mode_label">Seall pasganan…</string>
|
||||
<string name="folder_list_display_mode_all">Na h-uile pasgan</string>
|
||||
|
@ -617,9 +590,6 @@
|
|||
<string name="account_setup_push_limit_1000">1,000 pasgan</string>
|
||||
<string name="animations_title">Beòthachadh</string>
|
||||
<string name="animations_summary">Cleachd èifeachdan lèirsinneach leòmach</string>
|
||||
<string name="volume_navigation_title">Seòladaireachd le putanan àirde na fuaime</string>
|
||||
<string name="volume_navigation_message">Ann an seallaidhean theachdaireachdan</string>
|
||||
<string name="volume_navigation_list">Ann an seallaidhean liostaichean</string>
|
||||
<string name="show_unified_inbox_title">Seall an t-oll-bhogsa</string>
|
||||
<string name="integrated_inbox_title">An t-oll-bhogsa</string>
|
||||
<string name="integrated_inbox_detail">Na h-uile teachdaireachd ann am pasganan co-aonaichte</string>
|
||||
|
|
|
@ -496,9 +496,6 @@
|
|||
<string name="account_setup_push_limit_1000">1000 cartafoles</string>
|
||||
<string name="animations_title">Animación</string>
|
||||
<string name="animations_summary">Utilizar animacións</string>
|
||||
<string name="volume_navigation_title">Navegación coas teclas de volume</string>
|
||||
<string name="volume_navigation_message">Na vista de mensaxes</string>
|
||||
<string name="volume_navigation_list">Nas listaxes</string>
|
||||
<string name="integrated_inbox_title">Caixa de entrada unificada</string>
|
||||
<string name="integrated_inbox_detail">Todas as mensaxes en cartafoles unificados</string>
|
||||
<string name="folder_settings_include_in_integrated_inbox_label">Unificar</string>
|
||||
|
|
|
@ -599,8 +599,6 @@ Por favor envíen informes de fallos, contribúa con novas características e co
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Certificado descoñecido</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Aceptar certificado</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Rexeitar certificado</string>
|
||||
<string name="message_view_help_key">Del (ou D) - Eliminar\nR - Respostar\nA - Respostar a todos\nC - Compoñer\nF - Reenviar\nM - Mover\nV - Arquivar\nY - Copiar\nZ - Marcar (Non)lido\nG - Estrela\nO - Sort type\nI - Sort order\nQ - Voltar aos cartafoles\nS - Seleccionar/Non seleccionar\nJ ou P - Mensaxe anterior\nK ou N - Seguinte mensaxe</string>
|
||||
<string name="message_list_help_key">Del (ou D) - Eliminar\nC - Compoñer\nM - Mover\nV - Arquivar\nY - Copiar\nZ - Marcar (Non)lido\nG - Estrela\nO - Tipo de orde\nI - Establecer orde\nQ - Voltar aos cartafoles\nS - Seleccionar/Non Seleccionar</string>
|
||||
<string name="folder_list_filter_hint">Nome do cartafol contén</string>
|
||||
<string name="folder_list_display_mode_label">Carpetas</string>
|
||||
<string name="folder_list_display_mode_all">Ver todas as carpetas</string>
|
||||
|
@ -648,9 +646,6 @@ Por favor envíen informes de fallos, contribúa con novas características e co
|
|||
<string name="account_setup_push_limit_1000">1000 carpetas</string>
|
||||
<string name="animations_title">Animacións</string>
|
||||
<string name="animations_summary">Usar animacións</string>
|
||||
<string name="volume_navigation_title">Navegación con teclas de volume</string>
|
||||
<string name="volume_navigation_message">Vista de mensaxe</string>
|
||||
<string name="volume_navigation_list">Listas de mensaxes</string>
|
||||
<string name="show_unified_inbox_title">Amosar a caixa de entrada unificada</string>
|
||||
<string name="show_starred_count_title">Amosar o reconto das estrelas</string>
|
||||
<string name="integrated_inbox_title">Entrada unificada</string>
|
||||
|
|
|
@ -539,8 +539,6 @@
|
|||
<string name="account_setup_failed_dlg_invalid_certificate_title">Nepoznat Certifikat</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_accept">Prihvati Ključ</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Odbij ključ</string>
|
||||
<string name="message_view_help_key">Del (ili D) - Obriši\nR - Odgovori\nA - Odgovori svima\nC - Sastavi\nF - Proslijedi\nM - Pomakni\nV - Arhiviraj\nY - Kopiraj\nZ - Označi (Ne)pročitano\nG - Dodaj zvijezdicu\nO - Način sortiranja\nI - Poredak sortiranja\nQ - Nazad na mape\nS - Označi/odznači\nJ ili P - Prethodna poruka\nK ili N - Sljedeća poruka</string>
|
||||
<string name="message_list_help_key">Del (ili D) - Obriši\nC - Sastavi\nM - Pomakni\nV - Arhiviraj\nY - Kopiraj\nZ - Označi (Ne)pročitano\nG - Dodaj zvijezdicu\nO - Način sortiranja\nI - Poredak sortiranja\nQ - Nazad na mape\nS - Označi/odznači</string>
|
||||
<string name="folder_list_filter_hint">Naziv mape sadrži</string>
|
||||
<string name="folder_list_display_mode_label">Prikaži mape…</string>
|
||||
<string name="folder_list_display_mode_all">Sve mape</string>
|
||||
|
@ -588,9 +586,6 @@
|
|||
<string name="account_setup_push_limit_1000">1000 mapa</string>
|
||||
<string name="animations_title">Animacija</string>
|
||||
<string name="animations_summary">Koristi šarolike vizualne efekte</string>
|
||||
<string name="volume_navigation_title">Navigacija tipkama glasnoće</string>
|
||||
<string name="volume_navigation_message">U pregledu poruka</string>
|
||||
<string name="volume_navigation_list">U pregledu popisa</string>
|
||||
<string name="integrated_inbox_title">Objedinjena Dolazna Pošta</string>
|
||||
<string name="integrated_inbox_detail">Sve poruke u objedinjenim mapama</string>
|
||||
<string name="folder_settings_include_in_integrated_inbox_label">Objedini</string>
|
||||
|
|
|
@ -631,8 +631,6 @@ Hibajelentések beküldésével közreműködhet az új funkciókban, és kérd
|
|||
<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 elfogadása</string>
|
||||
<string name="account_setup_failed_dlg_invalid_certificate_reject">Kulcs visszautasítása</string>
|
||||
<string name="message_view_help_key">Del (vagy D) – Törlés\nR – Válasz\nA – Válasz mindenkinek\nC – Írás\nF – Továbbítás\nM – Áthelyezés\nV – Archiválás\nY – Másolás\nZ – Megjelölés olvasottként/olvasatlanként\nG – Csillagozás\nO – Rendezés típusa\nI – Rendezési sorrend\nQ – Visszatérés a mappákhoz\nS – Kijelölés/Kijelölés megszüntetése\nJ vagy P – Előző üzenet\nK vagy N – Következő üzenet</string>
|
||||
<string name="message_list_help_key">Del (vagy D) – Törlés\nC – Írás\nM – Áthelyezés\nV – Archiválás\nY – Másolás\nZ – Megjelölés olvasottként/olvasatlanként\nG – Csillagozás\nO – Rendezés típusa\nI – Rendezési sorrend\nQ – Visszatérés a mappákhoz\nS – Kijelölés/Kijelölés megszüntetése</string>
|
||||
<string name="folder_list_filter_hint">Mappa neve tartalmazza</string>
|
||||
<string name="folder_list_display_mode_label">Mappák megjelenítése…</string>
|
||||
<string name="folder_list_display_mode_all">Összes mappa</string>
|
||||
|
@ -680,9 +678,6 @@ Hibajelentések beküldésével közreműködhet az új funkciókban, és kérd
|
|||
<string name="account_setup_push_limit_1000">1000 mappa</string>
|
||||
<string name="animations_title">Animációk</string>
|
||||
<string name="animations_summary">Rikító látható hatások használata</string>
|
||||
<string name="volume_navigation_title">Hangerő gomb navigáció</string>
|
||||
<string name="volume_navigation_message">Üzenetnézetekben</string>
|
||||
<string name="volume_navigation_list">Listanézetekben</string>
|
||||
<string name="show_unified_inbox_title">Egységes beérkezett üzenetek megjelenítése</string>
|
||||
<string name="show_starred_count_title">Csillagszámláló megjelenítése</string>
|
||||
<string name="integrated_inbox_title">Egységes beérkezett üzenetek</string>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue