Skip to content

Commit

Permalink
Optimizations & refactorings galore
Browse files Browse the repository at this point in the history
  • Loading branch information
Eboreg committed Nov 3, 2023
1 parent 37a91ab commit dcf83b8
Show file tree
Hide file tree
Showing 64 changed files with 1,398 additions and 1,883 deletions.
8 changes: 3 additions & 5 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@file:Suppress("UnstableApiUsage")

import java.io.FileInputStream
import java.util.Properties

Expand Down Expand Up @@ -41,8 +39,8 @@ android {
applicationId = "us.huseli.retain"
minSdk = 26
targetSdk = targetSdk
versionCode = 3
versionName = "1.0.0-beta.3"
versionCode = 4
versionName = "1.0.0-beta.4"
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// buildConfigField("String", "dropboxAppKey", "\"${dropboxAppKey}\"")
Expand Down Expand Up @@ -168,5 +166,5 @@ dependencies {
implementation("com.dropbox.core:dropbox-core-sdk:5.4.5")

// Theme:
implementation("com.github.Eboreg:RetainTheme:2.1.0")
implementation("com.github.Eboreg:RetainTheme:2.2.1")
}
1 change: 1 addition & 0 deletions app/src/main/java/us/huseli/retain/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ object Constants {
const val DEFAULT_SFTP_BASE_DIR = ".retain"
const val IMAGE_SUBDIR = "images"
const val NAV_ARG_IMAGE_CAROUSEL_CURRENT_ID = "imageCarouselCurrentId"
const val NAV_ARG_NEW_NOTE_TYPE = "noteType"
const val NAV_ARG_NOTE_ID = "noteId"
const val PREF_DROPBOX_CREDENTIAL = "dropboxCredential"
const val PREF_MIN_COLUMN_WIDTH = "minColumnWidth"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package us.huseli.retain.data
package us.huseli.retain

import androidx.room.TypeConverter
import java.time.Instant
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package us.huseli.retain.data
package us.huseli.retain

import android.content.Context
import android.util.Log
Expand All @@ -9,13 +9,13 @@ import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import us.huseli.retain.BuildConfig
import us.huseli.retain.LogMessage
import us.huseli.retain.Logger
import us.huseli.retain.data.entities.ChecklistItem
import us.huseli.retain.data.entities.DeletedNote
import us.huseli.retain.data.entities.Image
import us.huseli.retain.data.entities.Note
import us.huseli.retain.dao.ChecklistItemDao
import us.huseli.retain.dao.ImageDao
import us.huseli.retain.dao.NoteDao
import us.huseli.retain.dataclasses.entities.ChecklistItem
import us.huseli.retain.dataclasses.entities.DeletedNote
import us.huseli.retain.dataclasses.entities.Image
import us.huseli.retain.dataclasses.entities.Note
import java.util.concurrent.Executors

@androidx.room.Database(
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/us/huseli/retain/Enums.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package us.huseli.retain

object Enums {
enum class NoteType { TEXT, CHECKLIST }

enum class Side { LEFT, RIGHT }

enum class HomeScreenViewType { LIST, GRID }

enum class SyncBackend(val displayName: String) {
NONE("None"),
NEXTCLOUD("Nextcloud"),
Expand Down
66 changes: 27 additions & 39 deletions app/src/main/java/us/huseli/retain/Functions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package us.huseli.retain
import android.content.ContentResolver
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageDecoder
import android.net.Uri
import android.os.Build
Expand All @@ -11,13 +12,11 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.core.graphics.scale
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import us.huseli.retain.Constants.ZIP_BUFFER_SIZE
import us.huseli.retain.data.entities.Image
import us.huseli.retain.dataclasses.entities.Image
import java.io.File
import java.io.FileOutputStream
import java.io.StringWriter
Expand Down Expand Up @@ -56,51 +55,36 @@ fun outlinedTextFieldColors() = OutlinedTextFieldDefaults.colors(
)


fun cleanUri(value: String): String {
val regex = Regex("^https?://.+")
if (value.isBlank()) return ""
if (!regex.matches(value)) return "https://$value".trimEnd('/')
return value.trimEnd('/')
fun String.cleanUri(): String {
if (isBlank()) return ""
if (!Regex("^https?://.+").matches(this)) return "https://$this".trimEnd('/')
return trimEnd('/')
}


@Suppress("SameReturnValue")
fun fileToImageBitmap(file: File, context: Context): ImageBitmap? {
if (file.isFile) {
Uri.fromFile(file)?.let { uri ->
val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, uri))
} else {
@Suppress("DEPRECATION")
MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
}
return bitmap?.asImageBitmap()
}
}
return null
}

fun ZipFile.readTextFile(zipEntry: ZipEntry): String {
return getInputStream(zipEntry).use { inputStream ->
val buffer = ByteArray(ZIP_BUFFER_SIZE)
val writer = StringWriter()
var length: Int

fun readTextFileFromZip(zipFile: ZipFile, zipEntry: ZipEntry): String {
val inputStream = zipFile.getInputStream(zipEntry)
val buffer = ByteArray(ZIP_BUFFER_SIZE)
val writer = StringWriter()
var length: Int
while (inputStream.read(buffer).also { length = it } > 0) {
writer.write(buffer.decodeToString(0, length))
while (inputStream.read(buffer).also { length = it } > 0) {
writer.write(buffer.decodeToString(0, length))
}
writer.toString()
}
return writer.toString()
}


fun extractFileFromZip(zipFile: ZipFile, zipEntry: ZipEntry, outfile: File) {
fun ZipFile.extractFile(zipEntry: ZipEntry, outfile: File) {
val buffer = ByteArray(ZIP_BUFFER_SIZE)

FileOutputStream(outfile).use { outputStream ->
val inputStream = zipFile.getInputStream(zipEntry)
var length: Int
while (inputStream.read(buffer).also { length = it } > 0) {
outputStream.write(buffer, 0, length)
outfile.outputStream().use { outputStream ->
getInputStream(zipEntry).use { inputStream ->
var length: Int
while (inputStream.read(buffer).also { length = it } > 0) {
outputStream.write(buffer, 0, length)
}
}
}
}
Expand All @@ -127,13 +111,14 @@ suspend fun uriToImage(context: Context, uri: Uri, noteId: UUID): Image? {
val factor = Constants.DEFAULT_MAX_IMAGE_DIMEN.toFloat() / max(bitmap.width, bitmap.height)
val width = (bitmap.width * factor).roundToInt()
val height = (bitmap.height * factor).roundToInt()

basename = "${UUID.randomUUID()}.png"
mimeType = "image/png"
finalBitmap = bitmap.scale(width = width, height = height)
imageFile = File(imageDir, basename)

withContext(Dispatchers.IO) {
FileOutputStream(imageFile).use { outputStream ->
imageFile.outputStream().use { outputStream ->
finalBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
}
}
Expand Down Expand Up @@ -168,3 +153,6 @@ fun isImageFile(filename: String): Boolean {
fun Uri.getMimeType(context: Context): String? =
if (scheme == ContentResolver.SCHEME_CONTENT) context.contentResolver.getType(this)
else Files.probeContentType(Paths.get(path))


fun File.toBitmap(): Bitmap? = takeIf { it.isFile }?.inputStream().use { BitmapFactory.decodeStream(it) }
18 changes: 6 additions & 12 deletions app/src/main/java/us/huseli/retain/Logger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.parcelize.Parcelize
import us.huseli.retaintheme.snackbar.SnackbarEngine
import java.time.Instant
import javax.inject.Singleton

Expand Down Expand Up @@ -39,19 +40,16 @@ data class LogMessage(
class Logger {
private val _logMessages = MutableSharedFlow<LogMessage?>(
replay = 500,
onBufferOverflow = BufferOverflow.DROP_OLDEST
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)
private val _snackbarMessage = MutableSharedFlow<LogMessage>(extraBufferCapacity = 5, replay = 1000)
private var _lastSnackbarMessage: LogMessage? = null

val logMessages = _logMessages.asSharedFlow()
val snackbarMessage = _snackbarMessage.asSharedFlow()
val lastSnackbarMessage: LogMessage?
get() = _lastSnackbarMessage

private fun addMessage(logMessage: LogMessage, showInSnackbar: Boolean = false) {
if (showInSnackbar) {
_snackbarMessage.tryEmit(logMessage)
when (logMessage.level) {
Log.ERROR -> SnackbarEngine.addError(logMessage.message)
else -> SnackbarEngine.addInfo(logMessage.message)
}
}
if (BuildConfig.DEBUG) {
Log.println(
Expand All @@ -64,10 +62,6 @@ class Logger {
}

fun log(logMessage: LogMessage, showInSnackbar: Boolean = false) = addMessage(logMessage, showInSnackbar)

fun setLastSnackbarMessage(logMessage: LogMessage) {
_lastSnackbarMessage = logMessage
}
}

interface LogInterface {
Expand Down
33 changes: 17 additions & 16 deletions app/src/main/java/us/huseli/retain/RetainDestinations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,11 @@ package us.huseli.retain
import androidx.navigation.NavType
import androidx.navigation.navArgument
import us.huseli.retain.Constants.NAV_ARG_IMAGE_CAROUSEL_CURRENT_ID
import us.huseli.retain.Constants.NAV_ARG_NEW_NOTE_TYPE
import us.huseli.retain.Constants.NAV_ARG_NOTE_ID
import us.huseli.retain.Enums.NoteType
import java.util.UUID

abstract class NoteDestination {
abstract val baseRoute: String
val arguments = listOf(
navArgument(NAV_ARG_NOTE_ID) { type = NavType.StringType },
)
val routeTemplate: String
get() = "$baseRoute/{$NAV_ARG_NOTE_ID}"

fun route(noteId: UUID) = "$baseRoute/$noteId"
}

object HomeDestination {
const val route = "home"
}
Expand All @@ -29,12 +20,22 @@ object DebugDestination {
const val route = "debug"
}

object TextNoteDestination : NoteDestination() {
override val baseRoute = "textNote"
}
object NoteDestination {
const val routeTemplate = "note?id={$NAV_ARG_NOTE_ID}&type={$NAV_ARG_NEW_NOTE_TYPE}"
val arguments = listOf(
navArgument(NAV_ARG_NOTE_ID) {
type = NavType.StringType
nullable = true
},
navArgument(NAV_ARG_NEW_NOTE_TYPE) {
type = NavType.StringType
nullable = true
},
)

fun route(noteId: UUID) = "note?id=$noteId"

object ChecklistNoteDestination : NoteDestination() {
override val baseRoute = "checklistNote"
fun route(newNoteType: NoteType) = "note?type=$newNoteType"
}

object ImageCarouselDestination {
Expand Down
Loading

0 comments on commit dcf83b8

Please sign in to comment.