package net.osmand.telegram.ui import android.animation.* import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.os.Build import android.os.Bundle import android.support.design.widget.AppBarLayout import android.support.v4.app.Fragment import android.support.v4.content.ContextCompat import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.view.* import android.widget.* import net.osmand.telegram.R import net.osmand.telegram.TelegramApplication import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper.TelegramListener import net.osmand.telegram.ui.MyLocationTabFragment.MyLocationListAdapter.ChatViewHolder import org.drinkless.td.libcore.telegram.TdApi private const val SELECTED_CHATS_KEY = "selected_chats" class MyLocationTabFragment : Fragment(), TelegramListener { private var textMarginSmall: Int = 0 private var textMarginBig: Int = 0 private var searchBoxHeight: Int = 0 private var searchBoxSidesMargin: Int = 0 private val app: TelegramApplication get() = activity?.application as TelegramApplication private val telegramHelper get() = app.telegramHelper private lateinit var appBarLayout: AppBarLayout private lateinit var textContainer: LinearLayout private lateinit var title: TextView private lateinit var description: TextView private lateinit var searchBox: FrameLayout private lateinit var searchBoxBg: GradientDrawable private val adapter = MyLocationListAdapter() private var appBarCollapsed = false private lateinit var appBarOutlineProvider: ViewOutlineProvider private val selectedChats = HashSet() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { textMarginSmall = resources.getDimensionPixelSize(R.dimen.content_padding_standard) textMarginBig = resources.getDimensionPixelSize(R.dimen.my_location_text_sides_margin) searchBoxHeight = resources.getDimensionPixelSize(R.dimen.search_box_height) searchBoxSidesMargin = resources.getDimensionPixelSize(R.dimen.content_padding_half) savedInstanceState?.apply { selectedChats.addAll(getLongArray(SELECTED_CHATS_KEY).toSet()) } val mainView = inflater.inflate(R.layout.fragment_my_location_tab, container, false) appBarLayout = mainView.findViewById(R.id.app_bar_layout).apply { if (Build.VERSION.SDK_INT >= 21) { appBarOutlineProvider = outlineProvider outlineProvider = null } addOnOffsetChangedListener { appBar, offset -> val collapsed = Math.abs(offset) == appBar.totalScrollRange if (collapsed != appBarCollapsed) { appBarCollapsed = collapsed adjustText() adjustSearchBox() } } } textContainer = mainView.findViewById(R.id.text_container).apply { if (Build.VERSION.SDK_INT >= 16) { layoutTransition.enableTransitionType(LayoutTransition.CHANGING) } title = findViewById(R.id.title) description = findViewById(R.id.description) } searchBoxBg = GradientDrawable().apply { shape = GradientDrawable.RECTANGLE setColor(ContextCompat.getColor(context!!, R.color.screen_bg_light)) cornerRadius = (searchBoxHeight / 2).toFloat() } searchBox = mainView.findViewById(R.id.search_box).apply { if (Build.VERSION.SDK_INT >= 16) { background = searchBoxBg } else { @Suppress("DEPRECATION") setBackgroundDrawable(searchBoxBg) } findViewById(R.id.search_button).setOnClickListener { Toast.makeText(context, "Search", Toast.LENGTH_SHORT).show() } findViewById(R.id.search_icon) .setImageDrawable(app.uiUtils.getThemedIcon(R.drawable.ic_action_search_dark)) } mainView.findViewById(R.id.recycler_view).apply { layoutManager = LinearLayoutManager(context) adapter = this@MyLocationTabFragment.adapter } return mainView } override fun onResume() { super.onResume() updateList() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putLongArray(SELECTED_CHATS_KEY, selectedChats.toLongArray()) } override fun onTelegramStatusChanged( prevTelegramAuthorizationState: TelegramHelper.TelegramAuthorizationState, newTelegramAuthorizationState: TelegramHelper.TelegramAuthorizationState ) { when (newTelegramAuthorizationState) { TelegramHelper.TelegramAuthorizationState.READY -> { updateList() } TelegramHelper.TelegramAuthorizationState.CLOSED, TelegramHelper.TelegramAuthorizationState.UNKNOWN -> { adapter.chats = emptyList() } else -> Unit } } override fun onTelegramChatsRead() { updateList() } override fun onTelegramChatsChanged() { updateList() } override fun onTelegramChatChanged(chat: TdApi.Chat) { updateList() } override fun onTelegramUserChanged(user: TdApi.User) { updateList() } override fun onTelegramError(code: Int, message: String) { } override fun onSendLiveLocationError(code: Int, message: String) { } private fun adjustText() { val gravity = if (appBarCollapsed) Gravity.START else Gravity.CENTER val padding = if (appBarCollapsed) textMarginSmall else textMarginBig textContainer.apply { setPadding(padding, paddingTop, padding, paddingBottom) } title.gravity = gravity description.gravity = gravity } private fun adjustSearchBox() { val cornerRadiusFrom = if (appBarCollapsed) searchBoxHeight / 2 else 0 val cornerRadiusTo = if (appBarCollapsed) 0 else searchBoxHeight / 2 val marginFrom = if (appBarCollapsed) searchBoxSidesMargin else 0 val marginTo = if (appBarCollapsed) 0 else searchBoxSidesMargin val cornerAnimator = ObjectAnimator.ofFloat( searchBoxBg, "cornerRadius", cornerRadiusFrom.toFloat(), cornerRadiusTo.toFloat() ) val marginAnimator = ValueAnimator.ofInt(marginFrom, marginTo) marginAnimator.addUpdateListener { val value = it.animatedValue as Int val params = searchBox.layoutParams as LinearLayout.LayoutParams params.setMargins(value, params.topMargin, value, params.bottomMargin) searchBox.layoutParams = params } val animatorSet = AnimatorSet() animatorSet.duration = 200 animatorSet.playTogether(cornerAnimator, marginAnimator) if (Build.VERSION.SDK_INT >= 21) { if (appBarCollapsed) { animatorSet.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { if (Build.VERSION.SDK_INT >= 21 && appBarCollapsed) { appBarLayout.outlineProvider = appBarOutlineProvider } } }) } else { appBarLayout.outlineProvider = null } } animatorSet.start() } private fun updateList() { val chatList = telegramHelper.getChatList() val chats: MutableList = mutableListOf() for (orderedChat in chatList) { val chat = telegramHelper.getChat(orderedChat.chatId) if (chat != null) { chats.add(chat) } } adapter.chats = chats } inner class MyLocationListAdapter : RecyclerView.Adapter() { var chats: List = emptyList() set(value) { field = value notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.user_list_item, parent, false) return ChatViewHolder(view) } override fun onBindViewHolder(holder: ChatViewHolder, position: Int) { val chat = chats[position] val lastItem = position == itemCount - 1 var drawable: Drawable? = null var bitmap: Bitmap? = null val chatPhoto = chat.photo?.small if (chatPhoto != null && chatPhoto.local.path.isNotEmpty()) { bitmap = app.uiUtils.getCircleBitmap(chatPhoto.local.path) } if (bitmap == null) { drawable = app.uiUtils.getThemedIcon(R.drawable.ic_group) } if (bitmap != null) { holder.icon?.setImageBitmap(bitmap) } else { holder.icon?.setImageDrawable(drawable) } holder.title?.text = chat.title holder.description?.text = "Some description" // FIXME holder.checkBox?.apply { visibility = View.VISIBLE setOnCheckedChangeListener(null) isChecked = selectedChats.contains(chat.id) setOnCheckedChangeListener { _, isChecked -> if (isChecked) { selectedChats.add(chat.id) } else { selectedChats.remove(chat.id) } } } holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE holder.itemView.setOnClickListener { holder.checkBox?.apply { isChecked = !isChecked } } } override fun getItemCount() = chats.size inner class ChatViewHolder(val view: View) : RecyclerView.ViewHolder(view) { val icon: ImageView? = view.findViewById(R.id.icon) val title: TextView? = view.findViewById(R.id.title) val description: TextView? = view.findViewById(R.id.description) val checkBox: CheckBox? = view.findViewById(R.id.check_box) val bottomShadow: View? = view.findViewById(R.id.bottom_shadow) } } }