Skip to content

Commit c8a8bf7

Browse files
authored
improve handling attachments (#2948)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Refactored code.
1 parent 8d4340c commit c8a8bf7

23 files changed

Lines changed: 346 additions & 58 deletions
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com
3+
* Contributors: denbond7
4+
*/
5+
6+
package com.flowcrypt.email.ui.fragment
7+
8+
import androidx.test.espresso.Espresso.onView
9+
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
10+
import androidx.test.espresso.assertion.ViewAssertions.matches
11+
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
12+
import androidx.test.espresso.matcher.ViewMatchers.withText
13+
import androidx.test.ext.junit.rules.activityScenarioRule
14+
import androidx.test.ext.junit.runners.AndroidJUnit4
15+
import androidx.test.filters.MediumTest
16+
import com.flowcrypt.email.R
17+
import com.flowcrypt.email.TestConstants
18+
import com.flowcrypt.email.junit.annotations.FlowCryptTestSettings
19+
import com.flowcrypt.email.rules.ClearAppSettingsRule
20+
import com.flowcrypt.email.rules.FlowCryptMockWebServerRule
21+
import com.flowcrypt.email.rules.GrantPermissionRuleChooser
22+
import com.flowcrypt.email.rules.RetryRule
23+
import com.flowcrypt.email.rules.ScreenshotTestRule
24+
import com.flowcrypt.email.ui.activity.MainActivity
25+
import com.flowcrypt.email.ui.base.BaseGmailApiTest
26+
import com.flowcrypt.email.util.TestGeneralUtil
27+
import okhttp3.mockwebserver.Dispatcher
28+
import okhttp3.mockwebserver.MockResponse
29+
import okhttp3.mockwebserver.RecordedRequest
30+
import org.junit.Rule
31+
import org.junit.Test
32+
import org.junit.rules.RuleChain
33+
import org.junit.rules.TestRule
34+
import org.junit.runner.RunWith
35+
36+
/**
37+
* @author Denys Bondarenko
38+
*/
39+
@MediumTest
40+
@RunWith(AndroidJUnit4::class)
41+
@FlowCryptTestSettings(useCommonIdling = false)
42+
class MainSettingsFragmentEnterpriseFlowTest :
43+
BaseGmailApiTest(BASE_ACCOUNT_ENTITY.copy(useConversationMode = true)) {
44+
override val activityScenarioRule = activityScenarioRule<MainActivity>(
45+
TestGeneralUtil.genIntentForNavigationComponent(
46+
destinationId = R.id.mainSettingsFragment
47+
)
48+
)
49+
50+
override val mockWebServerRule =
51+
FlowCryptMockWebServerRule(TestConstants.MOCK_WEB_SERVER_PORT, object : Dispatcher() {
52+
override fun dispatch(request: RecordedRequest): MockResponse {
53+
return when {
54+
else -> handleCommonAPICalls(request)
55+
}
56+
}
57+
})
58+
59+
@get:Rule
60+
var ruleChain: TestRule = RuleChain
61+
.outerRule(RetryRule.DEFAULT)
62+
.around(ClearAppSettingsRule())
63+
.around(GrantPermissionRuleChooser.grant(android.Manifest.permission.POST_NOTIFICATIONS))
64+
.around(addAccountToDatabaseRule)
65+
.around(addPrivateKeyToDatabaseRule)
66+
.around(activityScenarioRule)
67+
.around(ScreenshotTestRule())
68+
69+
@Test
70+
fun testHiddenOrVisibleItems() {
71+
//should be hidden as we have NO_PRV_BACKUP
72+
onView(withText(getResString(R.string.backups)))
73+
.check(doesNotExist())
74+
//should be hidden as we have RESTRICT_ANDROID_ATTACHMENT_HANDLING
75+
onView(withText(getResString(R.string.general)))
76+
.check(doesNotExist())
77+
78+
//should be visible
79+
onView(withText(getResString(R.string.security_and_privacy)))
80+
.check(matches(isDisplayed()))
81+
onView(withText(getResString(R.string.contacts)))
82+
.check(matches(isDisplayed()))
83+
onView(withText(getResString(R.string.keys)))
84+
.check(matches(isDisplayed()))
85+
onView(withText(getResString(R.string.attester)))
86+
.check(matches(isDisplayed()))
87+
onView(withText(getResString(R.string.experimental)))
88+
.check(matches(isDisplayed()))
89+
}
90+
}

FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/fragment/MainSettingsFragmentNavigationToSubMenuFlowTest.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com
3-
* Contributors: DenBond7
3+
* Contributors: denbond7
44
*/
55

66
package com.flowcrypt.email.ui.fragment
@@ -89,6 +89,24 @@ class MainSettingsFragmentNavigationToSubMenuFlowTest : BaseTest() {
8989
)
9090
}
9191

92+
@Test
93+
fun testHiddenOrVisibleItems() {
94+
onView(withText(getResString(R.string.backups)))
95+
.check(matches(isDisplayed()))
96+
onView(withText(getResString(R.string.security_and_privacy)))
97+
.check(matches(isDisplayed()))
98+
onView(withText(getResString(R.string.contacts)))
99+
.check(matches(isDisplayed()))
100+
onView(withText(getResString(R.string.keys)))
101+
.check(matches(isDisplayed()))
102+
onView(withText(getResString(R.string.attester)))
103+
.check(matches(isDisplayed()))
104+
onView(withText(getResString(R.string.general)))
105+
.check(matches(isDisplayed()))
106+
onView(withText(getResString(R.string.experimental)))
107+
.check(matches(isDisplayed()))
108+
}
109+
92110
private fun checkIsScreenDisplaying(screenName: String) {
93111
checkIsScreenDisplaying(screenName, screenName)
94112
}

FlowCrypt/src/main/java/com/flowcrypt/email/Constants.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@ class Constants {
5555
const val PREF_KEY_MESSAGES_NOTIFICATION_FILTER = "preferences_key_messages_notification_filter"
5656
const val PREF_KEY_MANAGE_NOTIFICATIONS = "preferences_key_manage_notifications"
5757
const val PREF_KEY_SECURITY_CHANGE_PASS_PHRASE = "preferences_key_security_change_pass_phrase"
58+
const val PREFERENCES_KEY_ATTACHMENTS_DISABLE_SMART_MODE_FOR_PREVIEW =
59+
"preferences_key_attachments_disable_smart_mode_for_preview"
5860
const val PREF_KEY_LAST_ATT_ORDER_ID = "preferences_key_last_att_order_id"
5961
const val PREF_KEY_IS_CHECK_KEYS_NEEDED = "preferences_key_is_check_keys_needed"
6062
const val PREF_KEY_BACKUPS = "pref_key_backups"
6163
const val PREF_KEY_INSTALL_VERSION = "pref_key_install_version"
6264
const val PREF_KEY_SERVER_SETTINGS = "pref_key_server_settings"
65+
const val PREF_KEY_GENERAL = "pref_key_general"
6366

6467
/**
6568
* The max total size off all attachment which can be send via the app.

FlowCrypt/src/main/java/com/flowcrypt/email/providers/EmbeddedAttachmentsProvider.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ class EmbeddedAttachmentsProvider : DocumentsProvider() {
5959
return getFileDescriptor(getBytesForDocumentId(documentId))
6060
}
6161

62+
override fun getDocumentType(documentId: String?): String {
63+
return documentId?.let {
64+
Cache.getInstance().get(documentId)?.type ?: super.getDocumentType(documentId)
65+
} ?: super.getDocumentType(documentId)
66+
}
67+
6268
private fun getBytesForDocumentId(documentId: String): ByteArray {
6369
val attachmentInfo = Cache.getInstance().get(documentId)
6470
return requireNotNull(attachmentInfo?.rawData)

FlowCrypt/src/main/java/com/flowcrypt/email/service/attachment/AttachmentDownloadManagerService.kt

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -623,23 +623,6 @@ class AttachmentDownloadManagerService : LifecycleService() {
623623
val fileUri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
624624

625625
requireNotNull(fileUri)
626-
627-
//we should check maybe a file is already exist. Then we will use the file name from the system
628-
val cursor =
629-
resolver.query(fileUri, arrayOf(MediaStore.DownloadColumns.DISPLAY_NAME), null, null, null)
630-
cursor?.let {
631-
if (it.moveToFirst()) {
632-
val nameIndex = it.getColumnIndex(MediaStore.DownloadColumns.DISPLAY_NAME)
633-
if (nameIndex != -1) {
634-
val nameFromSystem = it.getString(nameIndex)
635-
if (nameFromSystem != finalFileName) {
636-
finalFileName = nameFromSystem
637-
}
638-
}
639-
}
640-
}
641-
cursor?.close()
642-
643626
val srcInputStream = attFile.inputStream()
644627
val destOutputStream = resolver.openOutputStream(fileUri)
645628
?: throw IllegalArgumentException("provided URI could not be opened")
@@ -652,6 +635,23 @@ class AttachmentDownloadManagerService : LifecycleService() {
652635
put(MediaStore.Downloads.IS_PENDING, 0)
653636
}, null, null)
654637

638+
resolver.query(
639+
fileUri,
640+
arrayOf(MediaStore.DownloadColumns.DISPLAY_NAME),
641+
null,
642+
null,
643+
null
644+
)
645+
?.use { cursor ->
646+
//we should check maybe a file is already exist.
647+
//Then we will use the file name from the system.
648+
if (cursor.moveToFirst()) {
649+
finalFileName = cursor.getString(
650+
cursor.getColumnIndexOrThrow(MediaStore.DownloadColumns.DISPLAY_NAME)
651+
)
652+
}
653+
}
654+
655655
return fileUri
656656
}
657657

FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/CreateMessageFragment.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import androidx.lifecycle.Lifecycle
3939
import androidx.lifecycle.ViewModel
4040
import androidx.navigation.NavDirections
4141
import androidx.navigation.fragment.navArgs
42+
import androidx.preference.PreferenceManager
4243
import androidx.recyclerview.widget.LinearLayoutManager
4344
import androidx.recyclerview.widget.RecyclerView
4445
import com.flowcrypt.email.Constants
@@ -109,6 +110,7 @@ import com.flowcrypt.email.ui.adapter.recyclerview.itemdecoration.MarginItemDeco
109110
import com.flowcrypt.email.util.FileAndDirectoryUtils
110111
import com.flowcrypt.email.util.GeneralUtil
111112
import com.flowcrypt.email.util.LogsUtil
113+
import com.flowcrypt.email.util.SharedPreferencesHelper
112114
import com.flowcrypt.email.util.UIUtil
113115
import com.flowcrypt.email.util.exception.DecryptionException
114116
import com.flowcrypt.email.util.exception.ExceptionUtil
@@ -253,13 +255,17 @@ class CreateMessageFragment : BaseFragment<FragmentCreateMessageBinding>(),
253255
attachmentActionListener = object : AttachmentsRecyclerViewAdapter.AttachmentActionListener {
254256
override fun onDownloadClick(attachmentInfo: AttachmentInfo) {}
255257

256-
override fun onAttachmentClick(attachmentInfo: AttachmentInfo) {
257-
onPreviewClick(attachmentInfo)
258-
}
259-
260258
override fun onPreviewClick(attachmentInfo: AttachmentInfo) {
261259
if (attachmentInfo.uri != null) {
262-
val intent = GeneralUtil.genViewAttachmentIntent(attachmentInfo.uri, attachmentInfo)
260+
val intent = GeneralUtil.genViewAttachmentIntent(
261+
uri = attachmentInfo.uri,
262+
attachmentInfo = attachmentInfo,
263+
useCommonPattern = SharedPreferencesHelper.getBoolean(
264+
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()),
265+
key = Constants.PREFERENCES_KEY_ATTACHMENTS_DISABLE_SMART_MODE_FOR_PREVIEW,
266+
defaultValue = false
267+
)
268+
)
263269
try {
264270
startActivity(intent)
265271
} catch (e: ActivityNotFoundException) {

FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MainSettingsFragment.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com
3-
* Contributors: DenBond7
3+
* Contributors: denbond7
44
*/
55

66
package com.flowcrypt.email.ui.activity.fragment
@@ -95,6 +95,14 @@ class MainSettingsFragment : BasePreferenceFragment() {
9595
true
9696
}
9797

98+
findPreference<Preference>(getString(R.string.pref_key_general))
99+
?.setOnPreferenceClickListener {
100+
navController?.navigate(
101+
MainSettingsFragmentDirections.actionMainSettingsFragmentToGeneralSettingsFragment()
102+
)
103+
true
104+
}
105+
98106
findPreference<Preference>(getString(R.string.pref_key_experimental))
99107
?.setOnPreferenceClickListener {
100108
navController?.navigate(
@@ -110,8 +118,10 @@ class MainSettingsFragment : BasePreferenceFragment() {
110118
!(accountEntity?.hasClientConfigurationProperty(ClientConfiguration.ConfigurationProperty.NO_PRV_BACKUP)
111119
?: false)
112120

113-
if (accountEntity?.useAPI == false) {
114-
findPreference<Preference>(Constants.PREF_KEY_SERVER_SETTINGS)?.isVisible = true
115-
}
121+
findPreference<Preference>(Constants.PREF_KEY_SERVER_SETTINGS)?.isVisible =
122+
accountEntity?.useAPI == false
123+
124+
findPreference<Preference>(Constants.PREF_KEY_GENERAL)?.isVisible =
125+
accountEntity?.isHandlingAttachmentRestricted() == false
116126
}
117127
}

FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/MessageDetailsFragment.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import androidx.lifecycle.ViewModel
4242
import androidx.lifecycle.lifecycleScope
4343
import androidx.navigation.NavDirections
4444
import androidx.navigation.fragment.navArgs
45+
import androidx.preference.PreferenceManager
4546
import androidx.recyclerview.widget.LinearLayoutManager
4647
import androidx.recyclerview.widget.RecyclerView
4748
import com.flowcrypt.email.Constants
@@ -131,6 +132,7 @@ import com.flowcrypt.email.ui.widget.EmailWebView
131132
import com.flowcrypt.email.ui.widget.TileDrawable
132133
import com.flowcrypt.email.util.DateTimeUtil
133134
import com.flowcrypt.email.util.GeneralUtil
135+
import com.flowcrypt.email.util.SharedPreferencesHelper
134136
import com.flowcrypt.email.util.UIUtil
135137
import com.flowcrypt.email.util.exception.CommonConnectionException
136138
import com.flowcrypt.email.util.exception.GmailAPIException
@@ -201,10 +203,6 @@ class MessageDetailsFragment : BaseFragment<FragmentMessageDetailsBinding>(), Pr
201203
}
202204
}
203205

204-
override fun onAttachmentClick(attachmentInfo: AttachmentInfo) {
205-
onPreviewClick(attachmentInfo)
206-
}
207-
208206
override fun onPreviewClick(attachmentInfo: AttachmentInfo) {
209207
if (attachmentInfo.uri != null) {
210208
if (attachmentInfo.isPossiblyEncrypted) {
@@ -1828,7 +1826,15 @@ class MessageDetailsFragment : BaseFragment<FragmentMessageDetailsBinding>(), Pr
18281826
useContentApp: Boolean = false
18291827
) {
18301828
val intent = if (attachmentInfo.uri != null) {
1831-
GeneralUtil.genViewAttachmentIntent(requireNotNull(attachmentInfo.uri), attachmentInfo)
1829+
GeneralUtil.genViewAttachmentIntent(
1830+
uri = requireNotNull(attachmentInfo.uri),
1831+
attachmentInfo = attachmentInfo,
1832+
useCommonPattern = SharedPreferencesHelper.getBoolean(
1833+
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()),
1834+
key = Constants.PREFERENCES_KEY_ATTACHMENTS_DISABLE_SMART_MODE_FOR_PREVIEW,
1835+
defaultValue = false
1836+
)
1837+
)
18321838
} else {
18331839
toast(getString(R.string.preview_is_not_available))
18341840
return

0 commit comments

Comments
 (0)