Skip to content

Commit

Permalink
Merge pull request #1 from Itsfitts/feature/many-models
Browse files Browse the repository at this point in the history
Feature/many models
  • Loading branch information
Itsfitts authored Jan 26, 2024
2 parents 1de3a42 + 16b6653 commit 5b6c844
Show file tree
Hide file tree
Showing 51 changed files with 1,076 additions and 223 deletions.
11 changes: 8 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
namespace 'com.shifthackz.aisdv1.app'
defaultConfig {
applicationId "com.shifthackz.aisdv1.app"
versionName "0.5.3"
versionCode 166
versionName "0.5.4"
versionCode 167

buildConfigField "String", "IMAGE_CDN_URL", "\"https://random.imagecdn.app\""
buildConfigField "String", "HORDE_AI_URL", "\"https://stablehorde.net\""
Expand Down Expand Up @@ -48,9 +48,14 @@ android {
foss {
dimension "type"
applicationIdSuffix = ".foss"
resValue "string", "app_name", "SDAI"
resValue "string", "app_name", "SDAI FOSS"
buildConfigField "String", "BUILD_FLAVOR_TYPE", "\"FOSS\""
}
playstore {
dimension "type"
resValue "string", "app_name", "SDAI"
buildConfigField "String", "BUILD_FLAVOR_TYPE", "\"GOOGLE_PLAY\""
}
}
}

Expand Down
27 changes: 27 additions & 0 deletions app/src/foss/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-feature
android:name="android.hardware.camera"
android:required="false" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />

<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="31"
tools:ignore="ScopedStorage" />

<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />

</manifest>
30 changes: 2 additions & 28 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,6 @@
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-feature
android:name="android.hardware.camera"
android:required="false" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />

<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="31"
tools:ignore="ScopedStorage" />

<application
android:name=".AiStableDiffusionClientApp"
android:icon="@mipmap/ic_launcher"
Expand All @@ -34,7 +16,8 @@
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:taskAffinity=""
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
tools:ignore="LockedOrientationActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand All @@ -50,14 +33,5 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>

<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-5994265132349884~9645142847" />

<meta-data
android:name="applovin.sdk.key"
android:value="HIShVpilJ0_bWZ4mFNgLTkzJBXDODBScGQa478ynIUQut8zdD8QkhpWnWi5cdvFWNIT8gwL_TzvXzCNCTuDGm8"/>

</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.shifthackz.aisdv1.app.di.featureModule
import com.shifthackz.aisdv1.app.di.preferenceModule
import com.shifthackz.aisdv1.app.di.providersModule
import com.shifthackz.aisdv1.core.common.log.FileLoggingTree
import com.shifthackz.aisdv1.core.common.log.errorLog
import com.shifthackz.aisdv1.core.imageprocessing.di.imageProcessingModule
import com.shifthackz.aisdv1.core.validation.di.validatorsModule
import com.shifthackz.aisdv1.data.di.dataModule
Expand All @@ -25,6 +26,7 @@ class AiStableDiffusionClientApp : Application() {
override fun onCreate() {
super.onCreate()
StrictMode.setVmPolicy(VmPolicy.Builder().build())
Thread.currentThread().setUncaughtExceptionHandler { _, t -> errorLog(t) }
initializeKoin()
initializeLogging()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.shifthackz.aisdv1.app.di

import com.shifthackz.aisdv1.app.BuildConfig
import com.shifthackz.aisdv1.core.common.appbuild.BuildInfoProvider
import com.shifthackz.aisdv1.core.common.appbuild.BuildType
import com.shifthackz.aisdv1.core.common.appbuild.BuildVersion
import com.shifthackz.aisdv1.core.common.file.FileProviderDescriptor
import com.shifthackz.aisdv1.core.common.links.LinksProvider
Expand All @@ -11,6 +12,7 @@ import com.shifthackz.aisdv1.domain.feature.auth.AuthorizationStore
import com.shifthackz.aisdv1.domain.preference.PreferenceManager
import com.shifthackz.aisdv1.feature.diffusion.entity.LocalDiffusionFlag
import com.shifthackz.aisdv1.feature.diffusion.environment.DeviceNNAPIFlagProvider
import com.shifthackz.aisdv1.feature.diffusion.environment.LocalModelIdProvider
import com.shifthackz.aisdv1.network.qualifiers.ApiUrlProvider
import com.shifthackz.aisdv1.network.qualifiers.CredentialsProvider
import com.shifthackz.aisdv1.network.qualifiers.HordeApiKeyProvider
Expand Down Expand Up @@ -73,12 +75,13 @@ val providersModule = module {
override val isDebug: Boolean = BuildConfig.DEBUG
override val buildNumber: Int = BuildConfig.VERSION_CODE
override val version: BuildVersion = BuildVersion(BuildConfig.VERSION_NAME)
override val type: BuildType = BuildType.fromBuildConfig(BuildConfig.BUILD_FLAVOR_TYPE)

override fun toString(): String = buildString {
append("$version")
if (BuildConfig.DEBUG) append("-dev")
append(" ($buildNumber)")
append(" FOSS")
if (type == BuildType.FOSS) append(" FOSS")
}
}
}
Expand Down Expand Up @@ -108,4 +111,8 @@ val providersModule = module {
.let(LocalDiffusionFlag::value)
}
}

single {
LocalModelIdProvider { get<PreferenceManager>().localModelId }
}
}
23 changes: 23 additions & 0 deletions app/src/playstore/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-feature
android:name="android.hardware.camera"
android:required="false" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />

<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="31"
tools:ignore="ScopedStorage" />

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,14 @@ interface BuildInfoProvider {
val isDebug: Boolean
val buildNumber: Int
val version: BuildVersion
val type: BuildType

companion object {
val stub = object : BuildInfoProvider {
override val isDebug: Boolean = true
override val buildNumber: Int = 0
override val version: BuildVersion = BuildVersion()
override val type: BuildType = BuildType.FOSS
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.shifthackz.aisdv1.core.common.appbuild

enum class BuildType {
FOSS,
PLAY;

companion object {
fun fromBuildConfig(input: String) = when (input) {
"FOSS" -> FOSS
else -> PLAY
}
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,92 @@
package com.shifthackz.aisdv1.data.local

import com.shifthackz.aisdv1.core.common.appbuild.BuildInfoProvider
import com.shifthackz.aisdv1.core.common.appbuild.BuildType
import com.shifthackz.aisdv1.core.common.file.FileProviderDescriptor
import com.shifthackz.aisdv1.core.common.log.debugLog
import com.shifthackz.aisdv1.data.mappers.mapDomainToEntity
import com.shifthackz.aisdv1.data.mappers.mapEntityToDomain
import com.shifthackz.aisdv1.domain.datasource.DownloadableModelDataSource
import com.shifthackz.aisdv1.domain.entity.LocalAiModel
import com.shifthackz.aisdv1.domain.preference.PreferenceManager
import com.shifthackz.aisdv1.storage.db.persistent.dao.LocalModelDao
import com.shifthackz.aisdv1.storage.db.persistent.entity.LocalModelEntity
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import java.io.File

internal class DownloadableModelLocalDataSource(
private val fileProviderDescriptor: FileProviderDescriptor,
private val dao: LocalModelDao,
private val preferenceManager: PreferenceManager,
private val buildInfoProvider: BuildInfoProvider,
) : DownloadableModelDataSource.Local {
override fun getAll(): Single<List<LocalAiModel>> = dao.query()
.map(List<LocalModelEntity>::mapEntityToDomain)
.map { models ->
buildList {
addAll(models)
if (buildInfoProvider.type == BuildType.FOSS) add(LocalAiModel.CUSTOM)
}
}
.flatMap { models -> models.withLocalData() }

override fun getById(id: String): Single<LocalAiModel> {
val chain = if (id == LocalAiModel.CUSTOM.id) Single.just(LocalAiModel.CUSTOM)
else dao
.queryById(id)
.map(LocalModelEntity::mapEntityToDomain)

return chain.flatMap { model -> model.withLocalData() }
}

override fun getSelected(): Single<LocalAiModel> = Single
.just(preferenceManager.localModelId)
.flatMap(::getById)
.onErrorResumeNext { Single.error(Throwable("No selected model")) }

override fun select(id: String): Completable = Completable.fromAction {
preferenceManager.localModelId = id
}

private val localModelDirectory: File
get() = File(fileProviderDescriptor.localModelDirPath)
override fun save(list: List<LocalAiModel>) = list
.filter { it.id != LocalAiModel.CUSTOM.id }
.mapDomainToEntity()
.let(dao::insertList)

override fun exists(): Single<Boolean> = Single.create { emitter ->
override fun isDownloaded(id: String): Single<Boolean> = Single.create { emitter ->
try {
val files = (localModelDirectory.listFiles()?.filter { it.isDirectory }) ?: emptyList<File>()
if (!emitter.isDisposed) emitter.onSuccess(localModelDirectory.exists() && files.size == 4)
if (id == LocalAiModel.CUSTOM.id) {
if (!emitter.isDisposed) emitter.onSuccess(true)
} else {
val localModelDir = getLocalModelDirectory(id)
val files =
(localModelDir.listFiles()?.filter { it.isDirectory }) ?: emptyList<File>()
if (!emitter.isDisposed) emitter.onSuccess(localModelDir.exists() && files.size == 4)
}
} catch (e: Exception) {
if (!emitter.isDisposed) emitter.onSuccess(false)
}
}

override fun delete(): Completable = Completable.fromAction {
localModelDirectory.deleteRecursively()
override fun delete(id: String): Completable = Completable.fromAction {
getLocalModelDirectory(id).deleteRecursively()
}

private fun getLocalModelDirectory(id: String): File {
return File("${fileProviderDescriptor.localModelDirPath}/${id}")
}

private fun List<LocalAiModel>.withLocalData(): Single<List<LocalAiModel>> = Observable
.fromIterable(this)
.flatMapSingle { model -> model.withLocalData() }
.toList()

private fun LocalAiModel.withLocalData(): Single<LocalAiModel> = isDownloaded(id)
.map { downloaded ->
copy(
downloaded = downloaded,
selected = preferenceManager.localModelId == id,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.shifthackz.aisdv1.data.mappers

import com.shifthackz.aisdv1.domain.entity.LocalAiModel
import com.shifthackz.aisdv1.network.response.DownloadableModelResponse
import com.shifthackz.aisdv1.storage.db.persistent.entity.LocalModelEntity

//region RAW --> DOMAIN
fun List<DownloadableModelResponse>.mapRawToDomain(): List<LocalAiModel> =
map(DownloadableModelResponse::mapRawToDomain)

fun DownloadableModelResponse.mapRawToDomain(): LocalAiModel = with(this) {
LocalAiModel(
id = id ?: "",
name = name ?: "",
size = size ?: "",
sources = sources ?: emptyList(),
)
}
//endregion

//region DOMAIN --> ENTITY
fun List<LocalAiModel>.mapDomainToEntity(): List<LocalModelEntity> =
map(LocalAiModel::mapDomainToEntity)

fun LocalAiModel.mapDomainToEntity(): LocalModelEntity = with(this) {
LocalModelEntity(id, name, size, sources)
}
//endregion

//region ENTITY --> DOMAIN
fun List<LocalModelEntity>.mapEntityToDomain(): List<LocalAiModel> =
map(LocalModelEntity::mapEntityToDomain)

fun LocalModelEntity.mapEntityToDomain(): LocalAiModel = with(this) {
LocalAiModel(id, name, size, sources)
}
//endregion
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ class PreferenceManagerImpl(
.putBoolean(KEY_FORCE_SETUP_AFTER_UPDATE, value)
.apply()

override var localModelId: String
get() = preferences.getString(KEY_LOCAL_MODEL_ID, "") ?: ""
set(value) = preferences.edit()
.putString(KEY_LOCAL_MODEL_ID, value)
.apply()

override var localUseNNAPI: Boolean
get() = preferences.getBoolean(KEY_LOCAL_NN_API, false)
set(value) = preferences.edit()
Expand Down Expand Up @@ -117,6 +123,7 @@ class PreferenceManagerImpl(
private const val KEY_SERVER_SOURCE = "key_server_source"
private const val KEY_HORDE_API_KEY = "key_horde_api_key"
private const val KEY_LOCAL_NN_API = "key_local_nn_api"
private const val KEY_LOCAL_MODEL_ID = "key_local_model_id"
private const val KEY_FORCE_SETUP_AFTER_UPDATE = "force_upd_setup_v0.x.x-v0.5.3"
}
}
Loading

0 comments on commit 5b6c844

Please sign in to comment.