Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FlowCrypt/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ android {
versionCode = extra["appVersionCode"] as Int
versionName = extra["appVersionName"] as String
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("int", "MIN_SDK_VERSION", "$minSdk")

/*
The following argument makes the Android Test Orchestrator run its
Expand Down
7 changes: 1 addition & 6 deletions FlowCrypt/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com
~ Contributors: DenBond7
~ Contributors: denbond7
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
Expand All @@ -13,11 +13,6 @@
<uses-permission android:name="android.permission.INTERNET" />
<!-- android.permission.ACCESS_NETWORK_STATE is used to check is internet connection available-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- android.permission.WRITE_EXTERNAL_STORAGE is used to save attachments for Build.VERSION.SDK_INT <= Build.VERSION_CODES.P -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
<!-- android.permission.WAKE_LOCK will be used by classes which extend JobIntentService -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Request the foreground service permission. Details here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package com.flowcrypt.email.extensions
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.widget.Toast
import com.flowcrypt.email.FlowCryptApplication

Expand All @@ -23,18 +22,11 @@ fun Context.toast(resId: Int, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, resId, duration).show()
}

@SuppressWarnings("deprecation")
@Suppress("DEPRECATION")
fun Context?.hasActiveConnection(): Boolean {
return this?.let {
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val cap = cm?.getNetworkCapabilities(cm.activeNetwork) ?: return false
return cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
} else {
val activeNetwork: android.net.NetworkInfo? = cm?.activeNetworkInfo
activeNetwork?.isConnectedOrConnecting == true
}
val cap = cm?.getNetworkCapabilities(cm.activeNetwork) ?: return false
return cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
} ?: false
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/*
* © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com
* Contributors: DenBond7
* Contributors: denbond7
*/

package com.flowcrypt.email.extensions.android.webkit

import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.webkit.WebView
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature
Expand All @@ -18,9 +17,7 @@ import androidx.webkit.WebViewFeature
fun WebView.setupDayNight() {
setBackgroundColor(Color.TRANSPARENT)
if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
WebSettingsCompat.setAlgorithmicDarkeningAllowed(settings, true)
}
WebSettingsCompat.setAlgorithmicDarkeningAllowed(settings, true)
} else {
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Binder
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.HandlerThread
import android.os.IBinder
Expand All @@ -22,11 +20,8 @@ import android.os.RemoteException
import android.provider.MediaStore
import android.text.TextUtils
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.FileProvider
import androidx.lifecycle.LifecycleService
import com.flowcrypt.email.BuildConfig
import com.flowcrypt.email.Constants
import com.flowcrypt.email.R
import com.flowcrypt.email.api.email.gmail.GmailApiHelper
import com.flowcrypt.email.api.email.model.AttachmentInfo
Expand All @@ -40,7 +35,6 @@ import com.flowcrypt.email.extensions.kotlin.toHex
import com.flowcrypt.email.security.KeysStorageImpl
import com.flowcrypt.email.security.SecurityUtils
import com.flowcrypt.email.security.pgp.PgpDecryptAndOrVerify
import com.flowcrypt.email.util.FileAndDirectoryUtils
import com.flowcrypt.email.util.GeneralUtil
import com.flowcrypt.email.util.LogsUtil
import com.flowcrypt.email.util.exception.ExceptionUtil
Expand Down Expand Up @@ -510,7 +504,7 @@ class AttachmentDownloadManagerService : LifecycleService() {
FileUtils.copyInputStreamToFile(inputStream, attTempFile)
attTempFile = decryptFileIfNeeded(context, attTempFile)
if (!Thread.currentThread().isInterrupted) {
val uri = storeFileToSharedFolder(context, attTempFile)
val uri = storeFileUsingScopedStorage(context, attTempFile)
listener?.onAttDownloaded(
attInfo = att.copy(
name = finalFileName,
Expand Down Expand Up @@ -600,7 +594,7 @@ class AttachmentDownloadManagerService : LifecycleService() {
if (Thread.currentThread().isInterrupted) {
listener?.onCanceled(att.copy(name = finalFileName))
} else {
val uri = storeFileToSharedFolder(context, attTempFile)
val uri = storeFileUsingScopedStorage(context, attTempFile)
listener?.onAttDownloaded(
attInfo = att.copy(
name = finalFileName,
Expand All @@ -615,15 +609,6 @@ class AttachmentDownloadManagerService : LifecycleService() {
}
}

private fun storeFileToSharedFolder(context: Context, attFile: File): Uri {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
storeFileUsingScopedStorage(context, attFile)
} else {
storeLegacy(attFile, context)
}
}

@RequiresApi(Build.VERSION_CODES.Q)
private fun storeFileUsingScopedStorage(context: Context, attFile: File): Uri {
val resolver = context.contentResolver
val mimeType = finalFileName.getPossibleAndroidMimeType()
Expand Down Expand Up @@ -670,43 +655,6 @@ class AttachmentDownloadManagerService : LifecycleService() {
return fileUri
}

/**
* We use this method to support saving files on Android 9 and less which uses an old approach.
*/
private fun storeLegacy(attFile: File, context: Context): Uri {
val fileName = finalFileName
val flowCryptDirectoryForDownloadsName = "FlowCrypt"
val fileDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).apply {
if (!exists()) {
if (!mkdir()) {
error("Creating ${Environment.DIRECTORY_DOWNLOADS} failed!")
}
}
}

val flowCryptDirectoryForDownloads = File(fileDir, flowCryptDirectoryForDownloadsName).apply {
if (!exists()) {
if (!mkdir()) {
error("Creating FlowCrypt directory in ${Environment.DIRECTORY_DOWNLOADS} failed!")
}
}
}

var downloadedFile = File(flowCryptDirectoryForDownloads, fileName)
downloadedFile = if (downloadedFile.exists()) {
FileAndDirectoryUtils.createFileWithIncreasedIndex(flowCryptDirectoryForDownloads, fileName)
} else {
downloadedFile
}

finalFileName = downloadedFile.name
attFile.inputStream().use { srcStream ->
FileUtils.openOutputStream(downloadedFile).use { outStream -> srcStream.copyTo(outStream) }
}
return FileProvider.getUriForFile(context, Constants.FILE_PROVIDER_AUTHORITY, downloadedFile)
}

fun setListener(listener: OnDownloadAttachmentListener) {
this.listener = listener
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,16 @@

package com.flowcrypt.email.ui.activity.fragment

import android.Manifest
import android.accounts.AuthenticatorException
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.graphics.Shader
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.text.Html
Expand All @@ -33,7 +30,6 @@ import android.widget.CompoundButton
import android.widget.ListView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.ColorRes
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
Expand Down Expand Up @@ -182,15 +178,6 @@ class MessageDetailsFragment : BaseFragment<FragmentMessageDetailsBinding>(), Pr
}
}

private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
downloadAttachment()
} else {
toast(R.string.cannot_save_attachment_without_permission, Toast.LENGTH_LONG)
}
}

private val attachmentsRecyclerViewAdapter = AttachmentsRecyclerViewAdapter(
isDeleteEnabled = false,
attachmentActionListener = object : AttachmentsRecyclerViewAdapter.AttachmentActionListener {
Expand Down Expand Up @@ -2011,16 +1998,7 @@ class MessageDetailsFragment : BaseFragment<FragmentMessageDetailsBinding>(), Pr
}
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ||
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
) {
downloadAttachment()
} else {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
downloadAttachment()
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@

package com.flowcrypt.email.ui.activity.fragment

import android.Manifest
import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
Expand All @@ -19,8 +16,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ListView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
Expand Down Expand Up @@ -141,16 +136,6 @@ class ThreadDetailsFragment : BaseFragment<FragmentThreadDetailsBinding>(), Prog
}
}
}
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
toast(
if (isGranted) {
R.string.permissions_granted_and_now_you_can_download_attachments
} else {
R.string.cannot_save_attachment_without_permission
}, Toast.LENGTH_LONG
)
}

private val messagesInThreadListAdapter = MessagesInThreadListAdapter(
object : MessagesInThreadListAdapter.AdapterListener {
Expand Down Expand Up @@ -1328,16 +1313,7 @@ class ThreadDetailsFragment : BaseFragment<FragmentThreadDetailsBinding>(), Prog
)
) return

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ||
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
) {
downloadAttachment(attachmentInfo, message)
} else {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
downloadAttachment(attachmentInfo, message)
}

private fun downloadAttachment(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/*
* © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com
* Contributors: DenBond7
* Contributors: denbond7
*/

package com.flowcrypt.email.ui.activity.fragment.base

import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
Expand All @@ -18,7 +17,6 @@ import androidx.viewbinding.ViewBinding
import com.flowcrypt.email.R
import com.flowcrypt.email.database.entity.AccountEntity
import com.flowcrypt.email.extensions.androidx.fragment.app.doBaseUISetup
import com.flowcrypt.email.extensions.hasActiveConnection
import com.flowcrypt.email.jetpack.lifecycle.ConnectionLifecycleObserver
import com.flowcrypt.email.jetpack.viewmodel.AccountViewModel
import com.flowcrypt.email.jetpack.viewmodel.RoomBasicViewModel
Expand Down Expand Up @@ -212,11 +210,7 @@ abstract class BaseFragment<T : ViewBinding> : Fragment(), UiUxSettings, IdlingC
}

protected fun isConnected(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
connectionLifecycleObserver.connectionLiveData.value ?: false
} else {
context.hasActiveConnection()
}
return connectionLifecycleObserver.connectionLiveData.value ?: false
}

protected fun showAuthIssueHint(
Expand Down
2 changes: 0 additions & 2 deletions FlowCrypt/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@
<string name="source_has_wrong_pgp_structure">Предоставленное вами содержимое не похоже на действительный %1$s ключ PGP.</string>
<string name="file_has_wrong_pgp_structure">Содержимое Вашего файла не похоже на действительный %1$s ключ PGP.</string>
<string name="attachment_not_found">Вложение не найдено</string>
<string name="cannot_save_attachment_without_permission">Вложение нельзя сохранить без разрешения на запись во внешнее хранилище</string>
<string name="sync">Синхронизация</string>
<string name="switch_to_secure_email">Переключиться на безопасное сообщение</string>
<string name="supported_public_key_not_found">Поддерживаемый открытый ключ не найден</string>
Expand Down Expand Up @@ -642,7 +641,6 @@
<string name="make_backup_in_the_email_box">Сделайте резервную копию в почтовом ящике</string>
<string name="make_backup_explanation_text">Сохранить предоставленные закрытые ключи PGP, защищенные парольной фразой, в качестве резервной копии в папке «Входящие». Это поможет Вам получить доступ к Вашим зашифрованным сообщениям с других устройств (при условии предоставление Вашей парольной фразы). Вы можете безопасно оставить его в своем почтовом ящике или заархивировать.\n\nЕсли Вам не нужна такая резервная копия, отключите эту опцию.</string>
<string name="draft">Черновик</string>
<string name="permissions_granted_and_now_you_can_download_attachments">Разрешения предоставлены и теперь Вы можете загружать вложения.</string>
<string name="delete_draft">Удалить черновик?</string>
<string name="thread_was_deleted_or_moved">Переписка удалена или перемещена</string>
<plurals name="drafts_count">
Expand Down
2 changes: 0 additions & 2 deletions FlowCrypt/src/main/res/values-uk/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@
<string name="source_has_wrong_pgp_structure">Наданий Вами вміст не схожий на дійсний %1$s ключ PGP.</string>
<string name="file_has_wrong_pgp_structure">Вміст Вашого файлу не схожий на дійсний %1$s ключ PGP.</string>
<string name="attachment_not_found">Вкладення не знайдене</string>
<string name="cannot_save_attachment_without_permission">Вкладення неможливо зберегти без дозволу на запис до зовнішнього сховища</string>
<string name="sync">Синхронізація</string>
<string name="switch_to_secure_email">Переключитись на безпечне повідомлення</string>
<string name="supported_public_key_not_found">Підтримуваний відкритий ключ не знайдено</string>
Expand Down Expand Up @@ -643,7 +642,6 @@
<string name="make_backup_in_the_email_box">Зробіть резервну копію в електронній скриньці</string>
<string name="make_backup_explanation_text">Зберегти надані секретні ключі PGP, захищені парольною фразою, як резервну копію в папці «Вхідні». Це допоможе отримати Вам доступ до Ваших зашифрованих повідомлень з інших пристроїв (за умови надання Вашої парольної фрази). Ви можете спокійно залишити його у папці "Вхідні" або заархівувати.\n\nЯкщо Вам не потрібна така резервна копія, вимкніть цю опцію.</string>
<string name="draft">Чорновик</string>
<string name="permissions_granted_and_now_you_can_download_attachments">Дозволи надано, і тепер ви можете завантажити вкладені файли</string>
<string name="delete_draft">Видалити чернетку?</string>
<string name="thread_was_deleted_or_moved">Бесіду видалено або переміщено</string>
<plurals name="drafts_count">
Expand Down
3 changes: 0 additions & 3 deletions FlowCrypt/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@
<string name="waiting_to_load">Waiting to load</string>
<string name="download_complete">Download complete</string>
<string name="template_attachment_already_loading">Attachment \"%1$s\" is already loading</string>
<string name="cannot_save_attachment_without_permission">The attachment cannot be saved without the write external
storage permission</string>
<string name="can_not_attach_this_file">Can\'t attach this file!</string>
<string name="template_warning_max_total_attachments_size">Total size of added attachments should be under
%1$s</string>
Expand Down Expand Up @@ -653,7 +651,6 @@
<string name="make_backup_in_the_email_box">Make a backup in the email box</string>
<string name="make_backup_explanation_text">Save the given passphrase-protected PGP private keys as a backup in the inbox. It will help you access your encrypted messages from other devices (along with your pass phrase). You can safely leave it in your inbox or archive it.\n\nIf you don\'t need to have such a backup, please disable this option.</string>
<string name="draft">Draft</string>
<string name="permissions_granted_and_now_you_can_download_attachments">The permissions have been granted, and now you can download attachments</string>
<string name="delete_draft">Delete draft?</string>
<string name="thread_was_deleted_or_moved">The thread was deleted or moved</string>
<plurals name="drafts_count">
Expand Down
Loading