Skip to content

Commit

Permalink
followup changes to save file feature
Browse files Browse the repository at this point in the history
- use MaterialAlertDialogBuilder
- save files to matching folders depending on mimeType
- show toast

Signed-off-by: Marcel Hibbe <[email protected]>
  • Loading branch information
mahibi committed Nov 7, 2023
1 parent 946eb84 commit ac0d9b9
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.ActivityFullScreenImageBinding
import com.nextcloud.talk.jobs.SaveFileToStorageWorker
import com.nextcloud.talk.ui.theme.ViewThemeUtils
Expand All @@ -59,12 +62,16 @@ import com.nextcloud.talk.utils.Mimetype.IMAGE_PREFIX_GENERIC
import pl.droidsonroids.gif.GifDrawable
import java.io.File
import java.util.concurrent.ExecutionException
import javax.inject.Inject

@AutoInjector(NextcloudTalkApplication::class)
class FullScreenImageActivity : AppCompatActivity() {
lateinit var binding: ActivityFullScreenImageBinding
private lateinit var windowInsetsController: WindowInsetsControllerCompat
private lateinit var path: String
private var showFullscreen = false

@Inject
lateinit var viewThemeUtils: ViewThemeUtils

override fun onCreateOptionsMenu(menu: Menu): Boolean {
Expand Down Expand Up @@ -109,23 +116,32 @@ class FullScreenImageActivity : AppCompatActivity() {
}

private fun showWarningDialog() {
val builder = AlertDialog.Builder(this)
builder.setTitle(R.string.nc_dialog_save_to_storage_title)
builder.setMessage(R.string.nc_dialog_save_to_storage_content)
builder.setPositiveButton(R.string.nc_dialog_save_to_storage_yes) { dialog: DialogInterface, which: Int ->
val fileName = intent.getStringExtra("FILE_NAME").toString()
saveImageToStorage(fileName)
dialog.dismiss()
}
builder.setNegativeButton(R.string.nc_dialog_save_to_storage_no) { dialog: DialogInterface, which: Int ->
dialog.dismiss()
}
val dialog = builder.create()
dialog.show()
val dialogText = StringBuilder()
dialogText.append(resources.getString(R.string.nc_dialog_save_to_storage_content))
dialogText.append("\n")
dialogText.append("\n")
dialogText.append(resources.getString(R.string.nc_dialog_save_to_storage_continue))

val dialogBuilder = MaterialAlertDialogBuilder(this)
.setTitle(R.string.nc_dialog_save_to_storage_title)
.setMessage(dialogText)
.setPositiveButton(R.string.nc_dialog_save_to_storage_yes) { _: DialogInterface?, _: Int ->
val fileName = intent.getStringExtra("FILE_NAME").toString()
saveImageToStorage(fileName)
}
.setNegativeButton(R.string.nc_dialog_save_to_storage_no) { _: DialogInterface?, _: Int ->
}
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, dialogBuilder)
val dialog = dialogBuilder.show()
viewThemeUtils.platform.colorTextButtons(
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)

binding = ActivityFullScreenImageBinding.inflate(layoutInflater)
setContentView(binding.root)
Expand Down
41 changes: 25 additions & 16 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ class ChatActivity :
}
} else {
Log.d(TAG, "Downloaded to cache")
downloadFileToCache(message,true ) {
downloadFileToCache(message, true) {
setUpWaveform(message)
}
}
Expand Down Expand Up @@ -4141,13 +4141,13 @@ class ChatActivity :
if (file.exists()) {
share(message)
} else {
downloadFileToCache(message, false ) {
downloadFileToCache(message, false) {
share(message)
}
}
}

private fun saveImage(message: ChatMessage){
private fun saveImage(message: ChatMessage) {
if (permissionUtil.isFilesPermissionGranted()) {
saveImageToStorage(message)
} else {
Expand All @@ -4156,18 +4156,26 @@ class ChatActivity :
}

private fun showSaveToStorageWarning(message: ChatMessage) {
val builder = AlertDialog.Builder(this)
builder.setTitle(R.string.nc_dialog_save_to_storage_title)
builder.setMessage(R.string.nc_dialog_save_to_storage_content)
builder.setPositiveButton(R.string.nc_dialog_save_to_storage_yes) { dialog: DialogInterface, _: Int ->
saveImage(message)
dialog.dismiss()
}
builder.setNegativeButton(R.string.nc_dialog_save_to_storage_no) { dialog: DialogInterface, _: Int ->
dialog.dismiss()
}
val dialog = builder.create()
dialog.show()
val dialogText = StringBuilder()
dialogText.append(resources.getString(R.string.nc_dialog_save_to_storage_content))
dialogText.append(LINEBREAK)
dialogText.append(LINEBREAK)
dialogText.append(resources.getString(R.string.nc_dialog_save_to_storage_continue))

val dialogBuilder = MaterialAlertDialogBuilder(this)
.setTitle(R.string.nc_dialog_save_to_storage_title)
.setMessage(dialogText)
.setPositiveButton(R.string.nc_dialog_save_to_storage_yes) { _: DialogInterface?, _: Int ->
saveImage(message)
}
.setNegativeButton(R.string.nc_dialog_save_to_storage_no) { _: DialogInterface?, _: Int ->
}
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(this, dialogBuilder)
val dialog = dialogBuilder.show()
viewThemeUtils.platform.colorTextButtons(
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
)
}

fun checkIfSaveable(message: ChatMessage) {
Expand All @@ -4177,7 +4185,7 @@ class ChatActivity :
if (file.exists()) {
showSaveToStorageWarning(message)
} else {
downloadFileToCache(message ,false) {
downloadFileToCache(message, false) {
showSaveToStorageWarning(message)
}
}
Expand Down Expand Up @@ -4608,5 +4616,6 @@ class ChatActivity :
private const val TYPING_STOPPED_SIGNALING_MESSAGE_TYPE = "stoppedTyping"
private const val CALL_STARTED_ID = -2
private const val MILISEC_15: Long = 15
private const val LINEBREAK = "\n"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* @author Fariba Khandani
* @author Marcel Hibbe
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
* Copyright (C) 2021 Marcel Hibbe <[email protected]>
* Copyright (C) 2023 Fariba Khandani <khandani@winworker.de>
* Copyright (C) 2023 Marcel Hibbe <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -25,14 +25,23 @@ package com.nextcloud.talk.jobs
import android.content.ContentValues
import android.content.Context
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.provider.MediaStore.Files.FileColumns
import android.util.Log
import android.widget.Toast
import androidx.work.Worker
import androidx.work.WorkerParameters
import autodagger.AutoInjector
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.utils.Mimetype.AUDIO_PREFIX
import com.nextcloud.talk.utils.Mimetype.IMAGE_PREFIX
import com.nextcloud.talk.utils.Mimetype.VIDEO_PREFIX
import java.io.File
import java.io.IOException
import java.io.OutputStream
Expand All @@ -50,16 +59,22 @@ class SaveFileToStorageWorker(val context: Context, workerParameters: WorkerPara
val contentResolver = context.contentResolver
val mimeType = URLConnection.guessContentTypeFromName(cacheFile.name)

val appName = applicationContext.resources!!.getString(R.string.nc_app_product_name)

val values = ContentValues().apply {
if (mimeType.startsWith(IMAGE_PREFIX) || mimeType.startsWith(VIDEO_PREFIX)) {
put(FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/" + appName)
}
put(FileColumns.DISPLAY_NAME, cacheFile.name)
put(FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)

if (mimeType != null) {
put(FileColumns.MIME_TYPE, URLConnection.guessContentTypeFromName(cacheFile.name))
put(FileColumns.MIME_TYPE, mimeType)
}
}

val collection = MediaStore.Files.getContentUri("external")
val uri = contentResolver.insert(collection, values)
val collectionUri = getUriByType(mimeType)

val uri = contentResolver.insert(collectionUri, values)

uri?.let { fileUri ->
try {
Expand All @@ -79,16 +94,53 @@ class SaveFileToStorageWorker(val context: Context, workerParameters: WorkerPara
// Notify the media scanner about the new file
MediaScannerConnection.scanFile(context, arrayOf(cacheFile.absolutePath), null, null)

Handler(Looper.getMainLooper()).post {
Toast.makeText(
context,
context.resources.getString(R.string.nc_save_success),
Toast.LENGTH_SHORT
).show()
}

return Result.success()
} catch (e: IOException) {
Log.e(TAG, "Something went wrong when trying to save file to internal storage", e)
Handler(Looper.getMainLooper()).post {
Toast.makeText(
context,
context.resources.getString(R.string.nc_common_error_sorry),
Toast.LENGTH_SHORT
).show()
}

return Result.failure()
} catch (e: NullPointerException) {
Log.e(TAG, "Something went wrong when trying to save file to internal storage", e)
Handler(Looper.getMainLooper()).post {
Toast.makeText(
context,
context.resources.getString(R.string.nc_common_error_sorry),
Toast.LENGTH_SHORT
).show()
}

return Result.failure()
}
}

private fun getUriByType(contentType: String): Uri {
return when {
contentType.startsWith(VIDEO_PREFIX) -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
contentType.startsWith(AUDIO_PREFIX) -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
contentType.startsWith(IMAGE_PREFIX) -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
else -> if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
Uri.fromFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS))
} else {
MediaStore.Downloads.EXTERNAL_CONTENT_URI
}
}
}

companion object {
private val TAG = SaveFileToStorageWorker::class.java.simpleName
const val KEY_FILE_NAME = "KEY_FILE_NAME"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,6 @@ class MessageActionsDialog(
dialogMessageActionsBinding.emojiMore.installForceSingleEmoji()
}



/*
This method is a hacky workaround to avoid bug #1914
As the bug happens only for the very first time when the popup is opened,
Expand Down Expand Up @@ -355,8 +353,8 @@ class MessageActionsDialog(
dialogMessageActionsBinding.menuOpenInNcApp.visibility = getVisibility(visible)
}

private fun initMenuItemSave (visible: Boolean) {
if (visible){
private fun initMenuItemSave(visible: Boolean) {
if (visible) {
dialogMessageActionsBinding.menuSaveMessage.setOnClickListener {
chatActivity.checkIfSaveable(message)
dismiss()
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-v27/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="colorSurface">@color/bg_default</item>
</style>

<style name="FullScreenMediaTheme" parent="Theme.AppCompat.Light.NoActionBar">
Expand All @@ -17,5 +18,6 @@
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="colorSurface">@color/bg_default</item>
</style>
</resources>
10 changes: 4 additions & 6 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ How to translate with transifex:
<string name="nc_common_error_sorry">Sorry, something went wrong!</string>
<string name="nc_common_create">Create</string>


<!-- Bottom Navigation -->
<string name="nc_settings">Settings</string>

Expand Down Expand Up @@ -519,15 +518,14 @@ How to translate with transifex:
<string name="nc_phone_book_integration_chat_via">Chat via %s</string>
<string name="nc_phone_book_integration_account_not_found">Account not found</string>

//save feature
<!-- save feature -->
<string name="nc_save_message">Save</string>
<string name="nc_dialog_save_to_storage_title">Save to storage?</string>
<string name="nc_dialog_save_to_storage_content">Saving this media to storage will allow any other apps on
your device to access it.\nContinue?</string>
<string name="nc_dialog_save_to_storage_content">Saving this media to storage will allow any other apps on your device to access it.</string>
<string name="nc_dialog_save_to_storage_continue">Continue?</string>
<string name="nc_dialog_save_to_storage_yes">Yes</string>
<string name="nc_dialog_save_to_storage_no">No</string>


<string name="nc_save_success">Saved successfully</string>

<string name="starred">Favorite</string>
<string name="user_status">Status</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="colorSurface">@color/bg_default</item>
</style>

<style name="FullScreenMediaTheme" parent="Theme.AppCompat.Light.NoActionBar">
Expand All @@ -229,6 +230,7 @@
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="colorSurface">@color/bg_default</item>
</style>

<style name="TextInputLayoutTheme" parent="Theme.AppCompat">
Expand Down

0 comments on commit ac0d9b9

Please sign in to comment.