Skip to content

Commit 88d5ec6

Browse files
authored
Web UI & Custom navigation & UX Improvements (#224)
* Web UI & custom navigation * Update * Update drawer header * Implemented Donate screen * Removed obsolete parameter
1 parent 94f07c4 commit 88d5ec6

File tree

90 files changed

+2387
-188
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+2387
-188
lines changed

core/common/src/main/java/com/shifthackz/aisdv1/core/common/extensions/DateExtensions.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.shifthackz.aisdv1.core.common.extensions
22

33
import java.text.SimpleDateFormat
4-
import java.util.*
4+
import java.util.Date
5+
import java.util.Locale
56

67
fun Date.getRawDay(): Int = SimpleDateFormat("dd", Locale.ROOT).format(this).toInt()
78

@@ -16,3 +17,19 @@ fun Date.getDayRange(): Pair<Date, Date> {
1617
val end = formatter.parse("${prefix}T23:59:59.999") ?: this
1718
return start to end
1819
}
20+
21+
fun Date.format(
22+
format: String = "yyyy-MM-dd",
23+
locale: Locale = Locale.ROOT,
24+
): String = runCatching {
25+
val df = SimpleDateFormat(format, locale)
26+
df.format(this)
27+
}.getOrDefault("")
28+
29+
fun String.toDate(
30+
format: String = "yyyy-MM-dd",
31+
locale: Locale = Locale.ROOT,
32+
): Date = runCatching {
33+
val df = SimpleDateFormat(format, locale)
34+
df.parse(this)
35+
}.getOrDefault(Date())

data/src/main/java/com/shifthackz/aisdv1/data/di/LocalDataSourceModule.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.shifthackz.aisdv1.data.local.StabilityAiCreditsLocalDataSource
1212
import com.shifthackz.aisdv1.data.local.StableDiffusionHyperNetworksLocalDataSource
1313
import com.shifthackz.aisdv1.data.local.StableDiffusionModelsLocalDataSource
1414
import com.shifthackz.aisdv1.data.local.StableDiffusionSamplersLocalDataSource
15+
import com.shifthackz.aisdv1.data.local.SupportersLocalDataSource
1516
import com.shifthackz.aisdv1.data.local.SwarmUiModelsLocalDataSource
1617
import com.shifthackz.aisdv1.domain.datasource.DownloadableModelDataSource
1718
import com.shifthackz.aisdv1.domain.datasource.EmbeddingsDataSource
@@ -23,6 +24,7 @@ import com.shifthackz.aisdv1.domain.datasource.StabilityAiCreditsDataSource
2324
import com.shifthackz.aisdv1.domain.datasource.StableDiffusionHyperNetworksDataSource
2425
import com.shifthackz.aisdv1.domain.datasource.StableDiffusionModelsDataSource
2526
import com.shifthackz.aisdv1.domain.datasource.StableDiffusionSamplersDataSource
27+
import com.shifthackz.aisdv1.domain.datasource.SupportersDataSource
2628
import com.shifthackz.aisdv1.domain.datasource.SwarmUiModelsDataSource
2729
import com.shifthackz.aisdv1.domain.gateway.DatabaseClearGateway
2830
import org.koin.android.ext.koin.androidContext
@@ -45,5 +47,6 @@ val localDataSourceModule = module {
4547
factoryOf(::GenerationResultLocalDataSource) bind GenerationResultDataSource.Local::class
4648
factoryOf(::DownloadableModelLocalDataSource) bind DownloadableModelDataSource.Local::class
4749
factoryOf(::HuggingFaceModelsLocalDataSource) bind HuggingFaceModelsDataSource.Local::class
50+
factoryOf(::SupportersLocalDataSource) bind SupportersDataSource.Local::class
4851
factory { MediaStoreGatewayFactory(androidContext(), get()).invoke() }
4952
}

data/src/main/java/com/shifthackz/aisdv1/data/di/RemoteDataSourceModule.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.shifthackz.aisdv1.data.remote.StableDiffusionHyperNetworksRemoteDataS
2020
import com.shifthackz.aisdv1.data.remote.StableDiffusionLorasRemoteDataSource
2121
import com.shifthackz.aisdv1.data.remote.StableDiffusionModelsRemoteDataSource
2222
import com.shifthackz.aisdv1.data.remote.StableDiffusionSamplersRemoteDataSource
23+
import com.shifthackz.aisdv1.data.remote.SupportersRemoteDataSource
2324
import com.shifthackz.aisdv1.data.remote.SwarmUiEmbeddingsRemoteDataSource
2425
import com.shifthackz.aisdv1.data.remote.SwarmUiGenerationRemoteDataSource
2526
import com.shifthackz.aisdv1.data.remote.SwarmUiLorasRemoteDataSource
@@ -41,6 +42,7 @@ import com.shifthackz.aisdv1.domain.datasource.StableDiffusionGenerationDataSour
4142
import com.shifthackz.aisdv1.domain.datasource.StableDiffusionHyperNetworksDataSource
4243
import com.shifthackz.aisdv1.domain.datasource.StableDiffusionModelsDataSource
4344
import com.shifthackz.aisdv1.domain.datasource.StableDiffusionSamplersDataSource
45+
import com.shifthackz.aisdv1.domain.datasource.SupportersDataSource
4446
import com.shifthackz.aisdv1.domain.datasource.SwarmUiGenerationDataSource
4547
import com.shifthackz.aisdv1.domain.datasource.SwarmUiModelsDataSource
4648
import com.shifthackz.aisdv1.domain.datasource.SwarmUiSessionDataSource
@@ -87,6 +89,7 @@ val remoteDataSourceModule = module {
8789
factoryOf(::ServerConfigurationRemoteDataSource) bind ServerConfigurationDataSource.Remote::class
8890
factoryOf(::RandomImageRemoteDataSource) bind RandomImageDataSource.Remote::class
8991
factoryOf(::DownloadableModelRemoteDataSource) bind DownloadableModelDataSource.Remote::class
92+
factoryOf(::SupportersRemoteDataSource) bind SupportersDataSource.Remote::class
9093
factoryOf(::HuggingFaceModelsRemoteDataSource) bind HuggingFaceModelsDataSource.Remote::class
9194
factoryOf(::StabilityAiGenerationRemoteDataSource) bind StabilityAiGenerationDataSource.Remote::class
9295
factoryOf(::StabilityAiCreditsRemoteDataSource) bind StabilityAiCreditsDataSource.Remote::class

data/src/main/java/com/shifthackz/aisdv1/data/di/RepositoryModule.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.shifthackz.aisdv1.data.repository.StableDiffusionGenerationRepository
2020
import com.shifthackz.aisdv1.data.repository.StableDiffusionHyperNetworksRepositoryImpl
2121
import com.shifthackz.aisdv1.data.repository.StableDiffusionModelsRepositoryImpl
2222
import com.shifthackz.aisdv1.data.repository.StableDiffusionSamplersRepositoryImpl
23+
import com.shifthackz.aisdv1.data.repository.SupportersRepositoryImpl
2324
import com.shifthackz.aisdv1.data.repository.SwarmUiGenerationRepositoryImpl
2425
import com.shifthackz.aisdv1.data.repository.SwarmUiModelsRepositoryImpl
2526
import com.shifthackz.aisdv1.data.repository.TemporaryGenerationResultRepositoryImpl
@@ -42,6 +43,7 @@ import com.shifthackz.aisdv1.domain.repository.StableDiffusionGenerationReposito
4243
import com.shifthackz.aisdv1.domain.repository.StableDiffusionHyperNetworksRepository
4344
import com.shifthackz.aisdv1.domain.repository.StableDiffusionModelsRepository
4445
import com.shifthackz.aisdv1.domain.repository.StableDiffusionSamplersRepository
46+
import com.shifthackz.aisdv1.domain.repository.SupportersRepository
4547
import com.shifthackz.aisdv1.domain.repository.SwarmUiGenerationRepository
4648
import com.shifthackz.aisdv1.domain.repository.SwarmUiModelsRepository
4749
import com.shifthackz.aisdv1.domain.repository.TemporaryGenerationResultRepository
@@ -80,4 +82,5 @@ val repositoryModule = module {
8082
factoryOf(::RandomImageRepositoryImpl) bind RandomImageRepository::class
8183
factoryOf(::DownloadableModelRepositoryImpl) bind DownloadableModelRepository::class
8284
factoryOf(::HuggingFaceModelsRepositoryImpl) bind HuggingFaceModelsRepository::class
85+
factoryOf(::SupportersRepositoryImpl) bind SupportersRepository::class
8386
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.shifthackz.aisdv1.data.local
2+
3+
import com.shifthackz.aisdv1.data.mappers.mapDomainToEntity
4+
import com.shifthackz.aisdv1.data.mappers.mapEntityToDomain
5+
import com.shifthackz.aisdv1.domain.datasource.SupportersDataSource
6+
import com.shifthackz.aisdv1.domain.entity.Supporter
7+
import com.shifthackz.aisdv1.storage.db.persistent.dao.SupporterDao
8+
import com.shifthackz.aisdv1.storage.db.persistent.entity.SupporterEntity
9+
import io.reactivex.rxjava3.core.Completable
10+
import io.reactivex.rxjava3.core.Single
11+
12+
internal class SupportersLocalDataSource(
13+
private val dao: SupporterDao,
14+
) : SupportersDataSource.Local {
15+
16+
override fun save(data: List<Supporter>): Completable = dao
17+
.deleteAll()
18+
.andThen(dao.insertList(data.mapDomainToEntity()))
19+
20+
override fun getAll(): Single<List<Supporter>> = dao
21+
.queryAll()
22+
.map(List<SupporterEntity>::mapEntityToDomain)
23+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.shifthackz.aisdv1.data.mappers
2+
3+
import com.shifthackz.aisdv1.core.common.extensions.toDate
4+
import com.shifthackz.aisdv1.domain.entity.Supporter
5+
import com.shifthackz.aisdv1.network.model.SupporterRaw
6+
import com.shifthackz.aisdv1.storage.db.persistent.entity.SupporterEntity
7+
import java.util.Date
8+
9+
//region RAW --> DOMAIN
10+
fun List<SupporterRaw>.mapRawToDomain(): List<Supporter> = map(SupporterRaw::mapRawToDomain)
11+
12+
fun SupporterRaw.mapRawToDomain(): Supporter = with(this) {
13+
Supporter(
14+
id = id ?: -1,
15+
name = name ?: "",
16+
date = date?.toDate() ?: Date(),
17+
message = message ?: "",
18+
)
19+
}
20+
//endregion
21+
22+
//region DOMAIN --> ENTITY
23+
fun List<Supporter>.mapDomainToEntity(): List<SupporterEntity> = map(Supporter::mapDomainToEntity)
24+
25+
fun Supporter.mapDomainToEntity(): SupporterEntity = with(this) {
26+
SupporterEntity(
27+
id = id,
28+
name = name,
29+
date = date,
30+
message = message,
31+
)
32+
}
33+
//endregion
34+
35+
//region ENTITY --> DOMAIN
36+
fun List<SupporterEntity>.mapEntityToDomain(): List<Supporter> = map(SupporterEntity::mapEntityToDomain)
37+
38+
fun SupporterEntity.mapEntityToDomain(): Supporter = with(this) {
39+
Supporter(
40+
id = id,
41+
name = name,
42+
date = date,
43+
message = message,
44+
)
45+
}
46+
//endregion

data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.shifthackz.aisdv1.core.common.extensions.fixUrlSlashes
55
import com.shifthackz.aisdv1.core.common.extensions.shouldUseNewMediaStore
66
import com.shifthackz.aisdv1.domain.entity.ColorToken
77
import com.shifthackz.aisdv1.domain.entity.DarkThemeToken
8+
import com.shifthackz.aisdv1.domain.entity.FeatureTag
89
import com.shifthackz.aisdv1.domain.entity.HuggingFaceModel
910
import com.shifthackz.aisdv1.domain.entity.ServerSource
1011
import com.shifthackz.aisdv1.domain.entity.Settings
@@ -50,7 +51,7 @@ class PreferenceManagerImpl(
5051
.also { onPreferencesChanged() }
5152

5253
override var monitorConnectivity: Boolean
53-
get() = if (source != ServerSource.AUTOMATIC1111) false
54+
get() = if (!source.featureTags.contains(FeatureTag.OwnServer)) false
5455
else preferences.getBoolean(KEY_MONITOR_CONNECTIVITY, true)
5556
set(value) = preferences.edit()
5657
.putBoolean(KEY_MONITOR_CONNECTIVITY, value)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.shifthackz.aisdv1.data.remote
2+
3+
import com.shifthackz.aisdv1.data.mappers.mapRawToDomain
4+
import com.shifthackz.aisdv1.domain.datasource.SupportersDataSource
5+
import com.shifthackz.aisdv1.domain.entity.Supporter
6+
import com.shifthackz.aisdv1.network.api.sdai.DonateApi
7+
import com.shifthackz.aisdv1.network.model.SupporterRaw
8+
import io.reactivex.rxjava3.core.Single
9+
10+
internal class SupportersRemoteDataSource(
11+
private val api: DonateApi,
12+
) : SupportersDataSource.Remote {
13+
14+
override fun fetch(): Single<List<Supporter>> = api
15+
.fetchSupporters()
16+
.map(List<SupporterRaw>::mapRawToDomain)
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.shifthackz.aisdv1.data.repository
2+
3+
import com.shifthackz.aisdv1.domain.datasource.SupportersDataSource
4+
import com.shifthackz.aisdv1.domain.entity.Supporter
5+
import com.shifthackz.aisdv1.domain.repository.SupportersRepository
6+
import io.reactivex.rxjava3.core.Completable
7+
import io.reactivex.rxjava3.core.Single
8+
9+
internal class SupportersRepositoryImpl(
10+
private val rds: SupportersDataSource.Remote,
11+
private val lds: SupportersDataSource.Local,
12+
) : SupportersRepository {
13+
14+
override fun fetchSupporters(): Completable = rds
15+
.fetch()
16+
.flatMapCompletable(lds::save)
17+
18+
override fun fetchAndGetSupporters(): Single<List<Supporter>> = fetchSupporters()
19+
.onErrorComplete()
20+
.andThen(getSupporters())
21+
22+
override fun getSupporters(): Single<List<Supporter>> = lds.getAll()
23+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.shifthackz.aisdv1.data.local
2+
3+
import com.shifthackz.aisdv1.data.mocks.mockSupporterEntities
4+
import com.shifthackz.aisdv1.data.mocks.mockSupporters
5+
import com.shifthackz.aisdv1.storage.db.persistent.dao.SupporterDao
6+
import io.mockk.every
7+
import io.mockk.mockk
8+
import io.reactivex.rxjava3.core.Completable
9+
import io.reactivex.rxjava3.core.Single
10+
import org.junit.Test
11+
12+
class SupportersLocalDataSourceTest {
13+
14+
private val stubException = Throwable("Database error.")
15+
private val stubDao = mockk<SupporterDao>()
16+
17+
private val localDataSource = SupportersLocalDataSource(stubDao)
18+
19+
@Test
20+
fun `given attempt to get supporters, dao returns list, expected valid domain model list value`() {
21+
every {
22+
stubDao.queryAll()
23+
} returns Single.just(mockSupporterEntities)
24+
25+
localDataSource
26+
.getAll()
27+
.test()
28+
.assertNoErrors()
29+
.assertValue { mockSupporters.size == it.size }
30+
.await()
31+
.assertComplete()
32+
}
33+
34+
@Test
35+
fun `given attempt to get supporters, dao returns empty list, expected empty domain model list value`() {
36+
every {
37+
stubDao.queryAll()
38+
} returns Single.just(emptyList())
39+
40+
localDataSource
41+
.getAll()
42+
.test()
43+
.assertNoErrors()
44+
.assertValue(emptyList())
45+
.await()
46+
.assertComplete()
47+
}
48+
49+
@Test
50+
fun `given attempt to get supporters, dao throws exception, expected error value`() {
51+
every {
52+
stubDao.queryAll()
53+
} returns Single.error(stubException)
54+
55+
localDataSource
56+
.getAll()
57+
.test()
58+
.assertError(stubException)
59+
.assertNoValues()
60+
.await()
61+
.assertNotComplete()
62+
}
63+
64+
@Test
65+
fun `given attempt to insert supporters, dao replaces list, expected complete value`() {
66+
every {
67+
stubDao.deleteAll()
68+
} returns Completable.complete()
69+
70+
every {
71+
stubDao.insertList(any())
72+
} returns Completable.complete()
73+
74+
localDataSource
75+
.save(mockSupporters)
76+
.test()
77+
.assertNoErrors()
78+
.await()
79+
.assertComplete()
80+
}
81+
82+
@Test
83+
fun `given attempt to insert supporters, dao throws exception during delete, expected error value`() {
84+
every {
85+
stubDao.deleteAll()
86+
} returns Completable.error(stubException)
87+
88+
every {
89+
stubDao.insertList(any())
90+
} returns Completable.complete()
91+
92+
localDataSource
93+
.save(mockSupporters)
94+
.test()
95+
.assertError(stubException)
96+
.await()
97+
.assertNotComplete()
98+
}
99+
100+
@Test
101+
fun `given attempt to insert supporters, dao throws exception during insertion, expected error value`() {
102+
every {
103+
stubDao.deleteAll()
104+
} returns Completable.complete()
105+
106+
every {
107+
stubDao.insertList(any())
108+
} returns Completable.error(stubException)
109+
110+
localDataSource
111+
.save(mockSupporters)
112+
.test()
113+
.assertError(stubException)
114+
.await()
115+
.assertNotComplete()
116+
}
117+
}

0 commit comments

Comments
 (0)