-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ep/feature/tickets list UI #142
base: ep/feature/refactoringHelpyPsd
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
package com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.tickets_list | ||
|
||
import android.content.Intent | ||
import android.os.Bundle | ||
import android.view.View | ||
import android.widget.ImageButton | ||
import android.widget.Toast | ||
import androidx.lifecycle.Observer | ||
import androidx.recyclerview.widget.LinearLayoutManager | ||
import androidx.recyclerview.widget.RecyclerView | ||
import com.pyrus.pyrusservicedesk.PyrusServiceDesk | ||
import com.pyrus.pyrusservicedesk.R | ||
import com.pyrus.pyrusservicedesk.presentation.ConnectionActivityBase | ||
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.ticket.TicketActivity | ||
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.tickets_list.recyclerview_tickets_list.TicketsListAdapter | ||
import com.pyrus.pyrusservicedesk.presentation.ui.view.recyclerview.item_decorators.SpaceItemDecoration | ||
import com.pyrus.pyrusservicedesk.sdk.data.Author | ||
import com.pyrus.pyrusservicedesk.sdk.data.Comment | ||
import com.pyrus.pyrusservicedesk.sdk.data.TicketShortDescription | ||
import kotlinx.android.synthetic.main.psd_activity_ticket.comments | ||
import kotlinx.android.synthetic.main.psd_activity_ticket.refresh | ||
import kotlinx.android.synthetic.main.psd_tickets_list.filter_fl | ||
import kotlinx.android.synthetic.main.psd_tickets_list.tickets_rv | ||
import kotlinx.android.synthetic.main.psd_toolbar.psd_toolbar_filter_ib | ||
import kotlinx.android.synthetic.main.psd_toolbar.psd_toolbar_qr_ib | ||
import java.util.Date | ||
|
||
/** | ||
* Activity for rendering ticket/feed comments. | ||
*/ | ||
internal class TicketListActivity : ConnectionActivityBase<TicketsListViewModel>(TicketsListViewModel::class.java) { | ||
|
||
companion object { | ||
private const val KEY_USER_ID = "KEY_USER_ID" | ||
private const val KEY_UNREAD_COUNT = "KEY_UNREAD_COUNT" | ||
|
||
private const val STATE_KEYBOARD_SHOWN = "STATE_KEYBOARD_SHOWN" | ||
|
||
private const val CHECK_IS_AT_BOTTOM_DELAY_MS = 50L | ||
|
||
/** | ||
* Provides intent for launching the screen. | ||
* | ||
* @param userid id of user e.g. restaurant id to be rendered. | ||
* When not, this should be omitted for the new ticket. | ||
* @param unreadCount current count of unread tickets. | ||
*/ | ||
fun getLaunchIntent(): Intent { | ||
return Intent( | ||
PyrusServiceDesk.get().application, | ||
TicketListActivity::class.java | ||
) | ||
} | ||
|
||
} | ||
|
||
override val layoutResId = R.layout.psd_tickets_list | ||
override val toolbarViewId = R.id.toolbar_tickets_list | ||
override val refresherViewId = View.NO_ID | ||
override val progressBarViewId: Int = View.NO_ID | ||
|
||
// | ||
// private val attachFileSharedViewModel: AttachFileSharedViewModel by getViewModel( | ||
// AttachFileSharedViewModel::class.java) | ||
// private val commentActionsSharedViewModel: PendingCommentActionSharedViewModel by getViewModel( | ||
// PendingCommentActionSharedViewModel::class.java) | ||
// | ||
|
||
// private val adapter = TicketsListAdapter().apply { | ||
// setOnTicketItemClickListener { | ||
// it.ticketId.let { ticketId -> | ||
// [email protected](TicketActivity.getLaunchIntent( | ||
// ticketId, | ||
// when{ | ||
// !it.isRead -> viewModel.getUnreadCount() - 1 | ||
// else -> viewModel.getUnreadCount() | ||
// } | ||
// )) | ||
// viewModel.onTicketOpened(it) | ||
// } | ||
// } | ||
// } | ||
|
||
private lateinit var adapter: TicketsListAdapter | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
|
||
val toolbarFilter = findViewById<ImageButton>(R.id.psd_toolbar_filter_ib) | ||
val toolbarQr = findViewById<ImageButton>(R.id.psd_toolbar_qr_ib) | ||
val ticketsRv = findViewById<RecyclerView>(R.id.tickets_rv) | ||
|
||
//supportActionBar?.apply { title = getString(R.string.psd_tickets_activity_title) } | ||
toolbarFilter.setOnClickListener { | ||
toolbarFilter.setBackgroundResource(if(filter_fl.visibility == View.VISIBLE) R.drawable.ic_filter else R.drawable.ic_selected_filter) | ||
filter_fl.visibility = if(filter_fl.visibility == View.VISIBLE) View.GONE else View.VISIBLE | ||
Toast.makeText(applicationContext, "фильтры", Toast.LENGTH_SHORT).show() | ||
} | ||
toolbarQr.setOnClickListener { | ||
//TODO | ||
Toast.makeText(applicationContext, "QR", Toast.LENGTH_SHORT).show() | ||
} | ||
|
||
adapter = TicketsListAdapter(/*provideTickets()*/emptyList()) | ||
.apply { | ||
setOnTicketItemClickListener { | ||
it.ticketId.let { ticketId -> | ||
[email protected](TicketActivity.getLaunchIntent( | ||
ticketId, | ||
when { | ||
!it.isRead -> viewModel.getUnreadCount() - 1 | ||
else -> viewModel.getUnreadCount() | ||
} | ||
) | ||
) | ||
viewModel.onTicketOpened(it) | ||
} | ||
} | ||
} | ||
tickets_rv.adapter = adapter | ||
tickets_rv.layoutManager = LinearLayoutManager(this) | ||
|
||
//TODO button New ticket, maybe addItemDecoration | ||
//tickets_rv.addItemDecoration(SpaceItemDecoration(resources.getDimensionPixelSize(R.dimen.psd_tickets_item_space))) | ||
// new_conversation.setOnClickListener { | ||
// UiNavigator.toNewTicket(this, viewModel.getUnreadCount()) | ||
// } | ||
|
||
} | ||
|
||
override fun startObserveData() { | ||
super.startObserveData() | ||
//TODO | ||
// viewModel.getTicketsLiveData().observe( | ||
// this, | ||
// Observer { list -> | ||
// refresh.isRefreshing = false | ||
// list?.let{ adapter.setItems(it) } | ||
// } | ||
// ) | ||
// val list = provideTickets() | ||
// list.let{ adapter.setItems(it) } | ||
} | ||
|
||
//TODO delete | ||
private fun provideTickets(): List<TicketShortDescription> { | ||
val tasks = listOf( | ||
TicketShortDescription(0, "Ошибка в счете", false, Comment( | ||
0, "iiko: Мы рады, что смогли Вам помочь решить проблему ☺", creationDate = Date(1731074815), author = Author("Autor"))), | ||
TicketShortDescription(0, "Проблемы с авторизацией в учетной зписи long", true, Comment( | ||
0, "Вы: После обновления страницы ничего не происходит. Как перевести в режим прос", creationDate = Date(1730815615000), author = Author("Autor"))), | ||
TicketShortDescription(0, "Ошибка в счете", true, Comment( | ||
0, "печатает", creationDate = Date(1731074815), author = Author("Autor"))), | ||
TicketShortDescription(0, "Ошибка в счете", true, Comment( | ||
0, "iiko: Мы рады, что смогли Вам помочь решить проблему ☺", creationDate = Date(1728137215000), author = Author("Autor"))), | ||
) | ||
return tasks | ||
} | ||
|
||
override fun finish() { | ||
super.finish() | ||
PyrusServiceDesk.onServiceDeskStop() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не очень понял смылс этого There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не нужно, удалила |
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.tickets_list | ||
|
||
|
||
/** | ||
* Base class for entries that are used for rendering list of ticket/feed comments. | ||
*/ | ||
internal abstract class TicketsListEntry { | ||
/** | ||
* Type of the ticket entry. See [Type]. | ||
*/ | ||
abstract val type: Type | ||
} | ||
|
||
/** | ||
* Available types of entries. Used for speed optimization to avoid class casting. | ||
* TODO check the possibility of using sealed classes for this purpose. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да, проще будет sealed классами There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Или можно взять наш кастомный адаптер из основного проекта There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. пока тоже нет необходимости, вообще класс лишний |
||
*/ | ||
internal enum class Type { | ||
Comment, | ||
Date, | ||
WelcomeMessage, | ||
Rating, | ||
Buttons | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.tickets_list | ||
|
||
import android.content.Context | ||
import android.net.Uri | ||
import android.os.Handler | ||
import android.os.Looper | ||
import android.widget.Toast | ||
import androidx.lifecycle.LiveData | ||
import androidx.lifecycle.MediatorLiveData | ||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.Observer | ||
import androidx.recyclerview.widget.DiffUtil | ||
import com.pyrus.pyrusservicedesk.PyrusServiceDesk | ||
import com.pyrus.pyrusservicedesk.R | ||
import com.pyrus.pyrusservicedesk.ServiceDeskProvider | ||
import com.pyrus.pyrusservicedesk.log.PLog | ||
import com.pyrus.pyrusservicedesk.presentation.call.* | ||
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.ticket.CommentsDiffCallback | ||
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.ticket.HtmlTagUtils | ||
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.ticket.entries.* | ||
import com.pyrus.pyrusservicedesk.presentation.ui.view.recyclerview.DiffResultWithNewItems | ||
import com.pyrus.pyrusservicedesk.presentation.viewmodel.ConnectionViewModelBase | ||
import com.pyrus.pyrusservicedesk.sdk.data.Attachment | ||
import com.pyrus.pyrusservicedesk.sdk.data.Author | ||
import com.pyrus.pyrusservicedesk.sdk.data.Comment | ||
import com.pyrus.pyrusservicedesk.sdk.data.FileManager | ||
import com.pyrus.pyrusservicedesk.sdk.data.LocalDataProvider | ||
import com.pyrus.pyrusservicedesk.sdk.data.TicketShortDescription | ||
import com.pyrus.pyrusservicedesk.sdk.data.intermediate.AddCommentResponseData | ||
import com.pyrus.pyrusservicedesk.sdk.data.intermediate.Comments | ||
import com.pyrus.pyrusservicedesk.sdk.response.PendingDataError | ||
import com.pyrus.pyrusservicedesk.sdk.updates.OnUnreadTicketCountChangedSubscriber | ||
import com.pyrus.pyrusservicedesk.sdk.updates.PreferencesManager | ||
import com.pyrus.pyrusservicedesk.sdk.verify.LocalDataVerifier | ||
import com.pyrus.pyrusservicedesk.sdk.web.OnCancelListener | ||
import com.pyrus.pyrusservicedesk.sdk.web.UploadFileHooks | ||
import com.pyrus.pyrusservicedesk.utils.ConfigUtils | ||
import com.pyrus.pyrusservicedesk.utils.MILLISECONDS_IN_MINUTE | ||
import com.pyrus.pyrusservicedesk.utils.MILLISECONDS_IN_SECOND | ||
import com.pyrus.pyrusservicedesk.utils.RequestUtils.Companion.MAX_FILE_SIZE_BYTES | ||
import com.pyrus.pyrusservicedesk.utils.RequestUtils.Companion.MAX_FILE_SIZE_MEGABYTES | ||
import com.pyrus.pyrusservicedesk.utils.getWhen | ||
import kotlinx.coroutines.* | ||
import java.lang.Exception | ||
import java.lang.Runnable | ||
import java.util.* | ||
import kotlin.collections.ArrayList | ||
|
||
/** | ||
* ViewModel for the tickets list screen. | ||
*/ | ||
internal class TicketsListViewModel( | ||
serviceDeskProvider: ServiceDeskProvider, | ||
private val preferencesManager: PreferencesManager | ||
) : ConnectionViewModelBase(serviceDeskProvider) { | ||
|
||
|
||
private val tickets = MediatorLiveData<List<TicketShortDescription>>() | ||
|
||
private var unreadCount = 0 | ||
|
||
private companion object { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. companion object There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. конкретно здесь пока вообще не нужен удалила |
||
|
||
private val TAG = TicketsListViewModel::class.java.simpleName | ||
|
||
private const val BUTTON_PATTERN = "<button>(.*?)</button>" | ||
|
||
fun Comment.hasAttachmentWithExceededSize(): Boolean = | ||
attachments?.let { it.any { attach -> attach.hasExceededFileSize() } } ?: false | ||
|
||
fun Attachment.hasExceededFileSize(): Boolean = bytesSize > MAX_FILE_SIZE_BYTES | ||
} | ||
|
||
/** | ||
* Drafted text. Assigned once when view model is created. | ||
*/ | ||
//val draft: String | ||
|
||
private val draftRepository = serviceDeskProvider.getDraftRepository() | ||
private val localDataProvider: LocalDataProvider = serviceDeskProvider.getLocalDataProvider() | ||
private val fileManager: FileManager = serviceDeskProvider.getFileManager() | ||
private val localDataVerifier: LocalDataVerifier = serviceDeskProvider.getLocalDataVerifier() | ||
|
||
private var isCreateTicketSent = false | ||
|
||
private val unreadCounter = MutableLiveData<Int>() | ||
private val commentDiff = MutableLiveData<DiffResultWithNewItems<TicketEntry>>() | ||
|
||
private var ticketEntries: List<TicketEntry> = emptyList() | ||
|
||
private val mainHandler = Handler(Looper.getMainLooper()) | ||
|
||
|
||
private var pendingCommentUnderAction: CommentEntry? = null | ||
private var userId = PyrusServiceDesk.get().userId | ||
|
||
private var currentInterval: Long = 0 | ||
|
||
init { | ||
|
||
} | ||
|
||
override fun onLoadData() { | ||
//update() | ||
} | ||
|
||
|
||
|
||
/** | ||
* Provides live data that delivers list of [TicketShortDescription] to be rendered. | ||
*/ | ||
fun getTicketsLiveData(): LiveData<List<TicketShortDescription>> = tickets | ||
|
||
//TODO delete | ||
// private fun provideTickets(): List<TicketShortDescription> { | ||
// val tasks = listOf( | ||
// TicketShortDescription( | ||
// 0, "Ошибка в счете", false, Comment( | ||
// 0, | ||
// "iiko: Мы рады, что смогли Вам помочь решить проблему ☺", | ||
// creationDate = Date(1731074815), | ||
// author = Author("Autor") | ||
// ) | ||
// ), | ||
// TicketShortDescription( | ||
// 0, "Проблемы с авторизацией в учетной зписи long", false, Comment( | ||
// 0, | ||
// "Вы: После обновления страницы ничего не происходит. Как перевести в режим прос", | ||
// creationDate = Date(1730815615000), | ||
// author = Author("Autor") | ||
// ) | ||
// ), | ||
// TicketShortDescription( | ||
// 0, "Ошибка в счете", false, Comment( | ||
// 0, "печатает", creationDate = Date(1731074815), author = Author("Autor") | ||
// ) | ||
// ), | ||
// TicketShortDescription( | ||
// 0, "Ошибка в счете", false, Comment( | ||
// 0, | ||
// "iiko: Мы рады, что смогли Вам помочь решить проблему ☺", | ||
// creationDate = Date(1728137215000), | ||
// author = Author("Autor") | ||
// ) | ||
// ), | ||
// ) | ||
// return tasks | ||
// } | ||
|
||
|
||
/** | ||
* Provides live data that delivers count of currently unread tickets | ||
*/ | ||
fun getUnreadCount() = unreadCount | ||
|
||
|
||
/** | ||
* Callback to be invoked when user opens [ticket] in UI | ||
*/ | ||
fun onTicketOpened(ticket: TicketShortDescription) { | ||
if (!ticket.isRead) { | ||
unreadCount-- | ||
val ticketsMutable = tickets.value!!.toMutableList() | ||
//ticketsMutable[ticketsMutable.indexOf(ticket)] = ticket.isRead | ||
tickets.value = ticketsMutable | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Давай binding завезем
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
сделала