Full write logic of entries fragment
This commit is contained in:
parent
438aca7b75
commit
dbcb29ce79
@ -6,7 +6,9 @@ import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ViewModelComponent
|
||||
import ru.myitschool.work.data.repo.AccountRepositoryImpl
|
||||
import ru.myitschool.work.data.repo.AuthorizationRepositoryImpl
|
||||
import ru.myitschool.work.data.repo.EntryRepositoryImpl
|
||||
import ru.myitschool.work.domain.auth.repo.AuthorizationRepository
|
||||
import ru.myitschool.work.domain.entry.repo.EntryRepository
|
||||
import ru.myitschool.work.domain.profile.repo.UserInfoRepository
|
||||
|
||||
@Module
|
||||
@ -22,4 +24,9 @@ abstract class RepoModule {
|
||||
abstract fun bindAccountRepo(
|
||||
impl: AccountRepositoryImpl
|
||||
): UserInfoRepository
|
||||
|
||||
@Binds
|
||||
abstract fun bindEntryRepository(
|
||||
impl: EntryRepositoryImpl
|
||||
): EntryRepository
|
||||
}
|
17
app/src/main/java/ru/myitschool/work/data/dto/EntriesDto.kt
Normal file
17
app/src/main/java/ru/myitschool/work/data/dto/EntriesDto.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package ru.myitschool.work.data.dto
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class EntriesDto(
|
||||
@SerializedName("id")
|
||||
val id: Long,
|
||||
@SerializedName("username")
|
||||
val username: String,
|
||||
@SerializedName("time")
|
||||
val time: String,
|
||||
@SerializedName("type")
|
||||
val type: VisitType,
|
||||
@SerializedName("readerId")
|
||||
val readerId: String,
|
||||
)
|
@ -0,0 +1,5 @@
|
||||
package ru.myitschool.work.data.dto
|
||||
|
||||
enum class VisitType {
|
||||
SCANNER, NFC
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package ru.myitschool.work.data.mapper
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import ru.myitschool.work.data.dto.EntriesDto
|
||||
import ru.myitschool.work.data.dto.UserInfoDto
|
||||
import ru.myitschool.work.domain.profile.entities.UserInfoEntity
|
||||
import ru.myitschool.work.ui.entrylist.adapter.EntryHistoryEntity
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
class EntryInfoMapper @Inject constructor() {
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
operator fun invoke(model: List<EntriesDto>): Result<List<EntryHistoryEntity>> {
|
||||
return kotlin.runCatching {
|
||||
model.map {
|
||||
EntryHistoryEntity(
|
||||
type = it.type.name,
|
||||
identificator = it.readerId,
|
||||
time = it.time.toString(),
|
||||
)
|
||||
}.toList()
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val simpleDateFormat = SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'HH:mm:ss",
|
||||
Locale.US
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package ru.myitschool.work.data.repo
|
||||
|
||||
import dagger.Lazy
|
||||
import dagger.Reusable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.myitschool.work.data.mapper.EntryInfoMapper
|
||||
import ru.myitschool.work.data.mapper.UserInfoMapper
|
||||
import ru.myitschool.work.data.source.AccountNetworkDataSource
|
||||
import ru.myitschool.work.data.source.EntryNetworkDataSource
|
||||
import ru.myitschool.work.domain.entry.entities.EntryEntity
|
||||
import ru.myitschool.work.domain.entry.repo.EntryRepository
|
||||
import ru.myitschool.work.domain.profile.entities.UserInfoEntity
|
||||
import ru.myitschool.work.domain.profile.repo.UserInfoRepository
|
||||
import ru.myitschool.work.ui.entrylist.adapter.EntryHistoryEntity
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class EntryRepositoryImpl @Inject constructor(
|
||||
private val entryNetworkDataSource: EntryNetworkDataSource,
|
||||
private val entryInfoMapper: Lazy<EntryInfoMapper>,
|
||||
): EntryRepository {
|
||||
override suspend fun getEntries(basicAuth: String): Result<List<EntryHistoryEntity>> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
entryNetworkDataSource.getEntries(basicAuth).fold(
|
||||
onSuccess = { value -> entryInfoMapper.get().invoke(value) },
|
||||
onFailure = { error -> Result.failure(error) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
12
app/src/main/java/ru/myitschool/work/data/source/EntryApi.kt
Normal file
12
app/src/main/java/ru/myitschool/work/data/source/EntryApi.kt
Normal file
@ -0,0 +1,12 @@
|
||||
package ru.myitschool.work.data.source
|
||||
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import ru.myitschool.work.data.dto.EntriesDto
|
||||
|
||||
interface EntryApi {
|
||||
@GET("api/employee/visits")
|
||||
suspend fun getEntries(
|
||||
@Header("Authorization") basicAuth: String
|
||||
) : List<EntriesDto>
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package ru.myitschool.work.data.source
|
||||
|
||||
import dagger.Reusable
|
||||
import retrofit2.Retrofit
|
||||
import ru.myitschool.work.data.dto.EntriesDto
|
||||
import ru.myitschool.work.data.dto.OpenQrDto
|
||||
import ru.myitschool.work.data.dto.UserInfoDto
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class EntryNetworkDataSource @Inject constructor(
|
||||
private val retrofit: Retrofit
|
||||
) {
|
||||
private val api by lazy {
|
||||
retrofit.create(EntryApi::class.java)
|
||||
}
|
||||
|
||||
suspend fun getEntries(basicAuth: String): Result<List<EntriesDto>> {
|
||||
return kotlin.runCatching { api.getEntries(basicAuth = basicAuth) }
|
||||
}
|
||||
}
|
@ -7,9 +7,6 @@ import javax.inject.Inject
|
||||
class LoginUseCase @Inject constructor(
|
||||
private val repo: AuthorizationRepository,
|
||||
) {
|
||||
// suspend operator fun invoke(login: String): Result<Unit> {
|
||||
// return repo.login(username = login)
|
||||
// }
|
||||
suspend operator fun invoke(data: LoginDto): Result<Unit>{
|
||||
return repo.login(data=data)
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package ru.myitschool.work.domain.entry
|
||||
|
||||
import ru.myitschool.work.domain.auth.GetLoginUseCase
|
||||
import ru.myitschool.work.domain.entry.repo.EntryRepository
|
||||
import ru.myitschool.work.ui.entrylist.adapter.EntryHistoryEntity
|
||||
import javax.inject.Inject
|
||||
|
||||
class EntryListUseCase @Inject constructor(
|
||||
private val repo: EntryRepository,
|
||||
private val getLoginUseCase: GetLoginUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(): Result<List<EntryHistoryEntity>> {
|
||||
return getLoginUseCase().fold(
|
||||
onSuccess = { basicAuth -> repo.getEntries(basicAuth) },
|
||||
onFailure = { error -> Result.failure(error) }
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package ru.myitschool.work.domain.entry.entities
|
||||
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class EntryEntity(
|
||||
val username: String,
|
||||
val time: LocalDateTime,
|
||||
val type: EntryType,
|
||||
val readerId: String,
|
||||
)
|
@ -0,0 +1,5 @@
|
||||
package ru.myitschool.work.domain.entry.entities
|
||||
|
||||
enum class EntryType {
|
||||
SCANNER, NFC
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package ru.myitschool.work.domain.entry.repo
|
||||
|
||||
import ru.myitschool.work.ui.entrylist.adapter.EntryHistoryEntity
|
||||
|
||||
interface EntryRepository {
|
||||
suspend fun getEntries(basicAuth: String) : Result<List<EntryHistoryEntity>>
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package ru.myitschool.work.ui.entrylist
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import androidx.fragment.app.viewModels
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
@ -8,8 +9,11 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.squareup.picasso.Picasso
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.databinding.FragmentEntryListBinding
|
||||
@ -21,6 +25,8 @@ import ru.myitschool.work.ui.login.LoginViewModel
|
||||
import ru.myitschool.work.ui.profile.ProfileDestination
|
||||
import ru.myitschool.work.ui.profile.ProfileViewModel
|
||||
import ru.myitschool.work.utils.collectWhenStarted
|
||||
import ru.myitschool.work.utils.visibleOrGone
|
||||
|
||||
@AndroidEntryPoint
|
||||
class EntryListFragment : Fragment(R.layout.fragment_entry_list) {
|
||||
|
||||
@ -29,22 +35,49 @@ class EntryListFragment : Fragment(R.layout.fragment_entry_list) {
|
||||
|
||||
private val viewModel: EntryListViewModel by viewModels()
|
||||
|
||||
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentEntryListBinding.bind(view)
|
||||
initCallback()
|
||||
subscribe()
|
||||
|
||||
swipeRefreshLayout = binding.swipeRefreshLayout2
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
viewModel.updateEntryList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initCallback() {
|
||||
binding.floatingActionButton2.setOnClickListener { viewModel.closeEntryList() }
|
||||
|
||||
|
||||
binding.recyclerView.adapter = AdapterEntryHistory(viewModel.getEntryList())
|
||||
// binding.recyclerView.adapter = AdapterEntryHistory(viewModel.getEntryList())
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
}
|
||||
|
||||
private fun subscribe() {
|
||||
viewModel.state.collectWhenStarted(this) { state ->
|
||||
binding.recyclerView.visibleOrGone(state is EntryListViewModel.State.Show)
|
||||
binding.error2.visibleOrGone(state is EntryListViewModel.State.Error)
|
||||
|
||||
when(state) {
|
||||
is EntryListViewModel.State.Loading -> {
|
||||
swipeRefreshLayout.isRefreshing = true
|
||||
}
|
||||
is EntryListViewModel.State.Error -> {
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
binding.error2.text = state.errorText
|
||||
}
|
||||
is EntryListViewModel.State.Show -> {
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
binding.recyclerView.adapter = AdapterEntryHistory(state.entryList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.action.collectWhenStarted(this) { action ->
|
||||
when (action) {
|
||||
is EntryListViewModel.Action.OpenProfile -> {
|
||||
|
@ -3,31 +3,38 @@ package ru.myitschool.work.ui.entrylist
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.Lazy
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.domain.entry.EntryListUseCase
|
||||
import ru.myitschool.work.ui.entrylist.adapter.EntryHistoryEntity
|
||||
import ru.myitschool.work.ui.profile.ProfileViewModel
|
||||
import ru.myitschool.work.ui.profile.ProfileViewModel.Action
|
||||
import ru.myitschool.work.ui.profile.ProfileViewModel.State
|
||||
import ru.myitschool.work.utils.MutablePublishFlow
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@HiltViewModel
|
||||
class EntryListViewModel @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val entryUseCase: Lazy<EntryListUseCase>,
|
||||
) : ViewModel() {
|
||||
private val _action = MutablePublishFlow<Action>()
|
||||
val action = _action.asSharedFlow()
|
||||
|
||||
private val _state = MutableStateFlow<EntryListViewModel.State>(initialState)
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
init {
|
||||
updateEntryList()
|
||||
}
|
||||
|
||||
// Новый список данных
|
||||
private val entryList = listOf(
|
||||
private var entryList = listOf(
|
||||
EntryHistoryEntity("type1", "2023-10-01T12:00:00", "id001"),
|
||||
EntryHistoryEntity("type2", "2023-10-02T13:00:00", "id002"),
|
||||
EntryHistoryEntity("type3", "2023-10-03T14:00:00", "id003"),
|
||||
@ -36,8 +43,28 @@ class EntryListViewModel @Inject constructor(
|
||||
)
|
||||
|
||||
// Функция для получения данных
|
||||
fun getEntryList(): List<EntryHistoryEntity> {
|
||||
return entryList
|
||||
fun updateEntryList() {
|
||||
viewModelScope.launch {
|
||||
_state.update { State.Loading }
|
||||
entryUseCase.get().invoke().fold(
|
||||
onSuccess = { entryListEntity ->
|
||||
entryList = entryListEntity
|
||||
_state.update {
|
||||
State.Show(
|
||||
entryList = entryListEntity
|
||||
)
|
||||
}
|
||||
},
|
||||
onFailure = { error ->
|
||||
_state.update {
|
||||
State.Error(
|
||||
errorText = error.localizedMessage
|
||||
?: context.resources.getString(R.string.login_error)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun closeEntryList(){
|
||||
@ -49,4 +76,20 @@ class EntryListViewModel @Inject constructor(
|
||||
sealed interface Action {
|
||||
data object OpenProfile: Action
|
||||
}
|
||||
|
||||
sealed interface State {
|
||||
data object Loading : State
|
||||
|
||||
data class Error(
|
||||
val errorText: String,
|
||||
) : State
|
||||
|
||||
data class Show(
|
||||
val entryList: List<EntryHistoryEntity>
|
||||
) : State
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val initialState = State.Loading
|
||||
}
|
||||
}
|
@ -36,8 +36,8 @@ class AdapterEntryHistory(private val datas: List<EntryHistoryEntity>) : Recycle
|
||||
|
||||
|
||||
holder.dateText.text = LocalDateTime.parse(datas[position].time).format(DateTimeFormatter.ofPattern("d MMMM yyyy, HH:mm:ss", Locale.getDefault()))
|
||||
holder.identificatorText.text = datas[position].identificator.toString()
|
||||
holder.typeText.text = datas[position].type.toString()
|
||||
holder.identificatorText.text = datas[position].identificator
|
||||
holder.typeText.text = if (datas[position].type == "SCANNER") "Сканер (Телефон)" else "NFC-карта"
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,40 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/frameLayout2"
|
||||
android:id="@+id/swipeRefreshLayout2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
tools:context=".ui.entrylist.EntryListFragment">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/floatingActionButton2"
|
||||
style="@style/Theme.UiTemplate.FAB.Gray"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
tools:context=".ui.entrylist.EntryListFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView5"
|
||||
style="@style/Theme.UiTemplate.TextH2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/entry_history"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintTop_toTopOf="@+id/floatingActionButton2" />
|
||||
<TextView
|
||||
android:id="@+id/error2"
|
||||
style="@style/Theme.UiTemplate.TextH5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Something wrong. Try later" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/floatingActionButton2" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/floatingActionButton2"
|
||||
style="@style/Theme.UiTemplate.FAB.Gray"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView5"
|
||||
style="@style/Theme.UiTemplate.TextH2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/entry_history"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintTop_toTopOf="@+id/floatingActionButton2" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/floatingActionButton2" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
@ -1,40 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/frameLayout2"
|
||||
android:id="@+id/swipeRefreshLayout2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
tools:context=".ui.entrylist.EntryListFragment">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/floatingActionButton2"
|
||||
style="@style/Theme.UiTemplate.FAB.Gray"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
tools:context=".ui.entrylist.EntryListFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView5"
|
||||
style="@style/Theme.UiTemplate.TextH2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/entry_history"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintTop_toTopOf="@+id/floatingActionButton2" />
|
||||
<TextView
|
||||
android:id="@+id/error2"
|
||||
style="@style/Theme.UiTemplate.TextH5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Something wrong. Try later" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/floatingActionButton2" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/floatingActionButton2"
|
||||
style="@style/Theme.UiTemplate.FAB.Gray"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView5"
|
||||
style="@style/Theme.UiTemplate.TextH2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/entry_history"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/floatingActionButton2"
|
||||
app:layout_constraintTop_toTopOf="@+id/floatingActionButton2" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/floatingActionButton2" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
Loading…
x
Reference in New Issue
Block a user