From 27ccc38a08a5a026cc3c0ba8576b3c7bc5f288be Mon Sep 17 00:00:00 2001 From: crimean Date: Thu, 7 Jun 2018 17:44:43 +0300 Subject: [PATCH] Telegram - added chats list --- OsmAnd-telegram/build.gradle | 1 + .../osmand/telegram/LoginDialogFragment.kt | 2 + .../java/net/osmand/telegram/MainActivity.kt | 195 +++++++++++----- .../net/osmand/telegram/TelegramHelper.kt | 214 +++++++++++------- .../telegram/{ => utils}/AndroidUtils.kt | 2 +- .../telegram/utils/CancellableAsyncTask.kt | 76 +++++++ .../telegram/{ => utils}/PlatformUtil.java | 2 +- .../src/main/res/drawable-hdpi/ic_group.png | Bin 0 -> 1299 bytes .../src/main/res/drawable-mdpi/ic_group.png | Bin 0 -> 1208 bytes .../src/main/res/drawable-xhdpi/ic_group.png | Bin 0 -> 1408 bytes .../src/main/res/drawable-xxhdpi/ic_group.png | Bin 0 -> 1677 bytes .../main/res/layout/action_progress_bar.xml | 8 +- .../src/main/res/layout/activity_main.xml | 10 +- .../src/main/res/layout/chat_list_item.xml | 61 +++++ .../src/main/res/layout/login_dialog.xml | 14 +- OsmAnd-telegram/src/main/res/values/attrs.xml | 7 + .../src/main/res/values/colors.xml | 6 + .../src/main/res/values/dimens.xml | 10 + .../src/main/res/values/styles.xml | 3 + 19 files changed, 461 insertions(+), 150 deletions(-) rename OsmAnd-telegram/src/main/java/net/osmand/telegram/{ => utils}/AndroidUtils.kt (97%) create mode 100644 OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/CancellableAsyncTask.kt rename OsmAnd-telegram/src/main/java/net/osmand/telegram/{ => utils}/PlatformUtil.java (99%) create mode 100644 OsmAnd-telegram/src/main/res/drawable-hdpi/ic_group.png create mode 100644 OsmAnd-telegram/src/main/res/drawable-mdpi/ic_group.png create mode 100644 OsmAnd-telegram/src/main/res/drawable-xhdpi/ic_group.png create mode 100644 OsmAnd-telegram/src/main/res/drawable-xxhdpi/ic_group.png create mode 100644 OsmAnd-telegram/src/main/res/layout/chat_list_item.xml create mode 100644 OsmAnd-telegram/src/main/res/values/attrs.xml create mode 100644 OsmAnd-telegram/src/main/res/values/dimens.xml diff --git a/OsmAnd-telegram/build.gradle b/OsmAnd-telegram/build.gradle index 5142beabcd..a8420b3f70 100644 --- a/OsmAnd-telegram/build.gradle +++ b/OsmAnd-telegram/build.gradle @@ -120,6 +120,7 @@ dependencies { implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'com.android.support:support-annotations:27.1.1' implementation 'commons-logging:commons-logging-api:1.1' + implementation 'com.android.support:recyclerview-v7:27.1.1' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' diff --git a/OsmAnd-telegram/src/main/java/net/osmand/telegram/LoginDialogFragment.kt b/OsmAnd-telegram/src/main/java/net/osmand/telegram/LoginDialogFragment.kt index 79c1812e1f..a6bdcea70b 100644 --- a/OsmAnd-telegram/src/main/java/net/osmand/telegram/LoginDialogFragment.kt +++ b/OsmAnd-telegram/src/main/java/net/osmand/telegram/LoginDialogFragment.kt @@ -11,6 +11,8 @@ import android.view.WindowManager import android.view.inputmethod.EditorInfo import android.widget.Button import android.widget.EditText +import net.osmand.telegram.utils.AndroidUtils +import net.osmand.telegram.utils.PlatformUtil class LoginDialogFragment : DialogFragment() { diff --git a/OsmAnd-telegram/src/main/java/net/osmand/telegram/MainActivity.kt b/OsmAnd-telegram/src/main/java/net/osmand/telegram/MainActivity.kt index 0a0bd22066..e211676575 100644 --- a/OsmAnd-telegram/src/main/java/net/osmand/telegram/MainActivity.kt +++ b/OsmAnd-telegram/src/main/java/net/osmand/telegram/MainActivity.kt @@ -2,11 +2,12 @@ package net.osmand.telegram import android.os.Bundle import android.support.v7.app.AppCompatActivity -import android.view.Menu -import android.view.MenuItem +import android.support.v7.widget.* +import android.view.* import android.widget.Toast import net.osmand.telegram.LoginDialogFragment.LoginDialogType import net.osmand.telegram.TelegramHelper.* +import org.drinkless.td.libcore.telegram.TdApi class MainActivity : AppCompatActivity(), TelegramListener { @@ -17,9 +18,13 @@ class MainActivity : AppCompatActivity(), TelegramListener { private const val PROGRESS_MENU_ID = 2 } - private var authParamRequestHandler: AuthParamRequestHandler? = null + private var telegramAuthorizationRequestHandler: TelegramAuthorizationRequestHandler? = null private var paused: Boolean = false + private lateinit var chatsView: RecyclerView + private lateinit var chatViewAdapter: ChatsAdapter + private lateinit var chatViewManager: RecyclerView.LayoutManager + private val app: TelegramApplication get() = application as TelegramApplication @@ -32,20 +37,30 @@ class MainActivity : AppCompatActivity(), TelegramListener { paused = false - authParamRequestHandler = telegramHelper.setAuthParamRequestHandler(object : AuthParamRequestListener { - override fun onRequestAuthParam(paramType: AuthParamType) { - runOnUiThread { - if (!paused) { - showLoginDialog(paramType) - } + chatViewManager = LinearLayoutManager(this) + chatViewAdapter = ChatsAdapter() + + chatsView = findViewById(R.id.groups_view).apply { + //setHasFixedSize(true) + + // use a linear layout manager + layoutManager = chatViewManager + + // specify an viewAdapter (see also next example) + adapter = chatViewAdapter + + } + + telegramAuthorizationRequestHandler = telegramHelper.setTelegramAuthorizationRequestHandler(object : TelegramAuthorizationRequestListener { + override fun onRequestTelegramAuthenticationParameter(parameterType: TelegramAuthenticationParameterType) { + runOnUi { + showLoginDialog(parameterType) } } - override fun onAuthRequestError(code: Int, message: String) { - runOnUiThread { - if (!paused) { - Toast.makeText(this@MainActivity, "$code - $message", Toast.LENGTH_LONG).show() - } + override fun onTelegramAuthorizationRequestError(code: Int, message: String) { + runOnUi { + Toast.makeText(this@MainActivity, "$code - $message", Toast.LENGTH_LONG).show() } } }) @@ -66,24 +81,59 @@ class MainActivity : AppCompatActivity(), TelegramListener { paused = true } - override fun onTelegramStatusChanged(prevAutoState: AuthState, newAuthState: AuthState) { - runOnUiThread { - if (!paused) { - val fm = supportFragmentManager - when (newAuthState) { - AuthState.READY, - AuthState.CLOSED, - AuthState.UNKNOWN -> LoginDialogFragment.dismiss(fm) - else -> Unit + override fun onTelegramStatusChanged(prevTelegramAuthorizationState: TelegramAuthorizationState, + newTelegramAuthorizationState: TelegramAuthorizationState) { + runOnUi { + val fm = supportFragmentManager + when (newTelegramAuthorizationState) { + TelegramAuthorizationState.READY, + TelegramAuthorizationState.CLOSED, + TelegramAuthorizationState.UNKNOWN -> LoginDialogFragment.dismiss(fm) + else -> Unit + } + invalidateOptionsMenu() + updateTitle() + + when (newTelegramAuthorizationState) { + TelegramAuthorizationState.READY -> { + updateChatsList() + telegramHelper.requestChats() } - invalidateOptionsMenu() - updateTitle() + TelegramAuthorizationState.CLOSED, + TelegramAuthorizationState.UNKNOWN -> { + chatViewAdapter.chats = emptyList() + } + else -> Unit } } } + override fun onTelegramChatsRead() { + runOnUi { + updateChatsList() + } + } + + override fun onTelegramError(code: Int, message: String) { + runOnUi { + Toast.makeText(this@MainActivity, "$code - $message", Toast.LENGTH_LONG).show() + } + } + + private fun updateChatsList() { + val chatList = telegramHelper.getChatList() + val chats: MutableList = mutableListOf() + for (orderedChat in chatList) { + val chat = telegramHelper.getChat(orderedChat.chatId) + if (chat != null) { + chats.add(chat) + } + } + chatViewAdapter.chats = chats + } + fun logoutTelegram(silent: Boolean = false) { - if (telegramHelper.getAuthState() == AuthState.READY) { + if (telegramHelper.getTelegramAuthorizationState() == TelegramAuthorizationState.READY) { telegramHelper.logout() } else { invalidateOptionsMenu() @@ -98,6 +148,12 @@ class MainActivity : AppCompatActivity(), TelegramListener { telegramHelper.close() } + private fun runOnUi(action: (() -> Unit)) { + if (!paused) { + runOnUiThread(action) + } + } + override fun onOptionsItemSelected(item: MenuItem?): Boolean { return when (item?.itemId) { LOGIN_MENU_ID -> { @@ -115,17 +171,17 @@ class MainActivity : AppCompatActivity(), TelegramListener { override fun onCreateOptionsMenu(menu: Menu?): Boolean { if (menu != null) { menu.clear() - when (telegramHelper.getAuthState()) { - AuthState.UNKNOWN, - AuthState.WAIT_PARAMETERS, - AuthState.WAIT_PHONE_NUMBER, - AuthState.WAIT_CODE, - AuthState.WAIT_PASSWORD, - AuthState.LOGGING_OUT, - AuthState.CLOSING -> createProgressMenuItem(menu) - AuthState.READY -> createMenuItem(menu, LOGOUT_MENU_ID, R.string.shared_string_logout, + when (telegramHelper.getTelegramAuthorizationState()) { + TelegramAuthorizationState.UNKNOWN, + TelegramAuthorizationState.WAIT_PARAMETERS, + TelegramAuthorizationState.WAIT_PHONE_NUMBER, + TelegramAuthorizationState.WAIT_CODE, + TelegramAuthorizationState.WAIT_PASSWORD, + TelegramAuthorizationState.LOGGING_OUT, + TelegramAuthorizationState.CLOSING -> createProgressMenuItem(menu) + TelegramAuthorizationState.READY -> createMenuItem(menu, LOGOUT_MENU_ID, R.string.shared_string_logout, MenuItem.SHOW_AS_ACTION_WITH_TEXT or MenuItem.SHOW_AS_ACTION_ALWAYS) - AuthState.CLOSED -> createMenuItem(menu, LOGIN_MENU_ID, R.string.shared_string_login, + TelegramAuthorizationState.CLOSED -> createMenuItem(menu, LOGIN_MENU_ID, R.string.shared_string_login, MenuItem.SHOW_AS_ACTION_WITH_TEXT or MenuItem.SHOW_AS_ACTION_ALWAYS) } } @@ -148,35 +204,35 @@ class MainActivity : AppCompatActivity(), TelegramListener { } private fun updateTitle() { - title = when (telegramHelper.getAuthState()) { + title = when (telegramHelper.getTelegramAuthorizationState()) { - AuthState.UNKNOWN, - AuthState.WAIT_PHONE_NUMBER, - AuthState.WAIT_CODE, - AuthState.WAIT_PASSWORD, - AuthState.READY, - AuthState.CLOSED -> getString(R.string.app_name) + TelegramAuthorizationState.UNKNOWN, + TelegramAuthorizationState.WAIT_PHONE_NUMBER, + TelegramAuthorizationState.WAIT_CODE, + TelegramAuthorizationState.WAIT_PASSWORD, + TelegramAuthorizationState.READY, + TelegramAuthorizationState.CLOSED -> getString(R.string.app_name) - AuthState.WAIT_PARAMETERS -> getString(R.string.initialization) + "..." - AuthState.LOGGING_OUT -> getString(R.string.logging_out) + "..." - AuthState.CLOSING -> getString(R.string.closing) + "..." + TelegramAuthorizationState.WAIT_PARAMETERS -> getString(R.string.initialization) + "..." + TelegramAuthorizationState.LOGGING_OUT -> getString(R.string.logging_out) + "..." + TelegramAuthorizationState.CLOSING -> getString(R.string.closing) + "..." } } - private fun showLoginDialog(authParamType: AuthParamType) { - when (authParamType) { - AuthParamType.PHONE_NUMBER -> LoginDialogFragment.showDialog(supportFragmentManager, LoginDialogType.ENTER_PHONE_NUMBER) - AuthParamType.CODE -> LoginDialogFragment.showDialog(supportFragmentManager, LoginDialogType.ENTER_CODE) - AuthParamType.PASSWORD -> LoginDialogFragment.showDialog(supportFragmentManager, LoginDialogType.ENTER_PASSWORD) + private fun showLoginDialog(telegramAuthenticationParameterType: TelegramAuthenticationParameterType) { + when (telegramAuthenticationParameterType) { + TelegramAuthenticationParameterType.PHONE_NUMBER -> LoginDialogFragment.showDialog(supportFragmentManager, LoginDialogType.ENTER_PHONE_NUMBER) + TelegramAuthenticationParameterType.CODE -> LoginDialogFragment.showDialog(supportFragmentManager, LoginDialogType.ENTER_CODE) + TelegramAuthenticationParameterType.PASSWORD -> LoginDialogFragment.showDialog(supportFragmentManager, LoginDialogType.ENTER_PASSWORD) } } fun applyAuthParam(loginDialogFragment: LoginDialogFragment?, loginDialogType: LoginDialogType, text: String) { loginDialogFragment?.updateDialog(LoginDialogType.SHOW_PROGRESS) when (loginDialogType) { - LoginDialogType.ENTER_PHONE_NUMBER -> authParamRequestHandler?.applyAuthParam(AuthParamType.PHONE_NUMBER, text) - LoginDialogType.ENTER_CODE -> authParamRequestHandler?.applyAuthParam(AuthParamType.CODE, text) - LoginDialogType.ENTER_PASSWORD -> authParamRequestHandler?.applyAuthParam(AuthParamType.PASSWORD, text) + LoginDialogType.ENTER_PHONE_NUMBER -> telegramAuthorizationRequestHandler?.applyAuthenticationParameter(TelegramAuthenticationParameterType.PHONE_NUMBER, text) + LoginDialogType.ENTER_CODE -> telegramAuthorizationRequestHandler?.applyAuthenticationParameter(TelegramAuthenticationParameterType.CODE, text) + LoginDialogType.ENTER_PASSWORD -> telegramAuthorizationRequestHandler?.applyAuthenticationParameter(TelegramAuthenticationParameterType.PASSWORD, text) else -> Unit } } @@ -185,4 +241,35 @@ class MainActivity : AppCompatActivity(), TelegramListener { super.onDestroy() telegramHelper.close() } + + inner class ChatsAdapter : + RecyclerView.Adapter() { + + var chats: List = emptyList() + set(value) { + field = value + notifyDataSetChanged() + } + + inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) { + val icon: AppCompatImageView? = view.findViewById(R.id.icon) + val groupName: AppCompatTextView? = view.findViewById(R.id.name) + val shareLocationSwitch: SwitchCompat? = view.findViewById(R.id.share_location_switch) + val showOnMapSwitch: SwitchCompat? = view.findViewById(R.id.show_on_map_switch) + } + + override fun onCreateViewHolder(parent: ViewGroup, + viewType: Int): ChatsAdapter.ViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.chat_list_item, parent, false) + + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.groupName?.text = chats[position].title + } + + override fun getItemCount() = chats.size + } } diff --git a/OsmAnd-telegram/src/main/java/net/osmand/telegram/TelegramHelper.kt b/OsmAnd-telegram/src/main/java/net/osmand/telegram/TelegramHelper.kt index c7b574822e..5a0a57c569 100644 --- a/OsmAnd-telegram/src/main/java/net/osmand/telegram/TelegramHelper.kt +++ b/OsmAnd-telegram/src/main/java/net/osmand/telegram/TelegramHelper.kt @@ -1,7 +1,9 @@ package net.osmand.telegram import android.text.TextUtils -import net.osmand.telegram.TelegramHelper.AuthParamType.* +import net.osmand.telegram.TelegramHelper.TelegramAuthenticationParameterType.* +import net.osmand.telegram.utils.CancellableAsyncTask +import net.osmand.telegram.utils.PlatformUtil import org.drinkless.td.libcore.telegram.Client import org.drinkless.td.libcore.telegram.Client.ResultHandler import org.drinkless.td.libcore.telegram.TdApi @@ -10,12 +12,56 @@ import java.io.File import java.util.* import java.util.concurrent.ConcurrentHashMap + class TelegramHelper private constructor() { + + companion object { + private val log = PlatformUtil.getLog(TelegramHelper::class.java) + private const val CHATS_LIMIT = 100 + + private var helper: TelegramHelper? = null + + private val users = ConcurrentHashMap() + private val basicGroups = ConcurrentHashMap() + private val supergroups = ConcurrentHashMap() + private val secretChats = ConcurrentHashMap() + + private val chats = ConcurrentHashMap() + private val chatList = TreeSet() + + private val usersFullInfo = ConcurrentHashMap() + private val basicGroupsFullInfo = ConcurrentHashMap() + private val supergroupsFullInfo = ConcurrentHashMap() + + val instance: TelegramHelper + get() { + if (helper == null) { + helper = TelegramHelper() + } + return helper!! + } + + private fun setChatOrder(chat: TdApi.Chat, order: Long) { + synchronized(chatList) { + if (chat.order != 0L) { + chatList.remove(OrderedChat(chat.order, chat.id)) + } + + chat.order = order + + if (chat.order != 0L) { + chatList.add(OrderedChat(chat.order, chat.id)) + } + } + } + } + var appDir: String? = null private var libraryLoaded = false - private var authParamRequestHandler: AuthParamRequestHandler? = null + private var telegramAuthorizationRequestHandler: TelegramAuthorizationRequestHandler? = null private var client: Client? = null + private var haveFullChatList: Boolean = false private var authorizationState: AuthorizationState? = null private var isHaveAuthorization = false @@ -24,13 +70,23 @@ class TelegramHelper private constructor() { var listener: TelegramListener? = null - enum class AuthParamType { + fun getChatList(): TreeSet { + synchronized(chatList) { + return TreeSet(chatList) + } + } + + fun getChat(id: Long): TdApi.Chat? { + return chats[id] + } + + enum class TelegramAuthenticationParameterType { PHONE_NUMBER, CODE, PASSWORD } - enum class AuthState { + enum class TelegramAuthorizationState { UNKNOWN, WAIT_PARAMETERS, WAIT_PHONE_NUMBER, @@ -43,46 +99,51 @@ class TelegramHelper private constructor() { } interface TelegramListener { - fun onTelegramStatusChanged(prevAutoState: AuthState, newAuthState: AuthState) + fun onTelegramStatusChanged(prevTelegramAuthorizationState: TelegramAuthorizationState, + newTelegramAuthorizationState: TelegramAuthorizationState) + + fun onTelegramChatsRead() + fun onTelegramError(code: Int, message: String) } - interface AuthParamRequestListener { - fun onRequestAuthParam(paramType: AuthParamType) - fun onAuthRequestError(code: Int, message: String) + interface TelegramAuthorizationRequestListener { + fun onRequestTelegramAuthenticationParameter(parameterType: TelegramAuthenticationParameterType) + fun onTelegramAuthorizationRequestError(code: Int, message: String) } - inner class AuthParamRequestHandler(val authParamRequestListener: AuthParamRequestListener) { + inner class TelegramAuthorizationRequestHandler(val telegramAuthorizationRequestListener: TelegramAuthorizationRequestListener) { - fun applyAuthParam(paramType: AuthParamType, paramValue: String) { - if (!TextUtils.isEmpty(paramValue)) { - when (paramType) { - PHONE_NUMBER -> client!!.send(TdApi.SetAuthenticationPhoneNumber(paramValue, false, false), AuthorizationRequestHandler()) - CODE -> client!!.send(TdApi.CheckAuthenticationCode(paramValue, "", ""), AuthorizationRequestHandler()) - PASSWORD -> client!!.send(TdApi.CheckAuthenticationPassword(paramValue), AuthorizationRequestHandler()) + fun applyAuthenticationParameter(parameterType: TelegramAuthenticationParameterType, parameterValue: String) { + if (!TextUtils.isEmpty(parameterValue)) { + when (parameterType) { + PHONE_NUMBER -> client!!.send(TdApi.SetAuthenticationPhoneNumber(parameterValue, false, false), AuthorizationRequestHandler()) + CODE -> client!!.send(TdApi.CheckAuthenticationCode(parameterValue, "", ""), AuthorizationRequestHandler()) + PASSWORD -> client!!.send(TdApi.CheckAuthenticationPassword(parameterValue), AuthorizationRequestHandler()) } } } } - fun getAuthState(): AuthState { - val authorizationState = this.authorizationState ?: return AuthState.UNKNOWN + fun getTelegramAuthorizationState(): TelegramAuthorizationState { + val authorizationState = this.authorizationState + ?: return TelegramAuthorizationState.UNKNOWN return when (authorizationState.constructor) { - TdApi.AuthorizationStateWaitTdlibParameters.CONSTRUCTOR -> AuthState.WAIT_PARAMETERS - TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR -> AuthState.WAIT_PHONE_NUMBER - TdApi.AuthorizationStateWaitCode.CONSTRUCTOR -> AuthState.WAIT_CODE - TdApi.AuthorizationStateWaitPassword.CONSTRUCTOR -> AuthState.WAIT_PASSWORD - TdApi.AuthorizationStateReady.CONSTRUCTOR -> AuthState.READY - TdApi.AuthorizationStateLoggingOut.CONSTRUCTOR -> AuthState.LOGGING_OUT - TdApi.AuthorizationStateClosing.CONSTRUCTOR -> AuthState.CLOSING - TdApi.AuthorizationStateClosed.CONSTRUCTOR -> AuthState.CLOSED - else -> AuthState.UNKNOWN + TdApi.AuthorizationStateWaitTdlibParameters.CONSTRUCTOR -> TelegramAuthorizationState.WAIT_PARAMETERS + TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR -> TelegramAuthorizationState.WAIT_PHONE_NUMBER + TdApi.AuthorizationStateWaitCode.CONSTRUCTOR -> TelegramAuthorizationState.WAIT_CODE + TdApi.AuthorizationStateWaitPassword.CONSTRUCTOR -> TelegramAuthorizationState.WAIT_PASSWORD + TdApi.AuthorizationStateReady.CONSTRUCTOR -> TelegramAuthorizationState.READY + TdApi.AuthorizationStateLoggingOut.CONSTRUCTOR -> TelegramAuthorizationState.LOGGING_OUT + TdApi.AuthorizationStateClosing.CONSTRUCTOR -> TelegramAuthorizationState.CLOSING + TdApi.AuthorizationStateClosed.CONSTRUCTOR -> TelegramAuthorizationState.CLOSED + else -> TelegramAuthorizationState.UNKNOWN } } - fun setAuthParamRequestHandler(authParamRequestListener: AuthParamRequestListener): AuthParamRequestHandler { - val authParamRequestHandler = AuthParamRequestHandler(authParamRequestListener) - this.authParamRequestHandler = authParamRequestHandler - return authParamRequestHandler + fun setTelegramAuthorizationRequestHandler(telegramAuthorizationRequestListener: TelegramAuthorizationRequestListener): TelegramAuthorizationRequestHandler { + val handler = TelegramAuthorizationRequestHandler(telegramAuthorizationRequestListener) + this.telegramAuthorizationRequestHandler = handler + return handler } init { @@ -108,6 +169,42 @@ class TelegramHelper private constructor() { } } + fun requestChats() { + synchronized(chatList) { + if (!haveFullChatList && CHATS_LIMIT > chatList.size) { + // have enough chats in the chat list or chat list is too small + var offsetOrder = java.lang.Long.MAX_VALUE + var offsetChatId: Long = 0 + if (!chatList.isEmpty()) { + val last = chatList.last() + offsetOrder = last.order + offsetChatId = last.chatId + } + client?.send(TdApi.GetChats(offsetOrder, offsetChatId, CHATS_LIMIT - chatList.size), { obj -> + when (obj.constructor) { + TdApi.Error.CONSTRUCTOR -> { + val error = obj as TdApi.Error + listener?.onTelegramError(error.code, error.message) + } + TdApi.Chats.CONSTRUCTOR -> { + val chatIds = (obj as TdApi.Chats).chatIds + if (chatIds.isEmpty()) { + synchronized(chatList) { + haveFullChatList = true + } + } + // chats had already been received through updates, let's retry request + requestChats() + } + else -> listener?.onTelegramError(-1, "Receive wrong response from TDLib: $obj") + } + }) + return + } + } + listener?.onTelegramChatsRead() + } + fun logout(): Boolean { return if (libraryLoaded) { isHaveAuthorization = false @@ -129,7 +226,7 @@ class TelegramHelper private constructor() { } private fun onAuthorizationStateUpdated(authorizationState: AuthorizationState?) { - val prevAuthState = getAuthState() + val prevAuthState = getTelegramAuthorizationState() if (authorizationState != null) { this.authorizationState = authorizationState } @@ -156,15 +253,15 @@ class TelegramHelper private constructor() { } TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR -> { log.info("Request phone number") - authParamRequestHandler?.authParamRequestListener?.onRequestAuthParam(PHONE_NUMBER) + telegramAuthorizationRequestHandler?.telegramAuthorizationRequestListener?.onRequestTelegramAuthenticationParameter(PHONE_NUMBER) } TdApi.AuthorizationStateWaitCode.CONSTRUCTOR -> { log.info("Request code") - authParamRequestHandler?.authParamRequestListener?.onRequestAuthParam(CODE) + telegramAuthorizationRequestHandler?.telegramAuthorizationRequestListener?.onRequestTelegramAuthenticationParameter(CODE) } TdApi.AuthorizationStateWaitPassword.CONSTRUCTOR -> { log.info("Request password") - authParamRequestHandler?.authParamRequestListener?.onRequestAuthParam(PASSWORD) + telegramAuthorizationRequestHandler?.telegramAuthorizationRequestListener?.onRequestTelegramAuthenticationParameter(PASSWORD) } TdApi.AuthorizationStateReady.CONSTRUCTOR -> { isHaveAuthorization = true @@ -183,11 +280,11 @@ class TelegramHelper private constructor() { } else -> log.error("Unsupported authorization state: " + this.authorizationState!!) } - val newAuthState = getAuthState() + val newAuthState = getTelegramAuthorizationState() listener?.onTelegramStatusChanged(prevAuthState, newAuthState) } - private class OrderedChat internal constructor(internal val order: Long, internal val chatId: Long) : Comparable { + class OrderedChat internal constructor(internal val order: Long, internal val chatId: Long) : Comparable { override fun compareTo(other: OrderedChat): Int { if (this.order != other.order) { @@ -257,6 +354,9 @@ class TelegramHelper private constructor() { chat.order = 0 setChatOrder(chat, order) } + CancellableAsyncTask.run("onTelegramChatsRead", 100, { + listener?.onTelegramChatsRead() + }) } TdApi.UpdateChatTitle.CONSTRUCTOR -> { val updateChat = obj as TdApi.UpdateChatTitle @@ -371,7 +471,7 @@ class TelegramHelper private constructor() { TdApi.Error.CONSTRUCTOR -> { log.error("Receive an error: $obj") val errorObj = obj as TdApi.Error - authParamRequestHandler?.authParamRequestListener?.onAuthRequestError(errorObj.code, errorObj.message) + telegramAuthorizationRequestHandler?.telegramAuthorizationRequestListener?.onTelegramAuthorizationRequestError(errorObj.code, errorObj.message) onAuthorizationStateUpdated(null) // repeat last action } TdApi.Ok.CONSTRUCTOR -> { @@ -380,44 +480,4 @@ class TelegramHelper private constructor() { }// result is already received through UpdateAuthorizationState, nothing to do } } - - companion object { - private val log = PlatformUtil.getLog(TelegramHelper::class.java) - - private var helper: TelegramHelper? = null - - private val users = ConcurrentHashMap() - private val basicGroups = ConcurrentHashMap() - private val supergroups = ConcurrentHashMap() - private val secretChats = ConcurrentHashMap() - - private val chats = ConcurrentHashMap() - private val chatList = TreeSet() - - private val usersFullInfo = ConcurrentHashMap() - private val basicGroupsFullInfo = ConcurrentHashMap() - private val supergroupsFullInfo = ConcurrentHashMap() - - val instance: TelegramHelper - get() { - if (helper == null) { - helper = TelegramHelper() - } - return helper!! - } - - private fun setChatOrder(chat: TdApi.Chat, order: Long) { - synchronized(chatList) { - if (chat.order != 0L) { - chatList.remove(OrderedChat(chat.order, chat.id)) - } - - chat.order = order - - if (chat.order != 0L) { - chatList.add(OrderedChat(chat.order, chat.id)) - } - } - } - } } diff --git a/OsmAnd-telegram/src/main/java/net/osmand/telegram/AndroidUtils.kt b/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/AndroidUtils.kt similarity index 97% rename from OsmAnd-telegram/src/main/java/net/osmand/telegram/AndroidUtils.kt rename to OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/AndroidUtils.kt index 4c582d5a35..208f05226a 100644 --- a/OsmAnd-telegram/src/main/java/net/osmand/telegram/AndroidUtils.kt +++ b/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/AndroidUtils.kt @@ -1,4 +1,4 @@ -package net.osmand.telegram +package net.osmand.telegram.utils import android.app.Activity import android.content.Context diff --git a/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/CancellableAsyncTask.kt b/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/CancellableAsyncTask.kt new file mode 100644 index 0000000000..92fdaf5430 --- /dev/null +++ b/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/CancellableAsyncTask.kt @@ -0,0 +1,76 @@ +package net.osmand.telegram.utils + +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.atomic.AtomicInteger + +class CancellableAsyncTask(val taskId: String, val executeTimeout: Long = 0) { + + companion object { + private const val SLEEP_TIME = 50L + private val requestNumbersMap = ConcurrentHashMap() + private val singleThreadExecutorsMap = ConcurrentHashMap() + + fun run(taskId: String, executeTimeout: Long = 0, action: (() -> Unit)) { + CancellableAsyncTask(taskId, executeTimeout).run(action) + } + + fun clearResources(taskId: String) { + requestNumbersMap.remove(taskId) + singleThreadExecutorsMap.remove(taskId) + } + } + + private val singleThreadExecutor: ExecutorService + private var requestNumber: AtomicInteger + + var isCancelled: Boolean = false + + init { + val requestNumber = requestNumbersMap[taskId] + if (requestNumber == null) { + this.requestNumber = AtomicInteger() + requestNumbersMap[taskId] = this.requestNumber + } else { + this.requestNumber = requestNumber + } + + val singleThreadExecutor = singleThreadExecutorsMap[taskId] + if (singleThreadExecutor == null) { + this.singleThreadExecutor = Executors.newSingleThreadExecutor() + singleThreadExecutorsMap[taskId] = this.singleThreadExecutor + } else { + this.singleThreadExecutor = singleThreadExecutor + } + } + + fun run(action: (() -> Unit)) { + val req = requestNumber.incrementAndGet() + + singleThreadExecutor.submit(object : Runnable { + + private val isCancelled: Boolean + get() = requestNumber.get() != req || this@CancellableAsyncTask.isCancelled + + override fun run() { + try { + if (executeTimeout > 0) { + val startTime = System.currentTimeMillis() + while (System.currentTimeMillis() - startTime <= executeTimeout) { + if (isCancelled) { + return + } + Thread.sleep(SLEEP_TIME) + } + } + if (!isCancelled) { + action.invoke() + } + } catch (e: InterruptedException) { + // ignore + } + } + }) + } +} diff --git a/OsmAnd-telegram/src/main/java/net/osmand/telegram/PlatformUtil.java b/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/PlatformUtil.java similarity index 99% rename from OsmAnd-telegram/src/main/java/net/osmand/telegram/PlatformUtil.java rename to OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/PlatformUtil.java index 958907b558..d783e2ab28 100644 --- a/OsmAnd-telegram/src/main/java/net/osmand/telegram/PlatformUtil.java +++ b/OsmAnd-telegram/src/main/java/net/osmand/telegram/utils/PlatformUtil.java @@ -1,4 +1,4 @@ -package net.osmand.telegram; +package net.osmand.telegram.utils; import org.apache.commons.logging.Log; diff --git a/OsmAnd-telegram/src/main/res/drawable-hdpi/ic_group.png b/OsmAnd-telegram/src/main/res/drawable-hdpi/ic_group.png new file mode 100644 index 0000000000000000000000000000000000000000..fc1febc6653bdfbf6b1bd6f6300f490a21cad350 GIT binary patch literal 1299 zcmaJ>ZD`zN98X`IS~y%+3scmEbhVo{mzO5FCN%BZyIXr~*Olu@&kt&oJkPbUO`a@C zch{n|E$+pMqQbBfgjr;RX=PX~xH7Ba3uQv*h9U!BX1_Qch&oX>i$1yb>OPbOk|)oT z-~adj{onFTS7&>u;_eE9AVP_bSPHLOgZs7(_<4z#oW#premvuMqpY9PTu8J6q(d@c zX?-vSH88w)0X7jt+0$k^<7bk)6$4peEx?5HmV>PcqNyeCXvP5aNgei?wo3gnH&2l! zP^lg<$tImB>^D0`T-ZI*nKniS3>i=@&16$v!2}lcH8O7v+MbeEsRFNp--Ba@A`1|I zK&4hhWs+TF6uFQT!xC+O>1Up@1k%c@f z<~kaHq02^u<7u6fvUG$OSXwr4CL~D|B~1b{5HxDl9^8<>l|IEMI1Z;MN6`#J)ObUq zbr{iTj)MZN^HM+#0Ve>1Gc=82utX+kof}%Ic!c{icwHL|yjdG9XybWu@!;G)|9c5R zl+-3-t?B&5D@W9dk9KU_UsY*M9h$B?_4e%SsS9(NOn!W8`$BE~V7*b7sC@8?^IvV* z{8;aY;>Y0Na~t<=d7>VC+xaLrH&FHBLv`YtuPl`F4|Hhcf^0Lyw=SB-2Uq5 z1LLJx_1sS<*yuMebzi{fgUTl*&5dJondOO^&;OV?aIxv$cT+R3HV<(6*g6^JLViM;& Pg5Ojk-WhwVt#{%-Zlk@o literal 0 HcmV?d00001 diff --git a/OsmAnd-telegram/src/main/res/drawable-mdpi/ic_group.png b/OsmAnd-telegram/src/main/res/drawable-mdpi/ic_group.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c18f9c95d9d32dbd44912035be57f67339b4b2 GIT binary patch literal 1208 zcmaJ>OKjXk7MZ;N!bG_IGd`x2rH8<++Ptpijbli3`{O?O2@xUe- zepD+;ML$a??19;Uj?500@$4jqgzr5Jdg=xvaA<@;-I;Pjqn_a#yas!Zk3}9dOrpsQ zzagqp90pl0pg>FN0+wVIq+n9k^b|}z0u;6vrL?F>f&>likRd6cdGX9!K&nQ`%r||p zU51~CBHs|jTCJ9>9ZGt^xF|yiMM)7AMPL>}IO9gBF1X==7K2Gc9N2zjdoG9>k>yQC z8J;QK2*L4-#Z6*2Y$l4OOspecl#`O^IB{GJ>o6+O|7C1x9hPT&Dwb&IO$V6Oqk5nP zX1Tkyqu7wCF@^%06$MS19-eln8x_n9&%PvyO$=2d#Ikf!@Sn7>sr>-`eiw%re&z*vL@`)6sbR#&bP1yH;j;rY0J0Gd^fS`EwM&6 zpeXW!vgb{;x?p(1i@b2c^FcP-s5*FX)OLwi3m=Nhv=OyQ1N(VO@`2}oMxG6O3k?KY z5T|5Cuw=a|q!d*WAZD3hA!$0&2_!1wn|N|l{x!J;W7$TC$0 zOVML;N@SH_86(7tOrjXK&P}b&b=f=xY;Y=Hee)X|x|M?2SFV3; z{jv<^X2)rp&O@mzH=Jv{^Vr(%r7s1 zy^nR>Shz1g@YYzTd}sT!`6qrDgWKN!$^7-wz8&X2m;U9JzqnvsS?M}?;=&ud=Z~fD zT^LRLaRjVwUj~2ezj&_m%=O^5Kd+_7+P;4ptX*G}Ry&S-+VSO5`(n>$$CuX&JDxm0 zJALiyW&ZC+JHywzKYVHK?A;5`%&n%9GiTd=eBl1d%a`9?JpJ>#3r9a#xo2%Jx4oM? Y`0d=%n|Hi;IR2Lua)ai3{bR@f0|-HrZ~y=R literal 0 HcmV?d00001 diff --git a/OsmAnd-telegram/src/main/res/drawable-xhdpi/ic_group.png b/OsmAnd-telegram/src/main/res/drawable-xhdpi/ic_group.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea162c464b9e73c9c28f38e1f104273c0f79063 GIT binary patch literal 1408 zcmaJ>eM}o=7;j;A$RHy#x-lJ`M~rjhdLQjwdlw4!i&3+7q$8to$heOe==yQxdaNxO z(N1va7Q)<&jDHqIh(R+&w>Yxlrcn%;GEMg3*i<%^5vQUV>ZXhHEl}JaWS88%_rCW$ zzvuV-p69t2D?J->vsY(pG@4vjg~JP1B6Vl!;Ilg8)^51ut4^P~S*}-OyaF^z9{VswYztqlp$opZBqQOD16W%i_IYrR$UGY3cu(jzr-17NfHEx!6=3? zVk}`~F_x7mi~%H|MZpN_1u2cQn18w5Op~m^W_Qq5l5`r)q`_>rm(%4WWwIGqbK2Jx zj;efE1nJm*7<=B=dQV@@t^i(@l`2^drn{iBQC8(>qZ~o(_SvcDZ?rNp<5$w;@>%w5b z&BADbFq|g^4$itO;@cXH_GOpDS`{Dvx%=c(nby3K>9H~go44fQ!4*da2M2HD9`VSS z&sR}^w&Pvvwj}n}y%P9j+v;mMp1Es5wh7U^=o%q;5v?9A2dnf+w#V>w^zT6+pw$A0g-^TOz%ZTIDW z(RmHX-g@qlit6E--Vby`v4WW~ z9oIRu1|Ke|={@*8-E**}7c778Y*SZX>C%fU$;RiF?Cowl^y!0Bk7xb(R@+1Zk%?piW9W4LxI!<-TN%{ED%uStrB`>r=l zzIkDF$Eo{Qc@yLhJ^T8<>)TVhE%<;sx=kJ0J^sG#*U%r^U&|$sJLE*|_UUC?ho64K zdCs}Mq3+COccLYtC~y0Vr+!6Ju6ka@#236MdXlBTwx6NT~N zO@%q#F>rz(8{RzhJWttB$Gn}NcOdLU1wU`%28x0VotuDr3zYeXXYNhjJa3-g^Z9!& zn-k)rr%ef(B9Ta@8DeyaV2^R%z7xSS>EY36u)QNjrHCu|bkRu(tR#}*%`9ZFP#J6@ zOEI}Q7uX1iWWwj1DMd^%E>qFGMM}AKq%MmMpe2%s4_!8j&SFK#%w}*_HQalm5r#NM z4JRv%GNVn)W^yrk0=ptF-bCkR(If+ZxD<+Tsel0sD^ifll5MrCTxxj4t_r-nk5L#J zQ4zD$@Muse#so;q3oN9N5(q8B2yk+VNzbmKrxaeQ5lZnI07^fd#+WaT!_`az+*wj+G&Ba zi5zc*+!iS_?-126h;%dsi_K^pH*B?!6$+FLbx}4Hlgdzw#hurPwp~nQ{}1Dp+ICZ} zjYSh#JMR!^(2w*59x$lg>m9ijK{Tr60tcExW$Sp_VPUPJL8pen7b(LrD!GDT%w~c> zaDtE{q)bjCB+1|i!D6g}Hp|&`Gvl%IDtwe)M(CAtomQua#IPuNxL%3th%iMIfhn+X zJ>kI`tag#I(yYff2YioVwXemhv;s?sykO$_Y!3?(GI^1=XYw{ks~zb&^nNmDWq7B3 zk-JT!S?gGVTgx(ffww>-byjh&h=HNaB(217#EcQ?h!U5}5RwL!AP9wmpa_O!T9cuGx3a|Jju59?*tL59X%IhL0 z#>L-R{HykQ+K^v^&^J9TZy+}fJ57Dvr+b0BB^X{P^3`h#aSPADtszj*B9eV1wsnchLgb1(42 zn#Mizc2@Bz4i0YA{Q1V&)kRA+WjhDsPW@rYHyymOet%WrCz|Q8Jqtf8TB<$K5*b)` z`h!eke`{ZFLt90`m71`9ff@K&Q}eD{i=QX=Z)hF#IcDtLi_lku&iX^$)ed1+M-Nu9 ze{*)Ml*{$gl%x)Gg+CVrh3tAZxhY+fS9h;ker^5f<)=DYcii|5ddNLH_n-#rE-mp6 zH53QeAKCHO^`PM#P4AvBH$FH%;{vwmsbcW1qs7@}xO1is@u?1(Q(x4LUIi)-{fd%( zA1l9;Z4J(^1+tU + android:paddingRight="@dimen/content_padding_standard" + android:paddingLeft="@dimen/content_padding_standard"> + android:layout_width="@dimen/progress_bar_size_small" + android:layout_height="@dimen/progress_bar_size_small" /> \ No newline at end of file diff --git a/OsmAnd-telegram/src/main/res/layout/activity_main.xml b/OsmAnd-telegram/src/main/res/layout/activity_main.xml index df0998f1ea..94c382c0dc 100644 --- a/OsmAnd-telegram/src/main/res/layout/activity_main.xml +++ b/OsmAnd-telegram/src/main/res/layout/activity_main.xml @@ -1,16 +1,14 @@ - + android:layout_height="match_parent" + android:scrollbars="vertical" /> \ No newline at end of file diff --git a/OsmAnd-telegram/src/main/res/layout/chat_list_item.xml b/OsmAnd-telegram/src/main/res/layout/chat_list_item.xml new file mode 100644 index 0000000000..18882a304b --- /dev/null +++ b/OsmAnd-telegram/src/main/res/layout/chat_list_item.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd-telegram/src/main/res/layout/login_dialog.xml b/OsmAnd-telegram/src/main/res/layout/login_dialog.xml index 53bd76aa2c..2db8deb9b0 100644 --- a/OsmAnd-telegram/src/main/res/layout/login_dialog.xml +++ b/OsmAnd-telegram/src/main/res/layout/login_dialog.xml @@ -4,10 +4,10 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" - android:paddingBottom="24dp" - android:paddingLeft="48dp" - android:paddingRight="48dp" - android:paddingTop="24dp"> + android:paddingBottom="@dimen/dialog_padding_vertical" + android:paddingLeft="@dimen/dialog_padding_horizontal" + android:paddingRight="@dimen/dialog_padding_horizontal" + android:paddingTop="@dimen/dialog_padding_vertical"> + android:layout_width="@dimen/progress_bar_size_small" + android:layout_height="@dimen/progress_bar_size_small" /> diff --git a/OsmAnd-telegram/src/main/res/values/attrs.xml b/OsmAnd-telegram/src/main/res/values/attrs.xml new file mode 100644 index 0000000000..7bbaffc998 --- /dev/null +++ b/OsmAnd-telegram/src/main/res/values/attrs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OsmAnd-telegram/src/main/res/values/colors.xml b/OsmAnd-telegram/src/main/res/values/colors.xml index 3ab3e9cbce..e41fe93e86 100644 --- a/OsmAnd-telegram/src/main/res/values/colors.xml +++ b/OsmAnd-telegram/src/main/res/values/colors.xml @@ -3,4 +3,10 @@ #3F51B5 #303F9F #FF4081 + + #fff + #333b40 + #ccc + #ff4f4f4f + diff --git a/OsmAnd-telegram/src/main/res/values/dimens.xml b/OsmAnd-telegram/src/main/res/values/dimens.xml new file mode 100644 index 0000000000..b28658b4cb --- /dev/null +++ b/OsmAnd-telegram/src/main/res/values/dimens.xml @@ -0,0 +1,10 @@ + + + 8dp + 16dp + 32dp + 22sp + 24dp + 48dp + 48dp + \ No newline at end of file diff --git a/OsmAnd-telegram/src/main/res/values/styles.xml b/OsmAnd-telegram/src/main/res/values/styles.xml index eab06b654f..90b91cd756 100644 --- a/OsmAnd-telegram/src/main/res/values/styles.xml +++ b/OsmAnd-telegram/src/main/res/values/styles.xml @@ -6,6 +6,9 @@ @color/colorPrimary @color/colorPrimaryDark @color/colorAccent + + @color/bg_color_light + @color/icon_color_light