Skip to content
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

Open
wants to merge 4 commits into
base: ep/feature/refactoringHelpyPsd
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
android:name="com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.file_preview.FilePreviewActivity"
android:theme="@style/PyrusServiceDesk.Dialog"/>

<activity
android:name="com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.tickets_list.TicketListActivity"
android:theme="@style/PyrusServiceDesk.Dialog"/>

<provider
android:name=".sdk.PSDFileProvider"
android:authorities="${applicationId}.com.pyrus.pyrusservicedesk.sdk.PSDFileProvider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.annotation.MainThread
import com.google.gson.GsonBuilder
import com.pyrus.pyrusservicedesk.log.PLog
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.ticket.TicketActivity
import com.pyrus.pyrusservicedesk.presentation.ui.navigation_page.tickets_list.TicketListActivity
import com.pyrus.pyrusservicedesk.presentation.viewmodel.SharedViewModel
import com.pyrus.pyrusservicedesk.sdk.FileResolver
import com.pyrus.pyrusservicedesk.sdk.FileResolverImpl
Expand Down Expand Up @@ -399,8 +400,8 @@ class PyrusServiceDesk private constructor(
get().sharedViewModel.clearQuitServiceDesk()
get().onStopCallback = onStopCallback

activity.startActivity(TicketActivity.getLaunchIntent())

//activity.startActivity(TicketActivity.getLaunchIntent())
activity.startActivity(TicketListActivity.getLaunchIntent())
if (configuration == null)
return
val currentUserId = get().preferences.getString(PREFERENCE_KEY_USER_ID_V2, null)
Expand Down
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)
Comment on lines +38 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Давай binding завезем

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

сделала


//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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не очень понял смылс этого

Copy link
Author

Choose a reason for hiding this comment

The 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, проще будет sealed классами

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Или можно взять наш кастомный адаптер из основного проекта

Copy link
Author

Choose a reason for hiding this comment

The 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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

companion object
Размещаем внизу

Copy link
Author

@epryamonosova epryamonosova Nov 25, 2024

Choose a reason for hiding this comment

The 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
}
}

}
Loading