Skip to content

Commit

Permalink
Merge branch 'develop' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxBQb committed Jun 3, 2022
2 parents c31230e + 45d02df commit 314e037
Show file tree
Hide file tree
Showing 79 changed files with 1,015 additions and 957 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,4 @@ fabric.properties

# End of https://www.toptal.com/developers/gitignore/api/android,androidstudio,kotlin,windows
/keystore.properties
/app/release/
17 changes: 17 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ android {
// Google Client ID
buildConfigField "String", "GOOGLE_CLIENT_ID", keystoreProperties["GOOGLE_CLIENT_ID"]

// MasterKey for encrypted SharedPreference
buildConfigField "String", "SECURE_PREFS_MASTER_KEY", keystoreProperties["SECURE_PREFS_MASTER_KEY"]

// URL for main API
buildConfigField "String", "DARK_API_URL", keystoreProperties["DARK_API_URL"]

Expand Down Expand Up @@ -54,6 +57,9 @@ android {
freeCompilerArgs += "-Xcontext-receivers"
}
applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "DarkApp.apk"
}
variant.sourceSets.java.each {
it.srcDirs += "build/generated/ksp/${variant.name}/kotlin"
}
Expand Down Expand Up @@ -134,6 +140,17 @@ dependencies {
// Desugaring (Time-related features support for API 21+)
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'

// Images with Glide
def glide_version = "4.13.0"
implementation "com.github.bumptech.glide:glide:$glide_version"
annotationProcessor "com.github.bumptech.glide:compiler:$glide_version"
implementation "com.github.bumptech.glide:okhttp3-integration:4.11.0"
implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {
// Excludes the support library because it's already included by Glide.
transitive = false
}
kapt "com.github.bumptech.glide:compiler:$glide_version"

// Tests
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/lab/maxb/dark/domain/model/AuthCredentials.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lab.maxb.dark.domain.model

data class AuthCredentials(
val login: String,
val password: String? = null,
val initial: Boolean = false,
)

data class ReceivedAuthCredentials(
val token: String,
val id: String,
val role: Role,
val request: AuthCredentials,
)
8 changes: 0 additions & 8 deletions app/src/main/java/lab/maxb/dark/domain/model/Image.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import lab.maxb.dark.domain.operations.randomUUID

open class RecognitionTask(
open var names: Set<String>? = null,
open var images: List<Image>? = null,
open var images: List<String>? = null,
open var owner: User? = null,
open var reviewed: Boolean = false,
open var id: String = randomUUID,
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/lab/maxb/dark/domain/operations/Credentials.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lab.maxb.dark.domain.operations

import lab.maxb.dark.domain.model.Profile
import lab.maxb.dark.domain.model.ReceivedAuthCredentials
import lab.maxb.dark.domain.model.User

inline fun ReceivedAuthCredentials.toProfile(
user: (String) -> User? = { null },
) = Profile(
request.login,
user(id),
token,
role = role
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package lab.maxb.dark.domain.operations

import lab.maxb.dark.domain.model.Image
import lab.maxb.dark.domain.model.RecognitionTask
import lab.maxb.dark.domain.model.User

Expand All @@ -18,7 +17,7 @@ fun createRecognitionTask(

return RecognitionTask(
namesSet,
images.map { Image(it) },
images,
owner,
)
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/lab/maxb/dark/domain/operations/Source.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package lab.maxb.dark.domain.operations

typealias ValSource<T> = (String) -> T?
91 changes: 6 additions & 85 deletions app/src/main/java/lab/maxb/dark/presentation/extra/ImageHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,31 @@ package lab.maxb.dark.presentation.extra

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.koin.core.annotation.Single

private fun getContentResolver(context: Context) = context.applicationContext.contentResolver

private fun bitmapFromUri(uri: Uri,
context: Context,
opts: BitmapFactory.Options): Bitmap?
= BitmapFactory.decodeFileDescriptor(
getContentResolver(context).openFileDescriptor(
uri, "r"
)?.fileDescriptor,
null,
opts
)
@GlideModule
class MyAppGlideModule : AppGlideModule()

fun Uri.takePersistablePermission(context: Context) {
getContentResolver(context).takePersistableUriPermission(this,
context.applicationContext.contentResolver.takePersistableUriPermission(this,
Intent.FLAG_GRANT_READ_URI_PERMISSION)
}

fun Uri.toBitmap(
context: Context,
reqWidth: Int,
reqHeight: Int
): Bitmap?
// First decode with inJustDecodeBounds=true to check dimensions
= try {BitmapFactory.Options().run {
inJustDecodeBounds = true
bitmapFromUri(this@toBitmap, context, this)

// Calculate inSampleSize
inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)

// Decode bitmap with inSampleSize set
inJustDecodeBounds = false

bitmapFromUri(this@toBitmap, context, this) ?: return null
}} catch (exception: Throwable) { null }

private fun calculateInSampleSize(options: BitmapFactory.Options,
reqWidth: Int,
reqHeight: Int): Int {
// Raw height and width of image
val (height: Int, width: Int) = options.run {
outHeight to outWidth
}
var inSampleSize = 1

if (height > reqHeight || width > reqWidth) {

val halfHeight: Int = height / 2
val halfWidth: Int = width / 2

// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2
}
}

return inSampleSize
}

@Single
class ImageLoader(context: Context) {
private var context = context.applicationContext

suspend fun fromUri(uri: Uri): MultipartBody.Part = withContext(Dispatchers.IO) {
val contentResolver = getContentResolver(context)
val contentResolver = context.applicationContext.contentResolver
val content = contentResolver.openInputStream(uri)!!.readBytes()
return@withContext MultipartBody.Part.createFormData(
"file",
Expand All @@ -90,30 +37,4 @@ class ImageLoader(context: Context) {
)
)
}

suspend fun fromResponse(body: ResponseBody?, filename: String): String {
body ?: return ""

val path = "image_$filename"

return withContext(Dispatchers.IO) {
try {
body.byteStream().use { input ->
context.openFileOutput(path, Context.MODE_PRIVATE).use { output ->
val buffer = ByteArray(4 * 1024)
var read: Int
while (input.read(buffer).also { read = it } != -1)
output.write(buffer, 0, read)
output.flush()
}
}
return@withContext Uri.fromFile(
context.getFileStreamPath(path)
).toString()
} catch (e: Exception){
e.printStackTrace()
}
""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.lifecycle.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext
Expand Down
25 changes: 4 additions & 21 deletions app/src/main/java/lab/maxb/dark/presentation/extra/UserSettings.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
package lab.maxb.dark.presentation.extra

import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import lab.maxb.dark.presentation.extra.delegates.property
import org.koin.core.annotation.Single

@Single
class UserSettings(context: Context) {
private val pref = PreferenceManager.getDefaultSharedPreferences(context)
private val securePref: SharedPreferences = EncryptedSharedPreferences.create(
context,
"secure_dark_preferences",
MasterKey.Builder(context).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build(),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
var token: String by securePref.property()
var login: String by pref.property()
}
interface UserSettings {
var token: String
var login: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package lab.maxb.dark.presentation.extra

import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import lab.maxb.dark.BuildConfig
import lab.maxb.dark.presentation.extra.delegates.property
import org.koin.core.annotation.Single

@Single
class UserSettingsImpl(context: Context) : UserSettings {
private val pref = PreferenceManager.getDefaultSharedPreferences(context)
private val securePref: SharedPreferences = EncryptedSharedPreferences.create(
context,
"secure_dark.preferences",
MasterKey.Builder(context, BuildConfig.SECURE_PREFS_MASTER_KEY)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build(),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
override var token: String by securePref.property()
override var login: String by pref.property()
}

This file was deleted.

Loading

0 comments on commit 314e037

Please sign in to comment.