Skip to content

Commit 1304e43

Browse files
committed
Tags search and other improvements
1 parent 0583466 commit 1304e43

File tree

46 files changed

+837
-67
lines changed

Some content is hidden

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

46 files changed

+837
-67
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,14 @@
2424
<category android:name="android.intent.category.LAUNCHER" />
2525
</intent-filter>
2626
</activity>
27+
<provider
28+
android:name="androidx.core.content.FileProvider"
29+
android:authorities="${applicationId}.fileprovider"
30+
android:exported="false"
31+
android:grantUriPermissions="true">
32+
<meta-data
33+
android:name="android.support.FILE_PROVIDER_PATHS"
34+
android:resource="@xml/file_provider_paths" />
35+
</provider>
2736
</application>
2837
</manifest>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<paths>
3+
<cache-path
4+
name="folder_images"
5+
path="images/" />
6+
7+
<cache-path
8+
name="folder_logs"
9+
path="logs/" />
10+
11+
<external-path name="media" path="." />
12+
<external-path name="external_files" path="."/>
13+
<external-path name="external" path="."/>
14+
</paths>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.shifthackz.joyreactor.data.datasource.local
2+
3+
import com.shifthackz.joyreactor.data.mappers.toDomain
4+
import com.shifthackz.joyreactor.data.mappers.toEntity
5+
import com.shifthackz.joyreactor.domain.datasource.TagsDataSource
6+
import com.shifthackz.joyreactor.entity.Tag
7+
import com.shifthackz.joyreactor.storage.db.dao.TagDao
8+
import com.shifthackz.joyreactor.storage.db.entity.TagEntity
9+
10+
internal class TagsLocalDataSource(
11+
private val tagDao: TagDao,
12+
) : TagsDataSource.Local {
13+
14+
override suspend fun saveTags(tags: List<Tag>) {
15+
return tagDao.upsertList(tags.map(Tag::toEntity))
16+
}
17+
18+
override suspend fun searchTags(query: String): Result<List<Tag>> {
19+
return tagDao
20+
.search(query)
21+
.map(TagEntity::toDomain)
22+
.let(Result.Companion::success)
23+
}
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.shifthackz.joyreactor.data.datasource.remote
2+
3+
import com.shifthackz.joyreactor.domain.datasource.TagsDataSource
4+
import com.shifthackz.joyreactor.entity.PagePayload
5+
import com.shifthackz.joyreactor.entity.Tag
6+
import com.shifthackz.joyreactor.network.ApiImpl
7+
import com.shifthackz.joyreactor.network.parser.TagsParser
8+
9+
internal class TagsRemoteDataSource(
10+
private val tagsParser: TagsParser,
11+
private val api: ApiImpl,
12+
) : TagsDataSource.Remote {
13+
14+
override suspend fun fetchPage(url: String): Result<PagePayload<Tag>> {
15+
return tagsParser.fetchTags(url)
16+
}
17+
18+
override suspend fun searchTags(query: String): Result<List<Tag>> {
19+
return api.searchTag(query).let {
20+
Result.success(it.map {
21+
Tag(it, "https://joyreactor.cc/tag/$it", "")
22+
})
23+
} ?: Result.success(emptyList())
24+
}
25+
}

data/src/main/java/com/shifthackz/joyreactor/data/di/Modules.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package com.shifthackz.joyreactor.data.di
22

33
import com.shifthackz.joyreactor.data.datasource.local.PostsLocalDataSource
4+
import com.shifthackz.joyreactor.data.datasource.local.TagsLocalDataSource
45
import com.shifthackz.joyreactor.data.datasource.remote.CommentsRemoteDataSource
56
import com.shifthackz.joyreactor.data.datasource.remote.PostsRemoteDataSource
67
import com.shifthackz.joyreactor.data.datasource.remote.SectionsRemoteDataSource
8+
import com.shifthackz.joyreactor.data.datasource.remote.TagsRemoteDataSource
79
import com.shifthackz.joyreactor.data.repository.CommentsRepositoryImpl
810
import com.shifthackz.joyreactor.data.repository.PostsRepositoryImpl
911
import com.shifthackz.joyreactor.data.repository.SectionsRepositoryImpl
12+
import com.shifthackz.joyreactor.data.repository.TagsRepositoryImpl
1013
import com.shifthackz.joyreactor.domain.datasource.CommentsDataSource
1114
import com.shifthackz.joyreactor.domain.datasource.PostsDataSource
1215
import com.shifthackz.joyreactor.domain.datasource.SectionsDataSource
16+
import com.shifthackz.joyreactor.domain.datasource.TagsDataSource
1317
import com.shifthackz.joyreactor.domain.repository.CommentsRepository
1418
import com.shifthackz.joyreactor.domain.repository.PostsRepository
1519
import com.shifthackz.joyreactor.domain.repository.SectionsRepository
20+
import com.shifthackz.joyreactor.domain.repository.TagsRepository
1621
import org.koin.core.module.dsl.factoryOf
1722
import org.koin.dsl.bind
1823
import org.koin.dsl.module
@@ -21,16 +26,19 @@ internal val remoteDataSourceModule = module {
2126
factoryOf(::PostsRemoteDataSource) bind PostsDataSource.Remote::class
2227
factoryOf(::CommentsRemoteDataSource) bind CommentsDataSource.Remote::class
2328
factoryOf(::SectionsRemoteDataSource) bind SectionsDataSource.Remote::class
29+
factoryOf(::TagsRemoteDataSource) bind TagsDataSource.Remote::class
2430
}
2531

2632
internal val localDataSourceModule = module {
2733
factoryOf(::PostsLocalDataSource) bind PostsDataSource.Local::class
34+
factoryOf(::TagsLocalDataSource) bind TagsDataSource.Local::class
2835
}
2936

3037
internal val repositoryModule = module {
3138
factoryOf(::PostsRepositoryImpl) bind PostsRepository::class
3239
factoryOf(::CommentsRepositoryImpl) bind CommentsRepository::class
3340
factoryOf(::SectionsRepositoryImpl) bind SectionsRepository::class
41+
factoryOf(::TagsRepositoryImpl) bind TagsRepository::class
3442
}
3543

3644
val dataModule = (remoteDataSourceModule + localDataSourceModule + repositoryModule).toTypedArray()

data/src/main/java/com/shifthackz/joyreactor/data/mappers/TagMapers.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ fun Tag.toEntity(): TagEntity = with(this) {
77
TagEntity(
88
name = name,
99
url = url,
10+
imageUrl = imageUrl,
1011
)
1112
}
1213

1314
fun TagEntity.toDomain(): Tag = with(this) {
1415
Tag(
1516
name = name,
1617
url = url,
18+
imageUrl = imageUrl,
1719
)
1820
}

data/src/main/java/com/shifthackz/joyreactor/data/repository/PostsRepositoryImpl.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ class PostsRepositoryImpl(
1212
) : PostsRepository {
1313

1414
override suspend fun fetchPage(url: String): Result<PagePayload<Post>> = coroutineScope {
15-
return@coroutineScope postsRds.fetchPage(url).getOrNull()?.let {
16-
postsLds.savePosts(it.data)
17-
Result.success(it)
18-
} ?: Result.failure(IllegalStateException())
15+
postsRds.fetchPage(url).fold(
16+
onSuccess = {
17+
postsLds.savePosts(it.data)
18+
Result.success(it)
19+
},
20+
onFailure = { Result.failure(it) },
21+
)
1922
}
2023

2124
override suspend fun getPost(id: String): Result<Post> {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.shifthackz.joyreactor.data.repository
2+
3+
import com.shifthackz.joyreactor.domain.datasource.TagsDataSource
4+
import com.shifthackz.joyreactor.domain.repository.TagsRepository
5+
import com.shifthackz.joyreactor.entity.PagePayload
6+
import com.shifthackz.joyreactor.entity.Tag
7+
import kotlinx.coroutines.coroutineScope
8+
9+
internal class TagsRepositoryImpl(
10+
private val tagsRds: TagsDataSource.Remote,
11+
private val tagsLds: TagsDataSource.Local,
12+
) : TagsRepository {
13+
14+
override suspend fun fetchPage(url: String): Result<PagePayload<Tag>> = coroutineScope {
15+
tagsRds.fetchPage(url).fold(
16+
onSuccess = {
17+
tagsLds.saveTags(it.data)
18+
Result.success(it)
19+
},
20+
onFailure = Result.Companion::failure,
21+
)
22+
}
23+
24+
override suspend fun search(query: String): Result<List<Tag>> = coroutineScope {
25+
val remoteTags = tagsRds.searchTags(query).getOrThrow()
26+
val localTags = tagsLds.searchTags(query).getOrThrow()
27+
Result.success(listOf(remoteTags, localTags).flatten())
28+
}
29+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.shifthackz.joyreactor.domain.datasource
2+
3+
import com.shifthackz.joyreactor.entity.PagePayload
4+
import com.shifthackz.joyreactor.entity.Tag
5+
6+
sealed interface TagsDataSource {
7+
8+
interface Remote : TagsDataSource {
9+
suspend fun fetchPage(url: String): Result<PagePayload<Tag>>
10+
suspend fun searchTags(query: String): Result<List<Tag>>
11+
}
12+
13+
interface Local : TagsDataSource {
14+
suspend fun saveTags(tags: List<Tag>)
15+
suspend fun searchTags(query: String): Result<List<Tag>>
16+
}
17+
}

domain/src/main/java/com/shifthackz/joyreactor/domain/di/Modules.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import com.shifthackz.joyreactor.domain.usecase.post.GetFullPostUseCase
88
import com.shifthackz.joyreactor.domain.usecase.post.GetFullPostUseCaseImpl
99
import com.shifthackz.joyreactor.domain.usecase.sections.FetchSectionsUseCase
1010
import com.shifthackz.joyreactor.domain.usecase.sections.FetchSectionsUseCaseImpl
11+
import com.shifthackz.joyreactor.domain.usecase.tags.FetchTagsUseCase
12+
import com.shifthackz.joyreactor.domain.usecase.tags.FetchTagsUseCaseImpl
13+
import com.shifthackz.joyreactor.domain.usecase.tags.SearchTagsUseCase
14+
import com.shifthackz.joyreactor.domain.usecase.tags.SearchTagsUseCaseImpl
1115
import org.koin.core.module.dsl.factoryOf
1216
import org.koin.dsl.bind
1317
import org.koin.dsl.module
@@ -17,4 +21,6 @@ val domainModule = module {
1721
factoryOf(::GetFullPostUseCaseImpl) bind GetFullPostUseCase::class
1822
factoryOf(::FetchPostCommentsUseCaseImpl) bind FetchPostCommentsUseCase::class
1923
factoryOf(::FetchSectionsUseCaseImpl) bind FetchSectionsUseCase::class
24+
factoryOf(::FetchTagsUseCaseImpl) bind FetchTagsUseCase::class
25+
factoryOf(::SearchTagsUseCaseImpl) bind SearchTagsUseCase::class
2026
}

0 commit comments

Comments
 (0)