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
3 changes: 0 additions & 3 deletions apps/flipcash/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- needed for network connectivity detection in Api24NetworkObserver -->
<uses-permission
Expand Down Expand Up @@ -39,7 +37,6 @@
android:label="@string/app_name"
android:largeHeap="true"
android:enableOnBackInvokedCallback="true"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.Code"
tools:targetApi="tiramisu">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,45 @@
package com.flipcash.app.core.internal.extensions

import android.content.ContentResolver
import android.content.ContentValues
import android.graphics.Bitmap
import android.os.Environment
import android.provider.MediaStore
import com.getcode.utils.ErrorUtils
import com.getcode.utils.timedTrace
import java.io.File
import java.io.FileOutputStream

fun Bitmap.save(destination: File, name: () -> String): Boolean {
fun Bitmap.save(contentResolver: ContentResolver, name: () -> String): Boolean {
val filename = name()
if (!destination.exists()) {
if (!destination.mkdirs()) {
return false
}
}
val dest = File(destination, filename)

return timedTrace("saving bitmap") {
try {
FileOutputStream(dest).use { out ->
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, filename)
put(MediaStore.Images.Media.MIME_TYPE, "image/png")
put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
put(MediaStore.Images.Media.IS_PENDING, 1)
}

val uri = contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
) ?: return@timedTrace false

contentResolver.openOutputStream(uri)?.use { out ->
compress(Bitmap.CompressFormat.PNG, 90, out)
} ?: run {
contentResolver.delete(uri, null, null)
return@timedTrace false
}

contentValues.clear()
contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
contentResolver.update(uri, contentValues, null, null)

return@timedTrace true
} catch (e: Exception) {
ErrorUtils.handleError(e)
return@timedTrace false
}
return@timedTrace true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.flipcash.app.core.storage

import android.content.Context
import android.graphics.Bitmap
import com.flipcash.app.core.internal.extensions.save
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject

class MediaSaver @Inject constructor(
@ApplicationContext private val context: Context
) {
fun saveBitmap(bitmap: Bitmap, filename: String): Boolean {
return bitmap.save(context.contentResolver) { filename }
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.flipcash.app.backupkey.internal

import com.flipcash.app.accesskey.BaseAccessKeyViewModel
import com.flipcash.app.core.storage.MediaScanner
import com.flipcash.app.core.storage.MediaSaver
import com.flipcash.services.user.UserManager
import com.getcode.libs.qr.QRCodeGenerator
import com.getcode.opencode.managers.MnemonicManager
Expand All @@ -17,13 +17,13 @@ import kotlin.time.Duration.Companion.seconds
internal class BackupKeyScreenViewModel @Inject constructor(
resources: ResourceHelper,
mnemonicManager: MnemonicManager,
mediaScanner: MediaScanner,
mediaSaver: MediaSaver,
userManager: UserManager,
qrCodeGenerator: QRCodeGenerator,
) : BaseAccessKeyViewModel(
resources,
mnemonicManager,
mediaScanner,
mediaSaver,
userManager,
qrCodeGenerator
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.flipcash.app.analytics.Action
import com.flipcash.app.analytics.Button
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.auth.AuthManager
import com.flipcash.app.core.storage.MediaScanner
import com.flipcash.app.core.storage.MediaSaver
import com.flipcash.app.userflags.UserFlagsCoordinator
import com.flipcash.services.user.UserManager
import com.getcode.libs.qr.QRCodeGenerator
Expand All @@ -22,12 +22,12 @@ class LoginAccessKeyViewModel @Inject constructor(
resources: ResourceHelper,
mnemonicManager: MnemonicManager,
qrCodeGenerator: QRCodeGenerator,
mediaScanner: MediaScanner,
mediaSaver: MediaSaver,
userManager: UserManager,
private val userFlags: UserFlagsCoordinator,
private val authManager: AuthManager,
private val analytics: FlipcashAnalyticsService,
): BaseAccessKeyViewModel(resources, mnemonicManager, mediaScanner, userManager, qrCodeGenerator) {
): BaseAccessKeyViewModel(resources, mnemonicManager, mediaSaver, userManager, qrCodeGenerator) {

suspend fun onWroteDownInstead(): Result<Boolean> {
trackButton(Button.WroteAccessKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ import android.graphics.Path
import android.graphics.RectF
import android.graphics.Shader
import android.graphics.Typeface
import android.os.Environment
import androidx.core.graphics.applyCanvas
import androidx.core.graphics.createBitmap
import androidx.core.graphics.drawable.toBitmap
import androidx.lifecycle.viewModelScope
import com.flipcash.app.core.internal.extensions.save
import com.flipcash.app.core.storage.MediaScanner
import com.flipcash.app.core.storage.MediaSaver
import com.flipcash.app.theme.internal.Flipcash2ColorSpec
import com.flipcash.services.user.UserManager
import com.flipcash.shared.accesskey.R
Expand Down Expand Up @@ -63,7 +61,7 @@ data class AccessKeyUiModel(
abstract class BaseAccessKeyViewModel(
private val resources: ResourceHelper,
private val mnemonicManager: MnemonicManager,
private val mediaScanner: MediaScanner,
private val mediaSaver: MediaSaver,
userManager: UserManager,
private val qrCodeGenerator: QRCodeGenerator
) : ViewModel() {
Expand Down Expand Up @@ -129,22 +127,12 @@ abstract class BaseAccessKeyViewModel(
uiFlow.update { it.copy(exportState = LoadingSuccessState(loading = true)) }
val bitmap = uiFlow.value.accessKeyBitmap
?: return Result.failure(IllegalStateException("No access key?"))
val destination =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)

return withContext(Dispatchers.IO) {
runCatching {
val result = bitmap.save(
destination = destination,
name = {
val date: DateFormat = SimpleDateFormat("yyy-MM-dd-h-mm", Locale.CANADA)
"Flipcash-Recovery-${date.format(Date())}.png"
}
)
if (result) {
mediaScanner.scan(destination)
}
result
val date: DateFormat = SimpleDateFormat("yyy-MM-dd-h-mm", Locale.CANADA)
val filename = "Flipcash-Recovery-${date.format(Date())}.png"
mediaSaver.saveBitmap(bitmap, filename)
}
}.onFailure {
getAccessKeySaveError()
Expand Down
Loading