Skip to content

Commit 1f80313

Browse files
Merge pull request #51 from danishjamal104/impl-file-search-by-name
2 parents 4279400 + e6e9ac2 commit 1f80313

File tree

14 files changed

+258
-26
lines changed

14 files changed

+258
-26
lines changed

app/src/main/java/com/github/code/gambit/data/remote/NetworkDataSource.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.github.code.gambit.data.model.User
66

77
interface NetworkDataSource {
88
suspend fun getFiles(): List<File>
9+
suspend fun searchFiles(searchParam: String): List<File>
910
suspend fun uploadFile(file: File): File
1011
suspend fun deleteFile(fileId: String): File
1112

app/src/main/java/com/github/code/gambit/data/remote/NetworkDataSourceImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ class NetworkDataSourceImpl(
2323
return fileNetworkMapper.mapFromEntityList(fileService.getFiles())
2424
}
2525

26+
override suspend fun searchFiles(searchParam: String): List<File> {
27+
return fileNetworkMapper.mapFromEntityList(fileService.searchFile(searchParam))
28+
}
29+
2630
override suspend fun uploadFile(file: File): File {
2731
return fileNetworkMapper.mapFromEntity(fileService.uploadFile(fileNetworkMapper.mapToEntity(file)))
2832
}

app/src/main/java/com/github/code/gambit/data/remote/services/ApiService.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ interface ApiService {
2626
suspend fun deleteUser(@Path("userId") userId: String): Response<UserNetworkEntity>
2727

2828
@GET("user/{${AppConstant.API_PATH.USER_ID}}/file")
29-
suspend fun getFiles(@Path("userId") userId: String, @Query(AppConstant.API_QUERY.FILE_LEK) lastEvalKey: String): ListResponse<FileNetworkEntity>
29+
suspend fun getFiles(
30+
@Path("userId") userId: String,
31+
@Query(AppConstant.API_QUERY.FILE_LEK) lastEvalKey: String?,
32+
@Query(AppConstant.API_QUERY.FILE_SEARCH) searchParam: String?
33+
): ListResponse<FileNetworkEntity>
3034

3135
@GET("user/{${AppConstant.API_PATH.USER_ID}}/file")
3236
suspend fun getFiles(@Path("userId") userId: String): ListResponse<FileNetworkEntity>

app/src/main/java/com/github/code/gambit/data/remote/services/file/FileService.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.github.code.gambit.data.entity.network.FileNetworkEntity
55
interface FileService {
66

77
suspend fun getFiles(): List<FileNetworkEntity>
8+
suspend fun searchFile(searchParam: String): List<FileNetworkEntity>
89
suspend fun uploadFile(fileNetworkEntity: FileNetworkEntity): FileNetworkEntity
910
suspend fun deleteFile(fileId: String): FileNetworkEntity
1011
}

app/src/main/java/com/github/code/gambit/data/remote/services/file/FileServiceImpl.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ class FileServiceImpl(
1616

1717
override suspend fun getFiles(): List<FileNetworkEntity> {
1818
val lek: String = lekManager.getLastEvalKey(LastEvaluatedKeyManager.KeyType.FILE)
19-
val listResponse: ListResponse<FileNetworkEntity> = if (lek == "") {
20-
apiService.getFiles(userId)
21-
} else {
22-
apiService.getFiles(userId, lek)
23-
}
19+
val listResponse: ListResponse<FileNetworkEntity> = apiService.getFiles(userId, lek, null)
2420
if (listResponse.body.lastEvaluatedKey != null) {
2521
lekManager.putLastEvalKey(
2622
listResponse.body.lastEvaluatedKey!!,
@@ -30,6 +26,11 @@ class FileServiceImpl(
3026
return listResponse.body.items
3127
}
3228

29+
override suspend fun searchFile(searchParam: String): List<FileNetworkEntity> {
30+
val response = apiService.getFiles(userId, null, searchParam)
31+
return response.body.items
32+
}
33+
3334
override suspend fun uploadFile(fileNetworkEntity: FileNetworkEntity): FileNetworkEntity {
3435
return apiService.uploadFiles(userId, fileNetworkEntity).body
3536
}

app/src/main/java/com/github/code/gambit/repositories/HomeRepository.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.Flow
88
interface HomeRepository {
99

1010
suspend fun getFiles(): Flow<ServiceResult<List<File>>>
11+
suspend fun searchFile(searchString: String): Flow<ServiceResult<List<File>>>
1112
suspend fun generateUrl(file: File): Flow<ServiceResult<Url>>
1213
suspend fun getUrls(fileId: String): Flow<ServiceResult<List<Url>>>
1314
}

app/src/main/java/com/github/code/gambit/repositories/HomeRepositoryImpl.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ constructor(
3333
}
3434
}
3535

36+
override suspend fun searchFile(searchString: String): Flow<ServiceResult<List<File>>> {
37+
return flow {
38+
try {
39+
val data = networkDataSource.searchFiles(searchString)
40+
emit(ServiceResult.Success(data))
41+
} catch (internet: NoInternetException) {
42+
emit(ServiceResult.Error(internet))
43+
} catch (exception: Exception) {
44+
emit(ServiceResult.Error(exception))
45+
}
46+
}
47+
}
48+
3649
override suspend fun generateUrl(file: File): Flow<ServiceResult<Url>> {
3750
val url = Url("", file.id, file.hash, "", true, 50)
3851
return flow {

app/src/main/java/com/github/code/gambit/ui/BaseAdapter.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.github.code.gambit.ui
22

3+
import android.annotation.SuppressLint
34
import android.view.LayoutInflater
45
import android.view.View
56
import android.view.ViewGroup
7+
import android.widget.TextView
68
import androidx.recyclerview.widget.RecyclerView
79
import androidx.viewbinding.ViewBinding
810

@@ -17,8 +19,10 @@ import androidx.viewbinding.ViewBinding
1719
abstract class BaseAdapter<T, B : ViewBinding, LS : OnItemClickListener<T>>(private var layoutId: Int) :
1820
RecyclerView.Adapter<BaseAdapter.BaseViewHolder<B>>() {
1921

22+
private val backupData = ArrayList<T>()
2023
private var dataList = ArrayList<T>()
2124
var listener: LS? = null
25+
var counterView: TextView? = null
2226

2327
/**
2428
* Adds the clickListener to the root view of [BaseViewHolder.binding], which calls the abstract
@@ -72,6 +76,7 @@ abstract class BaseAdapter<T, B : ViewBinding, LS : OnItemClickListener<T>>(priv
7276
fun add(data: T) {
7377
dataList.add(data)
7478
notifyDataSetChanged()
79+
updateCounterText()
7580
}
7681

7782
/**
@@ -85,6 +90,22 @@ abstract class BaseAdapter<T, B : ViewBinding, LS : OnItemClickListener<T>>(priv
8590
}
8691
dataList.addAll(dataItems)
8792
notifyDataSetChanged()
93+
updateCounterText()
94+
}
95+
96+
/**
97+
* Sets the counter text view which is used for displaying the live item count
98+
*/
99+
fun bindCounterView(view: TextView) {
100+
counterView = view
101+
}
102+
103+
/**
104+
* updates the [counterView] with latest item count from [getItemCount]
105+
*/
106+
@SuppressLint("SetTextI18n")
107+
private fun updateCounterText() {
108+
counterView?.text = "$itemCount Results"
88109
}
89110

90111
/**
@@ -115,6 +136,26 @@ abstract class BaseAdapter<T, B : ViewBinding, LS : OnItemClickListener<T>>(priv
115136
dataList = dataItems
116137
}
117138

139+
/**
140+
* stores the current item for later user and clears the [dataList]
141+
*/
142+
fun backup() {
143+
backupData.addAll(dataList)
144+
dataList.clear()
145+
updateCounterText()
146+
notifyDataSetChanged()
147+
}
148+
149+
/**
150+
* restores the [dataList] to the latest [backupData]
151+
*/
152+
fun restore() {
153+
dataList.clear()
154+
dataList.addAll(backupData)
155+
backupData.clear()
156+
notifyDataSetChanged()
157+
}
158+
118159
/**
119160
* ViewHolder class for containing views for [BaseAdapter], This class is same for all the
120161
* adapters in this application. Parent class is not required to define custom ViewHolder, all
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.github.code.gambit.ui.fragment.home
2+
3+
import androidx.lifecycle.MutableLiveData
4+
import com.github.code.gambit.data.model.File
5+
6+
interface FileSearchComponent {
7+
fun setRefreshing()
8+
fun setFileLoaded(files: List<File>)
9+
fun getRequests(): MutableLiveData<String>
10+
fun show()
11+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.github.code.gambit.ui.fragment.home
2+
3+
import android.content.Context
4+
import android.text.Editable
5+
import android.text.TextWatcher
6+
import android.view.View
7+
import androidx.lifecycle.MutableLiveData
8+
import androidx.recyclerview.widget.LinearLayoutManager
9+
import com.github.code.gambit.data.model.File
10+
import com.github.code.gambit.data.model.Url
11+
import com.github.code.gambit.databinding.SearchLayoutBinding
12+
import com.github.code.gambit.utility.extention.hide
13+
import com.github.code.gambit.utility.extention.show
14+
15+
class FileSearchComponentImpl private constructor(
16+
private val binding: SearchLayoutBinding,
17+
private val adapter: FileListAdapter
18+
) : FileSearchComponent, FileUrlClickCallback {
19+
20+
val fileSearchRequest = MutableLiveData<String>()
21+
22+
companion object {
23+
fun bind(
24+
searchLayoutBinding: SearchLayoutBinding,
25+
adapter: FileListAdapter,
26+
context: Context,
27+
closeFunc: () -> Unit
28+
): FileSearchComponent {
29+
return FileSearchComponentImpl(searchLayoutBinding, adapter).apply {
30+
registerComponents(context, closeFunc)
31+
}
32+
}
33+
}
34+
35+
fun registerComponents(context: Context, closeFunc: () -> Unit) {
36+
adapter.bindCounterView(binding.counter)
37+
binding.fileList.layoutManager = LinearLayoutManager(context)
38+
binding.fileList.setHasFixedSize(false)
39+
binding.fileList.adapter = adapter
40+
adapter.listener = this
41+
binding.homeButton.setOnClickListener {
42+
closeFunc()
43+
}
44+
binding.searchInput.editText?.addTextChangedListener(object : TextWatcher {
45+
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
46+
47+
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
48+
val text = p0.toString()
49+
if (text.length >= 3) {
50+
newSearch(text)
51+
}
52+
}
53+
54+
override fun afterTextChanged(p0: Editable?) {}
55+
})
56+
}
57+
58+
override fun show() {
59+
binding.searchInput.editText?.setText("")
60+
}
61+
62+
private fun newSearch(searchString: String) {
63+
fileSearchRequest.postValue(searchString)
64+
}
65+
66+
override fun setRefreshing() {
67+
(binding.progressBar as View).show()
68+
}
69+
70+
override fun setFileLoaded(files: List<File>) {
71+
(binding.progressBar as View).hide()
72+
adapter.addAll(files as ArrayList<File>, true)
73+
}
74+
75+
override fun getRequests(): MutableLiveData<String> {
76+
return fileSearchRequest
77+
}
78+
79+
override fun onFileLongClick(file: File) = fileSearchRequest.postValue("")
80+
81+
override fun onCreateNewUrl(file: File) = fileSearchRequest.postValue("")
82+
83+
override fun onLoadMoreUrl(file: File) = fileSearchRequest.postValue("")
84+
85+
override fun onUrlLongClick(url: Url, file: File) = fileSearchRequest.postValue("")
86+
87+
override fun onUrlClick(url: Url, file: File) = fileSearchRequest.postValue("")
88+
89+
override fun onItemClick(item: File) = fileSearchRequest.postValue("")
90+
91+
override fun onItemLongClick(item: File) = fileSearchRequest.postValue("")
92+
}

0 commit comments

Comments
 (0)