Skip to content

Instantly share code, notes, and snippets.

@kyodgorbek
Created December 28, 2018 16:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kyodgorbek/0b5bbf082d25fc4b97c798cc7c85a1ff to your computer and use it in GitHub Desktop.
Save kyodgorbek/0b5bbf082d25fc4b97c798cc7c85a1ff to your computer and use it in GitHub Desktop.
StartIcon
lass StartSessionFragment : BaseMvpFragment(), StartSessionView {
companion object {
const val THERAPY_PACKAGE_ID = "THERAPY_PACKAGE_ID"
}
private var autoPlay: Boolean = true
private var isActivityDestroyed: Boolean = false
private val presenter = StartSessionPresenter(this)
private var activeTherapyPackage: TherapyPackage? = null
private var preSelectedTherapyPackageId: Int? = null
private val constraintSet1 = ConstraintSet()
private val constraintSet2 = ConstraintSet()
private var currentImage = 0
private var exerciseImages: MutableList<ExerciseFile> = mutableListOf()
private var imageTimer: Timer? = null
private var imageTask: TimerTask? = null
private val imageHandler = Handler()
private var animator: ObjectAnimator? = null
private var downloadProgressBroadcastReceiver: BroadcastReceiver? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_start_session, container, false)
return rootView
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
super.onViewCreated(view, savedInstanceState)
}
isActivityDestroyed = false
constraintSet1.clone(root)
constraintSet2.clone(context, R.layout.fragment_start_session_alt)
toolbar.setOnNavigateIconClickListener {
arguments?.let {
it.getString(ScheduleFragment.MODE, null)?.let {
router.newRootScreen(Screen.HOME)
return@setOnNavigateIconClickListener
}
router.exit()
} ?: router.exit()
}
toolbar.setOnToolIconClickListener { openNavDrawer() }
arguments?.let {
if (it.containsKey(Notifications.PushData.ACTION))
when (it.getString(Notifications.PushData.ACTION)) {
Notifications.PushData.Evaluation.EVALUATION -> {
//TODO dismiss when fragment destroy
EvaluationDialog(it.getInt(Notifications.PushData.Evaluation.EVALUATION_ID), fragment = this).build()?.show()
}
Notifications.PushData.Reminder.OPEN_SESSION -> {
preSelectedTherapyPackageId = it.getInt(Notifications.PushData.Reminder.THERAPY_PACKAGE_ID)
}
}
if (it.containsKey(THERAPY_PACKAGE_ID))
preSelectedTherapyPackageId = it.getInt(THERAPY_PACKAGE_ID)
}
initClickListeners()
initChangePain()
}
override fun onStart() {
super.onStart()
downloadProgressBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
presenter.getAllTherapyPackage()
}
}
context?.let { LocalBroadcastManager.getInstance(it).registerReceiver(downloadProgressBroadcastReceiver!!, IntentFilter(DownloadFileService.ACTION_DOWNLOAD_THERAPY_PACKAGE_FILE_COMPLETED)) }
}
override fun onResume() {
super.onResume()
presenter.getAllTherapyPackage()
tvName.setText(R.string.exercise_nsession)
tvChangePain.setText(R.string.change_pain)
}
override fun onStop() {
context?.let { LocalBroadcastManager.getInstance(it).unregisterReceiver(downloadProgressBroadcastReceiver!!) }
downloadProgressBroadcastReceiver = null
offTimer()
super.onStop()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
startImageTimer()
if (requestCode == VasActivity.VAS_REQUEST_CODE && data != null) {
presenter.createReport(data.getIntExtra("VAS", 0), autoPlay)
}
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
val params = Bundle()
params.putInt("therapyPackage", activeTherapyPackage!!.therapyPackageId)
router.navigateTo(Screen.PROGRESS, params)
}
DiagnosticActivity.handleResult(data, requestCode, resultCode, router)
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
private fun initClickListeners() {
icon_1.setOnClickListener {
presentActivity(icon_1)
autoPlay = true
}
icon_2.setOnClickListener {
presentActivity(icon_2)
autoPlay = false
}
download.setOnClickListener { _ ->
if (download.isChecked) {
presenter.updateTherapyPackageLevelMode(download.isChecked)
progress.visibility = View.VISIBLE
tvTitleStream.setTextColor(Color.BLACK)
tvTitleDownload.setTextColor(Color.WHITE)
context?.startService(Intent(context, DownloadFileService::class.java)
.setAction(DownloadFileService.ACTION_DOWNLOAD_THERAPY_PACKAGE)
.putExtra(DownloadFileService.THERAPY_PACKAGE_ID, activeTherapyPackage?.therapyPackageId))
} else {
if (progress.visibility == View.VISIBLE) {
cancelDownload()
} else {
showDeleteDialog()
}
}
}
icon_close.setOnClickListener {
val transition = AutoTransition()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
transition.duration = 400
}
transition.addListener(object : Transition.TransitionListener {
override fun onTransitionEnd(transition: Transition?) {
icon_start.visibility = View.VISIBLE
}
override fun onTransitionResume(transition: Transition?) {
}
override fun onTransitionPause(transition: Transition?) {
}
override fun onTransitionCancel(transition: Transition?) {
}
override fun onTransitionStart(transition: Transition?) {
startFadeAnimation(tvButtonTitle)
icon_start.visibility = View.GONE
tvText1.visibility = View.VISIBLE
tvText2.visibility = View.VISIBLE
icon_1.visibility = View.VISIBLE
icon_2.visibility = View.VISIBLE
icon_close.visibility = View.VISIBLE
icon_close.translationY = 15.dp.toFloat()
startFadeAnimation(icon_close, true)
startFadeAnimation(tvText1, true)
startFadeAnimation(tvText2, true)
startFadeAnimation(icon_1, true)
startFadeAnimation(icon_2, true)
updateViewsState()
}
})
val constraint = constraintSet1
constraint.applyTo(root)
TransitionManager.beginDelayedTransition(root, transition)
}
icon_start.setOnClickListener {
val transition = AutoTransition()
transition.duration = 400
transition.addListener(object : Transition.TransitionListener {
override fun onTransitionEnd(transition: Transition?) {
tvText1.visibility = View.VISIBLE
tvText2.visibility = View.VISIBLE
icon_close.visibility = View.VISIBLE
ObjectAnimator.ofFloat(tvText1, View.TRANSLATION_X, 30.dp.toFloat(), 0f).start()
ObjectAnimator.ofFloat(tvText2, View.TRANSLATION_X, 30.dp.toFloat(), 0f).start()
ObjectAnimator.ofFloat(icon_close, View.TRANSLATION_Y, -16.dp.toFloat(), 15.dp.toFloat()).start()
}
override fun onTransitionResume(transition: Transition?) {
}
override fun onTransitionPause(transition: Transition?) {
}
override fun onTransitionCancel(transition: Transition?) {
}
override fun onTransitionStart(transition: Transition?) {
startFadeAnimation(icon_2)
startFadeAnimation(icon_1)
startFadeAnimation(tvButtonTitle, true)
updateViewsState()
}
})
val constraint = constraintSet2
constraint.applyTo(root)
TransitionManager.beginDelayedTransition(root, transition)
}
}
private fun cancelDownload() {
presenter.updateTherapyPackageLevelMode(download.isChecked)
progress.progress = 0
tvTitleDownload.text = getString(R.string.start_session_download)
tvTitleStream.setTextColor(Color.WHITE)
tvTitleDownload.setTextColor(Color.BLACK)
progress.visibility = View.GONE
context?.startService(Intent(context, DownloadFileService::class.java)
.setAction(DownloadFileService.ACTION_CANCEL_DOWNLOAD)
.putExtra(DownloadFileService.ACTION_ID, activeTherapyPackage?.therapyPackageId))
}
private fun showDeleteDialog() {
CustomAlertDialogBuilder(context)
.setNegativeButton(getString(R.string.start_session_keep), object : CustomAlertDialogBuilder.OnItemDialogClickListener {
override fun onClick(dialog: CustomAlertDialogBuilder.CustomDialogInterface) {
download.isChecked = true
if (!isActivityDestroyed)
dialog.dismiss()
}
})
.setPositiveButton(getString(R.string.start_session_delete), object : CustomAlertDialogBuilder.OnItemDialogClickListener {
override fun onClick(dialog: CustomAlertDialogBuilder.CustomDialogInterface) {
cancelDownload()
if (!isActivityDestroyed)
dialog.dismiss(false)
}
})
.setOnDismissListener(object : CustomAlertDialogBuilder.OnDismissListener {
override fun onDismiss() {
download.isChecked = true
}
})
.addMessage(R.string.start_session_delete_message)
.build()?.show()
}
private fun presentActivity(view: View) {
offTimer()
if (presenter.isUserPaid()) {
val intent = Intent(context, VasActivity::class.java)
intent.putExtra(VasActivity.START, true)
if (presenter.isTherapeutic(activeTherapyPackage!!)) {
presenter.createReport(0, autoPlay)
} else {
startActivityFromCenterForResult(intent, view, VasActivity.VAS_REQUEST_CODE)
}
} else {
CustomAlertDialogBuilder(context)
.addMessage(R.string.unpaid_message)
.setPositiveButton(R.string.renew_subscription, object : CustomAlertDialogBuilder.OnItemDialogClickListener {
override fun onClick(dialog: CustomAlertDialogBuilder.CustomDialogInterface) {
if (!isActivityDestroyed) {
dialog.dismiss(object : CustomAlertDialogBuilder.OnDismissListener {
override fun onDismiss() {
router.navigateTo(Screen.SUBSCRIPTIONS)
}
})
}
}
})
.build()?.show()
}
}
private fun initChangePain() {
changePain.title = resources.getString(R.string.title_select_pain)
changePain.subTitle = resources.getString(R.string.subtitle_select_pain)
tvChangePain.setOnClickListener {
changePain.show()
}
}
private fun updateViewsState() {
tvChangePain.visibility = if (changePain.adapter.dataSet?.size == 1) View.GONE else View.VISIBLE
activeTherapyPackage?.let {
progress.visibility = if (it.activeTherapyPackageLevel?.isOffline() == true) {
activeTherapyPackage?.activeTherapyPackageLevel
?.calculateDownloadFiles()
?.let {
if (it.first == it.second) View.GONE else View.VISIBLE
} ?: View.VISIBLE
} else {
View.GONE
}
if(it.key.endsWith("_rf")) {
attentionIcon.setColorFilter(ContextCompat.getColor(context!!, R.color.therapyInfoRedFlag))
} else if(it.key.endsWith("_yf")) {
attentionIcon.setImageResource(R.drawable.ic_therapy_info_yellow_flag_attention)
attentionIcon.setColorFilter(ContextCompat.getColor(context!!, R.color.therapyInfoYellowWhiteFlag))
}else{
attentionIcon.setImageResource(R.drawable.ic_therapy_info_yellow_flag_attention)
attentionIcon.setColorFilter(ContextCompat.getColor(context!!, R.color.therapyInfoYellowWhiteFlag))
}
attentionIcon.visibility = if (it.key.endsWith("_rf") || it.key.endsWith("_yf") || it.key.endsWith("_of"))
View.VISIBLE
else
View.GONE
}
}
private fun startFadeAnimation(view: View, reverse: Boolean = false) {
ObjectAnimator.ofFloat(view, View.ALPHA, 0f, 1f).apply {
if (reverse)
reverse()
else start()
}
}
override fun setTherapyPackages(data: List<TherapyPackage>) {
if (data.size == 1) tvChangePain.visibility = View.GONE
else tvChangePain.visibility = View.VISIBLE
changePain.adapter = PickView.Adapter<TherapyPackage?>(object : PickView.ControlListener {
override fun onSelectClick(itemPosition: Int) {
changePain.adapter.dataSet?.get(itemPosition)?.let {
initTherapyPackage(it as TherapyPackage)
}
}
override fun onCancelClick() {
}
}, data)
activeTherapyPackage = if (activeTherapyPackage == null) {
data.firstOrNull { it.therapyPackageId == preSelectedTherapyPackageId }
?: data.first()
} else {
data.first { activeTherapyPackage!!.therapyPackageId == it.therapyPackageId }
}
changePain.dataSet(data.indexOf(activeTherapyPackage!!))
initTherapyPackage(activeTherapyPackage!!)
}
override fun showNoActiveTherapyDialog() {
CustomAlertDialogBuilder(context)
.addMessage(R.string.start_session_empty)
.setPositiveButton(android.R.string.ok, object : CustomAlertDialogBuilder.OnItemDialogClickListener {
override fun onClick(dialog: CustomAlertDialogBuilder.CustomDialogInterface) {
if (!isActivityDestroyed) {
dialog.dismiss()
}
router.exit()
}
}).build()?.show()
}
private fun changeImage() {
try {
Glide.with(this)
.load(exerciseImages[currentImage].getFile())
.listener(object : RequestListener<Drawable> {
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
if (resource == null)
return false
backgroundImage?.let {
animator = backgroundAnimation(backgroundImage, 2000, resource)
animator?.start()
}
return false
}
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
return false
}
})
.apply(RequestOptions()
.error(R.drawable.placeholder_exercise))
.into(backgroundImage)
} catch (e: Exception) {
Log.d("Start Session", e.message)
}
}
private fun getAnimatorListener(drawable: Drawable): AnimationListener {
return object : AnimationListener() {
override fun onAnimationStart(animation: Animator?) {
super.onAnimationStart(animation)
if (isAdded)
backgroundImage?.setImageDrawable(drawable)
}
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
if (isAdded)
backgroundImage2?.setImageDrawable(drawable)
if (currentImage < exerciseImages.size - 1)
currentImage++
else {
currentImage = 0
}
}
}
}
private fun backgroundAnimation(view: View?, duration: Long, drawable: Drawable): ObjectAnimator {
val animation = ObjectAnimator.ofFloat(view, View.ALPHA, 0f, 1f)
animation.duration = duration
animation.listeners
animation.addListener(getAnimatorListener(drawable))
animation.interpolator = LinearInterpolator()
return animation
}
private fun startImageTimer() {
offTimer()
imageTimer = Timer()
imageTask = object : TimerTask() {
override fun run() {
imageHandler.post {
changeImage()
}
}
}
imageTimer?.schedule(imageTask, 5000, 5000)
}
override fun getActiveTherapyPackage(): TherapyPackage = activeTherapyPackage!!
fun initTherapyPackage(first: TherapyPackage) {
offTimer()
currentImage = 0
exerciseImages = mutableListOf()
activeTherapyPackage = first
activeTherapyPackage!!.activeTherapyPackageLevel?.let {
toolbar.setTitle(getString(R.string.start_session_title_day,
DateUtils.diffDays(it.createAt)))
toolbar.setSecondTitle(getString(R.string.start_session_title_session,
it.count + 1))
tvExerciseTitle.text = first.title?.getText
download.isChecked = it.isOffline()
if (download.isChecked) {
tvTitleStream.setTextColor(Color.BLACK)
tvTitleDownload.setTextColor(Color.WHITE)
} else {
tvTitleStream.setTextColor(Color.WHITE)
tvTitleDownload.setTextColor(Color.BLACK)
}
progress.visibility = if (it.isOffline() == true) {
progress.progress = it.calculateDownloadFiles().let { (100 * it.second) / it.first }
if (progress.progress == 100) {
tvTitleDownload.text = getString(R.string.start_session_downloaded)
View.GONE
} else {
tvTitleDownload.text = getString(R.string.start_session_download)
View.VISIBLE
}
} else {
tvTitleDownload.text = getString(R.string.start_session_download)
progress.progress = 0
View.GONE
}
it.exercises.flatMap { it.files }
.filter { it.type == ExerciseFile.TYPE_IMAGE }
.forEach { exerciseImages.add(it) }
if (exerciseImages.isNotEmpty()) {
Glide.with(this)
.load(exerciseImages[currentImage].getFile())
.apply(RequestOptions().placeholder(R.drawable.placeholder_exercise).error(R.drawable.placeholder_exercise))
.into(backgroundImage2)
currentImage++
}
startImageTimer()
updateViewsState()
}
}
override fun startSession(data: Bundle) {
LocalBroadcastManager.getInstance(activity!!).sendBroadcast(Intent(MainActivity.ACTION_FRAGMENT))
startActivityForResult(Intent(context, ExerciseActivity::class.java).putExtras(data), 1)
}
private fun offTimer() {
animator?.end()
animator?.cancel()
imageTimer?.cancel()
imageTask?.cancel()
}
override fun onDestroy() {
isActivityDestroyed = true
super.onDestroy()
}
}
class TherapyInformationFragment : BaseMvpFragment(), TherapyInfoView, OnBackPressed {
companion object {
const val RED_FLAG = "RED_FLAG"
const val YELLOW_FLAG = "YELLOW_FLAG"
const val ORANGE_FLAG = "ORANGE_FLAG"
}
val presenter = TherapyInformationPresenter(this)
private var goToSchedule = false
var packages: MutableList<TherapyPackage>? = null
var position: Int = 0
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_therapy_information, container, false)
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
goToSchedule = arguments?.containsKey("ids") ?: false
if (arguments != null && arguments!!.containsKey("ids"))
presenter.getTherapyInformation(arguments!!.getIntegerArrayList("ids"))
else presenter.getAllTherapyInformation()
initToolbar()
imageBack.setOnClickListener {
if (position > 0)
viewPager.setCurrentItem(viewPager.currentItem - 1, true)
}
imageNext.setOnClickListener {
if (position != packages?.lastIndex) {
viewPager.setCurrentItem(viewPager.currentItem + 1, true)
} else {
if (goToSchedule) {
val data = Bundle()
data.putInt(SCREEN_TRANSITION_DIRECTION, Gravity.END)
data.putString(ScheduleFragment.MODE, ScheduleFragment.DIAGNOSTIC_FINISH_MODE)
data.putIntegerArrayList(ScheduleFragment.THERAPY_PACKAGE_IDS, arrayListOf(*packages!!.map { it.therapyPackageId }.toTypedArray()))
router.navigateTo(Screen.SCHEDULE, data)
}
}
}
}
private fun initToolbar() {
toolbar.setOnNavigateIconClickListener { router.exit() }
toolbar.setOnToolIconClickListener {
openNavDrawer()
}
if (goToSchedule) {
toolbar.setNavigateIcon(0)
toolbar.setToolIcon(0)
}
}
override fun onBackPressed(screen: String?, data: Bundle?): Boolean {
if (goToSchedule) {
router.newRootScreen(Screen.HOME)
}
return goToSchedule
}
private fun actualizeNavArrows() {
if (position == 0) {
imageBack.visibility = View.GONE
} else {
imageBack.visibility = View.VISIBLE
}
if (position == packages?.lastIndex) {
imageNext.visibility = if (goToSchedule) View.VISIBLE else View.GONE
} else {
imageNext.visibility = View.VISIBLE
}
}
override fun showPages(therapies: ArrayList<Therapy>) {
packages = therapies.flatMap { it.packeges }.toMutableList()
viewPager.adapter = object : FragmentPagerAdapter(childFragmentManager) {
override fun getItem(position: Int): Fragment {
val infoText = packages!![position].activeTherapyPackageLevel?.information?.getText
?: ""
val therapyName = packages!![position].title?.getText ?: ""
val fragment = TherapyInfoItem()
val key = packages!![position].key
val bundle = Bundle()
bundle.putString("info", infoText)
bundle.putString("therapyName", therapyName)
bundle.putString("flag", when {
key.endsWith("_rf") -> RED_FLAG
key.endsWith("_yf") -> YELLOW_FLAG
key.endsWith("_of") -> ORANGE_FLAG
else -> null
})
fragment.arguments = bundle
return fragment
}
override fun getCount(): Int {
return packages!!.size
}
}
viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
this@TherapyInformationFragment.position = position
actualizeNavArrows()
}
})
actualizeNavArrows()
}
class TherapyInfoItem : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.therapy_info_item, container, false)
val infoText = arguments?.getString("info")
val therapyName = arguments?.getString("therapyName")
val text = rootView.findViewById<TextView>(R.id.richTextInfo)
val flagContainer = rootView.findViewById<View>(R.id.flagsContainer)
val icon = rootView.findViewById<AppCompatImageView>(R.id.attentionIcon)
val tvAttention = rootView.findViewById<TextView>(R.id.tvAttention)
val tvFlag = rootView.findViewById<TextView>(R.id.tvFlag)
infoText?.let {
text.text = Html.fromHtml(it.replace("<div><br></div>", "").replace("\n\n", "").trim())
// with(webView.settings) {
// layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
// }
// webView.isVerticalScrollBarEnabled = false
// val page = HtmlUtils().getStyledPage(infoText, 16f, "#0000ff", "grotesk_light", 1.2f, 4f)
// webView.loadDataWithBaseURL(HtmlUtils.BASE_LOCAL_URL, page, HtmlUtils.MIME_TYPE, null, null)
}
arguments?.getString("flag")?.let {
when (it) {
RED_FLAG -> {
flagContainer.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.therapyInfoRedFlag, null))
icon.setImageResource(R.drawable.ic_therapy_info_red_flag_attention)
tvAttention.setTextColor(Color.RED)
tvFlag.setTextColor(Color.RED)
tvFlag.text = getString(R.string.recieved_red_flag)
}
YELLOW_FLAG -> {
flagContainer.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.therapyInfoYellowFlag, null))
icon.setImageResource(R.drawable.ic_therapy_info_yellow_flag_attention)
tvAttention.setTextColor(Color.BLACK)
tvFlag.setTextColor(Color.BLACK)
tvFlag.text = getString(R.string.recieved_yellow_flag)
}
ORANGE_FLAG -> {
flagContainer.setBackgroundColor(ResourcesCompat.getColor(resources, R.color.therapyInfoOrangeFlag, null))
icon.setImageResource(R.drawable.ic_therapy_info_yellow_flag_attention)
tvAttention.setTextColor(Color.BLACK)
tvFlag.setTextColor(Color.BLACK)
tvFlag.text = getString(R.string.recieved_orange_flag)
}
}
} ?: run { flagContainer.visibility = View.GONE }
// webView.setBackgroundColor(Color.TRANSPARENT)
rootView.findViewById<TextView>(R.id.therapyName).text = therapyName
return rootView
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment